Created
February 6, 2021 13:25
-
-
Save prokash-sarkar/94c99f0352e9833a63dd698ff1b930d6 to your computer and use it in GitHub Desktop.
A sample app to demonstrate the process of showing camera preview in web view
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
plugins { | |
id 'com.android.application' | |
id 'kotlin-android' | |
} | |
android { | |
// Code omitted for brevity | |
} | |
dependencies { | |
// Code omitted for brevity | |
implementation 'androidx.activity:activity:1.2.0-rc01' | |
implementation 'androidx.activity:activity-ktx:1.2.0-rc01' | |
implementation 'androidx.fragment:fragment:1.3.0-rc02 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.myapplication | |
import android.app.AlertDialog | |
import android.app.Dialog | |
import android.content.Context | |
import android.os.Bundle | |
import android.text.TextUtils | |
import androidx.fragment.app.DialogFragment | |
/** | |
Created by Prokash Sarkar on Sat, February 06, 2021 | |
**/ | |
class ConfirmationDialogFragment : DialogFragment() { | |
companion object { | |
private val ARG_RESOURCES = "resources" | |
/** | |
* Creates a new instance of ConfirmationDialogFragment. | |
* | |
* @param resources The list of resources requested by PermissionRequest. | |
* @return A new instance. | |
*/ | |
fun newInstance(resources: Array<String>): ConfirmationDialogFragment { | |
val fragment = ConfirmationDialogFragment() | |
val args = Bundle() | |
args.putStringArray(ARG_RESOURCES, resources) | |
fragment.arguments = args | |
return fragment | |
} | |
} | |
private lateinit var webPermissionListener: WebPermissionListener | |
override fun onAttach(context: Context) { | |
super.onAttach(context) | |
webPermissionListener = context as WebPermissionListener | |
} | |
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { | |
val resources = arguments?.getStringArray(ARG_RESOURCES) | |
return AlertDialog.Builder(activity) | |
.setMessage(getString(R.string.confirmation, TextUtils.join("\n", resources!!))) | |
.setNegativeButton(R.string.deny) { dialog, which -> | |
webPermissionListener.onConfirmation(false, resources) | |
} | |
.setPositiveButton(R.string.allow) { dialog, which -> | |
webPermissionListener.onConfirmation(true, resources) | |
} | |
.create() | |
} | |
/** | |
* Callback for the user's response. | |
*/ | |
interface WebPermissionListener { | |
/** | |
* Called when the PermissionRequest is allowed or denied by the user. | |
* | |
* @param allowed True if the user allowed the request. | |
* @param resources The resources to be granted. | |
*/ | |
fun onConfirmation(allowed: Boolean, resources: Array<String?>?) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.example.myapplication"> | |
<uses-permission android:name="android.permission.CAMERA" /> | |
<uses-feature android:name="android.hardware.camera" /> | |
<uses-feature android:name="android.hardware.camera.autofocus" /> | |
<uses-permission android:name="android.permission.INTERNET"/> | |
// Code omitted for brevity | |
</manifest> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.myapplication | |
import android.Manifest | |
import android.annotation.SuppressLint | |
import android.content.pm.PackageManager | |
import android.os.Build | |
import android.os.Bundle | |
import android.webkit.* | |
import android.widget.Toast | |
import androidx.activity.result.ActivityResultLauncher | |
import androidx.activity.result.contract.ActivityResultContracts | |
import androidx.appcompat.app.AppCompatActivity | |
import androidx.core.content.ContextCompat | |
import androidx.fragment.app.DialogFragment | |
/** | |
Created by Prokash Sarkar on Sat, February 06, 2021 | |
**/ | |
class WebViewActivity : AppCompatActivity(), ConfirmationDialogFragment.WebPermissionListener { | |
private lateinit var webView: WebView | |
private val URL = "replace_with_your_url" | |
/** | |
* This field stores the [PermissionRequest] from the web application until it is allowed | |
* or denied by user. | |
*/ | |
private var mPermissionRequest: PermissionRequest? = null | |
private val FRAGMENT_DIALOG = "dialog" | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
webView = findViewById(R.id.webview) | |
webView.webViewClient = webViewClient | |
webView.webChromeClient = webChromeClient | |
configureWebSettings() | |
checkForRequiredPermissions() | |
} | |
@SuppressLint("SetJavaScriptEnabled") | |
private fun configureWebSettings() { | |
webView.settings.apply { | |
javaScriptEnabled = true | |
domStorageEnabled = true | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { | |
mediaPlaybackRequiresUserGesture = false | |
} | |
} | |
} | |
private val webViewClient = object : WebViewClient() { | |
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { | |
view?.loadUrl(request?.url.toString()) | |
return true | |
} | |
} | |
private val webChromeClient = object : WebChromeClient() { | |
override fun onPermissionRequest(request: PermissionRequest?) { | |
println("onPermissionRequest") | |
mPermissionRequest = request | |
request?.resources?.let { | |
for (r in it) { | |
if (r == PermissionRequest.RESOURCE_VIDEO_CAPTURE) { | |
// In this sample, we only accept video capture request. | |
ConfirmationDialogFragment | |
.newInstance(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) | |
.show(supportFragmentManager, FRAGMENT_DIALOG) | |
break | |
} | |
} | |
} | |
} | |
override fun onPermissionRequestCanceled(request: PermissionRequest?) { | |
println("onPermissionRequestCanceled") | |
mPermissionRequest = null | |
val fragment: DialogFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_DIALOG) as DialogFragment | |
fragment.dismiss() | |
} | |
} | |
private fun checkForRequiredPermissions() { | |
val requestPermissionLauncher: ActivityResultLauncher<String> = | |
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean -> | |
if (isGranted) { | |
// Permission is granted. Continue the action or workflow in your app. | |
Toast.makeText(this, "Camera Permission Granted", Toast.LENGTH_SHORT).show() | |
webView.loadUrl(URL) | |
} else { | |
// Explain to the user that the feature is unavailable | |
Toast.makeText(this, "Camera Permission Denied", Toast.LENGTH_SHORT).show() | |
} | |
} | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | |
when { | |
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) | |
== PackageManager.PERMISSION_GRANTED -> { | |
// You can use the API that requires the permission. | |
Toast.makeText(this, "Camera Permission already Granted", Toast.LENGTH_SHORT) | |
.show() | |
webView.loadUrl(URL) | |
} | |
shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> { | |
// In an educational UI, explain to the user why your app requires this | |
Toast.makeText( | |
this, | |
"Camera Permission is required to use the app", | |
Toast.LENGTH_SHORT | |
).show() | |
} | |
else -> { | |
requestPermissionLauncher.launch(Manifest.permission.CAMERA) | |
} | |
} | |
} | |
} | |
override fun onConfirmation(allowed: Boolean, resources: Array<String?>?) { | |
if (allowed) { | |
mPermissionRequest!!.grant(resources) | |
println("Permission granted.") | |
} else { | |
mPermissionRequest!!.deny() | |
println("Permission denied.") | |
} | |
mPermissionRequest = null | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment