Android:WebView 中的网络摄像头错误(摄像头权限无效)
Android : Webcam Error in WebView (Camera Permission not working)
我已经创建了 WebView Activity 并正在加载 https://web.doar.zone/coronavirus
这 URL 需要相机权限,我在 Android 中获得了运行时权限。
这里是MainActivity.java的完整代码:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
Context context;
ActivityMainBinding binding;
private String url = "https://web.doar.zone/coronavirus";
@Override
protected void onResume() {
super.onResume();
checkCameraPermission();
}
private void checkCameraPermission() {
int writeExternalStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (writeExternalStorage != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1001) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Do your stuff
openWebView();
} else {
checkCameraPermission();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
context = getApplicationContext();
openWebView();
}
@SuppressLint("SetJavaScriptEnabled")
void openWebView() {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo networkInfo;
if (connectivityManager != null) {
networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnectedOrConnecting()) {
binding.internetTextView.setVisibility(View.INVISIBLE);
binding.webView.setVisibility(View.VISIBLE);
//binding.webView.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.3");
binding.webView.getSettings().setJavaScriptEnabled(true);
binding.webView.getSettings().setUseWideViewPort(true);
binding.webView.getSettings().setDomStorageEnabled(true);
binding.webView.setInitialScale(1);
binding.webView.setWebChromeClient(new MyWebChromeClient());
binding.webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView webview, String url) {
Uri uri = Uri.parse(url);
if (uri.getScheme().contains("whatsapp") || uri.getScheme().contains("tel")) {
try {
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
if (intent.resolveActivity(getPackageManager()) != null)
startActivity(intent);
return true;
} catch (URISyntaxException use) {
Log.e("TAG", use.getMessage());
}
} else {
webview.loadUrl(url);
}
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
binding.webView.loadUrl(url);
} else {
binding.internetTextView.setVisibility(View.VISIBLE);
binding.buttonTryAgain.setVisibility(View.VISIBLE);
binding.webView.setVisibility(View.INVISIBLE);
Toast.makeText(context, "Connect to Internet and Refresh Again", Toast.LENGTH_LONG).show();
}
} else {
binding.internetTextView.setVisibility(View.VISIBLE);
binding.buttonTryAgain.setVisibility(View.VISIBLE);
binding.webView.setVisibility(View.INVISIBLE);
Toast.makeText(context, "Connect to Internet and Refresh Again", Toast.LENGTH_LONG).show();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (binding.webView.canGoBack()) {
binding.webView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
class MyWebChromeClient extends WebChromeClient {
MyWebChromeClient() {
// TODO Auto-generated constructor stub
binding.pb.setProgress(0);
}
@Override
public void onPermissionRequest(final PermissionRequest request) {
super.onPermissionRequest(request);
//request.grant(request.getResources());
}
public void onProgressChanged(WebView view, int progress) {
if (progress < 100 /* && pBar.getVisibility() == View.VISIBLE*/) {
binding.pb.setVisibility(View.VISIBLE);
}
binding.pb.setProgress(progress);
if (progress == 100) {
binding.pb.setVisibility(View.GONE);
}
}
}
}
现在当我评论这一行时出现如下错误:
request.grant(request.getResources());
如果我取消注释这一行,那么我会得到:
java.lang.IllegalStateException: Either grant() or deny() has been already called.
at org.chromium.android_webview.permission.AwPermissionRequest.c(PG:3)
at org.chromium.android_webview.permission.AwPermissionRequest.b(PG:1)
at Cn.grant(PG:8)
at com.example.webviewapp.MainActivity$MyWebChromeClient.onPermissionRequest(MainActivity.java:164)
at org.chromium.android_webview.AwContents.onPermissionRequest(PG:8)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:326)
at android.os.Looper.loop(Looper.java:181)
at android.app.ActivityThread.main(ActivityThread.java:7078)
2020-04-29 11:52:21.813 4943-4943/com.example.webviewapp W/System.err: at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
有帮助吗?
首先检查您的摄像头权限,然后加载您的网络视图。你怎么做到的:
1.remove openWebView()
在你的 onCreate
方法中
2.replace checkCameraPermission()
使用新方法
private void checkCameraPermissionAndStartWebView() {
int writeExternalStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (writeExternalStorage != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
} else {
openWebView();
}
}
3.in onResume
并在 onRequestPermissionsResult
中改为调用新的 checkCameraPermissionAndStartWebView
方法
您已经处理了 android os 的运行时相机权限。我们还需要在 webview 中授予相机权限 (RESOURCE_VIDEO_CAPTURE
)。
首先调用以下方法在没有用户手势的情况下打开相机:
binding.webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
像这样调用request.grant(request.getResources())
方法将授予所有请求的权限。
为避免这种情况,您应该只授予您需要的权限,即 RESOURCE_VIDEO_CAPTURE
:
@Override
public void onPermissionRequest(final PermissionRequest request) {
final String[] requestedResources = request.getResources();
for (String r : requestedResources) {
if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
break;
}
}
}
在您的代码中,这一行导致了问题:super.onPermissionRequest(request);
这个超级方法调用拒绝了权限。
我已经创建了 WebView Activity 并正在加载 https://web.doar.zone/coronavirus
这 URL 需要相机权限,我在 Android 中获得了运行时权限。
这里是MainActivity.java的完整代码:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
Context context;
ActivityMainBinding binding;
private String url = "https://web.doar.zone/coronavirus";
@Override
protected void onResume() {
super.onResume();
checkCameraPermission();
}
private void checkCameraPermission() {
int writeExternalStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (writeExternalStorage != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1001) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Do your stuff
openWebView();
} else {
checkCameraPermission();
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
context = getApplicationContext();
openWebView();
}
@SuppressLint("SetJavaScriptEnabled")
void openWebView() {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo networkInfo;
if (connectivityManager != null) {
networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnectedOrConnecting()) {
binding.internetTextView.setVisibility(View.INVISIBLE);
binding.webView.setVisibility(View.VISIBLE);
//binding.webView.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.3");
binding.webView.getSettings().setJavaScriptEnabled(true);
binding.webView.getSettings().setUseWideViewPort(true);
binding.webView.getSettings().setDomStorageEnabled(true);
binding.webView.setInitialScale(1);
binding.webView.setWebChromeClient(new MyWebChromeClient());
binding.webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView webview, String url) {
Uri uri = Uri.parse(url);
if (uri.getScheme().contains("whatsapp") || uri.getScheme().contains("tel")) {
try {
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
if (intent.resolveActivity(getPackageManager()) != null)
startActivity(intent);
return true;
} catch (URISyntaxException use) {
Log.e("TAG", use.getMessage());
}
} else {
webview.loadUrl(url);
}
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
binding.webView.loadUrl(url);
} else {
binding.internetTextView.setVisibility(View.VISIBLE);
binding.buttonTryAgain.setVisibility(View.VISIBLE);
binding.webView.setVisibility(View.INVISIBLE);
Toast.makeText(context, "Connect to Internet and Refresh Again", Toast.LENGTH_LONG).show();
}
} else {
binding.internetTextView.setVisibility(View.VISIBLE);
binding.buttonTryAgain.setVisibility(View.VISIBLE);
binding.webView.setVisibility(View.INVISIBLE);
Toast.makeText(context, "Connect to Internet and Refresh Again", Toast.LENGTH_LONG).show();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (binding.webView.canGoBack()) {
binding.webView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
class MyWebChromeClient extends WebChromeClient {
MyWebChromeClient() {
// TODO Auto-generated constructor stub
binding.pb.setProgress(0);
}
@Override
public void onPermissionRequest(final PermissionRequest request) {
super.onPermissionRequest(request);
//request.grant(request.getResources());
}
public void onProgressChanged(WebView view, int progress) {
if (progress < 100 /* && pBar.getVisibility() == View.VISIBLE*/) {
binding.pb.setVisibility(View.VISIBLE);
}
binding.pb.setProgress(progress);
if (progress == 100) {
binding.pb.setVisibility(View.GONE);
}
}
}
}
现在当我评论这一行时出现如下错误:
request.grant(request.getResources());
如果我取消注释这一行,那么我会得到:
java.lang.IllegalStateException: Either grant() or deny() has been already called.
at org.chromium.android_webview.permission.AwPermissionRequest.c(PG:3)
at org.chromium.android_webview.permission.AwPermissionRequest.b(PG:1)
at Cn.grant(PG:8)
at com.example.webviewapp.MainActivity$MyWebChromeClient.onPermissionRequest(MainActivity.java:164)
at org.chromium.android_webview.AwContents.onPermissionRequest(PG:8)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:326)
at android.os.Looper.loop(Looper.java:181)
at android.app.ActivityThread.main(ActivityThread.java:7078)
2020-04-29 11:52:21.813 4943-4943/com.example.webviewapp W/System.err: at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
有帮助吗?
首先检查您的摄像头权限,然后加载您的网络视图。你怎么做到的:
1.remove openWebView()
在你的 onCreate
方法中
2.replace checkCameraPermission()
使用新方法
private void checkCameraPermissionAndStartWebView() {
int writeExternalStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if (writeExternalStorage != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
} else {
openWebView();
}
}
3.in onResume
并在 onRequestPermissionsResult
中改为调用新的 checkCameraPermissionAndStartWebView
方法
您已经处理了 android os 的运行时相机权限。我们还需要在 webview 中授予相机权限 (RESOURCE_VIDEO_CAPTURE
)。
首先调用以下方法在没有用户手势的情况下打开相机:
binding.webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
像这样调用request.grant(request.getResources())
方法将授予所有请求的权限。
为避免这种情况,您应该只授予您需要的权限,即 RESOURCE_VIDEO_CAPTURE
:
@Override
public void onPermissionRequest(final PermissionRequest request) {
final String[] requestedResources = request.getResources();
for (String r : requestedResources) {
if (r.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
break;
}
}
}
在您的代码中,这一行导致了问题:super.onPermissionRequest(request);
这个超级方法调用拒绝了权限。