Expensify / react-native-share-menu

A module for React Native that adds your app to the share menu of the device
MIT License
652 stars 237 forks source link

The Google Files app causes my app to hang on launch from share Intent, or 'reset' the app state when coming to foreground from share Intent #312

Open stefoid opened 6 months ago

stefoid commented 6 months ago

My RN app uses react-native-share-menu to accept files shared from other android apps. this works fine when sharing from the photo gallery for instance, but for the Google 'Files' app on some devices (not all devices or on emulators) this sharing does not work well. The intent is sent and my app is launched or comes to the foreground as it is supposed to, but then the app state seems to be 'reset' somehow - resulting in my app performing strangely - launching then hangs/crashes or if it was already running, it looses its current state and behaves poorly.

I have tested commenting out the code below from the library getSharedText() function, and that 'fixes' the launch issue, but of course that code is there for a reason, and the behaviour is broken in a different way if it is just removed.

What happens instead is when launched app becomes associated with the Files app, such that if you click on the files app from the home screen, it resumes my RN app, not the Files app!

Also, with this code removed, if I run my app, THEN share via the Files app, it launches a new instance of my app (now I have two) and the 2nd instance is also associated with the File app.

Once again, without this code, if I share from an image browser rather than the Files app, then sharing works as I expect - the app is launched without being associated with the files app, and if it was already running, it is simply brought the foreground in its proper state - indicating (I guess) that the commented out code is meant to deal with whatever the Files app is doing specifically.

So the author of the library has made a solution with this code to the 'Google Files problem', but it is not a good solution for all RN apps which are not expecting to have startActivity with FLAG_ACTIVITY_NEW_TASK set????

How can this code be modified????

  <activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
    android:launchMode="singleTask"
    android:windowSoftInputMode="adjustResize"
    android:exported="true"
    android:alwaysRetainTaskState="true"
    android:documentLaunchMode="never">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
    </intent-filter>

    <!-- react-native-share-menu -->
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="*/*"/>
    </intent-filter>

here are the logs: Working (shared from image browser) 03-25 11:16:39.502 672 4613 I ActivityManager: START u0 {act=android.intent.action.SEND typ=application/pdf flg=0xb080001 cmp=com.geo.geoop.dev/com.geo.MainActivity clip={application/pdf U:content://com.google.android.apps.nbu.files.provider/2/3875} (has extras)} from uid 10117, pid -1 03-25 11:16:39.520 672 4613 I ActivityManager: Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is "singleInstance" or "singleTask" 03-25 11:16:39.547 672 4613 I ActivityManager: ->startActivity for ActivityRecord{60fe743 u0 com.geo.geoop.dev/com.geo.MainActivity t44} result:START_TASK_TO_FRONT

Not Working (shared from 'files' app 03-25 11:24:49.029 672 1654 I ActivityManager: START u0 {act=android.intent.action.SEND typ=application/pdf flg=0x13000001 pkg=com.geo.geoop.dev cmp=com.geo.geoop.dev/com.geo.MainActivity clip={application/pdf U:content://com.google.android.apps.nbu.files.provider/2/3876} (has extras)} from uid 10309, pid 11323 03-25 11:24:49.057 672 1654 I ActivityManager: ->startActivity for ActivityRecord{88d66b2 u0 com.geo.geoop.dev/com.geo.MainActivity t47} result:START_TASK_TO_FRONT

The only difference I can see is the flags. There are a few different ones between the two:

the working version has these

0x00080000 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 0x08000000 FLAG_RECEIVER_NO_ABORT 0x04000000 FLAG_ACTIVITY_CLEAR_TOP

the not working version has these flags

0x10000000 FLAG_ACTIVITY_NEW_TASK 0x02000000 FLAG_ACTIVITY_FORWARD_RESULT

thanks for any help with this, Im not an android expert by any means, and this has me scratching my head

stefoid commented 6 months ago

Please see this stack overflow post where I am also pursuing this issue:

https://stackoverflow.com/questions/78209973/android-sharing-files-from-other-apps-to-my-app-react-native-but-is-probably

The library code which I believe needs to be modified somehow to resolve it is here:

public void getSharedText(Callback successCallback) {
Activity currentActivity = getCurrentActivity();

if (currentActivity == null) {
  return;
}

// If this isn't the root activity then make sure it is
if (!currentActivity.isTaskRoot()) {
  Intent newIntent = new Intent(currentActivity.getIntent());
  newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  currentActivity.startActivity(newIntent);

  ReadableMap shared = extractShared(newIntent);
  successCallback.invoke(shared);
  clearSharedText();
  currentActivity.finish();
  return;
}

Intent intent = currentActivity.getIntent();

ReadableMap shared = extractShared(intent);
successCallback.invoke(shared);
clearSharedText();
}
stefoid commented 6 months ago

Hi @lindboe to duplicate this problem, run a react native app on a google pixel type of device or a device that uses the 'standard' Files explorer app. Share any file to your RN app and it will probably misbehave due to the code above which restarts the current Activity with Intent.FLAG_ACTIVITY_NEW_TASK

This makes sharing on this subset of android devices very problematic. Ill keep looking into it, but any help appreciated.

b901 commented 5 days ago

@stefoid Ran into the same issue today on Google Pixel and sharing from Files app. Did you make any progress resolving this?

stefoid commented 4 days ago

@stefoid Ran into the same issue today on Google Pixel and sharing from Files app. Did you make any progress resolving this?

I made a patch to remove the new task restart. Its still not ideal but its better than it was.

@@ -93,17 +93,19 @@ public class ShareMenuModule extends ReactContextBaseJavaModule implements Activ
     }

     // If this isn't the root activity then make sure it is
-    if (!currentActivity.isTaskRoot()) {
-      Intent newIntent = new Intent(currentActivity.getIntent());
-      newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-      currentActivity.startActivity(newIntent);
-
-      ReadableMap shared = `extractShared(newIntent);`
-      successCallback.invoke(shared);
-      clearSharedText();
-      currentActivity.finish();
-      return;
-    }