深度链接启动闪屏活动而不是主活动。

12
我按照这篇指南-正确的启动画面创建了一个Android应用程序的启动画面,现在我有两个活动(MainActivity和SplashActivity)。
问题是深度链接现在无法正常工作,因为它们不会启动MainActivity,而是启动SplashActivity
我不希望SplashActivity除了应用程序启动时以外的任何时候都出现。
我该怎么办? SplashActivity:
public class SplashActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        finish();
    }
}

MainActivity:

public class MainActivity extends SplashActivity implements OnImagePickerPermissionsCallback {

    private PermissionListener listener;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void setPermissionListener(PermissionListener listener)
    {
        this.listener = listener;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
    {
        if (listener != null)
        {
            listener.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }


    @Override
    public View createSplashLayout() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(getResources().getColor(R.color.navBarColor));
        }
        LinearLayout view = new LinearLayout(this);
//        view.setBackgroundColor(getResources().getColor(R.color.catalyst_redbox_background));
        view.setBackgroundResource(R.drawable.launch_screen_radius);
        return view;
    }
}

清单文件:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

<!-- For using react-native-fcm CLOUD MESSAGING-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" />


<!-- For using react-native-image-picker -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<!-- For react-native-webview-file-upload-android -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


<!-- For using NetInfo -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<uses-sdk
    android:minSdkVersion="16"
    android:targetSdkVersion="24" />

<application
    android:name=".MainApplication"
    android:allowBackup="true"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:theme="@style/AppTheme"
    >

    <!-- The 2 services below are for react-native-fcm cloud messaging -->
    <service android:name="com.evollu.react.fcm.MessagingService" android:enabled="true" android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>
    <service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
        </intent-filter>
    </service>

    <!-- The 2 receivers below are for react-native-fcm local notifications-->
    <receiver android:name="com.evollu.react.fcm.FIRLocalMessagingPublisher"/>
    <receiver android:enabled="true" android:exported="true"  android:name="com.evollu.react.fcm.FIRSystemBootEventReceiver">
        <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"/>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

    <activity
        android:name=".SplashActivity"
        android:label="@string/app_name"
        android:theme="@style/SplashTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:windowSoftInputMode="adjustResize"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:screenOrientation="portrait"
        android:launchMode="singleTop"
        >
        <!-- launchMode="singleTop" is for fcm cloud messaging -->
        <intent-filter>
            <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
        </intent-filter>

        <!--
            The intent filter below are for react-native-fcm click_action
            https://github.com/evollu/react-native-fcm#config-for-notification-and-click_action-in-android
        -->
        <intent-filter>
            <action android:name="fcm.ACTION.HELLO" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

        <intent-filter>
            <!-- Sets the intent action to view the activity -->
            <action android:name="android.intent.action.VIEW" />

            <!-- Allows the deep link to be used without specifying the app name -->
            <category android:name="android.intent.category.DEFAULT" />

            <!-- Allows the link to be opened from a web browser -->
            <category android:name="android.intent.category.BROWSABLE" />

            <!-- Accepts URIs that begin with "https://www.myExampleDomain.com -->
            <data android:scheme="https" android:host="www.myExampleDomain.com" />

            <!-- Accepts URIs that begin with "myExampleDomain:// -->
            <data android:scheme="myExampleDomain"/>
        </intent-filter>
    </activity>
    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>

编辑:有些人指出我在使用SplashActivity。事实上,这就是以下活动的代码。 它是我用于屏幕导航的库react-native-navigation的一部分。不确定是否有帮助,但下面是代码:

SplashActivity:

public abstract class SplashActivity extends AppCompatActivity {
    public static boolean isResumed = false;

    public static void start(Activity activity) {
        Intent intent = activity.getPackageManager().getLaunchIntentForPackage(activity.getPackageName());
        if (intent == null) return;
        intent.setAction(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        activity.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setSplashLayout();
        IntentDataHandler.saveIntentData(getIntent());
    }

    @Override
    protected void onResume() {
        super.onResume();
        isResumed = true;

        if (NavigationApplication.instance.getReactGateway().hasStartedCreatingContext()) {
            if (CompatUtils.isSplashOpenedOverNavigationActivity(this, getIntent())) {
                finish();
                return;
            }
            NavigationApplication.instance.getEventEmitter().sendAppLaunchedEvent();
            if (NavigationApplication.instance.clearHostOnActivityDestroy()) {
                overridePendingTransition(0, 0);
                finish();
            }
            return;
        }

        if (ReactDevPermission.shouldAskPermission()) {
            ReactDevPermission.askPermission(this);
            return;
        }

        if (NavigationApplication.instance.isReactContextInitialized()) {
            NavigationApplication.instance.getEventEmitter().sendAppLaunchedEvent();
            return;
        }

        // TODO I'm starting to think this entire flow is incorrect and should be done in Application
        NavigationApplication.instance.startReactContextOnceInBackgroundAndExecuteJS();
    }

    @Override
    protected void onPause() {
        super.onPause();
        isResumed = false;
    }

    private void setSplashLayout() {
        final int splashLayout = getSplashLayout();
        if (splashLayout > 0) {
            setContentView(splashLayout);
        } else {
            setContentView(createSplashLayout());
        }
    }

    /**
     * @return xml layout res id
     */
    @LayoutRes
    public int getSplashLayout() {
        return 0;
    }

    /**
     * @return the layout you would like to show while react's js context loads
     */
    public View createSplashLayout() {
        View view = new View(this);
        view.setBackgroundColor(Color.WHITE);
        return view;
    }
}

MainApplication.java public class MainApplication扩展自NavigationApplication并实现ReactInstanceHolder接口 {

    @Override
    public boolean clearHostOnActivityDestroy() {
        return false;
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH) {
            // only for KITKAT_WATCH and newer versions
            MultiDex.install(this);
        }
    }

