写点什么

Android 组件内核之组件间通信方案(四)上篇,文末有彩蛋

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

}//[1]定义中间人对象(IBinder)


public class MyBinder extends Binder{


public void callBanZheng(int money){//调用办证的方法 banZheng(money);}}}


  • 重写 ServiceConnection,onServiceConnected 时调用中间人对象 绑定服务 MainActivity


public class MainActivity extends Activity {


private MyConn conn;private MyBinder myBinder;//我定义的中间人对象 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);


Intent intent = new Intent(this,BanZhengService.class);//连接服务 conn = new MyConn();bindService(intent, conn, BIND_AUTO_CREATE);}//点击按钮调用服务里面办证的方法 public void click(View v) {


myBinder.callBanZheng(10000000);}


//监视服务的状态 private class MyConn implements ServiceConnection{


//当服务连接成功调用 @Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//获取中间人对象 myBinder = (MyBinder) service;}//失去连接 @Overridepublic void onServiceDisconnected(ComponentName name) {


}}@Overrideprotected void onDestroy() {//当 activity 销毁的时候 解绑服务 unbindService(conn);super.onDestroy();}}

2.2 第二种方式:通过接口 Iservice 调用 Service 方法

使用借口调用 service 和直接调用其实本质都是一样的,只不过多了借口一个步骤,


即实现步骤


  • 1.继承 Binder 定义中间人对象

  • 2.定义接口


public interface Iservice {


//把领导想暴露的方法都定义在接口里 public void callBanZheng(int money);// public void callPlayMaJiang();


  • 3.重写 ServiceConnection,onServiceConnected 时调用中间人对象,强转为接口(myBinder = (Iservice) service;) 绑定服务


这里就写一下不同的地方,其他都和上面的第一种一样 MainActivity


//监视服务的状态 private class MyConn implements ServiceConnection{//当服务连接成功调用 @Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//获取中间人对象 myBinder = (Iservice) service;}//失去连接 @Overridepublic void onServiceDisconnected(ComponentName name) {


}}@Overrideprotected void onDestroy() {//当 activity 销毁的时候 解绑服务 unbindService(conn);super.onDestroy();}


}

三、 Intent 传递数据大小限制

####3.1 前言


在 sendBroadcast,startActivity 时,我们会用到 Intent。Intent 可以


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


携带一些数据,比如基本类型数据 int、Boolean,或是 String,或是序列化对象,Parcelable 与 Serializable。Intent 传递数据时,如果数据太大,可能会出现异常。比如 App 闪退,或是 Intent 发送不成功,logcat 报错等等。这就牵涉到一个问题:Intent 传递数据大小限制。Intent 到底能够携带多少数据呢?使用 Intent 传送数据时,可能会出现异常在 Intent 中传入一个 Parcelable 对象;例如传入一个 bitmap 对象。


Bitmap b1 = Bitmap.createScaledBitmap(srcBmp, dstWid, dstHeight, false);Intent intent = new Intent(MSG_INTENT);intent.putExtra(K_PIC, b1);


选择 bitmap 的原因是,Bitmap 实现了 Parcelable 接口,并且可以通过 getByteCount()得知所占内存大小。sendBroadcast 时,报出如下信息:


V/ActivityManager: Broadcast: Intent { act=intent_bi flg=0x10 (has extras) } ordered=false userid=0 callerApp=ProcessRecord{27aeaaf5 31217:com.rustfisher.basic4/u0a113}E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!W/BroadcastQueue: Failure sending broadcast Intent { act=intent_bi flg=0x10 (has extras) }android.os.TransactionTooLargeExceptionat android.os.BinderProxy.transactNative(Native Method)at android.os.BinderProxy.transact(Binder.java:504)


atandroid.app.ApplicationThreadProxy.scheduleRegisteredReceiver(ApplicationThreadNative.java:1170) atcom.android.server.am.BroadcastQueue.performReceiveLocked(BroadcastQueue.java:576 atcom.android.server.am.BroadcastQueue.deliverToRegisteredReceiverLocked(BroadcastQueue.java:848) atcom.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:91 atcom.android.server.am.BroadcastQueue$BroadcastHandler.handleMessage(BroadcastQueue.java:254)at android.os.Handler.dispatchMessage(Handler.java:111)at android.os.Looper.loop(Looper.java:194)at android.os.HandlerThread.run(HandlerThread.java:61)at com.android.server.ServiceThread.run(ServiceThread.java:46)


查看异常类 TransactionTooLargeException,它继承了 RemoteException


package android.os; public class TransactionTooLargeException extends RemoteException { public TransactionTooLargeException() {


super();


}


public TransactionTooLargeException(String msg) {


super(msg);


}}


追踪到 Binder,它的 transactNative 方法会报出 RemoteException


public native boolean transactNative(int code, Parcel data, Parcel reply,


int flags) throws RemoteException;


抛出异常与 Binder 有关。


Intent 携带信息的大小受 Binder 限制


Intent 携带信息的大小其实是受 Binder 限制。本文标题也可以改为“Binder 传递数据大小限制”。


数据以 Parcel 对象的形式存放在 Binder 传递缓存中。


如果数据或返回值比传递 buffer 大,则此次传递调用失败并抛出 TransactionTooLargeException 异常。


Binder 传递缓存有一个限定大小,通常是 1Mb。但同一个进程中所有的传输共享缓存空间。

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android组件内核之组件间通信方案(四)上篇,文末有彩蛋