Android Service实现双向通信(一)
首先,大概来总结一下与Service的通信方式有很多种:
- 通过
BroadCastReceiver:这种方式是最简单的,只能用来交换简单的数据; - 通过
Messager:这种方式是通过一个传递一个Messager给对方,通过这个它来发送Message对象。这种方式只能单向传递数据。可以是Service到Activity,也可以是从Activity发送数据给Service。一个Messeger不能同时双向发送; - 通过Binder来实现远程调用(IPC):这种方式是Android的最大特色之一,让你调用远程
Service的接口,就像调用本地对象一样,实现非常灵活,写起来也相对复杂。
本文最重点谈一下怎么使用AIDL实现Service端和Client端的双向通信(或者叫"调用")。
首先定义一个AIDL接口如下:
// IRemoteService.aidl
package com.race604.servicelib;
interface IRemoteService {
int someOperate(int a, int b);
}
这里只定义了一个简单的接口someOperate(),输入参数a和b,返回一个int值。
Service的实现如下:
// RemoteService.java
package com.race604.remoteservice;
import ...
public class RemoteService extends Service {
private static final String TAG = RemoteService.class.getSimpleName();
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
@Override
public int someOperate(int a, int b) throws RemoteException {
Log.d(TAG, "called RemoteService someOperate()");
return a + b;
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder; // 注意这里返回binder
}
}
这里,在RemoteService里面实现一个IRemoteService.Stub接口的Binder,并且在onBind()中返回此Binder对象。 在AndroidManifest.xml对RemoteService的申明如下:
<service
android:name=".RemoteService"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="com.race604.servicelib.IRemoteService" />
</intent-filter>
</service>
这里android:exported="true"表示可以让其他进程绑定,这里还有一个<action android:name="com.race604.servicelib.IRemoteService" />,这里是为了让后面的Client通过此Action来绑定。
Client的调用方法如下:
package com.race604.client;
import ...
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
private IRemoteService mService;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_SHORT).show();
mService = IRemoteService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(MainActivity.this, "Service disconnected", Toast.LENGTH_SHORT).show();
mService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.bind).setOnClickListener(this);
findViewById(R.id.unbind).setOnClickListener(this);
findViewById(R.id.call).setOnClickListener(this);
}
private void callRemote() {
if (mService != null) {
try {
int result = mService.someOperate(1, 2);
Toast.makeText(this, "Remote call return: " + result, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
Toast.makeText(this, "Remote call error!", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "Service is not available yet!", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bind:
Intent intent = new Intent(IRemoteService.class.getName());
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
break;
case R.id.unbind:
unbindService(mServiceConnection);
break;
case R.id.call:
callRemote();
break;
}
}
}
在客户端,使用Context.bindService()函数,绑定到远程的Service。注意到这里的Intent intent = new Intent(IRemoteService.class.getName());,和上面的Service申明的Action一致。BIND_AUTO_CREATE这个Flag从名字就能看出,表示如果Bind的时候,如果还没有Service的实例,就自动创建。
这里有一个地方需要注意,在Android 5.0以后,就不允许使用非特定的Intent来绑定Service了,需要使用如下方法:
Intent intent = new Intent(IRemoteService.class.getName());
intent.setClassName("com.race604.remoteservice", "com.race604.remoteservice.RemoteService");
// 或者setPackage()
// intent.setPackage("com.race604.remoteservice");
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
到这里就基本实现了一个完整的Client调用远程Service的实例了。
源代码可以参考这个Commit。
Android Service实现双向通信(一)的更多相关文章
- android service两种启动方式
android service的启动方式有以下两种: 1.Context.startService()方式启动,生命周期如下所示,启动时,startService->onCreate()-> ...
- 1、Android Studio集成极光推送(Jpush) 报错 java.lang.UnsatisfiedLinkError: cn.jpush.android.service.PushProtoco
Android studio 集成极光推送(Jpush) (华为手机)报错, E/JPush: [JPushGlobal] Get sdk version fail![获取sdk版本失败!] W/Sy ...
- Android Service完全解析,关于服务你所需知道的一切(下)
转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...
- Android Service完全解析,关于服务你所需知道的一切(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...
- android service 的各种用法(IPC、AIDL)
http://my.oschina.net/mopidick/blog/132325 最近在学android service,感觉终于把service的各种使用场景和用到的技术整理得比较明白了,受益颇 ...
- Android service介绍和启动方式
1.Android service的作用: service通常是用来处理一些耗时操作,或后台执行不提供用户交互界面的操作,例如:下载.播放音乐. 2.Android service的生命周期: ser ...
- Android Service初始
一.Service概念 1.Service是一个应用程序组件 2.Service没有图像化界面 3.Service通常用来处理一些耗时比较长的操作 4.可以使用Service更新ContentProv ...
- Android Service与Thread的区别
Android Service,后台,Android的后台就是指,它的运行是完全不依赖UI的.即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行.比如说一些应用程序 ...
- Android service binder aidl 关系
/********************************************************************************** * Android servic ...
随机推荐
- Java策略模式(Strategy)
一.定义 定义一组算法,将每个算法都封装起来,并且使它们之间可以互换.策略模式使这些算法在客户端调用它们的时候能够互不影响地变化.(Java的TreeSet集合中,构造方法可传入具体的比较器对象以实现 ...
- 通过Proxool配置访问数据库的要点
proxool 配置的时候有Proxool.properties 或者 Proxool.xml 两种方式初始化. 我的配置环境是 myEclipse10+tomcat6.0 + mysql5.0 . ...
- 针对NM_CUSTOMDRAW消息的学习
消息的形式:1 窗口消息,2 命令消息,3 WM_NOTIFY消息,4 自定义消息 我们的NM_CUSTOMDRAW消息就是就属于第三种WM_NOTIFY消息,而添加消息映射的方法分为两种: BEGI ...
- HDU 5402 模拟 构造 Travelling Salesman Problem
题意: 有一个n * m的数字矩阵,每个格子放着一个非负整数,从左上角走到右下角,每个格子最多走一次,问所经过的格子的最大权值之和是多少,并且输出一个路径. 分析: 如果n和m有一个是偶数的话,那么只 ...
- virtual 三种用法
virtual用法一 #include using namespace std;class A{public: virtual void display(){ cout<<& ...
- 主席树 - Luogu 1001 A+B problem
看着大佬们的解法我瑟瑟发抖 我用主席树写一写吧 #include<iostream> #include<iomanip> #include<cmath> #incl ...
- 自己的Qt GUI 项目+vs2013+opencv+caffe环境配置
由于深度学习的种种优势,使我们对于深度学习的使用越来越频繁.很多时候,我们都需要在自己的项目中配置caffe环境,来调用caffe网络模型完成自己的任务.今天我主要讲的关于"在自己的项目中配 ...
- kb-07线段树-03--区间修改查询--lazy思想
/* 区间修改,区间查询和: 第一次使用lazy思想: poj3468 */ #include<iostream> #include<cstdio> #include<c ...
- BZOJ4259 残缺的字符串 【fft】
题目 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺. 你想 ...
- wampSever的mysql操作
单击wampserver图标,选择mysql console 输入密码 123qwe,root用户默认密码为空 mysql客户端管理工具使用wampserver自带的phpmyadmin