A. android 不用startactivity 怎么开启activity的方法
启动其他APK的Activity方法
有两个app,分别叫做App1和App2。
App1包含两个Activity,分别叫做App1_A和App1_B.其中App1_A是入口Activity.
也就是App1_A设置intent-filter,action为<action android:name="android.intent.action.MAIN" />
App2只有一个Activity,叫做App2_A。
现在在App2_A中通过startActivity启动App1_A是没问题的.但是启动App1_B的时候报了fc错误。
logcat如下:
08-03 02:23:44.119: WARN/ActivityManager(64): Permission denied: checkComponentPermission() reqUid=10030
08-03 02:23:44.119: WARN/ActivityManager(64): Permission Denial: starting Intent { act=android.intent.action.VIEW cmp=com.hello/.activity2 } from ProcessRecord{407c8bc8 665:com.fileExplorer/10032} (pid=665, uid=10032) requires null
用法如下:
Intent intent = new Intent();
ComponentName componentName = new ComponentName("com.hello","com.hello.App1_A");//这个没问题
//ComponentName componentName = new ComponentName("com.hello","com.hello.App1_B");//这个报错
intent.setComponent(componentName);
startActivity(intent);
解决方法:
(1)
通过隐式intent调用方法实现,需要在被调用的activity的manifest文件中添加
<intent-filter>
<action android:name="com.example.project.SHOW_ACTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
在StartActivity(it)之前,设定该intent对应的action(com.example.project.SHOW_ACTIVITY)
Intent intent = new Intent();
intent.setAction(action);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(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="com.sdmc.ottplayer.uercenter" />
</intent-filter>
然后可以通过隐式Intent来调用,而不用使用intent.setComponent方法,如下就OK了(但是经过验证,这种方法只是对APK的入口activity有用,对普通的没用,和上面的问题一样无法解决:启动其他APK的非入口activity)
Intent i = new Intent("com.sdmc.ottplayer.uercenter");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
异常处理:
Caused by: android.util.AndroidRuntimeException: 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。intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Intent intent = new Intent();
intent.setClass(mContext, VideoPlayer.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
B. Android NFC 如何启动Activity
可以给所有的activity定义统一的一个action,然后搞一个acitivy,让他来startpickeractivity,这样,就会把所有的定义了action的activity列出来,让用户选择
一开始启动一个chooseActivity,在这里面选,然后把选择结果保存sp
以后进程序如果sp里面有值就跳过chooseActivity
给个按钮,可以重新呼出chooseActivity
最简单的办法
C. android 启动 activity 是什么意思
当应用运行起来后就会开启一条线程,线程中会运行一个任务栈,当Activity实例创建后就会放入任务栈中。Activity启动模式的设置在AndroidManifest.xml文件中,通过配置Activity的属性android:launchMode=""设置。
1. Standard模式(默认)
我们平时直接创建的Activity都是这种模式的Activity,这种模式的Activity的特点是:只要你创建了Activity实例,一旦激活该Activity,则会向任务栈中加入新创建的实例,退出Activity则会在任务栈中销毁该实例。
2. SingleTop模式
这种模式会考虑当前要激活的Activity实例在任务栈中是否正处于栈顶,如果处于栈顶则无需重新创建新的实例,会重用已存在的实例,否则会在任务栈中创建新的实例。
3. SingleTask模式
如果任务栈中存在该模式的Activity实例,则把栈中该实例以上的Activity实例全部移除,调用该实例的newInstance()方法重用该Activity,使该实例处于栈顶位置,否则就重新创建一个新的Activity实例。
4. SingleInstance模式
当该模式Activity实例在任务栈中创建后,只要该实例还在任务栈中,即只要激活的是该类型的Activity,都会通过调用实例的newInstance()方法重用该Activity,此时使用的都是同一个Activity实例,它都会处于任务栈的栈顶。此模式一般用于加载较慢的,比较耗性能且不需要每次都重新创建的Activity。
D. android怎么设置程序启动进去就是自己指定的activity
没明白你到底要做什么 ,如要要做的效果是 点击 app图标就启动到你的 activity 中 可以看看下面的配置
<activity
android:name="org.xiaoyuno.LogoActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
E. android 怎么获取一个activity启动模式
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。
Android总Activity的启动模式分为四种:
Activity启动模式设置:
<activity android:name=".MainActivity" android:launchMode="standard" />
Activity的四种启动模式:
1. standard
模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。
2. singleTop
如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
3. singleTask
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
4. singleInstance
在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。
其中standard是系统默认的启动模式。
下面通过实例来演示standard的运行机制:
1 private TextView text_show;
2 private Button btn_mode;
3
4 @Override
5 public void onCreate(Bundle savedInstanceState) {
6 super.onCreate(savedInstanceState);
7 setContentView(R.layout.activity_main);
8
9 text_show = (TextView) this.findViewById(R.id.text_show);
10
11 text_show.setText(this.toString());
12
13 btn_mode = (Button) this.findViewById(R.id.btn_mode);
14
15 }
16
//按钮单击事件
17 public void LaunchStandard(View v){
18 startActivity(new Intent(this,MainActivity.class));
19
20 text_show.setText(this.toString());
21 }
F. Android 10.0 Activity的启动流程
本文主要学习记录,基于Android 10的源码,有错误欢迎指正,主要目的是梳理流程图。
以进程为单位的调用栈图如下:
1.activity中的startActivity方法最终都会通过拿到ATSM的代理IActivityTaskManager调用的startActivity;
2.之后进入system server进程中的ATMS startActivity,ATMS 经过收集Intent信息,然后使用ActivityStackSupervisor.startSpecificActivityLocked,如果进程已经存在,则直接使用realStartActivityLocked,通过App的binder客户端的代理ApplicationThread调用回到bindApplication,走入Activity的启动流程;如果进程不存在则通过socket链接Zygote,请求fork新的进程;
3.App进程创建完成后,进程启动会调用ActivityThread.main方法,初始化主线程Handler,接着走入attach方法,然后通过AMS的代理调用AMS的attachApplication方法,并将App进程的通信代理ApplicationThread传入AMS;
4.AMS获取到ATMS调用ApplicationThread的bindApplication回到App进程的ActivityThread.ApplicationThread.bindApplication方法中,然后使用Handler切换到主线程执行handleBindApplication,这里初始化了App的进程名字、时间,用户的硬件配置,包括App的文件系统,创建了App的Context实例,Instrumentation实例,调用App的onCreate回调方法,同时告诉AMS APP初始化工作完毕;
5.AMS接着会调用ATMS的attachApplication,最后调用ClientLifecycleManager的scheleTransaction方法,通过App的Binder代理ApplicationThread回到ActivityThread;
6.进入ActivityThread.ApplicationThread.scheleTransaction方法之后就进入了Activity的onStart、onResume回调
创建进程之前的过程主要是AMS的内部信息收集的判断的过程,下面主要看一下App进程启动的源码流程
从应用进程被创建开始,ActivityThread.main被执行
调用ActivityThread的attach方法,然后将activity和AMS通信的Binder代理IApplicationThread实例传入AMS
接着进入AMS进程,ActivityManagerService.attachApplicationLocked
1.thread.bindApplication :该方法主要讲App进程的配置信息通过IApplicationThread Binder通信回传到ActivityThread中
2.mAtmInternal.attachApplication :mAtmInternal实际就是ActivityTaskManager的实例,通过LocalServices加载
那么这里相当于走到了ActivityTaskManagerServer的attachApplication中
先看第一条:
注意:ActivityThread中存在于Binder通信的代理--》ApplicationThread extends IApplicationThread.Stub
ActivityThread--》ApplicationThread--》bindApplication
这里的bindApplication主要初始化了AppBindData,然后发送BIND_APPLICATION给APP的主线程BIND_APPLICATION,最后执行了handleBindApplication
handleBindApplication如下:
ActivityThread--》class H extends Handler
该方法主要在App进程中对App的一些硬件资源配置申请的属性、App的文件夹等完成App基本信息的初始化
接着看第二条:mAtmInternal.attachApplication
mAtmInternal.attachApplication最终会调用mRootActivityContainer.attachApplication(wpc)
RootActivityContainer.attachApplication
接着调用ActivityStackSupervisor.realStartActivityLocked开始创建Activity
ActivityStackSupervisor.realStartActivityLocked
创建ClientLifecycleManager和ClientTransactionHandler来辅助管理Activity的生命周期
注意
clientTransaction.addCallback是LaunchActivityItem
lifecycleItem是ResumeActivityItem
ClientLifecycleManager.scheleTransaction最终会调用ClientTransaction的schele方法
那么这个mClient是IApplicationThread的实例,那么此时也就回到了ActivityThread的ApplicationThread中
ActivityThread的ApplicationThread中
因为ActivityThread继承ClientTransactionHandler,所以到了ClientTransactionHandler中
通过Handler发送消息EXECUTE_TRANSACTION到H中
接着TransactionExecutor的execute方法
LaunchActivityItem.execute方法
client其实是在ActivityThread的实例,那么就回到了ActivityThread的handleLaunchActivity
接着调用performLaunchActivity
在performLaunchActivity中,主要是加载App的资源包,然后创建了Activity的context实例,并创建了Activity的实例,接着调用activity.attach方法,attach执行完之后调用了onCreate方法。
activity.attach
activity.attach中主要
1.创建了PhoneWindow实例
2.设置了Window接口的监听
3.初始化了成员变量,包括线程和WindowManager
到此Oncreate已经完成,那么OnStart和OnResume去哪了?
TransactionExecutor的execute方法
之前们只分析了executeCallbacks,接着executeLifecycleState方法
TransactionExecutor的executeLifecycleState方法
cycleToPath:lifecycleItem即为ResumeActivityItem
第一点:
int finish = lifecycleItem.getTargetState()
lifecycleItem对应ResumeActivityItem,如下:
ResumeActivityItem的getTargetState方法
对应ActivityLifecycleItem中的枚举类型:
第二点:ActivityClientRecord中的mLifecycleState,由于在前面已经执行了handleLaunchActivity所以mLifecycleState=1
对应ActivityLifecycleItem中的枚举类型:
PRE_ON_CREATE = 0
所以final int star = 1
接着看getLifecyclePath,此时start=1,finish=3
那么返回的IntArray就是2
接着看performLifecycleSequence
最终执行的是handleStartActivity所以最终走到了ActivityThread的handleResumeActivity
两点:
调用activity.performStart
调用Instrumetation.callActivityOnPostCreate
performStart方法:
调用了Instrumentation.callActivityOnStart方法:
最终到了activity的onStart方法
第二点:Instrumentation.callActivityOnPostCreate
上面主要走了cycleToPath,接着ResumeActivityItem.execute
调用了handleResumeActivity方法
handleResumeActivity最终调用performResumeActivity
调用了Instrumentation.callActivityOnResume,
到了activity.onResume()方法
参考文章: https://blog.csdn.net/u011386173/article/details/87802765
G. 怎样在程序中设置Android应用最开始运行的Activity
从一个Activity(界面)跳转到另一个Activity时,需要使用到Intent来启动Activity。
Intent在android中的定义为:public Intent (Context packageContext , Class<?> cls);
在Intent使用时,分为显式调用和隐式调用:
显式调用---直接调用Activity的Class类
例,Activity1调用Activity2
Intent intent = new Intent(this , Activity2.class);
startActivity(intent);
隐式调用---通过调用另一个Activity的action 来启动另一个Activity
Activity1隐式调用Activity2时需要在AndroidManifest.xml文件中配置Activity2的action和category,具体添加下面的代码到Activity2的定义中
<intent-filter>
<action android:name="myaction2"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="mycategory" />
</intent-filter>
接着同样用intent来启动Activity,代码如下:
Intent intent = new Intent("myaction2");
startActivity(intent);
这样就可以启动Activity2
注:intent隐式调用Activity时会遇到多个Activity的intent-filter中的action和category相同时,android会先弹一个选择界面的窗口,显式要启动的Activity列表,根据用户选择来启动Activity,如Activity2和Activity3的action和category相同
<Activity android:name=".Activity2">
<intent-filter>
<action android:name="myaction2"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="myCategory" />
</intent-filter>
</Activity>
<Activity android:name=".Activity3">
<intent-filter>
<action android:name="myaction2"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="myCategory" />
</intent-filter>
</Activity>
启动Activity代码如下:
Intent intent = new("action2");
intent.addCategory("myCategory");
startActivity(intent);
这时就会弹出Acvity的选择窗口,选择启动activity2还是activity3