Skip to content

Commit

Permalink
updated with camera permission handler on app level
Browse files Browse the repository at this point in the history
  • Loading branch information
V-m1r committed Oct 25, 2024
1 parent 3e74714 commit 3df3820
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 119 deletions.
54 changes: 32 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,29 @@ implementation("com.github.KinesteX:KinesteXSDKKotlin:1.1.5")

1. **Prerequisites**: Ensure you’ve added the necessary permissions in `AndroidManifest.xml`.

2. **Launching the view**: To display KinesteX, we will be using WebView. To launch Complete UX call `createMainView` in KinesteXSDK:
2. **Project setup**: When a user starts a workout, we need to present camera permission dialog. We are requesting camera permission on the app level and need to handle the result in the app level as well.

2.1 Make sure your activity or fragment implements the `PermissionHandler` interface:
`class MainActivity : AppCompatActivity(), PermissionHandler`
2.2 Create necessary variables and override the `requestCameraPermission` method in `PermissionHandler` interface:
```kotlin

private var kinesteXWebView: GenericWebView? = null


private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
webView?.handlePermissionResult(isGranted)
}

override fun requestCameraPermission() {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
```
3. To launch Complete UX call `createMainView` in KinesteXSDK:

```kotlin

@SuppressLint("SetJavaScriptEnabled", "MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -80,24 +98,11 @@ implementation("com.github.KinesteX:KinesteXSDKKotlin:1.1.5")
null,
customParams = data, // example of using custom parameters. CAN BE NULL
viewModel.isLoading,
::handleWebViewMessage
::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?
}
```

3. **Handling camera permission request**: We send a request for camera permissiona and it needs to be granted on app level:
```kotlin
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// handle the permission result on app level
kinesteXWebView?.handlePermissionResult(requestCode, grantResults)
}

```

4. **Handling the data**: Use a ViewModel to handle changes:

Expand Down Expand Up @@ -129,7 +134,8 @@ The KinesteX SDK provides multiple methods to create different views:
null, // user details
customParams = data, // example of using custom parameters
viewModel.isLoading,
::handleWebViewMessage // callback function to handle responses
::handleWebViewMessage, // callback function to handle responses
permissionHandler = this // permission handler
) as GenericWebView?
```

Expand All @@ -145,7 +151,8 @@ The KinesteX SDK provides multiple methods to create different views:
null,
null, // custom parameters is null
viewModel.isLoading,
::handleWebViewMessage
::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?
```

Expand All @@ -160,7 +167,8 @@ The KinesteX SDK provides multiple methods to create different views:
"Fitness Lite", // name of the workout
null,
isLoading = viewModel.isLoading,
onMessageReceived = ::handleWebViewMessage
onMessageReceived = ::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?
```

Expand All @@ -177,7 +185,8 @@ The KinesteX SDK provides multiple methods to create different views:
null,
customParams = null,
viewModel.isLoading,
::handleWebViewMessage
::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?
```

Expand All @@ -193,7 +202,8 @@ The KinesteX SDK provides multiple methods to create different views:
exercises = listOf("Squats","Jumping Jack"), // exercises that user is expected to do
user = null,
isLoading = viewModel.isLoading,
onMessageReceived = ::handleWebViewMessage
onMessageReceived = ::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?
```

Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ android {
}

dependencies {
// implementation(project(":kinestexsdkkotlin"))
implementation(project(":kinestexsdkkotlin"))
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
implementation("com.github.KinesteX:KinesteX-SDK-Kotlin:1.1.5")
// implementation("com.github.KinesteX:KinesteX-SDK-Kotlin:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
implementation("androidx.activity:activity-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.1")
Expand Down
50 changes: 24 additions & 26 deletions app/src/main/java/com/kinestex/kotlin_sdk/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.kinestex.kotlin_sdk

import android.Manifest.permission.CAMERA
import android.Manifest
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Color
import android.os.Bundle
import android.util.Log
Expand All @@ -13,25 +11,24 @@ import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import android.webkit.WebView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.kinestex.kinestexsdkkotlin.GenericWebView
import com.kinestex.kinestexsdkkotlin.KinesteXSDK
import com.kinestex.kinestexsdkkotlin.PermissionHandler
import com.kinestex.kinestexsdkkotlin.PlanCategory
import com.kinestex.kinestexsdkkotlin.WebViewMessage
import com.kinestex.kotlin_sdk.databinding.ActivityMainBinding
import kotlinx.coroutines.launch


class MainActivity : AppCompatActivity() {
class MainActivity : AppCompatActivity(), PermissionHandler {
private var tvMistake: TextView? = null
private var tvReps: TextView? = null

Expand All @@ -40,10 +37,18 @@ class MainActivity : AppCompatActivity() {
private val iconSubOptions = mutableListOf<ImageView>()
private var webView: GenericWebView? = null

private val apiKey = "apiKey" // store this key securely
private val company = "companyName"
private val apiKey = "apikey" // store this key securely
private val company = "companyname"
private val userId = "userId"

private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
webView?.handlePermissionResult(isGranted)
}
override fun requestCameraPermission() {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}

@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -81,18 +86,6 @@ class MainActivity : AppCompatActivity() {
binding.layVideo.addView(howToView)
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
webView?.handlePermissionResult(requestCode, grantResults)
}

private fun onCameraPermissionGranted() {
// Toast.makeText(this, "Camera permission granted", Toast.LENGTH_SHORT).show()
}

private fun initUiListeners() {
binding.apply {
Expand Down Expand Up @@ -204,7 +197,8 @@ class MainActivity : AppCompatActivity() {
null,
customParams = data, // example of using custom parameters
viewModel.isLoading,
::handleWebViewMessage
::handleWebViewMessage,
this
) as GenericWebView?
return webView
}
Expand All @@ -223,7 +217,8 @@ class MainActivity : AppCompatActivity() {
null,
data,
viewModel.isLoading,
::handleWebViewMessage
::handleWebViewMessage,
this
) as GenericWebView?
return webView

Expand All @@ -238,7 +233,8 @@ class MainActivity : AppCompatActivity() {
subOption ?: "Fitness Lite",
null,
isLoading = viewModel.isLoading,
onMessageReceived = ::handleWebViewMessage
onMessageReceived = ::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?
return webView
}
Expand All @@ -254,7 +250,8 @@ class MainActivity : AppCompatActivity() {
null,
customParams = null,
viewModel.isLoading,
::handleWebViewMessage
::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?
return webView
}
Expand Down Expand Up @@ -376,7 +373,8 @@ class MainActivity : AppCompatActivity() {
exercises = listOf("Squats", "Jumping Jack"),
user = null,
isLoading = viewModel.isLoading,
onMessageReceived = ::handleWebViewMessage
onMessageReceived = ::handleWebViewMessage,
permissionHandler = this
) as GenericWebView?

webView?.let { container.addView(setLayoutParamsFullScreen(it)) }
Expand Down
4 changes: 2 additions & 2 deletions kinestexsdkkotlin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ afterEvaluate {
}

dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
// ExoPlayer (Media3) dependencies
implementation(libs.androidx.media3.exoplayer)
implementation(libs.androidx.media3.exoplayer.dash)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
package com.kinestex.kinestexsdkkotlin

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.util.Log
import android.webkit.*
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.coroutines.flow.MutableStateFlow
import org.json.JSONArray
import org.json.JSONException
Expand All @@ -23,7 +18,8 @@ class GenericWebView(
private val url: String,
private val onMessageReceived: (WebViewMessage) -> Unit,
private val isLoading: MutableStateFlow<Boolean>,
private val data: Map<String, Any>
private val data: Map<String, Any>,
private val permissionHandler: PermissionHandler
) : WebView(context) {

init {
Expand All @@ -49,36 +45,19 @@ class GenericWebView(
// Store the request for later use
pendingCameraPermissionRequest = request

// Check current permission status
when {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
// If already granted, grant to WebView immediately
Log.d("KinesteX SDK", "Camera permission already granted, granting to WebView")
request.grant(request.resources)
}
(context as? Activity)?.shouldShowRequestPermissionRationale(
Manifest.permission.CAMERA
) == true -> {
// Optional: Show rationale if needed
Log.d("KinesteX SDK", "Should show permission rationale")
requestCameraPermission()
}
else -> {
// Request permission
Log.d("KinesteX SDK", "Requesting camera permission")
requestCameraPermission()
}
if (request.resources.contains(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
pendingCameraPermissionRequest = request
permissionHandler.requestCameraPermission()
} else {
request.deny()
}
} else {
Log.d("KinesteX SDK", "Denying non-camera permission request")
request.deny()
request.grant(request.resources)
}
} catch (e: Exception) {
Log.e("KinesteX SDK", "Error handling permission request", e)
request.deny()
request.grant(request.resources)
}
}
}
Expand All @@ -96,33 +75,13 @@ class GenericWebView(
loadUrl(url)
}

private fun requestCameraPermission() {
val activity = context as? Activity
if (activity != null) {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.CAMERA),
CAMERA_PERMISSION_CODE
)
} else {
Log.e("KinesteX SDK", "Context is not an activity, cannot request permission")
pendingCameraPermissionRequest?.deny()
pendingCameraPermissionRequest = null
}
}

// Method to be called from Activity's onRequestPermissionsResult
fun handlePermissionResult(requestCode: Int, grantResults: IntArray) {
Log.d("KinesteX SDK", "Handling permission result: code=$requestCode, results=${grantResults.contentToString()}")

if (requestCode == CAMERA_PERMISSION_CODE) {
fun handlePermissionResult(granted: Boolean) {
pendingCameraPermissionRequest?.let { request ->
try {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("KinesteX SDK", "Permission granted, granting to WebView")
if (granted) {
request.grant(request.resources)
} else {
Log.d("KinesteX SDK", "Permission denied, denying WebView request")
request.deny()
}
} catch (e: Exception) {
Expand All @@ -132,11 +91,7 @@ class GenericWebView(
pendingCameraPermissionRequest = null
}
}
}
}

companion object {
const val CAMERA_PERMISSION_CODE = 1010101
}

private fun postMessage() {
Expand Down
Loading

0 comments on commit 3df3820

Please sign in to comment.