Activity显式跳转再普通不过了,平时开发处理一般跳转时写的最多的:
context.startActivity(new Intent(context, BuildGroupNameActivity.class));
隐式跳转如何实现呢,给一个栗子:
<activity android:name=".MixWakeUpActivity"
android:theme="@style/WakeUp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="mix_push"
android:host="${mixPushPackageName}"
android:path="/mix_wake_up"/>
</intent-filter>
</activity>
Activity通过intentFilter来过滤隐式跳转的意图,具体的intent匹配规则请查看其他大佬如@任玉刚的安卓开发艺术探索等。
比如上面Activity通过如下意图可以进行跳转:
Intent intentHw = new Intent(Intent.ACTION_VIEW, Uri.parse("mix_push://" + getPackageName() + "/mix_wake_up"));
今天的状况出现在sdk中的一个需要隐式跳转的Activity,声明如下:
<activity android:name=".component.child.MqttComponentActivity"
android:theme="@style/MqttAppTransparentToolFullTheme">
<intent-filter>
<action android:name="com.ny.mqttuikit.launch_chat_session"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
这个类被多个app的业务开发调用,当同时安装两个app进行跳转时,好戏来了:
看到这个的时候我的反应:
下面是安卓开发者中的一段:
android:exported
This element sets whether the activity can be launched by components of other applications — "true" if it can be, and "false" if not. If "false", the activity can be launched only by components of the same application or applications with the same user ID.
If you are using intent filters, you should not set this element "false". If you do so, and an app tries to call the activity, system throws an ActivityNotFoundException. Instead, you should prevent other apps from calling the activity by not setting intent filters for it.
If you do not have intent filters, the default value for this element is "false". If you set the element "true", the activity is accessible to any app that knows its exact class name, but does not resolve when the system tries to match an implicit intent.
This attribute is not the only way to limit an activity's exposure to other applications. You can also use a permission to limit the external entities that can invoke the activity (see the permission attribute).
其中指出,如果IntentFilter有设置,则exported属性默认为true。
所以当组件有提供IntentFilter时,如果不需要跨进程调用,则需要显式地禁用掉组件的导出属性,防止不同app在使用同一sdk时发生功能撞车。
参考链接:
https://developer.android.google.cn/guide/topics/manifest/activity-element?hl=en
------------------------------------------------------ 新发现,以上结论作废 ------------------------------------------------------
发现在lib-module中如果设置了intent-filter和exported=false则无法进行隐式跳转。
在网上也找到相关的bug,比如有些情况false+intent-filter可能导致仍然可以跳转的情况。
所以新结论是:
1.intent-filter只用于进程间跳转,intent-fitler和exptort=true要绑定使用。
2.进程内解耦最好使用显示跳转。
3.sdk给多app调用时防撞车请使用{$applicationId}+“后缀”做应用间区分