应用中响应
android.intent.action.MAIN
和
android.intent.category.LAUNCHER
在本文中称为主界面。
本文基于 Android O
用PackageInstaller安装应用,在安装完成界面里点击打开,应用闪屏页打开后,按Home键回到桌面,点击桌面里的应用图标。
问题点:再打开一个闪屏页。
应用中启动别的应用,以上问题场景使用的是
PackageManager#getLaunchIntentForPackage()
这个API,它的实现是:
@Override
public Intent getLaunchIntentForPackage(String packageName) {
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory(Intent.CATEGORY_INFO);
intentToResolve.setPackage(packageName);
List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
if (ris == null || ris.size() <= 0) {
intentToResolve.removeCategory(Intent.CATEGORY_INFO);
intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
intentToResolve.setPackage(packageName);
ris = queryIntentActivities(intentToResolve, 0);
if (ris == null || ris.size() <= 0) {
return null;
Intent intent = new Intent(intentToResolve);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName(ris.get(0).activityInfo.packageName,
ris.get(0).activityInfo.name);
return intent;
复制代码
正常桌面启动某个应用的实现如下:
public static Intent makeLaunchIntent(Context context, LauncherActivityInfoCompat info,
UserHandleCompat user) {
long serialNumber = UserManagerCompat.getInstance(context).getSerialNumberForUser(user);
return new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setComponent(info.getComponentName())
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
.putExtra(EXTRA_PROFILE, serialNumber);
复制代码
对比以上两种启动另一个应用的代码实现,可以发现:
PackageManager#getLaunchIntentForPackage()
这个API 多了
intentToResolve.setPackage(packageName);
。
起始应用A直接使用该方法返回的
Intent
对象去启动目标应用B,该intent会被AMS增加一个flag:FLAG_ACTIVITY_BROUGHT_TO_FRONT,代码如下:
* Figure out which task and activity to bring to front when we have found an existing matching
* activity record in history. May also clear the task if needed.
* @param intentActivity Existing matching activity.
* @return {@link ActivityRecord} brought to front.
private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
mTargetStack = intentActivity.getStack();
mTargetStack.mLastPausedActivity = null;
final ActivityStack focusStack = mSupervisor.getFocusedStack();
ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
if (topTask != null
&& (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
&& !mAvoidMoveToFront) {
mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
if (mLaunchTaskBehind && mSourceRecord != null) {
intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
mMovedOtherTask = true;
复制代码
如果该B应用启动后置后台,那么会根据B应用的主界面的lauchMode创建或复用任务栈里的对象,会有意想不到的结果。比如:如果B应用的主界面launchMode是standard,那么会有第二个主界面被创建在任务栈里。
更详细原因分析请参考文章:
关于Android应用回到桌面会重复打开闪屏页
在起始应用A里发起跳转时:
Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName)
intent.setPackage(null)
context.startActivity(intent)
复制代码
第二种
在目标应用B的主界面
onCreate
里,添加:
super.onCreate(savedInstanceState);
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)> 0) {
finish();
return;
复制代码