Service与Activity通信与AIDL

出差深圳一个月,终于回来了,一个月里干了不少,这些天里会慢慢总结一点东西出来,今天说的是关于Service的一点事:通信。通信的做法比较固定,基本上按照模板来写就可以实现。

1、Service与Activity通信

Activity通过startService()方法启动Service之后,Service将独立于Activity运行(虽然仍然是同一个进程),Activity无法指导Service如何运行。当Activity需要根据一些条件决定Service如何运行的时候,就需要有另外的方法了:将Service申明为远程Service。

(1)、声明

将一个服务声明为远程服务只需在manifest文件的声明中加一句process=":remote"。如下所示:

<service
	android:name="com.iflytek.service.PowerService"
	android:process=":remote" >
</service>  

(2)Service端

private MyBinder mBinder= new MyBinder();

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

public MyBinder extends Binder{
	public void doSomething(){
		Log.d("Timothy", "I am doing something!")
	}
}

onBind()方法在创建Service的时候就已经默认创建了,这里只是实现了这个方法。mBinder就像是一座桥梁,连接了Service与Activity,将Service中的接口方法暴露给Activity,让Activity可以通过mBinder去调用这些接口。

(3)Activity端

private MyService.MyBinder myBinder;

private ServiceConnection connection = new ServiceConnection(){
	@Override
	public void onServiceDisconnected(ComponentName name){

	}

	@Override
	public void onServiceConnected(ComponentName name, IBinder service){
		myBinder = (MyService.MyBinder)service;
		myBinder.doSomething();
	}
}

Intent bindIntent = new Intent(this, MyService.class);

bindService(bindIntent, connection, BIND_AUTO_CREATE);

首先是声明一个MyBInder类,让Activity可以使用这座桥梁。然后就是声明一个ServiceConnection对象,绑定的时候如何调用Service的方法。最后就是绑定了。

需要说明一点:bindService()函数的第三个参数说明,当绑定服务的时候,将自动调用Service的onCreate()方法。

当需要多次调用doSomething()方法的时候,如果直接bindService是会报错的。这时候可以在bind之前加上下面这样的一段:

try{
    unbindService(connection);
}catch(Exception e){
    e.printTrace();
}

这样就不会报错了。

2、AIDL

我在开发中遇到的问题是:应用层app需要在一定的条件下调用系统的休眠和关机,而休眠和关机的接口只有系统级应用才能调用,这样就必须在系统层为应用提供能够远程调用的服务了。

上面说的远程服务,实际上依然是在同一个project中,但是我面对的问题很明显,是完全独立的两个应用,怎么样才能在project1的类中引用到project2中的类呢?

Google为此提供了一个叫做AIDL的东西,也就是Android Interface Describe Language。用这个东东作为调用的桥梁。关于AIDL的理论这里不多说,在此只介绍其用法。

(1)Service端

a、首先是修改manifest文件:

<service
    android:name="com.iflytek.service.PowerService"
    android:process=":remote" >
    <intent-filter>
        <action android:name="com.iflytek.vbox.power" />
    </intent-filter>
</service>

这东西看上去很像Broadcast Receiver的声明,猜测其内部实现也应该和广播差不多。

b、新建一个package,在package中新建AIDL文件,声明好Activity与Service通信的方法:

package com.***.aidl;

interface MyService{
	void goToSleep();
	void shutDown();
} 

注意这里不能用public、private修饰。编写好保存之后,将在gen目录下自动生成一个Java文件,这个文件不需要维护。

c、修改PowerService文件,实现上面声明的接口。

public class PowerService extends Service {
	MyService.Stub mBinder;
	PowerManager pm;
	String filePath;
	Handler handler;

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return mBinder;
	}

	@Override
	public void onCreate() {
		super.onCreate();

		mBinder = new Stub() {
			@Override
			public void goToSleep() throws RemoteException {
				Tools.writeLog("PowerService.goToSleep() is called");
				pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
				SleepThread sleepThread = new SleepThread(pm);
				sleepThread.start();
			}

			@Override
			public void shutDown() throws RemoteException {
				ShutDownThread shutDownThread = new ShutDownThread();
				shutDownThread.start();
			}
		};
	}
}

这里就是用mBinder实现了接口。接口中我启动了子线程去做真正的执行工作,这也是比较常见的用法。这里写法比较固定,照抄就好。

(2)Activity端

a、将Service中的AIDL连package一起复制过来,记得,是要连package一起。

b、开始抄吧

private MyService myService;
private static ServiceConnection sleepConnection;
private static ServiceConnection shutdownConnection;

