通过启动Activity来理解Intent+Bundle跨进程

Posted zhangjin1120

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过启动Activity来理解Intent+Bundle跨进程相关的知识,希望对你有一定的参考价值。

目录

从Intent+Bundle到Binder

进程间通信为什么叫IPC?

IPC是Inter-Process Communication 的缩写,意为进程间通讯或跨进程通信,指两个进程之间进行数据交换的过程。

Intent与Bundle之间的关系是什么?

Intent可以携带Bundle类型的对象,然后作为参数传递给AMS,AMS负责启动另外一个Activity或者其他组件。

   //Intent.java源码
    public Intent putExtras(Bundle extras) 
        if (mExtras == null) 
            mExtras = new Bundle();
        
        mExtras.putAll(extras);
        return this;
     

怎么用Intent启动另外一个App的Activity?

方式有几种,详细参考:Android在一个应用程序中启动另一个应用程序
下面其中一种,根据应用的包名,启动它的Activity。可以看到Intent作为参数,最终执行了startActivity(intent);

    private void openApp(String packageName) 
        PackageInfo pi = getPackageManager().getPackageInfo(packageName, 0);

        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        resolveIntent.setPackage(pi.packageName);

        List<ResolveInfo> apps = pm.queryIntentActivities(resolveIntent, 0);

        ResolveInfo ri = apps.iterator().next();
        if (ri != null) 
            String packageName = ri.activityInfo.packageName;
            String className = ri.activityInfo.name;

            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);

            ComponentName cn = new ComponentName(packageName, className);

            intent.setComponent(cn);
            startActivity(intent);
        
    

startActivity(intent);中,Intent到底传递给了谁?

ActivityManagerService
整个startActivity()的过程,这篇文章:【Android源码】Intent 源码分析 已经分析的很清楚了,我把跨进程通信相关的部分贴出来。从下面的代码可以看出来intent传递给了ActivityManagerNative.getDefault().startActivity();,而ActivityManagerNative是ActivityManagerService的父类,这个后面的问题会介绍。

public ActivityResult execStartActivity(
       Context who, IBinder contextThread, IBinder token, Activity target,
       Intent intent, int requestCode, Bundle options) 
   IApplicationThread whoThread = (IApplicationThread) contextThread;
   Uri referrer = target != null ? target.onProvideReferrer() : null;
   try 
        // 将Intent数据添加到剪切板上
       intent.migrateExtraStreamToClipData();
        // 准备离开当前进程
       intent.prepareToLeaveProcess(who);
        // 调用ActivityManagerService的startActivity方法
       int result = ActivityManagerNative.getDefault()
           .startActivity(whoThread, who.getBasePackageName(), intent,
                   intent.resolveTypeIfNeeded(who.getContentResolver()),
                   token, target != null ? target.mEmbeddedID : null,
                   requestCode, 0, null, options);
        // 检查并回调给调用者
       checkStartActivityResult(result, intent);
    catch (RemoteException e) 
       throw new RuntimeException("Failure from system", e);
   
   return null;

启动另一个进程的Activity和AMS有什么关系?为什么要把Intent传递给AMS?

Activity 启动过程是由 ActivityMangerService(AMS) 来启动的,底层原理是 Binder实现的,最终交给 ActivityThread 的 performActivity 方法来启动它。

Binder和AMS是什么关系?

AMS是一个Binder的子类。 AMS继承了ActivityManagerNative,ActivityManagerNative又继承了Binder,所以ActivityManagerService本身就是一个Binder,可以用于进程间通信。

可以得出结论:Intent+Bundle实现跨进程通信,本质还是Binder机制。

AMS属于哪个进程?

System_server进程

启动另一个App的Activity,还需要IPC吗?

现代化操作系统通常具备两种处理器模式:用户模式(User Mode)与内核模式(Kernel Mode)。操作系统(或指操作系统内核)位于内核模式,可管理计算机的全部资源,而处于用户模式的用户进程若需要执行如访问磁盘等特权操作,就需要通过系统调用(System Call)交由内核模式的操作系统执行。

原因很简单,银行是不会让取款的客户进金库自己数钱的。

android 底层的 Linux Kernel 自然采用了这一权限机制,内核与相关服务运行的内存空间称为内核空间(Kernel Space),而用户进程所运行的内存空间称为用户空间(User Space)。当用户进程通过系统调用进行特权操作时,称此时进程为内核态(Kernel Mode,需注意根据上下文与内核模式进行区分)与用户态(User Mode)。

ActivityManagerService是系统的引导服务,应用进程的启动、切换和调度、四大组件的启动和管理都需要AMS的支持。AMS属于system_server进程,应用进程要和AMS通信,就需要跨进程。

Activity的启动需要做哪些工作?

应用A启动应用B的Activity,属于应用程序的启动或者调度,又AMS负责。下图是Lancher启动某个应用的图解,可以辅助理解应用A启动应用B的Activity的流程。

为什么跨进程通信需要序列化?

android不同的进程都有自己独立的内存空间,且相互之间不能进行访问。如果像我们平常传一个句柄的方式去传值的话肯定是失败的,因为句柄也是指定内存空间的一个区域。现在进程无法访问目标进程的内存空间,所以句柄传过去也是没有用的。
所以我们必须将要传输的数据转换成能够在内存空间流通的形式。这个转化过程就叫做序列化和反序列化。 简单来说是这样的:比如现在我们要将一个对象的数据从客户端传到服务端去,我们就可以在客户端对这个对象进行序列化的操作,将其中包含的数据转化为序列化流,然后将这个序列化流传输到服务端的内存中去,再在服务端对这个数据流进行反序列化的操作,从而还原其中包含的数据。

以上是关于通过启动Activity来理解Intent+Bundle跨进程的主要内容,如果未能解决你的问题,请参考以下文章

Android12.2 利用Intent启动和关闭Activity

activity的隐式和显式启动

Android 应用的交互------Intent

Android 中Activity和Intent的详解

Android-----Intent中通过startActivity(Intent intent )显式启动新的Activity

Android零基础入门第78节:四大组件的纽带——Intent