Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android - Fix Overlay for Marshmallow 23+ #11316

Closed

Conversation

jpshelley
Copy link
Contributor

@jpshelley jpshelley commented Dec 6, 2016

Overview

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.

Addresses / Changes

  • targetSdkVersion 23 lead crash #10454 - targetSdkVersion 23 lead crash / App crash for targeting 23+
  • Add the overlay permission information #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:UIExplorer:android:app:installDebug
./packager/packager.sh
  • Notice the app doesn't crash as it use to
  • Turn on the overlay toggle for the app
  • Push the back button (this navigates back to UIExplorerApp)
  • Watch the UIExplorerApp fetch the JS Bundle!

Make sure tests pass on both Travis and Circle CI.

@facebook-github-bot
Copy link
Contributor

By analyzing the blame information on this pull request, we identified @foghina and @cmcewen to be potential reviewers.

@facebook-github-bot facebook-github-bot added GH Review: review-needed CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. labels Dec 6, 2016
@@ -29,6 +30,10 @@
* class doesn't implement {@link ReactApplication}.
*/
public class ReactActivityDelegate {

private final int REQUEST_OVERLAY_CODE = 1111;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe a more random number like 3798264?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And probably change the name to REQUEST_OVERLAY_PERMISSION_CODE?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can surely change the value, but I don't think there is any benefit of it being random. It doesn't need to be unique to other application just your own. So if your actvitiy ends up having multiple request codes its best to have them well defined, in order, and organized.
ie:

private final int MY_FIRST_CODE = 1111;
private final int MY_SECOND_CODE = 2222;
  • Also it doesn't need to be 4 digits in length, just a common pattern I've noticed in the community.
  • I'll update the name though, seems reasonable.

Copy link
Contributor

@satya164 satya164 Dec 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't need to be unique to other application just your own

It can conflict with third party modules / and even own code. Since this code is part of the RN library, not my application.

We don't follow this pattern anywhere else inside RN either. So I'd prefer a more random number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@satya164 The number must be between 0 and 65535 I believe
http://stackoverflow.com/a/37812367/1784299

I don't think Random is the correct approach because then it is "random" for a developer when that clashes. It should be predefined so a developer knows early on why they can't use 1 for example as their request code.

I don't think its that big of a deal to be honest but want to get it "right" the first time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@satya164 satya164 Dec 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because then it is "random" for a developer when that clashes

The developer is not going look into the library to see what code is used. This code is not part of the app. We can never prevent clash, but this number is too easy to clash with third party lib/user's code.

@SandroMachado that example is a sample app, I don't think libraries can follow the same convention as an app anyways.

RN code in general doesn't follow this convention. So I don't see what advantage it gives by following at a single place, unless all other code is changed to follow the convention.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, I don't think this is important enough to bikeshed on. Please do the changes @SandroMachado mentioned and I'll merge this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@satya164 Okay two thoughts:

  • We can use a random number as you suggest.
    • I'm okay with this, but we always have the potential of clashes then.
    • A can change the clash in their own app if they caused the clash
    • However if the clash came from another library/dependency then they would have to change or this project would have to change.
  • Or we can not hardcode it and allow the user to pass in whatever RequestCodethey want.
    • This could be through the Delegate constructor.
    • That way they always have control over it and can change it if needed so as not to clash.
    • We would just add an assertion after the number is passed in to make sure its a valid number
    • This isn't very common in the Android Community but from a Developer perspective I don't see why it wouldn't work.

@satya164
Copy link
Contributor

satya164 commented Dec 6, 2016

LGTM. Just one nit and I'll merge

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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably we can remove this now, WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its still worth showing to the developer though so they understand what they need to do. Especially since we distribute to quality assurance it would help them understand the situation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, makes sense! 👍 Please ignore.

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

protected void onCreate(Bundle savedInstanceState) {
boolean needsOverlayPermission = false;
if (getReactNativeHost().getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... >= Build.VERSION_CODES.M?

@SandroMachado
Copy link
Contributor

SandroMachado commented Dec 6, 2016

Also don't forget to update the disclaimer from here: https://github.com/facebook/react-native/blob/v0.39.0/docs/IntegrationWithExistingApps.md

If your app is targeting the Android api level 23 or greater, make sure you have, for the development build, the overlay permission enabled. You can check it with Settings.canDrawOverlays(this);. This is required because, if your app produces an error in the react native component, the error view is displayed above all the other windows. Due to the new permissions system, introduced in the api level 23, the user needs to approve it.

And probably you can squash the two commits. WDYT?

Great work! 👍

@jpshelley
Copy link
Contributor Author

How should we update the disclaimer @SandroMachado? I think its wise to keep "a disclaimer" but maybe change the words? Any thoughts on what would be best to say?

@satya164
Copy link
Contributor

satya164 commented Dec 6, 2016

I believe this doesn't affect "integrate with existing apps", and only affects apps using ReactActivity. In that case we shouldn't change the documentation.

@SandroMachado
Copy link
Contributor

@satya164 You are right, for integrating is not need to change because probably they will not create a ReactActivity. My bad.

@satya164
Copy link
Contributor

satya164 commented Dec 6, 2016

@facebook-github-bot shipit

@jpshelley
Copy link
Contributor Author

@satya164 not sure if the bot is supposed to take a long time, but Github did have a service degradation earlier that may have caused a hiccup in the command.

@satya164
Copy link
Contributor

satya164 commented Dec 6, 2016

@facebook-github-bot shipit

@mkonicek
Copy link
Contributor

mkonicek commented Dec 7, 2016

@jpshelley
Copy link
Contributor Author

@mkonicek As mentioned in the PR description and linked issues, that permission died in API 23 with the Marshmallow permission update. This is to benefit those that target API 23+

@satya164
Copy link
Contributor

satya164 commented Dec 7, 2016

@facebook-github-bot shipit

robclouth pushed a commit to robclouth/react-native that referenced this pull request Dec 7, 2016
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.

 - facebook#10454 - targetSdkVersion 23 lead crash / App crash for targeting 23+
 - facebook#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 facebook#11316

Differential Revision: D4286351

fbshipit-source-id: 024e97c08c40ee23646dd153794fcde7127b2308
@jpshelley
Copy link
Contributor Author

@satya164 Not sure if the PR is supposed to be closed but I think the commit made it to master if anything needs to happen on this PR d21aa92

@satya164 satya164 closed this Dec 8, 2016
mkonicek pushed a commit that referenced this pull request Dec 12, 2016
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
@jpshelley jpshelley deleted the android-FixOverlayForMarshmallow branch December 16, 2016 17:22
DanielMSchmidt pushed a commit to DanielMSchmidt/react-native that referenced this pull request Jan 4, 2017
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.

 - facebook#10454 - targetSdkVersion 23 lead crash / App crash for targeting 23+
 - facebook#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 facebook#11316

Differential Revision: D4286351

fbshipit-source-id: 024e97c08c40ee23646dd153794fcde7127b2308
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants