Permalink
Browse files

Android - Fix Overlay for Marshmallow 23+

Summary:
Currently any React Native apps that target API 23 or greater will crash on the first initial debug/dev build due to the overlay permission.

Sadly there isn't a concrete "request permission" baked into the Marshmallow permission system.
However, we can launch the overlay screen without starting the react app and once its turned on start the app.

 - #10454 - targetSdkVersion 23 lead crash / App crash for targeting 23+
 - #10479 - Add the overlay permission information / Larger discussion around targeting API 23+
- Intent to Overlay permission goes directly to the app in question, rather then the general full listing of applications. This allows a developer who is not familiar with the system to easily toggle the overlay without getting confused.

**Test plan (required)**
* Ran UIExplorer App on fresh install with Target 23
```
cd react-native
./gradlew :Examples:UI
Closes #11316

Differential Revision: D4286351

fbshipit-source-id: 024e97c08c40ee23646dd153794fcde7127b2308
  • Loading branch information...
1 parent fd144a2 commit e335ca0c144bdfcd14a44b5acd0968ae2e51046b @jpshelley jpshelley committed with mkonicek Dec 6, 2016
Showing with 22 additions and 6 deletions.
  1. +22 −6 ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java
@@ -6,6 +6,7 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
@@ -29,6 +30,10 @@
* class doesn't implement {@link ReactApplication}.
*/
public class ReactActivityDelegate {
+
+ private final int REQUEST_OVERLAY_PERMISSION_CODE = 1111;
+ private static final String REDBOX_PERMISSION_GRANTED_MESSAGE =
+ "Overlay permissions have been granted.";
private static final String REDBOX_PERMISSION_MESSAGE =
"Overlay permissions needs to be granted in order for react native apps to run in dev mode";
@@ -79,17 +84,19 @@ public ReactInstanceManager getReactInstanceManager() {
}
protected void onCreate(Bundle savedInstanceState) {
- if (getReactNativeHost().getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) {
+ boolean needsOverlayPermission = false;
+ if (getReactNativeHost().getUseDeveloperSupport() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Get permission to show redbox in dev builds.
if (!Settings.canDrawOverlays(getContext())) {
- Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
- getContext().startActivity(serviceIntent);
+ needsOverlayPermission = true;
+ Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));
FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
Toast.makeText(getContext(), REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();
+ ((Activity) getContext()).startActivityForResult(serviceIntent, REQUEST_OVERLAY_PERMISSION_CODE);
}
}
- if (mMainComponentName != null) {
+ if (mMainComponentName != null && !needsOverlayPermission) {
loadApp(mMainComponentName);
}
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
@@ -140,6 +147,16 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager()
.onActivityResult(getPlainActivity(), requestCode, resultCode, data);
+ } else {
+ // Did we request overlay permissions?
+ if (requestCode == REQUEST_OVERLAY_PERMISSION_CODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (Settings.canDrawOverlays(getContext())) {
+ if (mMainComponentName != null) {
+ loadApp(mMainComponentName);
+ }
+ Toast.makeText(getContext(), REDBOX_PERMISSION_GRANTED_MESSAGE, Toast.LENGTH_LONG).show();
+ }
+ }
}
}
@@ -191,8 +208,7 @@ public void onRequestPermissionsResult(
mPermissionsCallback = new Callback() {
@Override
public void invoke(Object... args) {
- if (mPermissionListener != null &&
- mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
+ if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}

0 comments on commit e335ca0

Please sign in to comment.