/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.permissionrequest; import android.Manifest; import android.annotation.SuppressLint; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.ConsoleMessage; import android.webkit.PermissionRequest; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import com.example.android.common.logger.Log; /** * This fragment shows a {@link WebView} and loads a web app from the {@link SimpleWebServer}. */ public class PermissionRequestFragment extends Fragment implements ConfirmationDialogFragment.Listener, MessageDialogFragment.Listener { private static final String TAG = PermissionRequestFragment.class.getSimpleName(); private static final String FRAGMENT_DIALOG = "dialog"; private static final int REQUEST_CAMERA_PERMISSION = 1; /** * We use this web server to serve HTML files in the assets folder. This is because we cannot * use the JavaScript method "getUserMedia" from "file:///android_assets/..." URLs. */ private SimpleWebServer mWebServer; /** * A reference to the {@link WebView}. */ private WebView mWebView; /** * This field stores the {@link PermissionRequest} from the web application until it is allowed * or denied by user. */ private PermissionRequest mPermissionRequest; /** * For testing. */ private ConsoleMonitor mConsoleMonitor; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_permission_request, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { mWebView = (WebView) view.findViewById(R.id.web_view); // Here, we use #mWebChromeClient with implementation for handling PermissionRequests. mWebView.setWebChromeClient(mWebChromeClient); configureWebSettings(mWebView.getSettings()); } @Override public void onResume() { super.onResume(); final int port = 8080; mWebServer = new SimpleWebServer(port, getResources().getAssets()); mWebServer.start(); // This is for runtime permission on Marshmallow and above; It is not directly related to // PermissionRequest API. if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestCameraPermission(); } else { mWebView.loadUrl("http://localhost:" + port + "/sample.html"); } } @Override public void onPause() { mWebServer.stop(); super.onPause(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { // This is for runtime permission on Marshmallow and above; It is not directly related to // PermissionRequest API. if (requestCode == REQUEST_CAMERA_PERMISSION) { if (permissions.length != 1 || grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { Log.e(TAG, "Camera permission not granted."); } else if (mWebView != null && mWebServer != null) { mWebView.loadUrl("http://localhost:" + mWebServer.getPort() + "/sample.html"); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void requestCameraPermission() { if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { MessageDialogFragment.newInstance(R.string.permission_message) .show(getChildFragmentManager(), FRAGMENT_DIALOG); } else { requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } } @SuppressLint("SetJavaScriptEnabled") private static void configureWebSettings(WebSettings settings) { settings.setJavaScriptEnabled(true); } /** * This {@link WebChromeClient} has implementation for handling {@link PermissionRequest}. */ private WebChromeClient mWebChromeClient = new WebChromeClient() { // This method is called when the web content is requesting permission to access some // resources. @Override public void onPermissionRequest(PermissionRequest request) { Log.i(TAG, "onPermissionRequest"); mPermissionRequest = request; final String[] requestedResources = request.getResources(); for (String r : requestedResources) { if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) { // In this sample, we only accept video capture request. ConfirmationDialogFragment .newInstance(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE}) .show(getChildFragmentManager(), FRAGMENT_DIALOG); break; } } } // This method is called when the permission request is canceled by the web content. @Override public void onPermissionRequestCanceled(PermissionRequest request) { Log.i(TAG, "onPermissionRequestCanceled"); // We dismiss the prompt UI here as the request is no longer valid. mPermissionRequest = null; DialogFragment fragment = (DialogFragment) getChildFragmentManager() .findFragmentByTag(FRAGMENT_DIALOG); if (null != fragment) { fragment.dismiss(); } } @Override public boolean onConsoleMessage(@NonNull ConsoleMessage message) { switch (message.messageLevel()) { case TIP: Log.v(TAG, message.message()); break; case LOG: Log.i(TAG, message.message()); break; case WARNING: Log.w(TAG, message.message()); break; case ERROR: Log.e(TAG, message.message()); break; case DEBUG: Log.d(TAG, message.message()); break; } if (null != mConsoleMonitor) { mConsoleMonitor.onConsoleMessage(message); } return true; } }; @Override public void onOkClicked() { requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } @Override public void onConfirmation(boolean allowed, String[] resources) { if (allowed) { mPermissionRequest.grant(resources); Log.d(TAG, "Permission granted."); } else { mPermissionRequest.deny(); Log.d(TAG, "Permission request denied."); } mPermissionRequest = null; } public void setConsoleMonitor(ConsoleMonitor monitor) { mConsoleMonitor = monitor; } /** * For testing. */ public interface ConsoleMonitor { void onConsoleMessage(ConsoleMessage message); } }