Android
This document provides instructions to create a WebView into an Android project.
Android Manifest
Add these lines to the AndroidManifest.xml file in your app module:
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Android WebView (Kotlin)
This is an example of an activity using a WebView
class WebViewActivity : AppCompatActivity() {
private var filePathCallback: ValueCallback<Array<Uri>>? = null
private var permissionRequest: PermissionRequest? = null
private lateinit var webView: WebView
private val url = "https://cadastro.io/:token"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.webView = getWebView()
setContentView(webView)
webView.loadUrl(url)
}
private fun getWebView(): WebView {
val webView = WebView(this)
val webSettings = webView.settings
webSettings.javaScriptEnabled = true
webSettings.domStorageEnabled = true
webSettings.mediaPlaybackRequiresUserGesture = false
webSettings.javaScriptCanOpenWindowsAutomatically = true
webSettings.loadWithOverviewMode = true
webSettings.useWideViewPort = true
webSettings.allowFileAccess = true
webSettings.allowContentAccess = true
webSettings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
webView.webChromeClient = MyWebChromeClient()
webView.webViewClient = WebViewClient()
return webView
}
/**
* The permission request result is handled here.
* If the permission is granted, the webView is loaded.
*/
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAMERA_REQUEST_CODE && grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
permissionRequest?.grant(permissionRequest?.resources)
} else {
permissionRequest?.deny()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == FILE_CHOOSER_REQUEST_CODE) {
if (filePathCallback == null) {
return
}
val results = WebChromeClient.FileChooserParams.parseResult(resultCode, data)
filePathCallback!!.onReceiveValue(results)
filePathCallback = null
}
}
private inner class MyWebChromeClient : WebChromeClient() {
var originalOrientation: Int = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
var originalVisibility: Int = View.INVISIBLE
private var customView: View? = null
private var customViewCallback: CustomViewCallback? = null
override fun onPermissionRequest(request: PermissionRequest) {
val requestedAndroidPermissions = ArrayList<String>()
for (requestedResource in request.resources) {
if (requestedResource == PermissionRequest.RESOURCE_VIDEO_CAPTURE &&
ContextCompat.checkSelfPermission(
this@WebViewActivity.applicationContext,
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED) {
requestedAndroidPermissions.add(Manifest.permission.CAMERA)
}
}
if (requestedAndroidPermissions.isEmpty()) {
request.grant(request.resources)
return
}
permissionRequest = request
requestPermissions(
requestedAndroidPermissions.toTypedArray<String>(),
CAMERA_REQUEST_CODE
)
}
/**
* Callback will tell the host application that the current page would
* like to show a custom View in a particular orientation
*/
override fun onShowCustomView(view: View, callback: CustomViewCallback) {
if (customView != null) {
onHideCustomView()
return
}
customView = view
originalVisibility = window.decorView.systemUiVisibility
originalOrientation = requestedOrientation
(window.decorView as FrameLayout).addView(
customView,
FrameLayout.LayoutParams(-1, -1)
)
// This will ensure the custom view is in fullscreen mode
window.decorView.systemUiVisibility = 3846 or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
/**
* Callback will tell the host application that the current page exited full screen mode,
* and the app has to hide custom view.
*/
override fun onHideCustomView() {
(window.decorView as FrameLayout).removeView(customView)
customView = null
window.decorView.systemUiVisibility = originalVisibility
requestedOrientation = originalOrientation
if (customViewCallback != null) {
customViewCallback!!.onCustomViewHidden()
}
customViewCallback = null
}
override fun onShowFileChooser(
webView: WebView,
filePathCallback: ValueCallback<Array<Uri>>,
fileChooserParams: FileChooserParams
): Boolean {
if (this@WebViewActivity.filePathCallback != null) {
this@WebViewActivity.filePathCallback?.onReceiveValue(null)
}
this@WebViewActivity.filePathCallback = filePathCallback
val intent = fileChooserParams.createIntent()
try {
startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE)
} catch (e: ActivityNotFoundException) {
this@WebViewActivity.filePathCallback = null
return false
}
return true
}
}
companion object {
private const val CAMERA_REQUEST_CODE = 1001
private const val FILE_CHOOSER_REQUEST_CODE = 1002
}
}
Android WebView (Java)
public class WebViewActivity extends AppCompatActivity {
private ValueCallback<Uri[]> filePathCallback;
private WebView webView;
private PermissionRequest permissionRequest;
private static final String url = "https://cadastro.io/:token";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.webView = getWebView();
setContentView(webView);
webView.loadUrl(url);
}
private WebView getWebView() {
WebView webView = new WebView(this);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setMediaPlaybackRequiresUserGesture(false);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setUseWideViewPort(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowContentAccess(true);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
webView.setWebChromeClient(new MyWebChromeClient());
webView.setWebViewClient(new WebViewClient());
return webView;
}
/**
* The permission request result is handled here.
* If the permission is granted, the webView is loaded.
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_REQUEST_CODE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (permissionRequest != null) {
permissionRequest.grant(permissionRequest.getResources());
}
} else {
if (permissionRequest != null) {
permissionRequest.deny();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILE_CHOOSER_REQUEST_CODE) {
if (filePathCallback == null) {
return;
}
Uri[] results = WebChromeClient.FileChooserParams.parseResult(resultCode, data);
filePathCallback.onReceiveValue(results);
filePathCallback = null;
}
}
private class MyWebChromeClient extends WebChromeClient {
private int originalOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
private int originalVisibility = View.INVISIBLE;
private View customView;
private CustomViewCallback customViewCallback;
@Override
public void onPermissionRequest(PermissionRequest request) {
ArrayList<String> requestedAndroidPermissions = new ArrayList<>();
for (String requestedResource : request.getResources()) {
if (requestedResource.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE) &&
ContextCompat.checkSelfPermission(
WebViewActivity.this,
android.Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED) {
requestedAndroidPermissions.add(android.Manifest.permission.CAMERA);
}
}
permissionRequest = request;
if (requestedAndroidPermissions.isEmpty()) {
request.grant(request.getResources());
return;
}
requestPermissions(requestedAndroidPermissions.toArray(new String[0]), CAMERA_REQUEST_CODE);
}
/**
* Callback will tell the host application that the current page would
* like to show a custom View in a particular orientation
*/
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if (customView != null) {
onHideCustomView();
return;
}
customView = view;
originalVisibility = getWindow().getDecorView().getSystemUiVisibility();
originalOrientation = getRequestedOrientation();
((FrameLayout) getWindow().getDecorView()).addView(
customView,
new FrameLayout.LayoutParams(-1, -1)
);
// This will ensure the custom view is in fullscreen mode
getWindow().getDecorView().setSystemUiVisibility(3846 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
/**
* Callback will tell the host application that the current page exited full screen mode,
* and the app has to hide custom view.
*/
@Override
public void onHideCustomView() {
((FrameLayout) getWindow().getDecorView()).removeView(customView);
customView = null;
getWindow().getDecorView().setSystemUiVisibility(originalVisibility);
setRequestedOrientation(originalOrientation);
if (customViewCallback != null) {
customViewCallback.onCustomViewHidden();
}
customViewCallback = null;
}
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (WebViewActivity.this.filePathCallback != null) {
WebViewActivity.this.filePathCallback.onReceiveValue(null);
}
WebViewActivity.this.filePathCallback = filePathCallback;
Intent intent = fileChooserParams.createIntent();
try {
startActivityForResult(intent, FILE_CHOOSER_REQUEST_CODE);
} catch (ActivityNotFoundException e) {
WebViewActivity.this.filePathCallback = null;
return false;
}
return true;
}
}
private static final int CAMERA_REQUEST_CODE = 1001;
private static final int FILE_CHOOSER_REQUEST_CODE = 1002;
}
Last updated