Service(服務)是一個沒有用戶界面的在後臺運行執行耗時操作的應用組件。其他應用組件能夠啓動Service,並且當用戶切換到另外的應用場景,Service將持續在後臺運行。另外,一個組件能夠綁定到一個service與之交互(IPC機制)。首先明確一點,儘管Service是進行後臺計算的,但它仍然是運行在主線程中,處理耗時造作仍然需要在子線程處理。
Service的分類,根據調用者和service在不在同一個進程裏,Service可以分爲:本地服務(LocalService)、遠程服務(RemoteService)。
它的作用:1.耗時操作的執行:ANR對Activity和BroadcastReceiver響應時間的限制(Activity對事件響應不超過5秒,BroadcastReceiver執行不超過10秒),使得在其中都不適合執行較耗時操作,這樣像網絡、數據庫、複雜計算這類耗時操作的執行就需要一個組件來承擔。Service作爲Android四大組件之一,其功能之一就是耗時操作的執行另外相對於Thread的耗時操作。
2.Service的可控性。任何 Activity 都可以控制同一 Service,而系統也只會創建一個對應 Service 的實例。Service可以在任何有 Context 的地方調用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,來控制它,你也可以在 Service 裏註冊 BroadcastReceiver,在其他地方通過發送 broadcast 來控制它,而新產生的Thread在銷燬了它的Activity仍然可以運行,但已經沒有辦法對這可Thread操控。。
3.應用內或應用間數據通信(IPC通信):Android每個應用程序都在自己的dalvik虛擬機中運行,一個應用是不允許訪問其他應用的內存信息的,爲此Android引入了Content Provider在不同應用間共享數據,BroadcastReceiver廣播信息給不同應用程序,但Content Provider更多用於數據的共享,BroadcastReceiver廣播的信息會被所有應用接收較耗費系統資源,對於兩個應用間動態的進行交互還需要通過Service來完成。
本地服務(LocalService)
調用者和service在同一個進程裏,所以運行在主進程的main線程中。所以不能進行耗時操作,可以採用在service裏面創建一個Thread來執行任務,service影響的是進程的生命週期。Service有兩種啓動狀態,Service這兩種狀態可以共存。
第一種是直接start方式開啓service,主要用於執行後臺的計算。
使用service的步驟:
1,定義一個類繼承service
2,manifest.xml文件中配置service
3,使用context的startService(Intent)方法啓動service
4,不在使用時,調用stopService(Intent)方法停止服務
使用start方式啓動的生命週期:onCreate() -- > onStartCommand() -- > onDestory()
注意:如果服務已經開啓,不會重複回調onCreate()方法,如果再次調用context.startService()方法,service而是會調用onStart()或者onStartCommand()方法。停止服務需要調用context.stopService()方法,服務停止的時候回調onDestory被銷燬。
特點:一旦服務開啓就跟調用者(開啓者)沒有任何關係了。開啓者退出了,開啓者掛了,服務還在後臺長期的運行,開啓者不能調用服務裏面的方法。
第二種是綁定狀態bind的方式啓動,主要用於和其他組件交互。
使用service的步驟:
1,定義一個類繼承Service
2,在manifest.xml文件中註冊service
3,使用context的bindService(Intent,ServiceConnection,int)方法啓動service
4,不再使用時,調用unbindService(ServiceConnection)方法停止該服務
使用這種start方式啓動的service的生命週期如下:onCreate() -- > onBind() --> onUnbind() -- > onDestory() (注意:綁定服務不會調用onStart()或者onStartCommand()方法)
特點:bind的方式開啓服務,綁定服務,調用者掛了,服務也會跟着掛掉。綁定者可以調用服務裏面的方法。
DEMO:ServiceLifeCycle類中的兩個靜態方法是爲了在驗證啓動模式的,主動關閉當前服務的效果,也可以通過廣播的形式來關閉開啓的服務。
public class ServiceLifeCycle extends Service {
private static ApkActivity m;
private String TAG = "ServiceLifeCycle";
public static void startService(Context context) {
if (null != context) {
m = (ApkActivity) context;
Intent intent = new Intent(context, ServiceLifeCycle.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(intent);
}
}
public static void stopService(Context context) {
if (null != context) {
Intent intent = new Intent(context, ServiceLifeCycle.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.stopService(intent);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate()");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.e(TAG, "onStart(...)");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy()");
if (m != null) {
m.finish();
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind(...)");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind(...)");
return super.onUnbind(intent);
}
public class MyBinder implements IBinder {
@Override
public String getInterfaceDescriptor() throws RemoteException {
return null;
}
@Override
public boolean pingBinder() {
return false;
}
@Override
public boolean isBinderAlive() {
return false;
}
@Override
public IInterface queryLocalInterface(String descriptor) {
return null;
}
@Override
public void dump(FileDescriptor fd, String[] args) throws RemoteException {
}
@Override
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
}
@Override
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
return false;
}
@Override
public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException {
}
@Override
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return false;
}
}
}
public class TestActivity extends Activity {
MyServiceConnection myServiceConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_apk);
initView();
}
private void initView() {
myServiceConnection = new MyServiceConnection();
TextView mStart = (TextView) findViewById(R.id.start_service);
TextView mStop = (TextView) findViewById(R.id.stop_service);
mStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ServiceLifeCycle.startService(ApkActivity.this);
bindService(new Intent(TestActivity.this, ServiceLifeCycle.class), myServiceConnection, BIND_AUTO_CREATE);
}
});
mStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//靜態方法關閉
// ServiceLifeCycle.stopService(ApkActivity.this);
unbindService(myServiceConnection);
}
});
}
private void testStartService() {
Intent mService = new Intent(this, ServiceLifeCycle.class);
startService(mService);
}
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ServiceLifeCycle.MyBinder myBinder = (ServiceLifeCycle.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
xml佈局簡單就不在提供了。
註冊列表:
<service android:name=“.downloadApk.ServiceLifeCycle"/>
startService啓動打印結果:
05-17 04:03:17.216 19745-19745/com.algorithm.algorithm E/ServiceLifeCycle: onCreate()
05-17 04:03:17.216 19745-19745/com.algorithm.algorithm E/ServiceLifeCycle: onStartCommand()
05-17 04:03:17.216 19745-19745/com.algorithm.algorithm E/ServiceLifeCycle: onStart(...)
bindService打印:
05-17 08:25:02.112 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onCreate()
05-17 08:25:02.112 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onBind(…)
點擊unbindService,打印:
05-17 08:26:15.408 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onUnbind(...)
05-17 08:26:15.408 1348-1348/com.algorithm.algorithm E/ServiceLifeCycle: onDestroy()
2.遠程服務
調用者和service不在同一個進程中,service在單獨的進程中的main線程,是一種垮進程通信方式.
綁定遠程服務的步驟:
a.在服務的內部創建一個內部類,提供一個方法,可以間接調用服務的方法
b.把暴露的接口文件的擴展名改爲.aidl文件 去掉訪問修飾符
c.實現服務的onbind方法,繼承Bander和實現aidl定義的接口,提供給外界可調用的方法
d.在activity 中綁定服務。bindService()
e.在服務成功綁定的時候會回調 onServiceConnected方法 傳遞一個 IBinder對象
f. AIDL定義的接口.Stub.asInterface(binder) 調用接口裏面的方法
具體的內容可以參照我之後的文章:android AIDL
========================================