    @Override
    public boolean isDebug() {
        // Make sure you are using BuildConfig from your own application
        return BuildConfig.DEBUG;
    }

    @Override
    public String getJSMainModuleName() {
        return "index";
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Log.v(TAG, "onConfigChange"+newConfig);
        Intent intent = new Intent("onConfigurationChanged");
        intent.putExtra("newConfig", newConfig);
        this.sendBroadcast(intent);
    }


    // 2. Override the getJSBundleFile method in order to let
    // the CodePush runtime determine where to get the JS
    // bundle location from on each app start
    @Override
    public String getJSBundleFile() {
        return CodePush.getJSBundleFile();
    }

    @NonNull
    @Override
    public List<ReactPackage> createAdditionalReactPackages() {
        return Arrays.<ReactPackage>asList(
            new LinearGradientPackage(),
            new OrientationPackage(),
            new VectorIconsPackage(),
            new KeychainPackage(),
            new BackgroundTimerPackage(),
            new RNI18nPackage(),
            BugsnagReactNative.getPackage(),
            new BlurViewPackage(),
            new PickerViewPackage(),
            new ImagePickerPackage(),
            new RNFetchBlobPackage(),
            new MapsPackage(),
            new FIRMessagingPackage(),
            new RNAmplitudeSDKPackage(MainApplication.this),
            new RNVersionCheckPackage(),
            new RNCardIOPackage(),
            new AndroidWebViewPackage(),
            new WheelPackage()
        );
    }


    @Override
    public void onCreate() {
        super.onCreate();
        setActivityCallbacks(new ActivityCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

            }

            @Override
            public void onActivityStarted(Activity activity) {

            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {

            }

            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent data) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
//            @Override
//            public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
//                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//            }

        });
    }

    @Override
    public ReactInstanceManager getReactInstanceManager() {
        return getReactNativeHost().getReactInstanceManager();
    }
}

非常感谢任何提示,谢谢!


2
你知道 MainActivity extends SplashActivity 吗? - tynn
@tynn 当然,那只是 com.reactnativenavigation.controllers.SplashActivity; 这是因为我正在使用一个React Native导航库,不要在意这个。 - SudoPlz
您可以通过不使用闪屏活动,而只是使用窗口背景并在加载后切换为真实背景来避免导航问题。这不是对您的问题的直接回答,因为它是一种不同的方法来处理此问题而非使用活动。您可以在此处找到tl;dr:https://github.com/bleeding182/samples/tree/master/SplashScreen - David Medenjak
3个回答

4

例如:您的 URL 将类似于https://example.com,并且您在 Android Manifest 中拥有以下意图过滤器:

<activity
    android:name="com.droid.MainActivity"
    android:label="@string/app_name" >

    <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:host="example.com"
            android:scheme="https" />
    </intent-filter>
</activity>

使用URL映射编辑器,可以通过Android应用链接(Android Studio > 工具 > Android应用链接)轻松地为您的活动添加URL意图过滤器。

谢谢您抽出时间回答,但是那个回答如何解决问题呢?顺便说一下,深度链接确实可以正常工作,只是显示了错误的屏幕。 - SudoPlz
1
plus1 用于添加 URL 链接...我在手机上打开它,直接重定向到我的应用程序...哇 - Maveňツ
如果我们需要通过深度链接启动App类,这是否可能? - Tushar Gogna

2

找到了问题的原因。

实际上是在MainApplication.java文件中的这行代码:

public boolean clearHostOnActivityDestroy() {
    return false;
}

当我把那个值改为true时,一切都开始按照预期工作了。
这是由我的导航库引起的问题:https://github.com/wix/react-native-navigation

2
安卓系统查看清单文件中第一个拥有以下标签的标签:
   <category android:name="android.intent.category.LAUNCHER" />

将MainActivity设置为使用此标记,而不是SplashActivity。

始终首先启动MainActivity,并在MainActivity onCreate中对Intent进行任何检查。

    //replace getStringExtra with whatever you use to identify deeplink.
Boolean isDeepLink= getIntent().getStringExtra("").startsWith("mydeeplink://");

if(!isDeepLink)
    {
        Intent splashIntent=new Intent(this, SplashActivity.class);
        startActivity(splashIntent);
    }

但是第二个被注释掉了!<!-- --> 对吧?我会编辑我的问题(删除已注释的代码片段)以避免混淆。 - SudoPlz
@SudoPlz 请查看已编辑的答案。如果对您有用,请告诉我。 - Mustafa Dualeh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接