这是milo很早之前写在论坛上的一个帖子,现在整理出来,milo也复习一下
一般来说Android 的四大组件都是运行在同一个进程中的,但远程Service运行在不同的进程里。这进程间的通信是使用了Android Binder机制。Android 中Service 有本地Service和远程Service之分,本地Service用法比较简单,而远程Service用法稍微要复杂一些。下面就是一个使用AIDL的用法。

AIDL即android 接口定义语言,概念不多说,网上有太多的帖子介绍概念。本文只想说明一下aidl的用法。由于最近开发一个播放器的项目使用了aidl。aidl是解决进程间通信用的。在本例中就是Activity(即client端)与Service(即服务端)的通信。
首先,定义Aidl文件,如Service中暴露给Activity的接口可以定义在aidl文件中,反之也一样。本文中,Service给Activity使用接口文件是ServiceAIDL.aidl
<pre lang="LANGUAGE" line="1">
package com.miloisbadboy.aidl;
import com.miloisbadboy.aidl.ActivityAIDL;
/**
* Service中暴露给Activity的接口可以定义在aidl文件中
*/
interface ServiceAIDL{
void callService();
/**
* 在Activity中注册ActivityAIDL到Service中,使Service中可以调用ActivityAIDL中的方法
**/
void registActivityCallBack(ActivityAIDL callBack);
}
</pre>
Activity给Service中使用的ActivityAIDL.aidl
<pre lang="LANGUAGE" line="1">
package com.miloisbadboy.aidl;
/**
* Activity中暴露给Service的接口可以定义在aidl文件中
*/
interface ActivityAIDL{
void callActivity();
}
</pre>
上面两个aidl在会自动在gen目录下生成对应的java文件。
第二步,写Service。写一个MyService继承于Service类,并在onBind()方法中 返回ServiceAidl.Stub对象
具体看下面代码
MyService.java
<pre lang="LANGUAGE" line="1">
package com.miloisbadboy;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.miloisbadboy.aidl.ActivityAIDL;
import com.miloisbadboy.aidl.ServiceAIDL;

/**
* 远程服务
*/
public class MyService extends Service {
public static final String SERVICE_NAME = "com.miloisbadboy.start.MyService";
public static final String TAG = "MyService";

private ActivityAIDL activityAIDL;

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}

private ServiceAIDL.Stub mBinder = new ServiceAIDL.Stub() {

@Override
public void callService() throws RemoteException {
Log.i(TAG, "Activity Call Service's method ****** callService()");
Toast.makeText(getApplicationContext(), "Call Service's method ****** callService()",
1000).show();

activityAIDL.callActivity();
}

@Override
public void registActivityCallBack(ActivityAIDL callBack) throws RemoteException {
activityAIDL = callBack;
}

};
}

</pre>
MyService中有ActiviyAIDL的一个引用,此类型的实例是在ServiceAIDL.Stud这个代理中得到的,即是在registActivityCallBack(ActivityAIDL callBack)方法中对其赋值,这个方法是在Activity中将ActivityAIDL的接口注册到Service中去的。
在ServiceAidl.Stub mBinder = new ServiceAidl.Stub(){}里面的callService() 和registActivityAidl(ActivityAidl activityAidl)方法就是在Activity将会被调用到的。
最后看一个Activity类
<pre lang="LANGUAGE" line="1">
package com.miloisbadboy;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
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 android.widget.Toast;

