6 四大组件之Service
6-1?Servie概述
組件篇——Service
定義:
1.后臺運行,不可見,沒有界面
2.優先級高于Activity
Service是Android系統的后臺服務組件,適用于開發無界面、長時間運行的應用功能。
Service特點如下:
沒有用戶界面
不會輕易被Android系統終止
在系統資源恢復后Service也將自動恢復
運行狀態
可用于進程間通信
用途:
播放音樂,記錄地理信息位置的改變,監聽某種動作
注意:
-運行在主線程,不能用它來做耗時的請求或者動作
-可以在服務中開一個線程,在線程中做耗時操作
類型:
本地服務(Local Service):
應用程序內部
start方式:startService stopService stopSelf stopSelfResult
啟動方式使用Service
通過調用Context.startService()啟動Service,通過調用Context.stopService()或Service.stopSefl()停止Service
Bind方式:bindService unbindService
綁定方式使用Service
使用Service的組件通過Context.bindService()建立服務鏈接,通過Context.unbindService()停止服務鏈接
如果在綁定過程中Service沒有啟動,Context.bindService()會自動啟動Service
遠程服務(Remote Service):
Android系統內部的應用程序間之間
定義IBinder接口
生命周期:
通過startService()方法啟動的服務于調用者沒有關系,即使調用者關閉了,服務仍然運行想停止服務要調用Context.stopService(),此時系統會調用onDestory(),使用此方法啟動時,服務首次啟動系統先調用服務的onCreate()-->onStart(),如果服務已經啟動再次調用只會觸發onStart()方法
onCreate():Service的生命周期開始,完成Service的初始化工作;
onStart():活動生命周期開始;
onDestroy():Service的生命周期結束,釋放Service所有占用的資源;
使用bindService()啟動的服務與調用者綁定,只要調用者關閉服務就終止,使用此方法啟動時,服務首次啟動系統先調用服務的onCreate()-->onBind(),如果服務已經啟動再次調用不會再觸發這2個方法,調用者退出時系統會調用服務的onUnbind()-->onDestory(),想主動解除綁定可使用Contex.unbindService(),系統依次調用onUnbind()-->onDestory();
bindService()綁定Servcie, onCreate()和onBindle()將先后被調用。
unbindService()取消綁定Servcie,onUnbind()將被調用,如果onUnbind()返回true,則表示在調用者綁定新服務時,onRebind()函數將被調用
非綁定式的service的生命周期
startService()--->onCreate()--->onStartCommand()--->ServingRunning--->onStop()--->onDestory()服務停止
綁定式的service的生命周期
bindService()--->onCreate()--->onBind()--->用戶與服務綁定?在解綁服務?onUnbind()--->onDestory()服務停止
start方式特點:
-服務跟啟動源沒有任何聯系?
-無法得到服務對象
Bind方式特點:
-通過Ibinder接口實例,返回一個ServerConnnection對象給啟動源
-通過ServiceConnection對象的相關方法可以得到Service對象
?
6-2?Start啟動
start方式的啟動時:
第一次創建Service需要調用onCreate(),而后調用onStartCommand(),不管調用了多少次的onStartCOmmand(),停止的時候只調用一次onDestroy();
StartService
1.?使用方法:
(1)寫一個MyStartService繼承自Service,重寫它的各種方法onCreate()、onStartCommand()、onDestory()
(2)在AndroidManifest.xml中注冊這個Service
(3)在主線程Activity中通過startSerice(intent)方式啟動
(4)通過stopService(intent)方式停止
2.?關于StartService
(1)啟動方式是通過啟動intent方式實現
(2)啟動之后該Service和啟動源沒有關系,即使主線程退出了,service還會繼續運行
由于Service和Activity類似,屬于Android四大組件之一,所以我們需要在AndroidManifest.xml中進行注冊。我們的組件都需要在AndroidManifest.xml中進行注冊。
3.啟動Service
顯式啟動
Intent中指明Service所在的類,并調用startService(Intent)函數啟動Service
final Intent serviceIntent = new Intent(this,RandomService.class);startService(serviceIntent);隱式啟動
需要隱式開啟Service,則可以在注冊Service時,聲明Intent-filter的action屬性
<service android:name=".RandomService" ><intent-filter><action android:name="StartRandomService" /></intent-filter> </service> final Intent serviceIntent = new Intent(); serviceIntent.setAction("edu.hrbeu.RandomService");?
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Start:" /><Buttonandroid:id="@+id/start"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="StartService" /><Buttonandroid:id="@+id/stop"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="StopService" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Bind:" /><Buttonandroid:id="@+id/bind"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="BindService" /><Buttonandroid:id="@+id/play"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="播放" /><Buttonandroid:id="@+id/pause"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="暫停" /><Buttonandroid:id="@+id/next"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="下一首" /><Buttonandroid:id="@+id/pervious"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="上一首" /><Buttonandroid:id="@+id/unbind"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="UnBindService" /></LinearLayout>MainActivity.java
package com.example.test;import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View;public class MainActivity extends Activity {Intent intent1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void doClick(View v) {switch (v.getId()) {case R.id.start:intent1 = new Intent(MainActivity.this, MyStartService.class);startService(intent1);break;case R.id.stop:stopService(intent1);break;}} }MyStartService.java
package com.example.test;import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log;public class MyStartService extends Service {@Overridepublic void onCreate() {// TODO Auto-generated method stubLog.i("info", "Service--onCreate()");super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubLog.i("info", "Service--onStartCommand()");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {// TODO Auto-generated method stubLog.i("info", "Service--onDestroy()");super.onDestroy();}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubLog.i("info", "Service--onBind()");return null;}}AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.test"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="15"android:targetSdkVersion="15" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name=".MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity> <service android:name="com.example.servicedemo.MyStartService"></service></application></manifest>?
6-3?Bind啟動
1.通過綁定服務獲取回傳數據:
通過Ibinder接口實例(繼承的類里面返回一個Ibinder對象的抽象方法),返回一個serviceConnection對象給啟動源,因為Ibinder里面含有我們要的數據,這里可以定義個內部類繼承Binder里面做想返回的參數
?
2.使用onBind()方法的IBinder返回值給啟動源返回信息?但是IBinder不能直接使用?需要通過Ibinder接口實例?返回一個ServiceConnection對象給啟動源,通過ServiceConnection對象的相關方法可以得到Service,MyBinder是繼承自Binder類的,而Binder類實際上實現了IBinder接口。
public class MyBinder extends Binder{public MyBindServic getService(){return MyBindService.this;//返回這個Service的實例} } public IBunder onBind(Intent intent){return new MyBinder(); }?
3.在啟動源定義ServiceConnection?該對象在綁定服務時傳輸到服務端(bindService(intent,conn,Service.BIND_AUTO_CREATE))?綁定后?通過onServiceConnected()?方法獲取service對象
?
4.unbindservice執行后,不能重復調用,會報錯,并且在destroy的時候必須解綁,?stopserveice則不會,
?
5.服務的兩種啟動方式:
1).通過startService(Intent?intent)啟動,stopService(Intent?intent)停止,比較簡單。服務啟動后與啟動源無關,也無返回服務本身。需注意要在配置文件中注冊服務。
2).通過bindService(Intent?intent,ServiceConnection?conn,int?flags)綁定服務啟動,unbindService(ServiceConnection?conn)去綁定停止,該方式可以返回服務本身,與啟動源相關。
?
6.通過bindService綁定服務啟動的具體步驟:
1)Intent?intent?=?new?Intent(上下文,?目標服務名.class);
bindService(intent,?conn,?Service.BIND_AUTO_CREATE);//綁定
2)在自定義的服務類中通過自定義一個內部類:
public?class?MyBinder?extends?Binder?{
public?MyBindService?getService()?{
return?MyBindService.this;//?獲取服務
}
}來返回服務本身
同時在自定義服務類重新父類Service的方法:
public?IBinder?onBind(Intent?intent)?{
//?TODO?Auto-generated?method?stub
return?new?MyBinder();
}
該方法可返回服務本身.
3)在啟動源的Activity中創建一個ServiceConnection實例,初始化ServiceConnection接口,在接口方法中重寫方法
ServiceConnection?conn?=?new?ServiceConnection()?{
//當啟動源跟service的連接意外丟失的時候會調用
//比如service崩潰了,或被強行殺死了
public?void?onServiceDisconnected(ComponentName?name)?{
}
//當啟動源跟service成功連接之后會調用這個方法
public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{
myBindService?=?((MyBinder)service).getService();//大類轉化為自身的小類,獲取內部類中的方法,從而獲得服務本身
}};
4)bindService()中指定ServiceConnection?conn參數
bindService(intent2,?conn,?Service.BIND_AUTO_CREATE);
5)在自定義的繼承于Servic類的類中,添加需要的方法,在啟動Service的Activity中可以直接調用服務中的方法。
通過bindService()啟動的服務是和啟動源(Activity)綁定在一起的,如果Activity退出的時候沒有調用unbindService()進行解綁定(停止),那么程序會報錯。所以我們需要在Activity的onDestroy()方法中調用unbindService()進行解綁定。而且對于已經解綁定的服務再次進行解綁定,那么也會報錯,這點和通過startService啟動的服務不同,stopService()方法可以調用多次。
?
7.StartService和BindService
1).?StartService啟動后啟動源和Service沒有關系,BindService調用bindService()啟動service后啟動源和Service相關,在退出activity之前必須要調用unbindService()取消綁定。
2).?startService()和bindService()可以混合使用。如果我們想要Activity退出了,但是服務還在繼續,那么我們就要選用startService的方式來啟動服務,如果我們想要在Activity中獲取Service對象,那么我們需要用bindService方法結合ServiceConnection來啟動Service,但是這種方法,由于將Service和Activity綁定在了一起,所以當Activity退出的時候,我們需要unbindService()來停掉Service,否則就會報錯。
?
8.BindService
通過bindService()得到的Service是和啟動源(Activity)綁定在一起的,在Activity退出的時候需要調用unbindService()進行解綁定(停止)。
調用bindService()時會調用到目標Service的onBind()函數,通過IBinder接口實例,返回一個ServiceConnection對象給啟動源。然后啟動源可以通過ServiceConnection對象得到啟動的Service對象
MyBindService.java
package com.example.test;import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.util.Log;public class MyBindService extends Service{@Overridepublic void onCreate() {// TODO Auto-generated method stubLog.i("info", "BindService--onCreate()");super.onCreate();}public class MyBinder extends Binder{public MyBindService getService(){return MyBindService.this;}}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubLog.i("info", "BindService--onBind()");return new MyBinder();}@Overridepublic void unbindService(ServiceConnection conn) {// TODO Auto-generated method stubLog.i("info", "BindService--unbindService()");super.unbindService(conn);}@Overridepublic void onDestroy() {// TODO Auto-generated method stubLog.i("info", "BindService--onDestroy()");super.onDestroy();}public void Play(){Log.i("info", "播放");}public void Pause(){Log.i("info", "暫停");}public void Pervious(){Log.i("info", "上一首");}public void next(){Log.i("info", "下一首");} }MainActivity.java
package com.example.test;import com.example.test.MyBindService.MyBinder;import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.Menu; import android.view.View;public class MainActivity extends Activity {Intent intent1;Intent intent2;MyBindService service;ServiceConnection conn = new ServiceConnection() {@Override//當服務跟啟動源斷開的時候 會自動回調public void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stub }@Override//當服務跟啟動源連接的時候 會自動回調public void onServiceConnected(ComponentName name, IBinder binder) {// TODO Auto-generated method stubservice = ((MyBinder)binder).getService();}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void doClick(View v){switch (v.getId()) {case R.id.start:intent1 = new Intent(MainActivity.this, MyStartService.class);startService(intent1);break;case R.id.stop:stopService(intent1);break;case R.id.play:service.Play();break;case R.id.pause:service.Pause();break;case R.id.pervious:service.Pervious();break;case R.id.next:service.next();break;case R.id.bind://綁定Service:
//bindService()方法綁定服務
//Intent對象傳遞給bindService(),聲明需要啟動的Service
//Context.BIND_AUTO_CREATE表明只要綁定存在,就自動建立Service;同時也告知Android系統,這個Service的重要程度與調用者相同 intent2 = new Intent(MainActivity.this, MyBindService.class);startService(intent2);bindService(intent2, conn, Service.BIND_AUTO_CREATE);//綁定了break;case R.id.unbind:unbindService(conn);break;}}@Overrideprotected void onDestroy() {// TODO Auto-generated method stub stopService(intent2);
//解綁Service:
//取消綁定使用unbindService()方法,并將ServiceConnnection對象傳遞給unbindService()方法。
//unbindService()方法調用成功后,系統并不會再次調用onServiceDisconnected()方法
//onServiceDisconnected()方法僅在意外斷開綁定時才被調用。 unbindService(conn);//解綁定super.onDestroy();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu);return true;}}
?
轉載于:https://www.cnblogs.com/crazyzx/articles/5350862.html
總結
以上是生活随笔為你收集整理的6 四大组件之Service的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学Python可以做Web前端开发吗?
- 下一篇: 岁月在变迁,彼此在成长。而我在流浪