服务是Android中实现程序后台运行的解决方案,服务的运行不依赖与任何用户界面,所以它非常适合于去执行那些不需要和用户交互且需要长期运行的任务。但是我们要注意一点,服务不是运行在一个独立的进程中,而是依赖于创建服务的应用程序进程,当某个应用程序被杀死时,依赖此应用程序创建的服务也会停止运行。
一、创建、启动和停止服务
创建服务是通过继承Service类,启动和停止服务是通过Context中提供的方法结合Intent进行操作。
1、创建服务
public class ServiceTest extends Service {
private static final String TAG = "xiaohong";
public ServiceTest() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
//服务第一次被创建的时候调用
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate:");
}
//每次服务启动的时候调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand:");
return super.onStartCommand(intent, flags, startId);
}
//服务停止的时候调用
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
在继承Service类之后,必须重写其中的onBind()方法,同时onCreate()、onStartCommand()、onDe他stroy()方法也是服务中比较常用的几个重写的方法,它们的执行时机在注释中已经写出。
2、启动和停止服务
Intent startServiceIntent = new Intent(MainActivity.this, ServiceTest.class);
//启动服务
startService(startServiceIntent);
Intent stopServiceIntent = new Intent(MainActivity.this, ServiceTest.class);
//停止服务
stopService(stopServiceIntent);
二、活动和服务进行通信
上面一节我们只是在Activity中通过点击按钮来启动或者停止服务,但服务启动后我们并不能控制服务去做一些事,现在就需要用到绑定服务来实现Activity和Service之间的通信,来告诉服务该去做什么。
1、在服务类中创建内部类,并继承自Binder,同时在其中定义需要用到的方法。
/**
* 下载的Binder类
*/
public class DownloadBinder extends Binder{
//模拟开始下载
public void downloadSomething(){
Log.d(TAG, "downSomething:");
}
//模拟下载进度
public int getProgress(){
Log.d(TAG, "getProgress:");
return 0;
}
}
2、在服务类中获得新创建的内部类的实例,并在onBind()方法中返回
private DownloadBinder downloadBinder = new DownloadBinder();
@Override
public IBinder onBind(Intent intent) {
//返回DownloadBinder类的实例
return downloadBinder;
}
3、在Activity中对ServiceConnection类进行重写,并在onServiceConnected()方法中执行具体的操作逻辑。
private ServiceTest.DownloadBinder downloadBinder;
private ServiceConnection connection= new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (ServiceTest.DownloadBinder) service;
downloadBinder.downloadSomething();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
4、绑定和解绑服务
Intent bindServiceIntent = new Intent(MainActivity.this, ServiceTest.class);
//绑定服务(参数依次为绑定的Intent, 服务连接, 此处传入的参数为绑定后自动创建服务)
bindService(bindServiceIntent, connection, BIND_AUTO_CREATE);
//解绑服务
unbindService(connection);
注:任何一个服务在整个应用程序范围内都是通用的,即你创建的服务可以和任何一个Activity绑定,而且在绑定后会获得相同的DownloadBinder实例。
三、服务的生命周期
1、当调用startService()方法时,服务就会被启动并回调onStartCommand()方法,如果服务还没创建,那就会先执行onCreate()方法再执行onStartCommand()方法。
2、每次调用startService()方法,onStartCommand()方法就会被调用,单实际每个服务只有一个实例,所以只需要调用一次的stopService()或stopSelf()方法,服务就会停止。
3、当调用bindService()方法时,服务中的onBind()方法就会被回调。
4、当调用了startService()方法之后再调用stopService()方法或者先调用了bindService()方法之后再调用unbindService()方法之,服务的onDestroy()方法就会被执行。
5、要是我们既调用了startService()方法又调用了bindService()方法,我们必须同时调用stopService()方法和unbindService()方法才能销毁这个服务。
四、使用前台服务
服务一般情况都是在后台默默运行,但由于服务的系统优先级比较低,当出现系统内存不足时,它很容易被回收掉,这时候我们就可以使用前台服务,还有一些应用为了显示的需要,也会使用前台服务,比如有些杀毒软件会在通知栏上一直显示当前手机的状态等。
其实这里的前台服务就是在服务的onCreate()方法中创建一个Notification,唯一不同之处在于最后调用startForeground(1, notofication);来显示通知。
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate:");
Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle("前台服务")
.setContentText("我是前台服务");
Notification notofication = builder.build();
startForeground(1, notofication);
}
注:关于Notification的用法可以看看我的这篇博客Notification的用法
五、使用IntentService
我们都知道服务是在主线程当中运行的,那如果我们直接在服务中执行耗时的操作,那很容易造成ANR,所以我们需要在服务的每个具体的方法中开启一个子线程去执行耗时的逻辑,然后执行完毕之后会关闭服务。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand:");
new Thread(new Runnable() {
@Override
public void run() {
//执行耗时逻辑
//执行完毕自动关闭服务
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
Android为我们提供了一种异步的、会自动停止的服务IntentService,我们可以通过继承它来实现我们的服务。
public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
public MyIntentService() {
//调用父类的有参构造方法,传入类名
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//在此方法中处理一些具体的逻辑
//打印当前线程id
Log.d(TAG, "onHandleIntent: " + Thread.currentThread().getId());
}
@Override
public void onDestroy() {
//服务结束后会自动停止
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
}
以上就是Android中Service的简单介绍。