一 日常应用
双进程守护和卸载监听都使用到了AM命令,应用卸载后的访问网页,命令拉起:
execlp("am", "am", "start","--user","0","-a", "android.intent.action.VIEW", "-d",
"http://www.baidu.com", NULL);
//execlp 是调用命令的函数
在有些手机上如三星fork不出来线程,小米修改了Am的源码导致重新拉起的服务无效
二 命令参数如何解析
- Android源码包名路径:
framework.base.cmds.am.src.com.android.commands.am.Am.java
- Am.java是可执行文件,有main函数
public static void main(String[] args){
(new Am()).run(args);
}
三 参数检测
- Am中main调用的run方法中:
if (args.length < 1) {
onShowUsage(System.out);
return;
}
- adb shell 进入手机
- am 会打印命令提示,而这些内容和Am.java里面onShowUsage打印的一样
四 run方法
run调用了父类BaseCommand的抽象方法onRun(),在子类Am中实现了
- onRun方法
->nextArgRequired()找到下一个参数
以开启网页和打电话的命令为例
am start -a andorid.intent.action.VIEW -d http://baidu.com
am start -a android.intent.action.CALL -d 10086
nextArgRequired返回的是start ,
- 接着调用 runStart() 开始拼接Intent
五 runStart
//intent am 开启四大组件 Intent
Intent intent = makeIntent(UserHandle.USER_CURRENT);
六 makeIntent 封装好参数 到新生成的Intent中
命令行的 -d 对应Intent的action
//nextOption 移动到下一个参数
while((opt = nexOption())! = null){
if(opt.equals("-a")){
// action
intent.setAction(nextArgRequired())
}else if(otp.equals("-d")){
data = Uri.parse(nextArgRequired());
if(intent == baseIntent){
hasItentInfo = true;
}
}else
...
intent.setDataAndType(data,type);
}
返回的Intent具备了uri、action ,能够开启一个组件(包括service、broadcast)
七 如何跨进程启动四大组件
返回到runStart中
//aidl文件
private IActivityManger mAm;
void runStart(){
// pm 安装 开启组件
IpacekageManager pm = IpacekageManager.Stub.asInterface(ServcieManager.getService(“package”));
//查询组件 Activity 注册
List<ResovleInfo> activities = pm.queryIntentActivities(intent,mimeType,0,mUserId);
//才能进行下一步跳转
...
//开启组件
res = mAm.startActivityAsUser(null,null,intent,mimeType,null,null,0,mStartFlags,profilerInfo,null,mUserId);
}