Skip to content

Commit

Permalink
Android - Fix Overlay for Marshmallow 23+
Browse files Browse the repository at this point in the history
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
jpshelley authored and Martin Konicek committed Dec 12, 2016
1 parent fd144a2 commit e335ca0
Showing 1 changed file with 22 additions and 6 deletions.
Expand Up @@ -6,6 +6,7 @@
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
Expand All @@ -29,6 +30,10 @@
* class doesn't implement {@link ReactApplication}. * class doesn't implement {@link ReactApplication}.
*/ */
public class ReactActivityDelegate { 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 = private static final String REDBOX_PERMISSION_MESSAGE =
"Overlay permissions needs to be granted in order for react native apps to run in dev mode"; "Overlay permissions needs to be granted in order for react native apps to run in dev mode";


Expand Down Expand Up @@ -79,17 +84,19 @@ public ReactInstanceManager getReactInstanceManager() {
} }


protected void onCreate(Bundle savedInstanceState) { 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. // Get permission to show redbox in dev builds.
if (!Settings.canDrawOverlays(getContext())) { if (!Settings.canDrawOverlays(getContext())) {
Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); needsOverlayPermission = true;
getContext().startActivity(serviceIntent); Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getContext().getPackageName()));
FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE); FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
Toast.makeText(getContext(), REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show(); 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); loadApp(mMainComponentName);
} }
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer(); mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
Expand Down Expand Up @@ -140,6 +147,16 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (getReactNativeHost().hasInstance()) { if (getReactNativeHost().hasInstance()) {
getReactNativeHost().getReactInstanceManager() getReactNativeHost().getReactInstanceManager()
.onActivityResult(getPlainActivity(), requestCode, resultCode, data); .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();
}
}
} }
} }


Expand Down Expand Up @@ -191,8 +208,7 @@ public void onRequestPermissionsResult(
mPermissionsCallback = new Callback() { mPermissionsCallback = new Callback() {
@Override @Override
public void invoke(Object... args) { public void invoke(Object... args) {
if (mPermissionListener != null && if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null; mPermissionListener = null;
} }
} }
Expand Down

0 comments on commit e335ca0

Please sign in to comment.