• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > android插件开发-就是你了!启动吧!插件的activity(一)

android插件开发-就是你了!启动吧!插件的activity(一)

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android插件开发-就是你了!启动吧!插件的activity(一)等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

android插件开发-就是你了!启动吧!插件的activity(一)


 

  通过之前的例子例子,我们学习了如何寻找hook点,并且做一些非常无聊的事情。比如是的粘贴板放一句无聊的句子,或者让系统在启动一个activity时打印一句话。这些看似无聊的事情其实都是为了本节做铺垫。

  这一节会把之前的知识都贯穿起来——启动插件中的activity,不过这篇博客比较长,所以我分开成为两部分了第二部分

  启动插件的activity还是非常难的一件事,因为在android中,所有的activity都必须在AndroidManifest.xml文件中声明。如果没有声明的话,启动它就会碰到下面的错误:

这里写图片描述
伤透脑筋啊~

由于android的机制,我们无法启动一个没有在AndroidManifest.xml中没有声明的activity,并且我们不能像平时写普通java代码一样,new一个Acticity对象出来就完事。因为android中的组件都是有生命的,不可以凭空产生,也不可以凭空消失,手动new出来的,它只是一个普通的对象,没有任何用处。那么我们是否可以,先在AndroidManifest.xml中声明一个activity,然后我们插件中的activity都通过它借尸还魂,以此来运行呢?想法有点大胆,不过也没办法,因为我们现在能想到的就这么多。

既然要借一个activity还魂,那么肯定得了解activity的启动原理啊,不然一切都真的是空谈。通过我们之前的学习,我们注意到,当启动一个activity时,Activity这个类中做这件事的其实是他的成员对象——mInstrumentation

这里写图片描述

在这个函数里面他最终是调用的是ActivityManagerNative.getDefault()的返回值来启动一个activity
这里写图片描述
ActivityManagerNative.getDefault返回的是一个Binder对象,他能够使用ActivityManagerService的服务(以下简称AMS)。正如其名,它正是管理activity的服务,由他赋予activity生命!
这里写图片描述
这里写图片描述
通过一系列的远程调用我们开始使用activity manager service的服务。其流程大概如下:
1:AMS调用ActivityStack的一系列方法来准备要启动的Activity的相关信息。我们平时说的什么任务栈啊都在这个类中有涉及
2:ActivityStack在完成一些准备工作后,通过ApplicationThread接口,远程通知当前的ui线程,我要准备调度了~注意!ApplicationThread这个接口是在activity启动另外一个activity的时候传入Activity的
关于它的信息在这里:
这里写图片描述
3:ApplicationThread不执行真正的启动操作,它通过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity。你大概可以感觉到了吧,ui线程通过ActivityManagerProxy与AMS”取得联系”,而AMS呢,通过ApplicationThread与ui线程获得联系
4: 对于通过点击应用程序图标来启动Activity的情景来说,AMS在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动
5: AMS调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操作;
6: ApplicationThread把这个启动Activity的操作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来。

以上内容有部分摘自老罗的博客
不过他看的android源码有点老了,现在的源码变化不小~

现在就开始分析吧

我们切入到AMS中看下:

1

这里写图片描述
他调用了另外一个成员函数(这里唠叨下,看到第一个参数没?AMS通过他和我们的ui线程通信)

2

这里写图片描述
这里的AMS代码被重构了一遍,这里是要进入到ActivityStackSupervisor这个类中去处理了。从名字上我们很容易看出,这里就是进行之前我们说的——让ActivityStack做一些准备工作

3

这里写图片描述

  final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        //查看下是否有component
        boolean componentSpecified = intent.getComponent() != null;

        // Don't modify the client's object!
        intent = new Intent(intent);

        // Collect information about the target of the Intent.
        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profilerInfo, userId);

            ...

            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options,
                    componentSpecified, null, container, inTask);
            ...
            return res;
        }
    }

这里有个非常重要的部分!

        //查看下是否有component
        boolean componentSpecified = intent.getComponent() != null;

我们平时可以有很多种方式启动一个activity,比如隐式,显式启动
隐式:

        Intent intent = new Intent("your action");
        ...
        startActivity(intent);

显式:

        Intent intent = new Intent(context, xxx.class);
        startActivity(intent);

我们这里只考虑显式。我们看下源码:
这里写图片描述
这个mComponent是一个ComponentName类型,他是系统用于区分组件的一个类:
这里写图片描述
好像有那么种感觉就是,AMS通过它区分要启动的activity是什么。回忆一下之前我介绍的activity启动流程。ActivityStack准备好一切之后,会回到ui线程,然后UI线程再回头问下AMS我是在当前进程启动一个activity还是再创建一个进程启动。这个过程是否有一种机制,让AMS能够快速识别这个Ui线程是哪个app的,毕竟手机里不止一个应用嘛。
我们不急,继续往下看。
之后的代码就是解析出当前要启动的activity信息:

  // Collect information about the target of the Intent.
        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profilerInfo, userId);

切进去看下:

         @Override
3027     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
3028             int flags, int userId) {
3029         if (!sUserManager.exists(userId)) return null;
3030         enforceCrossUserPermission(Binder.getCallingUid(), 
                 userId, false, false, "resolve intent");
3031         List query = queryIntentActivities(intent, resolvedType, flags, userId);
             //选择出最优的activity
3032         return chooseBestActivity(intent, resolvedType, flags, query, userId);
3033     }

queryIntentActivities:

3349     @Override
3350     public List More ...queryIntentActivities(Intent intent,
3351             String resolvedType, i



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

相关文章

  • 2017-05-26Spark的调度策略详解
  • 2017-05-26二维码Zxing&Zbar,zxing
  • 2017-05-26Android 系统版本&API对照表,android系统版本
  • 2017-05-26如何编写高效的android代码
  • 2017-05-26如何选择 compileSdkVersion, minSdkVersion 和 targetSdkVersion,compilesdkversion
  • 2017-05-227.6.4 基于UDP协议的Socket通信
  • 2017-05-26android:Activity数据传递之对象(Serializable)
  • 2017-05-26Android学习笔记(32):通知推送Notification浅析
  • 2017-05-26org.gradle.api.internal.tasks.DefaultTaskInputs$TaskInputUnionFileCollection cannot be cast to org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection,gradletaskinputs
  • 2017-05-26android下拉选择框spinner,android下拉spinner

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Linux内核系列—9.操作系统开发之Loader,linuxloader
    • Android学习--RelativeLayout相对布局
    • kvm性能优化
    • android实现文字渐变效果和歌词进度的效果
    • android.view.WindowLeaked的解决办法,androidwindowleaked
    • Stack Overflow 排错翻译,stackoverflow
    • Android 手机卫士--平移动画实现,android卫士
    • Android安全专项-Apk加固浅析
    • Swift开发iOS应用(1)列表的实现
    • Android 手机卫士--绑定sim卡序列号,androidsim

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有