Skip to content

Instantly share code, notes, and snippets.

@prokash-sarkar
Created February 6, 2021 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prokash-sarkar/94c99f0352e9833a63dd698ff1b930d6 to your computer and use it in GitHub Desktop.
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
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
}
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?>?)
}
}
<?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>
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