android - 无法添加窗口 android.view.ViewRootImpl——窗口类型 2006 的权限被拒绝。RN v.0.44

标签 android react-native

API 26+ 上使用 RN Debug 时遇到问题,项目中的 React Native v. 0.44.0。当仅在模拟器上制作 CRTL+M 时,应用程序崩溃并且 logcat 告诉我这个 fatal error :

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 有一个权限检查方法,可以正常工作以获取我需要的所有权限(覆盖图除外)。

最佳答案

我通过此更改使其对我有利 enter image description here

现在可以正常工作了

private fun initOverlay() {
    ...
    getWindowManager()
        .addView(getRootView(), WINDOW_PARAMETERS)
}

关于android - 无法添加窗口 android.view.ViewRootImpl——窗口类型 2006 的权限被拒绝。RN v.0.44,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51657569/

相关文章:

android - `packageManager.getInstalledPackages(0)` 没有返回所有应用

java - 从 Android/Java 向 Matlab 发送数据

android - 如何在 ListView 的按下状态下使用带有渐变的可绘制对象?

javascript - 事件指示器加载

reactjs - react native SectionList 与列

android - 使用 TabHost 时出现错误

android - sleep 功能不起作用

javascript - 如何在渲染 react native 中设置状态

javascript - react native : How to remove token with AsyncStorage with JWT ?

javascript - 有没有办法通过 React-Native (JS) 预打包 Realm 数据库 (default.Realm)