【问题标题】:How to dispatch intent to MainActivity from another activity? (react native)如何将意图从另一个活动发送到 MainActivity? (反应原生)
【发布时间】:2021-07-30 12:01:35
【问题描述】:

我在一个 React Native 项目中用 Java 创建了一个自定义深度链接调度程序。

我遇到的问题是我无法让MainActivity 从我的调度程序开始,我也无法弄清楚为什么。

我设置了 AndroidManifest,以便有效地在 LinkDispatcherActivity 中捕获深层链接,但 startActivity(dispatchedIntent) 永远不会到达 MainActivity,这是我认为它需要去的地方。通常在 AndroidManifest.xml 中,深层链接会发送到MainActivity)。

它确实打开了应用程序,但我认为这是因为 LinkDispatcherActivity 是应用程序的一部分?不确定,如果我说一些愚蠢的话,那是因为这只是我连续第三天写 Java ????

下面是我的代码。

package com.example.app;

//Inspired by https://github.com/justeat/Android.Samples.Deeplinks, Licensed under Apache 2.0

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

import net.openid.appauth.RedirectUriReceiverActivity;

public class LinkDispatcherActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            dispatchIntent(getIntent());
        } catch (IllegalArgumentException iae) {
            // Malformed URL
            if (BuildConfig.DEBUG) {
                Log.e("Deep links", "Invalid URI", iae);
            }
        } finally {
            // Always finish the activity so that it doesn't stay in our history
            finish();
        }
    }
    public void dispatchIntent(Intent intent) {
        final Uri uri = intent.getData();
        final String host = uri.getHost().toLowerCase();
        if (uri == null) throw new IllegalArgumentException("Uri cannot be null");
        // Default intent
        Intent dispatchedIntent = new Intent(LinkDispatcherActivity.this, MainActivity.class);
        dispatchedIntent.setData(uri);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        Log.d(dispatchedIntent.getDataString(), "dispatchIntent: intent string");
        // Auth intent only, this is why I need the dispatcher
        if ("login".equals(host)) {
            dispatchedIntent = new Intent(this, RedirectUriReceiverActivity.class);
            dispatchedIntent.putExtra("requestCode", 0);
            Log.d("Login", "mapAppLink: ");
            startActivityForResult(dispatchedIntent, 0);
            return;
        }
        Log.d("Default", "mapAppLink: ");
        startActivity(dispatchedIntent);
    }
}

这就是我的 AndroidManifest.xml 的样子:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
  package="com.example.app">

  <!-- < Only if you're using GCM or localNotificationSchedule() > -->
  <uses-permission android:name="android.permission.WAKE_LOCK" />
  <permission
    android:name="${applicationId}.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
  <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
  <!-- < Only if you're using GCM or localNotificationSchedule() > -->
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.VIBRATE" />
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

  <application
    android:name=".MainApplication"
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:theme="@style/AppTheme"
    android:requestLegacyExternalStorage="true">
    <meta-data
      android:name="com.google.android.geo.API_KEY"
      android:value="<redacted>" />

    <!--  < Notification Services >  -->
    <meta-data
      android:name="com.google.firebase.messaging.default_notification_icon"
      android:resource="@mipmap/ic_notification" />

    <meta-data
      android:name="com.google.firebase.messaging.default_notification_color"
      tools:replace="android:resource"
      android:resource="@color/colorAccent" />

    <!-- Change the value to true to enable pop-up for in foreground on receiving remote notifications (for prevent duplicating while showing local notifications set this to false) -->
    <meta-data  android:name="com.dieam.reactnativepushnotification.notification_foreground"
        android:value="true"/>
    <meta-data
      android:name="com.google.firebase.messaging.default_notification_channel_id"
      tools:replace="android:value"
      android:value="rn-push-notification-channel-id" />
    <meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name" android:value="Default Channel"/>
    <meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_description" android:value="Default channel for push notifications"/>
    <meta-data
      android:name="com.dieam.reactnativepushnotification.notification_color"
      android:resource="@color/colorAccent" />

    <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationActions" />
    <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
    <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
      </intent-filter>
    </receiver>

    <!-- START: Add this-->
    <service
        android:name=".MainNotificationService">
      <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
      </intent-filter>
    </service>

    <receiver
        android:name="com.intercom.reactnative.RNIntercomPushBroadcastReceiver"
        tools:replace="android:exported"
        android:exported="true"/>

    <activity
      android:name=".MainActivity"
      android:configChanges="keyboard|keyboardHidden|screenSize|uiMode"
      android:launchMode="singleTask"
      android:label="@string/app_name"
      android:screenOrientation="portrait"
      android:windowSoftInputMode="adjustResize">
      <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>
    </activity>
    <activity android:name=".LinkDispatcherActivity"
    tools:node="replace">
      <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data 
            android:scheme="example"
            android:host="login" />
      </intent-filter>
    </activity>
    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
  </application>
