Android进程通信的方法 (android auto)

教程大全 2025-07-12 23:11:23 浏览

在 Android 世界里,默认的每个 APP 是一个单独的进程。其实这样的描述是不严格的,因为咱们要研究 Android 的进程间通信,肯定出了和其他的 APP 通信外,还可能和同一个 APP 下的其他进程通信,下面为大家详细讲解一下Android进程通信。

IPC方法总是产生客户/服务端模式的调用,也即是客户端组件(Activity/Service)持有服务端Service的组件,只能是客户端主动调用服务端的方法,服务端无法反过来调用客户端的方法,因为IPC的另一端Service无法获取客户端的对象。

Binder 是一种进程间通信机制。安卓中跨进程通讯就是通过binder。当绑定服务的时候会返回一个binder对象,然后通过他进行多进程间的通信。Binder只需要一次数据拷贝,性能上仅次于共享内存。

在 Android 系统中,这个运行在内核空间,负责各个用户进程通过 Binder 实现通信的内核模块就叫 Binder 驱动(Binder Dirver)。

Binder IPC 机制中涉及到的内存映射通过 mmap() 来实现,mmap() 是操作系统中一种内存映射的方法。内存映射简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;反之内核空间对这段区域的修改也能直接反应到用户空间。

内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。两个空间各自的修改能直接反映在映射的内存区域,从而被对方空间及时感知。也正因为如此,内存映射能够提供对进程间通信的支持。

Binder IPC 正是基于内存映射(mmap)来实现的

我们已经解释清楚 Client、Server 借助 Binder 驱动完成跨进程通信的实现机制了,但是还有个问题会让我们困惑。A 进程想要 B 进程中某个对象(object)是如何实现的呢?毕竟它们分属不同的进程,A 进程 没法直接使用 B 进程中的 object。

前面我们介绍过跨进程通信的过程都有 Binder 驱动的参与,因此在数据流经 Binder 驱动的时候驱动会对数据做一层转换。当 A 进程想要获取 B 进程中的 object 时,驱动并不会真的把 object 返回给 A,而是返回了一个跟 object 看起来一模一样的代理对象 objectProxy,这个 objectProxy 具有和 object 一摸一样的方法,但是这些方法并没有 B 进程中 object 对象那些方法的能力,这些方法只需要把把请求参数交给驱动即可。对于 A 进程来说和直接调用 object 中的方法是一样的。

当 Binder 驱动接收到 A 进程的消息后,发现这是个 objectProxy 就去查询自己维护的表单,一查发现这是 B 进程 object 的代理对象。于是就会去通知 B 进程调用 object 的方法,并要求 B 进程把返回结果发给自己。当驱动拿到 B 进程的返回结果后就会转发给 A 进程,一次通信就完成了其实进程间通信就是为了实现数据共享。一个程序不同组件在不同进程也叫多进程,和俩个应用没有本质区别。使用process属性可以实现多进程,但是会带来很多麻烦,主要原因是共享数据会失败,弊端有:静态和单利失效,同步失效,sharedprefer也变的不可靠等问题。

1.使用intent的附加信息extras来传递,通过bundle,传递的是bundle支持的类型,比如基本数据类型、实现pracellable或serializeable的对象

/**指定包名和带包名的Activity的名字*/componentnamecomponentName=newComponentName(,);Intentintent=newIntent();intent.putExtra(,1001);intent.setComponent(componentName);startActivity(intent);
android

2.使用文件共享,序列化或是sharedpre,不过不适用于读写并发的操作 3.广播:Android的广播是系统级的,只要传递的Action一样,就可以接收到其他进程广播的消息,广播中可以通过Intent传递数据。 4.scheme协议是android中的一种页面内跳转协议,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面,并且传递数据,还是可以通过H5页面跳转指定页面等。 5.ContentProvider(进程间数据共享)和message一样,底层也是binder,除了oncreate方法其他方法(crud)都是运行在bindler线程里。所以在oncerate里不能做耗时操作。Android本身就提供了不少的ContentProvider访问,比如联系人、相册等。 访问ContentProvider,需要通过Uri,需要以“content://”开头。在其他应用访问通过uri(主机名):

