转载请注明出处: http://blog.csdn.net/a992036795/article/details/51539694
一、先来看如何最简单的创建一个Service
1、新建一个类继承自Service重写其中的几个重要方法
public class SimpleService extends Service{
private static final String TAG = "SimpleService";
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
stopSelf();
}
},2000);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "onStart: ");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
}
}
我在onStartCommand()中简单写了一个延时调用stopSelf()的方法,用来销毁services。以便测试他的onDestory()方法的执行。
记得要在清单文件中添加:
<service android:name=".SimpleService" />
最后我们在一个Activity中添加代码,使用startService()方法来启动Service
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
starService();
}
private void starService() {
Intent intent = new Intent();
intent.setComponent(new ComponentName(MainActivity.this,SimpleService.class)) ;
startService(intent);
}
最后log显示:
I/SimpleService: onCreate:
I/SimpleService: onStartCommand:
I/SimpleService: onStart:
多次点击将显示:
I/SimpleService:onStartCommand:
I/SimpleService: onStart:
I/SimpleService:onStartCommand:
I/SimpleService: onStart:
I/SimpleService:onStartCommand:
I/SimpleService: onStart:
I/SimpleService:onStartCommand:
I/SimpleService: onStart:
I/SimpleService:onStartCommand:
I/SimpleService: onStart:
但最终只会执行一次onDestory().
这是我们就知道,多次调用startService()会执行多次onStartCommand()和onStart(),但实际上每个服务只会存在一个实例。
二、IntentService
它继承自Service重写了Service的OnCrate()、onStart()以及onStartCommand()方法,内部有着一个线程、以及与该线程绑定的一个looper和Hanlder()。每当使用startService()启动该Service,该Services就会回调该service的onStart()方法。最终会执行一次 void onHandleIntent(Intent intent)方法,onHandleIntent是个抽象方法需要我们重写。
这里贴出IntentServie的主要方法:
OnCrate() :创建一个线程并启动该线程,说明一下HandlerThread继承自Thread,它在执行之后会地调用Loop.paper()和Loope.loop()使自己处于死循环。
这里除了启动线程,还获得了该线程对应的looper以及handler
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
onStartCommand()、和onStart()方法:
onStartCommand()调用onStart(),最后使用onCreate()中创建的handle来发送一个消息。
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
Handle:
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
最终会执行一个抽象方法,然后结束自己。
该抽象方法:
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
所以使用IntentService很简单
public class SimpleIntentService extends IntentService{
private static final String TAG = "SimpleIntentService";
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public SimpleIntentService(String name) {
super(name);
}
/**
* 这里执行任务,执行完成只够改Service会自动销毁
* @param intent
*/
@Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG, "onHandleIntent: ");
}
}
使用startService()来启动该Service。
三、使用bindService启动一个service
示例:
public class SimpleBindService extends Service {
private static final String TAG = "SimpleBindService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return new Binder();
}
}
在onBinder()方法中需返回一个Binder对象,传给调用程序。
在来看调用端的程序:
private ServiceConnection conn =new ServiceConnection() {
private static final String TAG = "MainActivity";
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// service 为 Service的onBind()方法返回的Ibinder对象。
Log.i(TAG, "onServiceConnected: MainActivity ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected: MainActivity ");
}
} ;
private void bindService() {
Intent intent =new Intent(MainActivity.this,SimpleBindService.class);
bindService(intent,conn,BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
使用bindService来启动service。第一绑定会执行Service的onBind()方法,该方法返回个binder会通过ServiceConnnection的onServiceConnected(ComponentName name, IBinder service)方法返回给调用程序。调用程序可使用这个binder对象来与Service通信。
四、启动一个前台的service.
启动将service默认是运行在后台的,因此它的优先级比价低,当启动出现内存不足的情况时,它有可能会被回收掉。如果希望Service可以一直保持运行状态,而不会因为系统内存不足被杀死。可以将service运行在前台。调用它的startForegroud()方法。
示例:
package com.simple.test03;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
/**
* Created by blueberry on 2016/5/30.
*/
public class SimpleService extends Service{
private static final String TAG = "SimpleService";
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("content") ;
//被点击时触发的Intent
Intent intent1 = new Intent(this,SecondActivity.class);
//创建任务栈build
TaskStackBuilder stackBuilder =TaskStackBuilder.create(this);
stackBuilder.addParentStack(SecondActivity.class);
stackBuilder.addNextIntent(intent1);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = builder.build();
mNotifyMgr.notify(123,notification);
startForeground(123,notification);
builder.build();
return START_STICKY;
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG, "onStart: ");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
// startService(new Intent(this,SimpleService.class));
Log.i(TAG, "onDestroy: ");
}
}
这样Service就运行在了前台。
最后在说明一下TaskStackBuilder 这个类,使用stackBuilder.addParentStack(SecondActivity.class);
和在SecondActivity在Manifest文件中的设置
<activity android:name=".SecondActivity"
android:parentActivityName=".MainActivity"
></activity>
,会有一种效果就是:
比如我有个应用我启动service之后会出现通知,然后我退出应用。这时点击通知会进入SecondActivity,然后我返回会启动MainActivity页面,而不是直接退出回到桌面。