启动其他APK的Activity方法
有两个app,分别叫做App1和App2。
App1包含两个Activity,分别叫做App1_A和App1_B其中App1_A是入口Activity
也就是App1_A设置intent-filter,action为<action android:name="androidintentactionMAIN" />
App2只有一个Activity,叫做App2_A。
现在在App2_A中通过startActivity启动App1_A是没问题的但是启动App1_B的时候报了fc错误。
logcat如下:
08-03 02:23:44119: WARN/ActivityManager(64): Permission denied: checkComponentPermission() reqUid=10030
08-03 02:23:44119: WARN/ActivityManager(64): Permission Denial: starting Intent { act=androidintentactionVIEW cmp=comhello/activity2 } from ProcessRecord{407c8bc8 665:comfileExplorer/10032} (pid=665, uid=10032) requires null
用法如下:
Intent intent = new Intent();
ComponentName componentName = new ComponentName("comhello","comhelloApp1_A");//这个没问题
//ComponentName componentName = new ComponentName("comhello","comhelloApp1_B");//这个报错
intentsetComponent(componentName);
startActivity(intent);
解决方法:
(1)
通过隐式intent调用方法实现,需要在被调用的activity的manifest文件中添加
<intent-filter>
<action android:name="comexampleprojectSHOW_ACTIVITY" />
<category android:name="androidintentcategoryDEFAULT" />
</intent-filter>
在StartActivity(it)之前,设定该intent对应的action(comexampleprojectSHOW_ACTIVITY)
Intent intent = new Intent();
intentsetAction(action);
intentaddFlags(IntentFLAG_ACTIVITY_NEW_TASK);
contextstartActivity(intent);推荐使用
利用setAction方法启动Activity还有一个好处就是不需要知道包名和Activity类名,只需要知道action就可以隐式的启动activity
(2)
即使直接指定了目标activity的ComponentName,跨应用的activity调用也要至少给目标activity指定一个带action的filter。如:
<intent-filter>
<action android:name="" />
</intent-filter>
action name为空即可。
(3)给被调用的Activity增加一个带action的filter,如下:
<intent-filter>
<action android:name="comsdmcottplayeruercenter" />
</intent-filter>
然后可以通过隐式Intent来调用,而不用使用intentsetComponent方法,如下就OK了(但是经过验证,这种方法只是对APK的入口activity有用,对普通的没用,和上面的问题一样无法解决:启动其他APK的非入口activity)
Intent i = new Intent("comsdmcottplayeruercenter");
isetFlags(IntentFLAG_ACTIVITY_NEW_TASK);
thisstartActivity(intent);
异常处理:
Caused by: androidutilAndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag Is this really what you want
Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法。
如果使用 Activity的startActivity方法,不会有任何限制,
而如果使用Context的startActivity方法的话,就需要开启一个新 的task,遇到上面那个异常的,都是因为使用了Context的startActivity方法。
解决办法是,加一个flag。intentaddFlags(IntentFLAG_ACTIVITY_NEW_TASK)
Intent intent = new Intent();
intentsetClass(mContext, VideoPlayerclass);
intentaddFlags(IntentFLAG_ACTIVITY_NEW_TASK);
mContextstartActivity(intent);
楼主要的应该是触摸dialog 以外的部分,dialog自动关闭吧?
void setCanceledOnTouchOutside(boolean cancel), 置成truexml的配置文件中也有对应的属性,你自己查一下
1、设置Intent
Intent intent = new Intent(当前Activitythis, 要打开的Activityclass);2、通过startActivity打开activity
startActivity(intent);//打开新的activity[1] 一个 APP 从启动到主页面显示经历了哪些过程
[2] startActivity 启动过程分析 - Gityuan
[3] 译Android Application 启动流程分析
[4] 凯子哥带你学 FrameworkActivity 启动过程全解析
[5] Android Framework 之 Activity 启动流程(一)
[6] 任务和返回堆栈
1 从 Activity 本地调用startActivity()--> Activity#startActivityForResult()
2 Instrumentation #execStartActivity:Instrumentation类相当于一个管家,它的职责是管理各个应用程序和系统的交互,Activity都有此对象的实际引用,可以通过它监测系统与应用程序之间的所有交互。
3 ActivityManagerProxy #startActivity():发起了一次跨进程调用,ActivityManagerService是ActivityManagerNative的具体实现。
4 ActivityStarter ():主要负责处理Activity的Intent和Flags, 还有关联相关的Stack和TaskRecord。
ActivityStackstartActivityMayWait():获取Activity的启动信息,包括ResolveInfo和ActivityInfo,以及获取CallingPid和CallingUid;
ActivityStackstartActivityLocked():创建一个ActivityRecord;
ActivityStackstartActivityUnchecked():设置TaskRecord, 完成后执行ActivityStackSupervisor类的resumeFocusedStackTopActivityLocked方法
5 ActivityStackSupervisor 和 ActivityStack :这里会判断进程是否存在和一些生命周期的方法
ActivityStackSupervisor#resumeFocusedStackTopActivityLocked()
--> ActivityStackSupervisor#resumeTopActivityUncheckedLocked():
--> ActivityStack#resumeTopActivityInnerLocked()
--> ActivityStackSupervisor#startSpecificActivityLocked()
6: ApplicationThread :IApplicationThread的直接实现,发起了一次跨进程调用
7: ActivityThread :会调用sendMessage,最后调用到mHsendMessage(msg);
8: ActivityThread # performLaunchActivity ():会收集要启动的Activity的相关信息,主要是package和component信息,然后通过ClassLoader将要启动的Activity类加载出来。最后调用mInstrumentationcallActivityOnCreate()
9: Activity # performStart ():Activity的生命周期方法是通过Instrumentation类调用callActivityOnXXX方法最终调用Activity的onCreate等方法,调用时机为ActivityThread#performLaunchActivitiy()方法中。
一 应用程序的MainActivity通过Binder进程间通信机制通知ActivityManagerService,它要启动一个新的Activity;
二 ActivityManagerService通过Binder进程间通信机制通知MainActivity进入Paused状态;
三 MainActivity通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就准备要在MainActivity所在的进程和任务中启动新的Activity了;
四 ActivityManagerService通过Binder进程间通信机制通知MainActivity所在的ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动 *** 作了。
Instrumentation : 监控应用与系统相关的交互行为。
AMS :组件管理调度中心,什么都不干,但是什么都管。
ActivityStarter :处理Activity什么时候启动,怎么样启动相关问题,也就是处理Intent与Flag相关问题,平时提到的启动模式都可以在这里找到实现。
ActivityStackSupervisior :这个类的作用你从它的名字就可以看出来,它用来管理Stack和Task。
ActivityStack :用来管理栈里的Activity。
ActivityThread :最终干活的人,是ActivityThread的内部类,Activity、Service、BroadcastReceiver的启动、切换、调度等各种 *** 作都在这个类里完成。
目录
activity的简单介绍就不写了,作为最常用的四大组件之一,肯定都很熟悉其基本用法了。
首先,是都很熟悉的一张图,即官方介绍的Activity生命周期图
情景:打开某个应用的的FirstActivity调用方法如下:
由于之前已经很熟悉了,这里就简单贴一些图。
按下返回键:
重新打开并按下home键:
再重新打开:
在其中打开一个DialogActivity(SecondActivity)
按下返回:
修改SecondAcitvity为普通Activity,依旧是上述 *** 作:
这里强调一下 onSaveInstanceState(Bundle outState) 方法的调用时机:
当Activity有可能被系统杀掉时调用,注意,一定是被系统杀掉,自己调用finish是不行的。
测试如下:FirstActivity启动SecondActivity:
一个App会包含很多个Activity,多个Activity之间通过intent进行跳转,那么原始的Activity就是使用栈这个数据结构来保存的。
Task
A task is a collection of activities that users interact with when performing a certain job The activities are arranged in a stack (the back stack ), in the order in which each activity is opened
即若干个Activity的集合的栈表示一个Task。
当App启动时如果不存在当前App的任务栈就会自动创建一个,默认情况下一个App中的所有Activity都是放在一个Task中的,但是如果指定了特殊的启动模式,那么就会出现同一个App的Activity出现在不同的任务栈中的情况,即会有任务栈中包含来自于不同App的Activity。
标准模式,在不指定启动模式的情况下都是以此种方式启动的。每次启动都会创建一个新的Activity实例,覆盖在原有的Activity上,原有的Activity入栈。
测试如下:在FirstActivity中启动FirstActivity:
当只有一个FirstActivity时堆栈情况:
此种模式下,Activity在启动时会进行判断,如果当前的App的栈顶的Activity即正在活动的Activity就是将要启动的Activity,那么就不会创建新的实例,直接使用栈顶的实例。
测试,设置FirstActivity为此启动模式,多次点击FirstActivity中的启动FirstActivity的按钮查看堆栈情况:
(其实点击按钮没有启动新Activity的动画就可以看出并没有启动新Activity)
大意就是:
对于使用singleTop启动或IntentFLAG_ACTIVITY_SINGLE_TOP启动的Activity,当该Activity被重复启动(注意一定是re-launched,第一次启动时不会调用)时就会调用此方法。
且调用此方法之前会先暂停Activity也就是先调用onPause方法。
而且,即使是在新的调用产生后此方法被调用,但是通过getIntent方法获取到的依旧是以前的Intent,可以通过setIntent方法设置新的Intent。
方法参数就是新传递的Intent
1如果是同一个App中启动某个设置了此模式的Activity的话,如果栈中已经存在该Activity的实例,那么就会将该Activity上面的Activity清空,并将此实例放在栈顶。
测试:SecondActivity启动模式设为singleTask,启动三个Activity:
这个模式就很好记,以此模式启动的Activity会存放在一个单独的任务栈中,且只会有一个实例。
测试:SecondActivity启动模式设为singleInstance
结果:
显然,启动了两次ThirdActivity任务栈中就有两个实例,而SecondActivity在另外一个任务栈中,且只有一个。
在使用Intent启动一个Activity时可以设置启动该Activity的启动模式:
这个属性有很多,大致列出几个:
每个启动的Activity都在一个新的任务栈中
singleTop
singleTask
用此种方式启动的Activity,在它启动了其他Activity后,会自动finish
官方文档介绍如下:
这样看来的话,通俗易懂的讲,就是给每一个任务栈起个名,给每个Activity也起个名,在Activity以singleTask模式启动时,就检查有没有跟此Activity的名相同的任务栈,有的话就将其加入其中。没有的话就按照这个Activity的名创建一个任务栈。
测试:在App1中设置SecondActivity的taskAffinity为“gsqtest”,App2中的ActivityX的taskAffinity也设为“gsqtest”
任务栈信息如下:
结果很显然了。
测试:在上述基础上,在ActivityX中进行跳转到ActivityY,ActivityY不指定启动模式和taskAffinity。结果如下:
这样就没问题了,ActivityY在一个新的任务栈中,名称为包名。
这时从ActivityY跳转到SecondActivity,那应该是gsqtest任务栈只有SecondActivity,ActivityX已经没有了。因为其启动模式是singleTask,在启动它时发现已经有一个实例存在,就把它所在的任务栈上面的Activity都清空了并将其置于栈顶。
还有一点需要提一下,在上面,FirstActivity是App1的lunch Activity,但是由于SecondActivity并没有指定MAIN和LAUNCHER过滤器,故在FirstActivity跳转到SecondActivity时,按下home键,再点开App1,回到的是FirstActivity。
大致就先写这么多吧,好像有点长,废话有点多,估计也有错别字,不要太在意~~~
以上就是关于android 不用startactivity 怎么开启activity的方法全部的内容,包括:android 不用startactivity 怎么开启activity的方法、Android 怎么在Activity中启动另一应用程序的方法,无需得到类名、android 如何打开一个新的activity等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)