Service的知识点
1、Service的基本概念
- Service是android系统中的四大组件之一,它跟Activity的级别差不多,但不能自己运行,只能在后台运行,并且可以和其他组件进行交互,service可以在很多场合的应用中使用
- 比如播放多媒体的时候,用户启动了其他activity,这个时候程序要在后台继续播放。
- 比如检测到SD卡上文件的变化
- 在或者在后台记录你的地理位置的改变。
A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. Each service class must have a corresponding <service> declaration in its package's AndroidManifest.xml. Services can be started with Context.startService() and Context.bindService().
- 一定要在AndroidManifest.xml文件中注册
2、如何实现一个Service
- startService()
- 服务同时只会被创建一次,可以通过外部调用stopService()或者this.stopSelf() //自己停止
- 当执行一个已经启动的服务,会直接调用onStartCommand()方法来执行业务
- bindService()
3、IntentService
- IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动Service的方式一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动的控制,另外,可以启动一个IntentService多次,而每一个耗时的操作会以工作队列的方式在IntentService的onHandlerIntent回调的方法中执行,并且,每次只会执行一个工作线程,执行完第一个在去执行第二个
@Override
protected void onHandleIntent(Intent intent) {
Log.d("MyIntentService", intent.getStringExtra("info"));
for (int i = 0; i < 50; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("MyIntentService", "onHandlerIntent-" + i + "-" + Thread.currentThread().getName());
}
}
4、Bind Service
- 应用程序组件,通过调用bindService()方法能够绑定服务,然后Android系统会调用服务的onBind()回调方法,这个方法会返回一个跟服务端交互的IBinder对象,这个绑定必须是异步的。bindService()方法立即返回,并且不给客户端返回IBinder对象,要接受IBinder对象,客户端必须创建一个ServiceConnection类的实例,并且把这个实例传递给bindService()方法,ServiceConnection对象包含了一个系统调用的传递IBinder对象的回调方法
- 注意:只有Activity、Service、和内容提供器(Content Provider)能偶绑定服务--->对于广播接收者不能绑定服务
- 第一步:创建Service
package com.example.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return new CatImpl();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
- 第二步:创建AIDL(在包名--右键--aidl文件---名字---finish)
// ICat.aidl
package com.example.servicedemo;
// Declare any non-default types here with import statements
interface ICat {
void setName(String name);
String desc();
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
package com.example.servicedemo;
import android.os.RemoteException;
import android.provider.MediaStore;
/**
* Created by 若兰 on 2016/2/13.
* 一个懂得了编程乐趣的小白,希望自己
* 能够在这个道路上走的很远,也希望自己学习到的
* 知识可以帮助更多的人,分享就是学习的一种乐趣
* QQ:1069584784
* csdn:http://blog.csdn.net/wuyinlei
*/
public class CatImpl extends ICat.Stub {
private String name;
@Override
public void setName(String name) throws RemoteException {
this.name = name;
}
@Override
public String desc() throws RemoteException {
return "hello , my name is " + name;
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
}
//解除绑定
private void unBoundClick() {
if (mBound) {
unbindService(conn);
}
}
//绑定一个服务
private void boundClick() {
//异步的操作
bindService(new Intent(this, MyService.class), conn, Context.BIND_AUTO_CREATE);
}
//绑定服务的连接回调接口
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定成功后回调的方法
mICat = ICat.Stub.asInterface(service);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
//服务异常终止的时候调用
mBound = false;
}
};
/**
* 绑定服务
* 通过绑定服务来实现功能的步骤
* 1、客户端通过bindService方法来绑定一个服务对象,会回调用ServiceConnection接口方法onServiceConnected
* 2、通过Service这个组件来暴漏这业务接口
* 3、服务端通过创建一个*。aidl来定义个可以被客户端调用的业务接口
* 一个aidl文件:
* (1)不能有修饰符 类似接口的写法
* (2)支持类型 8中基本数据类型 String CharSequence List<List> Map,自定义类型
* 4、服务端需要提供一个业务接口的实现类 通常继承Stub这个类
* 5、通过Service的onBind方法,返回这个业务接口的实现类(被绑定的业务对象)
* 6、客户端如果绑定成功,就可以调用自己的方法一样调用远程的业务对象
*/
5、Messenger
- 实现IPC通信,底层也是使用了AIDL方式,和AIDL方式不同的是,Messenger方式是利用Handler形式处理,因此,他是线程安全的,这也表示他不支持并发处理,而AIDL方式是非线程安全的,支持并发处理,因此我们使用AIDL方式时候需要保证代码的线程安全
- 大部分情况下,我们应用中不需要处理并发处理,因此我们通常只需要使用Messenger方式
- 思想:
- 在进程A中创建一个Message,将这个Message对象通过Messenger.send(message)方法传递到线程B(当然,Message对象本身是无法被传递到进程B的,send(message))方法会使用一个Parcel对象对Message对象编辑,在将Parcel对象传递到进程B中,然后解编集,得到一个和进程A中Message对象内容一样的对象),在把Message对象加入到进程B的消息队列里面,Handler回去处理它。