在项目中的API 26+
,React Native v。0.44.0上进行RN调试时遇到问题。当仅在模拟器上制作CRTL+M
时,应用程序崩溃并且logcat告诉我这个 致命错误:
FATAL EXCEPTION: main
Process: com.foodilog, PID: 27284
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@ea9429e -- permission denied for window type 2006
at android.view.ViewRootImpl.setView(ViewRootImpl.java:789)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at com.facebook.react.devsupport.DevLoadingViewController.setVisible(DevLoadingViewController.java:145)
at com.facebook.react.devsupport.DevLoadingViewController.access$100(DevLoadingViewController.java:34)
at com.facebook.react.devsupport.DevLoadingViewController$1.run(DevLoadingViewController.java:66)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
08-02 12:43:48.076 1582-1617/? W/ActivityManager: Force finishing activity com.foodilog/.MainActivity
我该怎么办?如何让应用程序请求覆盖窗口的权限? 我尝试了很多通过互联网描述的方式,但有人帮助了我( 还提供我的根目录:
MainApplication.java
package com.foodilog;
import android.annotation.TargetApi;
import android.content.Intent;
import android.app.Activity;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.provider.Settings;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import com.cboy.rn.splashscreen.SplashScreen;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
//Checking permissions for app before app finishes to load
public static final int PERMISSION_REQ_CODE = 1234;
public static final int OVERLAY_PERMISSION_REQ_CODE = -1010101;
private static final int OVERLAY_PERMISSION_REQUEST_CODE = 2;
@TargetApi(Build.VERSION_CODES.M)
private void _askForOverlayPermission() {
if (!BuildConfig.DEBUG || android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
if (!Settings.canDrawOverlays(this) && BuildConfig.DEBUG) {
Intent settingsIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(settingsIntent, OVERLAY_PERMISSION_REQUEST_CODE);
}
}
String[] perms = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.ACCESS_FINE_LOCATION"
};
public static Activity activity;
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
activity = this;
return "Foodilog";
}
@Override
public void onCreate (Bundle savedInstanceState) {
//Splash Screen implementation
//Hardcoded delay to keep Splash screen appear specified time it
needed to
// final Activity activity = this;
// final Handler handler = new Handler();
// handler.postDelayed(new Runnable() {
// @Override
// public void run() {
// SplashScreen.hide(activity);
// }
// }, 2000);
super.onCreate(savedInstanceState);
_askForOverlayPermission();
// Checking permissions on init
fixAndroid();
// Ckecking perms for debug tools
SplashScreen.show(this);
}
// method to check permission needed to let app to work properly
public void checkPerms() {
// Checking if device version > 22 and we need to use new permission model
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1) {
// Checking if we can draw window overlay
if (!Settings.canDrawOverlays(this) && BuildConfig.DEBUG) {
Log.v("App", "Requesting Permission" + Settings.canDrawOverlays(this));
// Requesting permission for window overlay(needed for all react-native apps)
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getApplicationContext().getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
}
for(String perm : perms){
// Checking each persmission and if denied then requesting permissions
if(checkSelfPermission(perm) == PackageManager.PERMISSION_DENIED){
requestPermissions(perms, PERMISSION_REQ_CODE);
break;
}
}
}
}
public void fixAndroid() {
Window window = getWindow();
WindowManager.LayoutParams params;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT);
} else {
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
PixelFormat.TRANSLUCENT);
}
window.setAttributes(params);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//Checking overlay permission before callback init to ensure
if (requestCode == OVERLAY_PERMISSION_REQ_CODE && BuildConfig.DEBUG) {
checkPerms();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
// Permission Granted by Overlay. Do stuff
MainApplication.getCallbackManager().onActivityResult(requestCode, resultCode, data);
}
}
} else {
checkPerms();
MainApplication.getCallbackManager().onActivityResult(requestCode, resultCode, data);
}
}
// Permission results
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
case PERMISSION_REQ_CODE:
// example how to get result of permissions requests (there can be more then one permission dialog)
// boolean readAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
// boolean writeAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;
// checking permissions to prevent situation when user denied some permission
boolean readAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
boolean writeAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;
boolean locationAccepted = grantResults[2]==PackageManager.PERMISSION_GRANTED;
checkPerms();
break;
}
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.foodilog"
android:versionCode="1"
android:versionName="1.0"
xmlns:tools="http://schemas.android.com/tools"
tools:node="replace"
>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission-sdk-23 android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="26" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:largeHeap="true"
android:theme="@style/AppTheme">
<activity
android:name=".SplashActivity"
android:theme="@style/SplashTheme"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:theme="@style/AppTheme"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:exported="true">
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id"/>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyBREpkpz6z5St_uJo1bWY36TyFClBxjSSg"/>
<meta-data
tools:node="replace"
android:name="android.support.VERSION"
android:value="26.1.0" />
</application>
MainApplication.java
package com.foodilog;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.reactlibrary.RNReactNativeSharingWinstagramPackage;
import io.fullstack.oauth.OAuthManagerPackage;
import com.horcrux.svg.SvgPackage;
import com.facebook.reactnative.androidsdk.FBSDKPackage;
//import com.facebook.reactnative.androidsdk.FBSDKPackage;
//import com.facebook.reactnative.androidsdk.FBSDKPackage;
//import com.facebook.reactnative.androidsdk.FBSDKPackage;
import com.airbnb.android.react.maps.MapsPackage;
import bhumi.customInstagramShare.CustomInstagramSharePackage;
//import com.facebook.reactnative.androidsdk.FBSDKPackage;
import com.barefootcoders.android.react.KDSocialShare.KDSocialShare;
import com.rngrp.RNGRPPackage;
import com.reactnative.ivpusic.imagepicker.PickerPackage;
import com.imagepicker.ImagePickerPackage;
import com.RNFetchBlob.RNFetchBlobPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import co.apptailor.googlesignin.RNGoogleSigninPackage;
import com.goldenowl.twittersignin.TwitterSigninPackage;
import com.cboy.rn.splashscreen.SplashScreenReactPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import com.facebook.CallbackManager;
import com.facebook.FacebookSdk;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private static CallbackManager mCallbackManager = CallbackManager.Factory.create();
protected static CallbackManager getCallbackManager() {
return mCallbackManager;
}
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return true;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNReactNativeSharingWinstagramPackage(),
new OAuthManagerPackage(),
new SvgPackage(),
new MapsPackage(),
new CustomInstagramSharePackage(MainActivity.activity),
new FBSDKPackage(mCallbackManager),
new KDSocialShare(),
new RNGRPPackage(),
new PickerPackage(),
new ImagePickerPackage(),
new RNFetchBlobPackage(),
new VectorIconsPackage(),
new RNGoogleSigninPackage(),
new TwitterSigninPackage(),
new SplashScreenReactPackage()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
FacebookSdk.sdkInitialize(getApplicationContext());
SoLoader.init(this, /* native exopackage */ false);
}
}
如您所见, MainActivity.java 具有一种权限检查方法,该方法对于除覆盖图之外的所有我需要的权限均适用。