import com.miloisbadboy.aidl.ActivityAIDL;
import com.miloisbadboy.aidl.ServiceAIDL;
/**
* 测试远程Service
*/
public class TestAIDLActivity extends Activity implements OnClickListener{

private static final String TAG = "TestAIDLActivity";

private Button start;
private Button stop;
private Button callService;
/**
* service call back
*/
private ServiceAIDL serviceAIDL;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

start = (Button)findViewById(R.id.start_service);
stop = (Button)findViewById(R.id.stop_service);
callService = (Button)findViewById(R.id.call_service);

start.setOnClickListener(this);
stop.setOnClickListener(this);
callService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(v == start){
Intent service = new Intent(MyService.SERVICE_NAME);
//绑定Service 并将ServiceConnection的实例传入
bindService(service, serviceConn, Context.BIND_AUTO_CREATE);
stop.setVisibility(View.VISIBLE);
}else if(v == stop){
unbindService(serviceConn);
}else{
try {
if(serviceAIDL!=null){
serviceAIDL.callService();
}else {
Toast.makeText(this, "Service is not started!", 1000).show();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
private ServiceConnection serviceConn = new ServiceConnection() {

@Override
public void onServiceDisconnected(ComponentName name) {
serviceAIDL = null;
Toast.makeText(getApplication(), "Service is unbind!", 1000).show();
}

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
serviceAIDL = ServiceAIDL.Stub.asInterface(service);
//在此将Activity暴露给Service的接口实现注册到Service中去
try {
serviceAIDL.registActivityCallBack(activityAidl);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
/**
* 在activity中实现ActivityAIDL接口
*/
private ActivityAIDL activityAidl = new ActivityAIDL.Stub() {

@Override
public void callActivity() throws RemoteException {
Log.i(TAG, "callActivity()");
Toast.makeText(getApplicationContext(), "service call activity", 1000).show();
}
};
}
</pre>
在activity中有三个按钮分别为 start service ; stop service ;callService
各个按钮的动作顾名思义啦。特别注意到。在Activity ServiceConnection中 会通过ServiceAIDL.Stub.asInterface(service)得到ServiceAIDL的实例,并且将activityAidl的引用注册到了Service中。
在start service 按钮事件里,通过bindService(service, serviceConn, Context.BIND_AUTO_CREATE)将Service 与Activity绑定。

这个程序跑起来的顺序是,启动Activity后,并start service后 点击callServiceBtn,就会调用MyService中实现的callService()接口,而在callService中又调用了activityAidl即Activity的回调callActivity()方法
这样就模拟了 Activity 与Service两个进程间的通信,即相互调用了对方的对象。
本文只是对Aidl的用法做了一个小小总结,算是抛砖引玉吧。

一个简单的demo学习Android远程Service(AIDL的使用)的更多相关文章

  1. 《IT蓝豹》吹雪花demo,学习android传感器

    吹雪花demo,学习android传感器 吹雪花demo,学习android传感器,嘴巴对着手机底部吹一下就会出现飘着雪花效果. 算是学习android传感器效果.本例子主要是通过android.me ...

  2. 【转载】Android Studio Service AIDL 详解

    公司产品之前IM这块存在很多问题,消息到达率低,加上协议上有些问题,丢消息频繁,所以需要重构IM,AIDL不能解决以上问题.好吧!那AIDL可以解决什么问题?什么是AIDL? 什么是AIDL? AID ...

  3. MyBatis 学习记录1 一个简单的demo

    主题 最近(N个月前)clone了mybatis的源码..感觉相比于spring真的非常小...然后看了看代码觉得写得很精简...感觉我的写代码思路和这个框架比较相似(很难具体描述...就是相对来说比 ...

  4. android 远程Service以及AIDL的跨进程通信

    在Android中,Service是运行在主线程中的,如果在Service中处理一些耗时的操作,就会导致程序出现ANR. 但如果将本地的Service转换成一个远程的Service,就不会出现这样的问 ...

  5. Android 中 Service AIDL使用

         1.创建两个项目创建两个.aidl文件 2.在传递值的类里面创建Service并且返回接口: 服务返回值onBind public IBinder onBind(Intent intent) ...

  6. 调用远程service aidl接口定义

    Android studio 查看aidl定义的文件:当你进入你的AIDL文件并编写好了之后,点击AS上方菜单栏中的Build->Make Project,之后便可以在当前工程的app/buil ...

  7. 学习LSM(Linux security module)之二:编写并运行一个简单的demo

    各种折腾,经过了一个蛋疼的周末,终于在Ubuntu14.04上运行了一个基于LSM的简单demo程序. 一:程序编写 先简单的看一下这个demo: //demo_lsm.c#include <l ...

  8. 无废话WCF入门教程六[一个简单的Demo]

    一.前言 前面的几个章节介绍了很多理论基础,如:什么是WCF.WCF中的A.B.C.WCF的传输模式.本文从零开始和大家一起写一个小的WCF应用程序Demo. 大多框架的学习都是从增.删.改.查开始来 ...

  9. [小北De编程手记] Lesson 01 - AutoFramework构建 之 从一个简单的Demo聊起

    写在最前面 这个系列的主旨是要跟大家分享一下关于自动化测试框架的构建的一些心得.这几年,做了一些自动化测试框架以及团队的构建的工作.过程中遇到了很多这样的同学,他们在学习了某一门语言和一些自动化测试的 ...

随机推荐

  1. DAO层,Service层,Controller层、View层

    DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,然后在Spring的配置文件中定义此接口的实现类,然后就可在模块中调用此接口 ...

  2. 关于Unity中的世界坐标和局部坐标

    1.物体的局部坐标的方向(物体自身的方向) transform.forward. transform.right. transform.up 2.物体的世界坐标的方向 Vector3.forward. ...

  3. 【C/C++】计时函数比较

    目前,存在着各种计时函数,一般的处理都是先调用计时函数,记下当前时间tstart,然后处理一段程序,再调用计时函数,记下处理后的时间tend,再tend和tstart做差,就可以得到程序的执行时间,但 ...

  4. tensorflow的升级与版本管理

    1 查看cuda与cudnn的版本 cuda一般安装在 /usr/local/cuda/ 路径下,该路径下有一个version.txt文档,里面记录了cuda的版本信息 cat  /usr/local ...

  5. VIM的自动补全

    自动补全可以很好的提高输入的效率: 触发自动补全的方法总结: 可供弹出式菜单的使用的命令: 其它再补充:

  6. 通过C#脚本实现旋转的立方体

    一.介绍 目的:通过一个简单的例子(鼠标点击,使立方体旋转和变色)熟悉Unity中C#脚本的编写. 软件环境:Unity 2017.3.0f3 . VS2013. 二.C#脚本实现 1,启动Unity ...

  7. core 文件查看

    步骤: (1)无论你是用Makefile来编译,还是直接在命令行手工输入命令来编译,都应该加上 -g 选项. (2)一般来说,在默认情况下,在程序崩溃时,core文件是不生成的(很多Linux发行版在 ...

  8. e821. 设置JScrollPane滚动栏

    A scroll bar in a scroll pane can be set to appear only as needed, always appear, or never appear. B ...

  9. springMVC工程使用jreloader实现热部署

    springMVC工程使用jreloader实现热部署applicationContext - ContextLoaderListener重新加载DispatcherServlet 重新加载提高开发效 ...

  10. Java基础--深克隆补充

    深克隆文章很多,这里推荐Java提高篇--对象克隆(复制). 以上文章条理清晰,一目了然,但最近在项目中碰到的实际问题是,所要克隆的对象是加上子类父类共计207个,无论用上述两种方式的哪一种,都要一一 ...