</manifest>

编辑:出于意图,我尝试过: new Intent(getApplicationContext(), MainActivity.class) new Intent(reactContext, MainActivity.class)(扩展 ReactActivity 而不是 Activity) new Intent(this, MainActivity.class) new Intent("MainActivity")

【问题讨论】:

  • 尝试 getApplicationContext() 而非 LinkDispatcherActivity.this
  • 谢谢 Ajay,我试过了,结果一样。
  • 你能发布你的清单文件吗?另外我认为“intent.addFlags(”行应该是“dispatchedIntent.addFlags(”
  • @N1234 发布了 android 清单。我按照您的建议更新了addFlags 命令,仍然没有运气从原始意图中获取数据,也没有传递它。我玩了很多不同的意图、不同的背景和不同的活动,我不确定什么是“正确的”……谢谢你的帮助!

标签: java android react-native


【解决方案1】:

尝试将 RedirectUriReceiverActivity 添加到清单中 - 我在其中看不到它。

<activity android:name="com.facebook.react.devsupport.RedirectUriReceiverActivity" />

【讨论】:

  • react native 就是这样,MainActivity 调用 react native 和其他所有的。不过,对于一般的 android 开发人员来说,了解一下还是不错的。
  • 我在清单中没有看到 RedirectUriReceiverActivity 可能是“dispatchedIntent = new Intent(this, RedirectUriReceiverActivity.class);”是否因为活动不在清单中而导致问题?
【解决方案2】:

这就是我对 LinkDispatcherActivity 的最终结果。总而言之,我所做的是调度深层活动最终应该直接调用的意图,而不是尝试转发意图。换句话说,如果你试图将一个意图从一个活动传递到另一个活动,也许不要考虑调度你想在之后运行的活动/功能/意图。我仍然认为转发意图应该有效,但这就是最终有效的方法。 为了完成上述工作,我:

  • 在 AppAuth 包中调用一个函数,该函数生成一个意图并分派它
  • 使用 ReactContext 发出 url 侦听器事件,React Native 使用该事件响应深层链接。

下面是代码:

//Inspired by https://github.com/justeat/Android.Samples.Deeplinks, Licensed under Apache 2.0
package com.example.app;

import android.content.Intent;
import android.net.Uri;
import android.util.Log;

import net.openid.appauth.AuthorizationManagementActivity;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;


public class LinkDispatcherActivity extends ReactActivity {
    @Override
    protected void onResume() {
        super.onResume();
        try {
            dispatchIntent(getIntent());
        } catch (IllegalArgumentException iae) {
            // Malformed URL
            if (BuildConfig.DEBUG) {
                Log.e("Deep links", "Invalid URI", iae);
            }
        } finally {
            // Always finish the activity so that it doesn't stay in our history
            finish();
        }
    }

    public void dispatchIntent(Intent intent) {
        final Uri uri = intent.getData();
        final String host = uri.getHost().toLowerCase();
        if (uri == null) throw new IllegalArgumentException("Uri cannot be null");
        // Default intent, e.g. settings, fitbit
        // wait for react context
        ReactInstanceManager reactInstanceManager = getReactInstanceManager();
        ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
        Intent dispatchedIntent = new Intent(getApplicationContext(), MainActivity.class);
        dispatchedIntent.setData(uri);
        dispatchedIntent.putExtra("url", uri.toString());
        dispatchedIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        // Auth intent only
        if ("login".equals(host)) {
            Intent authIntent = AuthorizationManagementActivity.createResponseHandlingIntent(getApplicationContext(), uri);
            startActivity(authIntent);
            return;
        }
        // Below from https://stackoverflow.com/questions/48445010/send-data-from-android-activity-to-react-native?rq=1
        WritableMap uriMap = Arguments.createMap();
        uriMap.putString("url", uri.toString());
        if(reactContext != null) {
            reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                    .emit("url", uriMap);
          // If there's no context, create a listener to wait for it
        } else {
            reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
                @Override
                public void onReactContextInitialized(ReactContext context) {
                    context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                            .emit("url", uriMap);
                    reactInstanceManager.removeReactInstanceEventListener(this);
                }
            });
        }
    }
}

【讨论】:

    猜你喜欢
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    相关资源
    最近更新 更多