sleepConnection = new ServiceConnection() {
	@Override
	public void onServiceConnected(ComponentName arg0, IBinder arg1) {
		Log.d("Timothy", "sleepConnection connected");
		myService = MyService.Stub.asInterface(arg1);
		try {
			myService.goToSleep();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void onServiceDisconnected(ComponentName arg0) {

	}
};

shutdownConnection = new ServiceConnection() {
	@Override
	public void onServiceConnected(ComponentName arg0, IBinder arg1) {
		Log.d("Timothy", "shutdownConnection");
		myService = MyService.Stub.asInterface(arg1);
		try {
			myService.shutDown();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void onServiceDisconnected(ComponentName arg0) {

	}
};

Intent sleepIntent = new Intent("com.***.***.power");
bindService(sleepIntent, sleepConnection, BIND_AUTO_CREATE);

Intent updateIntent = new Intent("com.***.***.power");
bindService(updateIntent, updateConnection, BIND_AUTO_CREATE);

可以看到,这里和上面的远程服务差的不多,也是在bind的时候调用Service的方法。

仔细看看上面的写法,你就会发现AIDL的精妙之处就在于:1、将远程接口声明在本地,这样就能像本地类一样调用远程方法,符合Java的语法规则。2、使用类似于广播的机制启动远程的服务,并调用其方法。

Service与Activity通信与AIDL,布布扣,bubuko.com

时间: 2024-10-04 17:16:56

Service与Activity通信与AIDL的相关文章

Android开发学习之路-该怎么学Android(Service和Activity通信为例)

在大部分地方,比如书本或者学校和培训机构,教学Android的方式都基本类似,就是告诉先上原理方法,然后对着代码讲一下. 但是,这往往不是一个很好的方法,为什么? ① 学生要掌握这个方法的用途,只能通过记忆而不是理解 ② 当某些原理稍微复杂的时候,通过讲解是不能直接理解的,有时候下课回去了再看也不一定看得明白 ③ 对英语文档不够重视,有问题先百度 本鸟自学Android一年,慢慢也学习到了很多的方法,如果你也是一个入门不久但是觉得很多东西都不明白的新手,希望本文对你有帮助. 我觉得要想学好And

Android自学之路——Service与Activity通信

A)MainActivity 类的代码 1 package com.example.cms.service; 2 3 import android.app.Service; 4 import android.content.ComponentName; 5 import android.content.Intent; 6 import android.content.ServiceConnection; 7 import android.os.IBinder; 8 import android.

activity 与 service 之间的通信

activity和service通信:通过binder 举个我实际项目中的例子:在service中下载更新应用 首先是下载更新apk的service: public class UpdateVersionService extends Service { private final String tag = "young"; private Context context = this; private BaseApplication application; private Down

Android Service与Activity之间通信的几种方式

在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activity中启动后台Service,通过Intent来启动,Intent中我们可以传递数据给Service,而当我们Service执行某些操作之后想要更新UI线程,我们应该怎么做呢?接下来我就介绍两种方式来实现Service与Activity之间的通信问题 通过Binder对象 当Activity通过调

Android中Service与多个Activity通信

由于项目需要,我们有时候需要在service中处理耗时操作,然后将结果发送给activity以更新状态.通常情况下,我们只需要在一个service与一个activity之间通信,通常这种情况下,我们使用最多的是通过回调接口.具体做法是在service中定义一个接口,在activity中实现该接口,并通过bindservice来传入.实现方式很简单,在此不再赘述. 当需要将service中的结果一次发送给多个activity时,我们又该如何实现呢?经过多个项目的积累,总结了三种实现的方式.分别是回

Android Service与Activity之间通信

主要分为: 通过Binder对象 通过broadcast(广播)的形式 Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法: 在Service中新建获取Binder实例: /** * 返回一个Binder对象 */ @Override public IB

Android -- Service绑定解绑和aidl

Service是安卓四大组件之一,先前讲到了Service的生命周期,以及非绑定类型的生命周期的例子,这次来分享一下绑定形式的. 应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder. 绑定是异步的,bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传给b

关于android编程中service和activity的区别

一. 绝大部分情况下,Service的作用是用来"执行"后台的.耗时的.重要的任务,三者缺一不可,而最重要的原因是第三点:要执行重要的任务. 因为当一个进程启动了Service后,进程的优先级变高了,系统除非在非常极端的情况下,不会杀掉该进程,反观Activity,不具备这样的特性. 如果没有满足上面所说的三点,请谨慎使用Service,千万别把使用Service的理由变成:这样可以常驻后台.从资源使用的角度来看,这是非常不可取的. 二. 1.Activity和Service的生命周期

本地/远程Service 和Activity 的交方式(转)

android SDK提供了Service,用于类似*nix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Remote Sercie):用于android系统内部的应用程序之间 前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好. 后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的