Reputation: 11
I need help or guidance in resolving the issue that I have regarding React Native interacting with other native applications via intents. I know that React Native supports deeplinking out of the box but does not cater for intents, which means that one needs to create an android native module (https://reactnative.dev/docs/native-modules-android). I created a native module that calls 3rd party applications via intents and passing data using startActivityForResults and created onActivityResult that is supposed to handle data returned from 3rd party applications after closing. However, the onActivityResult executes prematurely before external applications open.
Starting the activity using startActivityForResults:
@ReactMethod
public void launchApp(String stringArgument, ReadableMap args, Promise promise) throws JSONException{
try {
final JSONObject options = convertMapToJson(args);
Bundle extras = new Bundle();;
int LAUNCH_REQUEST = 0;
if (options.has("extras")) {
extras = createExtras(options.getJSONArray("extras"));
Log.d(TAG,"Extras found");
Log.d(TAG, options.getString("extras"));
} else {
extras = new Bundle();
Log.d(TAG,"No extras");
}
if (options.has("launchRequestCode")) {
LAUNCH_REQUEST = options.getInt("launchRequestCode");
}
Intent packageIntent = this.reactContext.getPackageManager().getLaunchIntentForPackage(stringArgument);
if(packageIntent != null){
packageIntent.putExtras(extras);
//callback.invoke("Starting activity for: "+stringArgument);
Activity activity = getReactApplicationContext().getCurrentActivity();
//this.reactContext.startActivityForResult(packageIntent, LAUNCH_REQUEST, extras);
activity.startActivityForResult(packageIntent, LAUNCH_REQUEST);
return;
//mPromise.put(LAUNCH_REQUEST, promise);
}
else{
Log.d(TAG, stringArgument+" package not found");
//callback.invoke("Package not found: "+stringArgument);
}
} catch (JSONException e) {
//TODO: handle exception
Log.d(TAG, e.toString());
}
// TODO: Implement some actually useful functionality
}
Expecting the data back using onActivityResults
ActivityEventListener mActivityEventListener = new ActivityEventListener(){
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
//super.onActivityResult(requestCode, resCode, data);
Log.d(TAG,"On activity result");
if (mPromise != null && resultCode == activity.RESULT_OK) {
WritableMap result = new WritableNativeMap();
result.putInt("resultCode", resultCode);
result.putMap("data", Arguments.makeNativeMap(data.getExtras()));
mPromise.resolve(result);
}
else{
Log.d(TAG,"Promise and intent data are empty");
//mPromise.reject("Unable to get promise or intent data is empty");
}
if(resultCode == activity.RESULT_CANCELED ){
Log.d(TAG,"Result cancelled or no result or crashed with code");
}
}
@Override
public void onNewIntent(Intent intent){
Log.d(TAG,"New Intent");
}
};
Android Manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.navapp">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
By using Android Studio Logcat to debug, I found out that the onActivityResults executes immediately before the external app opens up. Logcat screenshot
Upvotes: 0
Views: 1021
Reputation: 11
Thanks to this explanation here, I was able to drill down to what was causing the issue. In my React Native application, I used the package name of the external application instead of the action name to open it.
Manifest File of the external app:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.bld.pushnotification.Main"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
I also modified the my code for launching the app:
@ReactMethod
public void launchApp(String stringArgument, ReadableMap args, Promise promise) throws JSONException{
try {
final JSONObject options = convertMapToJson(args);
Bundle extras = new Bundle();;
int LAUNCH_REQUEST = 0;
if (options.has("extras")) {
extras = createExtras(options.getJSONArray("extras"));
Log.d(TAG,"Extras found");
Log.d(TAG, options.getString("extras"));
} else {
extras = new Bundle();
Log.d(TAG,"No extras");
}
if (options.has("launchRequestCode")) {
LAUNCH_REQUEST = options.getInt("launchRequestCode");
}
Intent packageIntent = new Intent(stringArgument);
Activity activity = getReactApplicationContext().getCurrentActivity();
activity.startActivityForResult(packageIntent, LAUNCH_REQUEST);
} catch (JSONException e) {
//TODO: handle exception
Log.d(TAG, e.toString());
}
}
Upvotes: 1