ContentResolverresolver=getActivity().getContentResolver();/**com.mh.getdata/stock这个要和Provider所在进程中添加的Uri一致*/Uriuri=Uri.parse();Cursorcursor=resolver.query(uri,null,null,null,null);

只有允许不同应用的客户端用 IPC 方式访问服务,并且想要在服务中处理多线程(多任务)时,才有必要使用 AIDL。 如果您不需要执行跨越不同应用的并发 IPC,就应该通过实现一个 Binder 创建接口;或者,如果您想执行 IPC,但根本不需要处理多线程,则使用 Messenger 类来实现接口。无论如何,在实现 AIDL 之前,请您务必理解绑定服务。 aidl文档

1.通过 Messenger进行传递(handler),在远程服务里创建handler(接收客户端发送的消息)、 Messenger对像,在onbind里返回( Messenger.getbinder)。在客户端绑定服务,拿着 Messenger对象发消息(可以用bundle)。在远程服务的handlermessage方法就会收到。他是一个个处理的,如果大量并发请求用aidl, Messenger底层就是aidl

在客户端中创建一个Messenger。然后,当客户端收到 onServiceConnected() 回调时,会向服务发送一条 Message,并在其 send() 方法的 replyTo 参数中包含客户端的 Messenger。 注意:Messenger和Message是俩个东西

publicvoidsayHello(Viewv){(!mBound);Messagemsg=Message.obtain(null,MessengerService.MSG_SAY_HELLO,0,0);try{mService.send(msg);}catch(RemoteExceptione){e.printStackTrace();}}

2.直接使用Binder对象:缺点是这种方式不能进行跨进程,跨应用程序的函数调用。只能实现在同一个进程之中,同一个应用程序之中的不同的组件之间通讯。

用法:继承Binder,然后在service里return 继承Binder用它的对象返回,客户端将bind对象强转成自定义Bind

Android interface definition language (android接口定义语言) , 用来跨进程的访问方法。

aidl操作步骤: 1.在两个项目中新建普通文件(new ->General->File),后缀名改成(aidl),客户端和服务端中这个文件所在的包名要保持一致,内容也要一样 编译之后, 会在gen目录下,自动产生同名的,后缀为 Java 的文件。里面有我们要用到的 Stub类。

publicstaticabstractclassStubextendsandroid.os.Binderimplementscom.example.aidl.AidlFunctions

2.在接口文件AIDLFunctions.aidl中,我们定义一个方法 show

interfaceAidlFunctions{voidshow();}

3.AIDL的使用,需要一个Service配合,所以我们在服务端还要声明一个Service

