11.1.什么是服务
- Service是一个可以长期在后台运行, 没有界面的组件.
- 它可以被其他组件绑定, 可以在进程之间通信.
11.2.创建Service
- 定义类继承Service, 实现回调函数.
- 在清单文件中声明
<service>
public class MyService extends Service {
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return null;
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
Service生命周期
11.3.启动服务,停止服务
- 在其他组件中可以调用startService()方法启动一个服务, 可以调用stopService()方法停止一个服务
- 在服务中可以使用stopSelf()方法停止服务
- 如果不传任何参数, 就是立即停止, 无论是否还有其他未执行结束的, 都会立即停止
- 传入startId则是等到所有其他的start()执行结束后再停止服务
public class MainActivity extends Activity {
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, MyService.class);
}
public void start(View v) {
startService(intent); // 启动服务, onStartCommand()
}
public void stop(View v) {
stopService(intent); // 停止服务, onDestroy()
}
}
- 1.点击“启动服务”按钮,执行生命周期:
onCreate()->onStartCommand() - 2.以后再点击“启动服务”按钮,执行
onStartCommand() - 3.点击“停止服务”按钮,执行生命周期:
onDestroy()
示例源码->百度网盘
11.4.耗时操作
- 如果需要在服务中做耗时的操作, 那么也需要开启新的线程.
- 如果希望服务长期运行, 即使在内存不足的时候也不要被杀, 那么可以设置为前台服务. startForeground()
新建一个通知,调用startForeground()将服务设置为前台服务
public class MyService extends Service {
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
Notification n = new Notification(R.drawable.ic_launcher, "MyService", System.currentTimeMillis());
Intent intent = new Intent();
intent.setClassName("net.dxs.service", "net.dxs.service.MainActivity");
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
n.setLatestEventInfo(this, "MyService", "MyService在后台长期运行", pi);
startForeground(Process.myPid(), n);
}
@Override
public int onStartCommand(Intent intent, int flags, final int startId) {
System.out.println("onStartCommand");
new Thread() {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i);
SystemClock.sleep(1000);
}
// stopSelf(); // 无论调用了多少次start(), 都停止服务
stopSelf(startId); // 标记当前的这次start()停止, 等到所有start()都停止的时候, 停止服务
}
}.start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return null;
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
11.5.绑定服务
11.5.1.应用内部绑定
- i.定义接口, 声明要提供的方法
- ii.Service中定义一个类继承Binder(IBinder的子类), 实现自定义接口, 实现业务方法, 在onBind()方法中返回该类对象
- iii.Activity中调用bindService()绑定服务, 传递一个ServiceConnection用来接收onBind()方法返回的IBinder, 强转为接口类型, 即可调用方法
定义一个接口InvokeInterface.java
public interface InvokeInterface {
/**
* 服务要提供的方法事先写在接口中
*/
public void pay();
public void play();
}
定义服务MyService.java
public class MyService extends Service {
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) { // bindService()时会执行
System.out.println("onBind");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
private class MyBinder extends Binder implements InvokeInterface {
public void pay() {
System.out.println("进行网络支付!");
}
public void play() {
System.out.println("进行音乐播放");
}
}
}
Activity中调用服务MainActivity.java
public class MainActivity extends Activity {
private InvokeInterface ii;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ii = (InvokeInterface) service; // 绑定成功的时候执行, IBinder就是onBind()方法返回的对象
}
@Override
public void onServiceDisconnected(ComponentName name) { // 在服务被杀的时候执行(解绑时不会执行)
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new Intent(this, MyService.class), conn, BIND_AUTO_CREATE); // 绑定服务, bindService(), 得到IBinder
}
public void pay(View v) {
ii.pay(); // 通过IBinder, 调用Service中的支付
ii.play();
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn); // 解绑服务, unbindService()
}
}
生命周期:
1,调用服务的MainActivity一启动:
onCreate()->onBind()
2,点击支付按钮:
执行接口中的方法pay()、play()
3,关闭调用服务的MainActivity:
onUnbind()->onDestroy()
示例源码->百度网盘
11.5.2.应用之间绑定
- i.使用AIDL定义接口, 刷新工程, Eclipse会自动生成一个Java接口
- ii.Service中定义一个类继承Stub类, 实现抽象方法
- iii.Activity中收到IBinder之后调用Stub.asInterface()方法把IBinder转为接口类型
定义aidl文件InvokeInterface.aidl
package net.dxs.remoteservice.invokeinterface;
interface InvokeInterface {
/**
* 服务要提供的方法事先写在接口中
*/
void pay();
}
定义服务RemoteService.java
package net.dxs.remoteservice;
import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class RemoteService extends Service {
@Override
public void onCreate() {
System.out.println("Remote onCreate");
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) { // bindService()时会执行
System.out.println("Remote onBind");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("Remote onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
System.out.println("Remote onDestroy");
super.onDestroy();
}
private class MyBinder extends Stub {
public void pay() throws RemoteException {
System.out.println("进行网络支付!");
}
}
}
远程Activity中调用服务,远程MainActivity.java
package net.dxs.remoteactivity;
import net.dxs.remoteservice.invokeinterface.InvokeInterface;
import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
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.view.View;
public class MainActivity extends Activity {
private InvokeInterface ii;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ii = Stub.asInterface(service); // Stub.asInterface() 可以把IBinder转为接口类型
}
@Override
public void onServiceDisconnected(ComponentName name) {// 在服务被杀的时候执行(解绑时不会执行)
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new Intent("dxs.service.REMOTE_SERVICE"), conn, BIND_AUTO_CREATE); // 绑定服务, bindService(), 得到IBinder
}
public void pay(View v) throws RemoteException {
ii.pay(); // 通过IBinder, 调用Service中的支付
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn); // 解绑服务, unbindService()
}
}
11.5.3.aidl中使用自定义类型
- aidl中默认只支持基本数据类型和String以及CharSequences
- 如果需要使用自定义类型, 那么该类需要实现Parcelable, 需要实现writeToParcel()方法, 需要定义CREATOR对象
- 再根据这个类定义一个同名的aidl
- 在aidl接口中使用自定义类型作为参数的时候需要加上in
定义aidl文件InvokeInterface.aidl
package net.dxs.remoteservice.invokeinterface;
import net.dxs.remoteservice.bean.Person;
interface InvokeInterface {
/**
* 服务要提供的方法事先写在接口中
*/
boolean pay(in Person p, int amount);
}
定义服务RemoteService.java
package net.dxs.remoteservice;
import net.dxs.remoteservice.bean.Person;
import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class RemoteService extends Service {
@Override
public void onCreate() {
System.out.println("Remote onCreate");
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) { // bindService()时会执行
System.out.println("Remote onBind");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("Remote onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
System.out.println("Remote onDestroy");
super.onDestroy();
}
private class MyBinder extends Stub {
@Override
public boolean pay(Person p, int amount) throws RemoteException {
System.out.println("向" + p.getName() + "支付" + amount);
return amount < 100;
}
}
}
远程Activity中调用服务,远程MainActivity.java
package net.dxs.remoteactivity;
import net.dxs.remoteservice.bean.Person;
import net.dxs.remoteservice.invokeinterface.InvokeInterface;
import net.dxs.remoteservice.invokeinterface.InvokeInterface.Stub;
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.view.View;
public class MainActivity extends Activity {
private InvokeInterface ii;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ii = Stub.asInterface(service); // Stub.asInterface() 可以把IBinder转为接口类型
}
@Override
public void onServiceDisconnected(ComponentName name) {// 在服务被杀的时候执行(解绑时不会执行)
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new Intent("dxs.service.REMOTE_SERVICE"), conn, BIND_AUTO_CREATE); // 绑定服务, bindService(), 得到IBinder
}
public void pay(View v) throws RemoteException {
System.out.println(ii.pay(new Person(101, "深情小建", 29), 150)); // 通过IBinder, 调用Service中的支付
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn); // 解绑服务, unbindService()
}
}
我们的Person类接口Person.aidl
package net.dxs.remoteservice.bean;
parcelable Person;
我们的Person类Person.java
package net.dxs.remoteservice.bean;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
private Integer id;
private String name;
private Integer age;
public Person() {
super();
}
public Person(Integer id, String name, Integer age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(id);
parcel.writeString(name);
parcel.writeInt(age);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
public Person createFromParcel(Parcel parcel) {
return new Person(parcel.readInt(), parcel.readString(), parcel.readInt());
}
public Person[] newArray(int size) {
return new Person[size];
}
};
}
附:提供给第三方调用的服务,要把aidl接口文件及javabean文件一块提供,且文件的包名要一致。