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() 




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/292763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac上Homebrew的使用 (Homebrew 使 OS X 更完整)

0 Homebrew是啥&#xff1f; “Homebrew installs the stuff you need that Apple didn’t.——Homebrew 使 OS X 更完整”。 Homebrew的官网[1]&#xff08;多语言版本&#xff09;简单明了地介绍了如何安装和使用这个工具&#xff0c;并提供了自己的Wiki。 1 安装Homebrew b…

Java泛型总结

Java泛型总结 Java泛型是JDK5引入的一个新特性&#xff0c;允许在定义类和接口的时候使用类型参数&#xff08;type parameter&#xff09;。声明的类型参数在使用的时候使用具体的类型来替换。泛型最主要的应用是在JDK5中的新集合类框架中。对于泛型概念的引入&#xff0c;开发…

mysql查看日志命令_面对成百上千台服务器产生的日志,试试这款轻量级日志搬运神器!

之前我们搭建的ELK日志收集系统&#xff0c;主要是用来收集SpringBoot应用的日志。其原理是应用通过Logstash插件&#xff0c;使用TCP向Logstash传输日志&#xff0c;从而存储到Elasticsearch中去。但是有很多中间件的日志都是直接存储在文件中的&#xff0c;比如Nginx、Elasti…

单元测试 | 如何Mock IHttpClientFactory

前言编写单元测试时&#xff0c;常常需要使用Mock框架&#xff08;例如Moq&#xff09;生成测试类的依赖接口的"模拟"实现&#xff0c;并验证接口是否按预期使用&#xff1a;_mediatorMock new Mock<IMediator>();_mediatorMock.Setup(x > x.Send(It.IsAny…

跨域资源共享(CORS)--跨域ajax

几年前&#xff0c;网站开发者都因为ajax的同源策略而撞了南墙。当我们惊叹于XMLHttpRequest对象跨浏览器支持所带来的巨大进步时&#xff0c;我们很快发现没有一个方法可以使我们用JavaScript实现请求跨域访 问&#xff0c;对此我们哀叹不已。每个人在他们自己的网站上建立代理…

Wireshark和 TcpDump抓包分析心得

1. Wireshark与tcpdump介绍 Wireshark是一个网络协议检测工具&#xff0c;支持Windows平台和Unix平台&#xff0c;我一般只在Windows平台下使用Wireshark&#xff0c;如果是Linux的话&#xff0c;我直接用tcpdump了&#xff0c;因为我工作环境中的Linux一般只有字符界面&#x…

StringBuffer和StringBuilder使用方法比較

StringBuffer是字符串缓冲区&#xff0c;是一个容器。 特点&#xff1a; 1&#xff0c;长度是可变化的。2&#xff0c;能够字节操作多个数据类型。 3&#xff0c;终于会通过toString方法变成字符串。 C create U update R read D delete1&#xff0c;存储。StringBuffer append…

遇到可爱女生如何搭讪?

1 旺仔落泪▼。。。2 养狗一日&#xff0c;用狗一时&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 试图混进芒果里的鹦鹉&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 把滴滴司机的坐垫沾走了▼5 如何高效记单词&#xff08;素材来源网络&#xf…

Tomcat 上添加虚拟相对路径

为什么80%的码农都做不了架构师&#xff1f;>>> <Context docBase"D:/SHARP" path"/test" reloadable"true" /> 转载于:https://my.oschina.net/zz006/blog/754631

198道K8sDocker面试真题大汇总,全网最全八股!

最近看到两个数据&#xff0c;想跟你们分享一下&#xff1a;一是&#xff0c;目前云原生开发人员已经达680万&#xff08;SlashData数据&#xff09;&#xff1b;二是&#xff0c;云和容器技术首超Linux&#xff0c;成最受青睐技能&#xff08;Linux基金会数据&#xff09;。云…

python ctypes 指针_Python Ctypes传递.h文件中定义的结构指针。

我认为您可能缺少的是确切地知道您希望分配结构内存的位置。下面的c代码提供了一个为struct分配内存并返回指向它的指针的函数&#xff08;new_struct&#xff08;&#xff09;&#xff09;。#include #include #include typedef struct { int a; int b; } my_struct; my_st…

iptables 手册

iptables防火墙可以用于创建过滤(filter)与NAT规则。所有Linux发行版都能使用iptables&#xff0c;因此理解如何配置iptables将会帮助你更有效地管理Linux防火墙。如果你是第一次接触iptables&#xff0c;你会觉得它很复杂&#xff0c;但是一旦你理解iptables的工作原理&#x…

Android之如何看混淆后的错误日志代码

第一步&#xff1a; 找到混淆的mapping.txt文件 build -> outputs -> mapping -> release -> mapping.txt 或者&#xff1a;1项目目录的progurad下有一个mapping.txt文件 这是混淆后的名字 和原名字的映射关系。 第二步: 找到项目用的sdk依次定位到sdk -> to…

inode

硬盘的最小存储单位叫“扇区(sector)”,每个扇区存储512字节(相当于0.5kb).系统读取硬盘时&#xff0c;只会读取多个sector即一个block.block 是文件存取的最小单位block的大小为&#xff14;kb,也就是8*sector1block. inode 是存放文件的元信息&#xff0c;如文件的创建者&…

男朋友的回答可以多敷衍?

1 跟最好的朋友好到什么程度&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼2 不要在妈妈打麻将的时候要生活费&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 现在卖家还要发毒誓了&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 刘德华老师…

Android之android.os.DeadObjectException原因

问题&#xff1a; 今天看到客户的手机出现了 &#xfeff;&#xfeff;andorid.os.DeadObjectException android.os.DeadObjectException 07-13 18:28:45.398: W/System.err(32272): at android.os.BinderProxy.transact(Native Method) 原因&#xff1a; 我们项目有2个进程 …

学习Java,容易被你忽略的小细节(2)

昨天心情真的太糟糕了&#xff0c;写完《学习Java&#xff0c;值得注意你注意的问题&#xff08;1&#xff09;》之后&#xff0c;迎来些许的支持以后就是一片片的谴责。我的主页上涌现出许许多多Java方面的牛人&#xff0c;谴责我水平太低&#xff0c;写的问题太初级。搞得我非…

WPF XAML 为项目设置全局样式

全局资源样式属性App.xaml<Application.Resources><ResourceDictionary><br><ResourceDictionary.MergedDictionaries><ResourceDictionary Source"Dictionary.xaml"/></ResourceDictionary.MergedDictionaries><br><S…

controller是什么意思_SpringMVC是什么??

SpringMVC是什么&#xff1f;一&#xff0c;首先是一个MVC框架。在web模型中&#xff0c;MVC是一种很流行的框架&#xff0c;通过把Model&#xff0c;View&#xff0c;Controller分离&#xff0c;把较为复杂的web应用分成逻辑清晰的几部分&#xff0c;是为了简化开发&#xff0…