以下:内容部分取自菜鸟教程:http://www.runoob.com/w3cnote/android-tutorial-service-1.html),内容仅用于自我记录学习使用。
Service分为两种启动方式,StartService和BindService。
Service本身还是在UI线程中,因此如果需要进行耗时操作仍需要开辟线程。
其生命周期如下图:
onCreate() : 当Service被创建时回调该方法,整个Service声明周期仅调用一次。onDestory()同理.
onStartCommand(intent,flag,startId) : 当客户端调用startService(Intent)方法时会回调,可多次调用StartService方法, 但不会再创建新的Service对象,而是继续复用前面产生的Service对象,但会继续回调 onStartCommand()方法!
IBinder onOnbind(intent):该方法是Service都必须实现的方法,该方法会返回一个 IBinder对象,app通过该对象与Service组件进行通信!
onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!
**StartService 方式启动Service:
启动会创建一个Service实例 --- > onCreate ---- > onStartCommand() ---> stopService() ---> onDestory()。 当再次调用StartService时并不会创建新的Service实例,而是调用原先Service的onStartCommand() 方法。
StartService 启动方式和调用者无关,即使调用者被销毁,只要不调用stopService() 方法就无法停止Service服务。同时不论启动多少次Service,调用一次stopService即可全部停止。
BindService方式启动Service:
- 启动时会创建一个Service实例 —> onCreate —> onBind() 。然后调用者可以通过IBinder和Service进行交互了。当再次使用bindService时,并不会在调用onCreate和onBind。只会直接把IBinder对象传递给其他后来增加的客户端!
- 解除与服务的绑定,只需调用unbindService(),此时onUnbind和onDestory方法将会被调用!这是一个客户端的情况,假如是多个客户端绑定同一个Service的话,情况如下 当一个客户完成和service之间的互动后,它调用 unbindService() 方法来解除绑定。当所有的客户端都和service解除绑定后,系统会销毁service。
- bindService模式下的Service是与调用者相互关联的,可以理解为 “一条绳子上的蚂蚱”,要死一起死,在bindService后,一旦调用者销毁,那么Service也立即终止!
- bindService(Intent Service,ServiceConnection conn,int flags)解析:
service:通过该intent指定要启动的Service
conn :ServiceConnection对象,用户监听访问者与Service间的连接情况, 连接成功回调该对象中的onServiceConnected(ComponentName,IBinder)方法; 如果Service所在的宿主由于异常终止或者其他原因终止,导致Service与访问者间断开 连接时调用onServiceDisconnected(CompanentName)方法,主动通过unBindService() 方法断开并不会调用上述方法!
flags:指定绑定时是否自动创建Service(如果Service还未创建), 参数可以是0(不自动创建),BIND_AUTO_CREATE(自动创建)。
先StartService后BindService启动方式:
如果Service已经由某个客户端通过StartService()启动,接下来由其他客户端 再调用bindService()绑定到该Service后调用unbindService()解除绑定最后在 调用bindService()绑定到Service的话,此时所触发的生命周期方法如下:
onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )
前提是:onUnbind()方法返回true!!! 这里或许部分读者有疑惑了,调用了unbindService后Service不是应该调用 onDistory()方法么!其实这是因为这个Service是由我们的StartService来启动的 ,所以你调用onUnbind()方法取消绑定,Service也是不会终止的!
得出的结论: 假如我们使用bindService来绑定一个启动的Service,注意是已经启动的Service!!! 系统只是将Service的内部IBinder对象传递给Activity,并不会将Service的生命周期 与Activity绑定,因此调用unBindService( )方法取消绑定时,Service也不会被销毁!
以下:
StartService启动方式与Activity实时信息交互:(不推荐启动模式下的交互)
onCreate -->onStartCommand
/**
* start方式启动Service
*/
private void startService(){
Intent intent = new Intent(getApplicationContext(), DownLoadStartService.class);
// 可以通过这种方式给Service传值
Bundle bundle = new Bundle();
bundle.putString("key", "传值内容");
intent.putExtra("bundle", bundle);
startService(intent);
}
public class DownLoadStartService extends Service{
private final static String TAG = DownLoadIntentService.class.getSimpleName();
@Override
public void onCreate() {
Log.e(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
Runnable runnable = new Runnable() {
@Override
public void run() {
// 在这里执行操作
}
};
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override // start 启动方式不调用
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
return null;
}
@Override // stopService时调用
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
}
}
- 广播方式:
package com.example.qxb_810.downloadservicedemo;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;
import com.example.qxb_810.downloadservicedemo.service.DownLoadBindService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadIntentService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadStartService;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
private final static String TAG = MainActivity.class.getSimpleName();
@BindView(R.id.btn_begin)
Button btnBegin;
@BindView(R.id.btn_pause)
Button btnPause;
@BindView(R.id.btn_stop)
Button btnStop;
private int mCurrProgress = 0;
// Broadcast
private LocalBroadcastManager mLocalBroadcastManager;
private DownloadReceiver mReceiver;
private IntentFilter mFilter;
private Intent mIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
regisiterBroadcast();
}
/**
* 注册广播
*/
private void regisiterBroadcast() {
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
mReceiver = new DownloadReceiver();
mFilter = new IntentFilter();
mFilter.addAction(DownloadReceiver.ACTION_REFRESH);
mLocalBroadcastManager.registerReceiver(mReceiver, mFilter);
}
/**
* 取消广播
*/
private void unregisiterBroadcast() {
mLocalBroadcastManager.unregisterReceiver(mReceiver);
}
@OnClick(R.id.btn_begin)
public void beginClick() {
startService();
}
/**
* start方式启动Service
*/
private void startService() {
mIntent = new Intent(getApplicationContext(), DownLoadStartService.class);
// 可以通过这种方式给Service传值
Bundle bundle = new Bundle();
bundle.putString("key", "传值内容");
mIntent.putExtra("bundle", bundle);
startService(mIntent);
}
@OnClick(R.id.btn_pause)
public void pauseClick() {
stopService(mIntent);
}
@OnClick(R.id.btn_stop)
public void stopClick() {
stopService(mIntent);
}
@Override
protected void onDestroy() {
mLocalBroadcastManager.unregisiterBroadcast();
super.onDestroy();
}
/**
* 广播接收者
*/
public class DownloadReceiver extends BroadcastReceiver {
public final static String ACTION_REFRESH = "refresh_progress"; // 更新进度条事件
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_REFRESH)) {
mCurrProgress = intent.getIntExtra("progress", mCurrProgress);
btnBegin.setText("正在下载..." + mCurrProgress + "%");
}
}
}
}
package com.example.qxb_810.downloadservicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.example.qxb_810.downloadservicedemo.MainActivity;
import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;
public class DownLoadStartService extends Service{
private final static String TAG = DownLoadIntentService.class.getSimpleName();
private int mCurrProgress = 0;
private Handler mHandler = new Handler();
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
// 在这里执行操作
// 当连接成功后赋值
if (mCurrProgress >= 100){
mHandler.removeCallbacks(this);
}else {
mCurrProgress += 1;
// 发送广播
Intent intent = new Intent(MainActivity.DownloadReceiver.ACTION_REFRESH);
intent.putExtra("progress", mCurrProgress);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
mHandler.postDelayed(this, 1000);
}
}
};
@Override
public void onCreate() {
Log.e(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
mHandler.postDelayed(mRunnable, 1000);
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override // start 启动方式不调用
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
return null;
}
@Override // stopService时调用
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
}
}
BindService启动方式与Activity实时信息交互:
- 接口回调方式:
package com.example.qxb_810.downloadservicedemo;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import com.example.qxb_810.downloadservicedemo.intfaces.DownLoadInteface;
import com.example.qxb_810.downloadservicedemo.service.DownLoadBindService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadIntentService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadStartService;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity{
private final static String TAG = MainActivity.class.getSimpleName();
@BindView(R.id.btn_begin)
Button btnBegin;
@BindView(R.id.btn_pause)
Button btnPause;
@BindView(R.id.btn_stop)
Button btnStop;
private DownLoadBindService.MyBinder myBinder;
private ServiceConnection mConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mConnection = new ServiceConnection() {
@Override // service连接成功时回调
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "连接成功");
myBinder = (DownLoadBindService.MyBinder)service; // 获取Binder类
myBinder.setDownLoadInteface(new DownLoadInteface() {
@Override
public void setCurrProgress(int progress) {
btnBegin.setText("正在下载..." + progress + "%");
}
});
}
@Override // service连接断开时回调
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "连接断开");
}
};
}
@OnClick(R.id.btn_begin)
public void beginClick() {
bindService();
}
/**
* bind方式启动Service
*/
private void bindService() {
Intent intent = new Intent(getApplicationContext(), DownLoadBindService.class);
// 可以通过这种方式给Service传值
Bundle bundle = new Bundle();
bundle.putString("key", "传值内容");
intent.putExtra("bundle", bundle);
bindService(intent, mConnection, Service.BIND_AUTO_CREATE);
}
/**
* bind方式启动IntentService
*/
private void bindIntentService(){
Intent intent = new Intent(getApplicationContext(), DownLoadIntentService.class);
// 可以通过这种方式给Service传值
Bundle bundle = new Bundle();
bundle.putString("key", "传值内容");
intent.putExtra("bundle", bundle);
bindService(intent, mConnection, Service.BIND_AUTO_CREATE);
}
@OnClick(R.id.btn_pause)
public void pauseClick() {
unbindService(mConnection);
}
@OnClick(R.id.btn_stop)
public void stopClick() {
unbindService(mConnection);
}
}
package com.example.qxb_810.downloadservicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import com.example.qxb_810.downloadservicedemo.intfaces.DownLoadInteface;
public class DownLoadBindService extends Service {
private final static String TAG = DownLoadBindService.class.getSimpleName();
private int mCurrProgress = 0;
private MyBinder myBinder = new MyBinder();
private Handler mHandler = new Handler();
private Runnable mRunable = new Runnable() {
@Override
public void run() {
// 当连接成功后赋值
if (myBinder.getDownLoadInteface() != null) {
mCurrProgress += 1;
myBinder.getDownLoadInteface().setCurrProgress(mCurrProgress); // 通知Activity数据更新
}
if (mCurrProgress >= 100){
mHandler.removeCallbacks(this);
}else {
mHandler.postDelayed(this, 1000);
}
}
};
@Override
public void onCreate() {
super.onCreate();
}
// 自定义Binder类,提供暴露给Activity的方法 --- 这里暴露接口
public class MyBinder extends Binder {
DownLoadInteface downLoadInteface;
public DownLoadInteface getDownLoadInteface() {
return downLoadInteface;
}
public void setDownLoadInteface(DownLoadInteface downLoadInteface) {
this.downLoadInteface = downLoadInteface;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
mHandler.postDelayed(mRunable, 1000);
return myBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind");
mHandler.removeCallbacks(mRunable);
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
}
}
- 广播方式:
package com.example.qxb_810.downloadservicedemo;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;
import com.example.qxb_810.downloadservicedemo.service.DownLoadBindService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadIntentService;
import com.example.qxb_810.downloadservicedemo.service.DownLoadStartService;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity{
private final static String TAG = MainActivity.class.getSimpleName();
@BindView(R.id.btn_begin)
Button btnBegin;
@BindView(R.id.btn_pause)
Button btnPause;
@BindView(R.id.btn_stop)
Button btnStop;
private int mCurrProgress = 0;
// Service
private DownLoadBindService.MyBinder myBinder;
private ServiceConnection mConnection;
// Broadcast
private DownloadReceiver mReceiver;
private IntentFilter mFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
regisiterBroadcast();
mConnection = new ServiceConnection() {
@Override // service连接成功时回调
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "连接成功");
}
@Override // service连接断开时回调
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "连接断开");
}
};
}
/**
* 注册广播
*/
private void regisiterBroadcast(){
mReceiver = new DownloadReceiver();
mFilter = new IntentFilter();
mFilter.addAction(DownloadReceiver.ACTION_REFRESH);
registerReceiver(mReceiver, mFilter);
}
/**
* 取消广播
*/
private void unregisiterBroadcast(){
mLocalBroadcastManager.unregisterReceiver(mReceiver);
}
@Override
protected void onDestroy() {
unregisiterBroadcast();
super.onDestroy();
}
@OnClick(R.id.btn_begin)
public void beginClick() {
bindService();
}
/**
* bind方式启动Service
*/
private void bindService() {
Intent intent = new Intent(getApplicationContext(), DownLoadBindService.class);
// 可以通过这种方式给Service传值
Bundle bundle = new Bundle();
bundle.putString("key", "传值内容");
intent.putExtra("bundle", bundle);
bindService(intent, mConnection, Service.BIND_AUTO_CREATE);
}
@OnClick(R.id.btn_pause)
public void pauseClick() {
unbindService(mConnection);
}
@OnClick(R.id.btn_stop)
public void stopClick() {
unbindService(mConnection);
}
/**
* 广播接收者
*/
public class DownloadReceiver extends BroadcastReceiver {
public final static String ACTION_REFRESH = "refresh_progress"; // 更新进度条事件
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_REFRESH)){
mCurrProgress = intent.getIntExtra("progress", mCurrProgress);
btnBegin.setText("正在下载..." + mCurrProgress + "%");
}
}
}
}
package com.example.qxb_810.downloadservicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import com.example.qxb_810.downloadservicedemo.MainActivity;
import com.example.qxb_810.downloadservicedemo.broadcastreceiver.DownloadReceiver;
import com.example.qxb_810.downloadservicedemo.intfaces.DownLoadInteface;
public class DownLoadBindService extends Service {
private final static String TAG = DownLoadBindService.class.getSimpleName();
private int mCurrProgress = 0;
private MyBinder myBinder = new MyBinder();
private Handler mHandler = new Handler();
private Intent intent = new Intent(DownloadReceiver.ACTION_REFRESH);
private Runnable mRunable = new Runnable() {
@Override
public void run() {
// 当连接成功后赋值
if (mCurrProgress >= 100){
mHandler.removeCallbacks(this);
}else {
mCurrProgress += 1;
// 发送广播
intent.putExtra("progress", mCurrProgress);
sendBroadcast(intent);
mHandler.postDelayed(this, 1000);
}
}
};
@Override
public void onCreate() {
super.onCreate();
}
// 自定义Binder类,提供暴露给Activity的方法
public class MyBinder extends Binder {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
mHandler.postDelayed(mRunable, 1000);
return myBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind");
mHandler.removeCallbacks(mRunable);
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
}
}
注意:
1. IntentService中onHandleIntent方法必须重写,在这个方法里单独开辟了新的线程,可以在里面执行耗时操作。IntentService也是一个Service,可通过start或者bind方式启动,需要注意的是,bind启动方式不会走onHandlerIntent方法,只执行onCreate和onBind方法,BindService启动方式果要实时更新数据需要通过接口回调或者广播方式。IntentService执行完任务后自动销毁。多个任务时将排队进行。
- Service 需要在AndroidManifest.xml注册,如下:
<service
android:name=".service.DownLoadIntentService"
android:exported="false">
<intent-filter>
<action android:name="DownLoadIntentService" />
</intent-filter>
</service>