publicclassAIDLServiceextendsService{//stub就是系统自动产生的AidlFunctions.Stubbinder;@Overridepublicvoid(){//TODOAuto-generatedmethodstubsuper.onCreate();}@OverridepublicIBinderonBind(Intentintent){//TODOAuto-generatedmethodstubbinder=newAidlFunctions.(){@Override//这里是我们在接口中声明的方法的实现publicvoidshow()throwsRemoteException{//TODOAuto-generatedmethodstubSystem.out.println();}};binder;}}

4.客户端:

//绑定服务,要用到ServiceConnectionprivateServiceConnectionserviceConnection;//自定义的接口,和服务端一样privateAidlFunctionsaidlFunctions;serviceConnection=new(){@OverridepublicvoidonServiceDisconnected(ComponentNamename){System.out.println();}@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){System.out.println();aidlFunctions=AidlFunctions.Stub.asInterface(service);}};Intentintent=newIntent();bindService(intent,serviceConnection,Context.BIND_AUTO_CREATE);//调用show方法try{aidlFunctions.show();}catch(RemoteExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}

使用多进程显而易见的好处就是分担主进程的内存压力。我们的应用越做越大,内存越来越多,将一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有些应用后台是有多个进程的,启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。还有就是防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。因为它们要常驻后台,特别是即时通讯或者社交应用。


怎么进入android的ddms

运行DDMS DDMS集成在Eclipse中,同时也附带在SDK下的tools目录下。 DDMS既可以在模拟器中工作也可以在已连接的设备上工作。 如果同时连接了设备和运行了模拟器,DDMS默认在模拟器中运行。 从Eclipse打开:点击* Window > Open Perspective > Other... > DDMS* 。 从命令行打开:在tools目录下输入ddms(或./ddms在Mac/Linux)DDMS怎样与调试器交互 在安卓平台上,每个应用都运行在自己的进程上,同时每个应用也都运行在自己的虚拟机(VM)上。 每个VM公布了唯一的端口号以供调试器连接。 当DDMS启动后,会连接到adb。 当有设备连接上,VM监测服务就在adb和DDMS之间创建,它会通知DDMS设备上的VM是启动了还是终止了。 一旦VM是运行的,DDMS就获取VM的进程ID(pid),通过adb和设备上的adb守护进程(adbd)建立到VM调试器的连接。 到此,DDMS就可以使用约定的线协议与VM通信。 DDMS给设备上的每个VM分配一个调试端口。 通常,DDMS分配的第一个可调试端口号是8600,下一个是8601,依次往下类推。 当调试器连接到已分配的一个端口时,VM上的所有通信都会被关联到调试器。 一个调试器只能连接一个单独的端口,但是DDMS同时可以处理多个连接的调试器。 默认的,DDMS也会监听DDMS的“基本端口”(默认为8700)。 基本端口是一个端口转发端口,可以通过8700端口接受来自VM所有调试端口的通信并可以发送信息到调试器。 这就允许你将调试器连接到8700端口,然后可以调试所有设备上的虚拟机。 在DDMS设备视图下,转发的通信可以被当前所选进程终止。 接下来的屏幕截图会在Eclipse中显示标准的DDMS屏幕视图。 如果你是从命令行启动的DDMS,截图会略有不同,但绝大部分功能是相同的。 注意这个特殊进程,它在模拟器上运行时的调试端口是8700,而分配给它的端口是8606。 这就表明DDMS当前将8606端口转发

android中handler和bundle有什么区别和联系 都是用来传递消息吗都是信息的载体吗

1、handler是消息处理者,通常重写Handler的handleMessage()方法,在方法中处理接收到的不同消息,例如:HandlermHandler=newHandler(){@OverridepublicvoidhandleMessage(Messagemsg){switch(){case110:progressValue+=1;pb_(progressValue);Log.d(progressValue-------------->,progressValue+);break;}}}2、Bundle是一个载体,可以存放基本数据类型、对象等内容,好比是一辆货车,可以装各种东西,然后运到需要的地方,例如:BundlemBundle=newBundle();(name,zhaolinit);(number,);(flag,false);//然后,放到Intent对象中IntentmIntent=newIntent();(mBundle);3、关于Handler和Bundle的更多介绍,可以网络:TeachCourse空间,希望可以帮助到你!!!

android两个activity之间怎么传递数据

Activity之间是没有办法直接传递数据的。 Android的设计原则是,用Intent在不同的Activity和进程之间进行通信,但是通常来讲,Intent中只能存入基本数据类型和系统默认支持的比如Uri之类的。 那么对于用户自己定义的数据结构是无法直接用Intent来传送的,如果想要通过Intent来传递自定义数据,可以让数据结构实现Parcelable接口,这样就可以把数据放入Intent。 但是Intent的传送效率也不是很高,特别是当传递一些如Bitmap的大数据,用Intent传递超过500K的Bitmap,就会造成Framework层的Java Binder挂掉,结果就是传递不成功。 这点可以算成是Android的一个弊端,没有很好的解决方案。 能做到的就是尽量设计的时候注意,尽量让Activity之间共享基本数据类型。 Android本身的应用中也深受其害,可以看到有很多应用程序的源代码中的主要的类在三千行以上的不在少数,比如Browser中的BrowserActivity有四千多行;Mms中的ComposeMessageActivity也有四千多行,等等。 为什么一个类会如此之大,就是因为它们是程序的主页面,是业务的核心逻辑所在,里面也控制着很多的其他的数据结构,而又无法与另外的Activity共享,所以就只能在一个Activity里面做所的事情。

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