Android之使用AIDL时的跨进程回调—Server回调Client
首先建立在server端建立两个aidl文件
ITaskCallback.aidl 用于存放要回调client端的方法
package com.cmcc.demo.server; interface ITaskCallback { void actionPerformed(int actionId);
}
ITaskBinder.aidl 用于存放供给client端调用的方法
package com.cmcc.demo.server; import com.cmcc.demo.server.ITaskCallback; interface ITaskBinder { boolean isTaskRunning(); void stopRunningTask(); void registerCallback(ITaskCallback cb); void unregisterCallback(ITaskCallback cb);
}
接着建立服务端,要实现回调,需要新建RemoteCallbackList对象(一个存储回调对象的列表),通过类似发送广播的形式来实现回调
MyService.java
package com.cmcc.demo.server; import com.cmcc.demo.server.ITaskBinder;
import com.cmcc.demo.server.ITaskCallback; import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log; public class MyService extends Service { private static final String TAG = "aidltest"; @Override public void onCreate() { printf("service create"); } @Override public void onStart(Intent intent, int startId) { printf("service start id=" + startId); callback(startId); } @Override public IBinder onBind(Intent t) { printf("service on bind"); return mBinder; } @Override public void onDestroy() { printf("service on destroy"); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { printf("service on unbind"); return super.onUnbind(intent); } public void onRebind(Intent intent) { printf("service on rebind"); super.onRebind(intent); } private void printf(String str) { Log.v(TAG, "###################------ " + str + "------"); } void callback(int val) { final int N = mCallbacks.beginBroadcast(); for (int i=0; i<N; i++) { try { mCallbacks.getBroadcastItem(i).actionPerformed(val); } catch (RemoteException e) { // The RemoteCallbackList will take care of removing // the dead object for us. } } mCallbacks.finishBroadcast(); } private final ITaskBinder.Stub mBinder = new ITaskBinder.Stub() { public void stopRunningTask() { } public boolean isTaskRunning() { return false; } public void registerCallback(ITaskCallback cb) { if (cb != null) { mCallbacks.register(cb); } } public void unregisterCallback(ITaskCallback cb) { if(cb != null) { mCallbacks.unregister(cb); } } }; final RemoteCallbackList <ITaskCallback>mCallbacks = new RemoteCallbackList <ITaskCallback>(); }
最后建立客户端,使用aidl,实现回调方法。
MyActivity.java
package com.cmcc.demo; import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; import com.cmcc.demo.server.*; public class MyActivity extends Activity { private static final String TAG = "aidltest"; private Button btnOk; private Button btnCancel; @Override
public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.test_service); btnOk = (Button)findViewById(R.id.btn_ok); btnCancel = (Button)findViewById(R.id.btn_cancel); btnOk.setText("Start Service"); btnCancel.setText("Stop Service"); btnCancel.setEnabled(false); btnOk.setOnClickListener(new OnClickListener() { public void onClick(View v) { onOkClick(); } }); btnCancel.setOnClickListener(new OnClickListener() { public void onClick(View v) { onCancelClick(); } }); } void onOkClick() { printf("send intent to start"); Bundle args = new Bundle(); Intent intent = new Intent("com.cmcc.demo.IMyService"); intent.putExtras(args); startService(intent); //bindService(intent, mConnection, Context.BIND_AUTO_CREATE); btnCancel.setEnabled(true); } void onCancelClick() { printf("send intent to stop"); //unbindService(mConnection); Intent intent = new Intent("com.cmcc.demo.IMyService"); stopService(intent); btnCancel.setEnabled(false); } private void printf(String str) { Log.v(TAG, "###################------ " + str + "------"); } ITaskBinder mService; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = ITaskBinder.Stub.asInterface(service); try { mService.registerCallback(mCallback); } catch (RemoteException e) { } } public void onServiceDisconnected(ComponentName className) { mService = null; } }; private ITaskCallback mCallback = new ITaskCallback.Stub() { public void actionPerformed(int id) { printf("callback id=" + id); } }; }
总结一下aidl的使用
AIDL的创建方法:
AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:
1. 不需要import声明的简单Java编程语言类型(int,boolean等)
2. String, CharSequence不需要特殊声明
3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.
(
(另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持).
下面是AIDL语法:
// 文件名: SomeClass.aidl // 文件可以有注释, 跟java的一样 // 在package以前的注释, 将会被忽略. // 函数和变量以前的注释, 都会被加入到生产java代码中. package com.cmcc.demo;
// import 引入语句 import com.cmcc.demo.ITaskCallback;
interface ITaskBinder {
//函数跟java一样, 可以有0到多个参数 ,可以有一个返回值 boolean isTaskRunning();
void stopRunningTask(); //参数可以是另外的一个aidl定义的接口 void registerCallback(ITaskCallback cb);
void unregisterCallback(ITaskCallback cb);
//参数可以是String, 可以用in表入输入类型, out表示输出类型.
int getCustomerList(in String branch, out String customerList);
}
实现接口时有几个原则:
.抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的.
.IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。 也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理.
.不能在AIDL接口中声明静态属性。
IPC的调用步骤:
1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。
2. 实现ServiceConnection。
3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.
4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用 YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。
5. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。
6. 断开连接,调用接口实例中的ApplicationContext.unbindService()
Android之使用AIDL时的跨进程回调—Server回调Client相关推荐
- Android笔记 使用AIDL和远程服务实现进程通信
简介 AIDL(Android Interface Definition Language:接口定义语言) 在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实 ...
- AIDL Service,跨进程调用Services
一.AIDL Service简介 Android系统中,各个应用都运行在自己的进程中,进程之间一般无法直接进行通信,为了实现进程通信,Android提供了AIDL Service: 二.与本地Serv ...
- Android Activity的隐式调用(跨进程)★
1.activity启动方式 Android启动Activity有两种方式:显式调用和隐式调用.显式调用需要明确地指定被启动对象的组件信息,包括包名和类名:隐式调用则不需要明确指定组件信息.原则上一个 ...
- Android 跨进程通信: AIDL
概念 在Android上一个进程通常是无法访问另一个进程的内存,而AIDL翻译过来就是Android 接口定义语言,你可以你利用它定义客户端和服务端进程间通信相互认可的编程接口. 适用范围 只有允许不 ...
- android studio 跨进程,Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用...
本文首发于微信公众号「后厂技术官」 在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messeng ...
- 【朝花夕拾】Android跨进程通信总结篇
前言 原文:https://www.cnblogs.com/andy-songwei/p/10256379.html 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一. ...
- 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇
前言 转载请声明,转自[https://www.cnblogs.com/andy-songwei/p/10256379.html],谢谢! 只要是面试高级工程师岗位,Android跨进程通信就是最受面 ...
- 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇...
前言 原文:https://www.cnblogs.com/andy-songwei/p/10256379.html 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一. ...
- IPCInvoker,Android跨进程调用如此简单
一个APP为什么需要多条进程? 如果一条进程能够拥有足够多的资源,且不会被系统kill掉的话,让程序运行在一条进程上是最好的选择.但是系统资源是按进程来分配的,每条进程资源分配是有个上限的,而且当我们 ...
最新文章
- LINUX下忘记MySQL的ROOT密码后修改,以及添加访问IP。
- 聚焦上海:千锤百炼出神器,高可用架构实战案例
- SimpleDateFormat 按照不同要求去改写时间的格式,或者把时间串变成date类型
- 你最擅长哪种数学思维?
- 作者:兰艳艳,女,中国科学院计算技术研究所副研究员、硕士生导师。
- 告别3D Touch 2019款iPhone手机或将拿掉屏幕压感功能
- 在Java下连接SQLite数据库
- docker-compose nginx + ssl配置
- python123高次方程求根_GitHub - loveunk/math-advanced-algebra-notes: 根据丘维声的《高等代数》整理...
- 微信小程序人脸识别获取照片,并解决相机拍照在ios上有声音问题
- 轻松搞懂【TF-IDF、word2vec、svm、cnn、textcnn、bilstm、cnn+bilstm、bilstm+attention实现】英文长文本分类
- idea git Untracked Files Prevent Pull
- 排列组合公式及排列组合算法
- php文本框代码_php怎么用代码给文本框输入值
- Php 类似coffeescript,有什么东西像CoffeeScript for PHP吗?
- K8S(二)安装配置篇
- PDF阅读器开关“手型工具阅读文章”功能
- 十句话,不黄不色,但很经典~~~~~~~~~~
- Linux学习笔记——1、Basic knowledge
- 小样本学习在滴滴治理和安全场景应用
热门文章
- 中国移动云能力中心 Iaas 产品部软件开发工程师陈焱山:社区始于连接,也成就于连接...
- 如何排查 StackOverflow 异常
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定...
- 基于单TCP连接的高吞吐模型设计
- Blazor 中如何下载文件到浏览器
- EF Core3.0+ 通过拦截器实现读写分离与SQL日志记录
- 浅谈AsyncLocal,我们应该知道的那些事儿
- 递归优化的这三种方式你知道吗?
- ASP.NET Core学习资源汇总
- 使用 docker 编译运行 abp 项目