Android筆記三十一.Service綜合執行個體(一),android.service
綜合執行個體1:訪問本地Service服務 a)通過Context的startService()方法啟動和停止Service ; b)通過Context的bindService()方法綁定和解除綁定 ; 實現本地Activity擷取service服務,並與之通訊,擷取service相關資料。
1.源碼(1)src/MainActivity.java:應用程式主Acitvity功能:擷取介面組件並為相關組件註冊事件監聽器(內部類形式)、啟動指定Service、與Service通訊開發核心步驟: a)執行個體化兩個Intent對象(Intent service),用於指定啟動本地哪個Service服務; b) 對於非綁定式Service: >調用Context.startService(Intent service)啟動非綁定式Service; >調用Context.stopService(Intent intent)關閉Service; 對於綁定式Service: >調用Context.bindService(Intent service, ServiceConnection conn, int flags) 啟動綁定式Service; >調用unbindService(ServiceConnection conn)解除與Servcie的綁定並關閉Service; >建立一個ServcieConnection對象,用於監聽訪問者與Service之間的串連情況 (1)串連成功:回調該ServiceConnection對象的onServiceConnected(ComponentName name,IBinder service)方法 (2)串連失敗:回調其onServiceDisconnected(ComponentName name)方法 其中,onServiceConnected方法用於擷取Service的onBind()方法返回的IBinder對象,通過該對象我們可以實現與Service的通訊。
<span style="font-family:Times New Roman;font-size:18px;">package com.example.servicetest1;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.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;public class MainActivity extends Activity { private Button startService; private Button stopService; private Button bindService; private Button unbindService; private Button getData; private MyBindService.MyIBinder binder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //a.擷取介面組件 startService = (Button)findViewById(R.id.start); stopService = (Button)findViewById(R.id.stop); bindService = (Button)findViewById(R.id.bind); unbindService = (Button)findViewById(R.id.unbind); getData = (Button)findViewById(R.id.get); //b.為組件註冊同一個監聽器 MyEvent Listener = new MyEvent(); //執行個體化一個事件監聽器 startService.setOnClickListener(Listener);//為組件註冊監聽器對象 stopService.setOnClickListener(Listener); bindService.setOnClickListener(Listener); unbindService.setOnClickListener(Listener); getData.setOnClickListener(Listener); } /*1.事件處理內部類 * 通過擷取視圖組件(v)並判定組件ID,來響應具體組件*/ public class MyEvent implements OnClickListener { //a.設定啟動指定Service的"意圖" Intent intent1 = new Intent("com.jiangdongguo.MyService"); Intent intent2 = new Intent("com.jiangdongguo.MyBindService"); //b.啟動指定的service public void onClick(View v) { switch (v.getId()) { //(1)啟動普通Service case R.id.start: startService(intent1);//啟動"intent"指定的Service服務 break; //(2)關閉普通Service case R.id.stop: stopService(intent1);//關閉"intent"指定的Service服務 break; //(3)啟動並綁定Service case R.id.bind: bindService(intent2, conn, Service.BIND_AUTO_CREATE); break; //(4)解除與Service綁定 case R.id.unbind: unbindService(conn); break; //(5)從service服務擷取資料 case R.id.get: Toast.makeText(MainActivity.this,"從Service讀取到的資料為:count="+Integer.toString(binder.getCount()), Toast.LENGTH_SHORT).show(); break; default: break; } } } /*2.ServcieConnection匿名內部類:建立一個ServcieConnection對象 * 該內部類的對象用於監聽訪問者與Service之間的串連情況 * (1)串連成功:回調該ServiceConnection對象的onServiceConnected(ComponentName name,IBinder service)方法 * (2)串連失敗:回調其onServiceDisconnected(ComponentName name)方法*/ private ServiceConnection conn = new ServiceConnection() { //a.串連服務成功:該方法用於擷取Service返回的IBinder對象,用於與Service進行通訊 public void onServiceConnected(ComponentName name, IBinder service) { System.out.println("---MainActivity's onServiceConnected invoked!---"); binder = (MyBindService.MyIBinder)service;//擷取Service返回的IBinder對象 } //b.串連服務失敗:提示失敗 public void onServiceDisconnected(ComponentName name) { System.out.println("---MainActivity's onServiceDisconnected invoked!---"); Toast.makeText(MainActivity.this, "與Service綁定失敗,請重試。", Toast.LENGTH_SHORT).show(); } };}</span>
(2)src/MyService.java:非綁定式Service服務功能:繼承Service的子類,實現當訪問者調用相關的Context.Xxxx()方法回調的相關方法開發核心步驟: a)重寫Context.startService(Intent service)啟動Service回調的方法 >onCreate():完成初始化或相關商務邏輯代碼 >onStartCommand(Intent intent, int flags, int startId):完成相關商務邏輯代碼 b)重寫Context.stopService(Intent intent)關閉Service回調的方法 >onDestory():關閉Service服務注意:onBind方法為抽象方法,在代碼中必須實現。但由於訪問者與Service服務無綁定關係,不能通訊,因此無需具體實現該方法,只需返回null即可。
<span style="font-family:Times New Roman;font-size:18px;">package com.example.servicetest1;import android.app.Service;import android.content.Intent;import android.os.IBinder;public class MyService extends Service { /*1.onBind方法 * service用於返回一個IBinder對象給用戶端方便通訊 * 如果是訪問者通過Context.startService啟動該Service,則返回為空白 */ @Override public IBinder onBind(Intent arg0) { System.out.println("---MyService’s onBind invoked!---"); return null; } /*2.onCreate方法 * 當Service啟動後,自動調用該方法,用於初始化 * */ public void onCreate() { System.out.println("---MyService’s onCreate invoked!---"); super.onCreate(); } /*3.onStartCommand方法 * 每次訪問者調用startService方法啟動該Service時都會回調該方法*/ public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("---MyService’s onStartCommand invoked!---"); return super.onStartCommand(intent, flags, startId); } /*4.onDestroy方法 * 當訪問者調用Context.stopService方法後,調用該方法關閉Service服務 * */ public void onDestroy() { System.out.println("---MyService’s onDestory invoked!---"); super.onDestroy(); }}</span>
(3)src/MyBindService.java:綁定式Service服務功能:繼承Service的子類,實現當訪問者調用相關的Context.Xxxx()方法回調的相關方法開發核心步驟: a)重寫Context.bindService(Intent service, ServiceConnection conn, int flags) 啟動Service回調的方法 >onCreate():完成初始化或相關商務邏輯代碼 >IBinder onBind(Intent arg0):用於返回一個IBinder對象給訪問者 b)實現一個內部類,該類繼承於Binder類並提供相關方法,使訪問者通過獲得的IBinder對象 調用該類成員方法,從而實現訪問者與Service服務之間的通訊。 如:public class MyIBinder extends Binder { /*.....成員方法或變數......*/ } c)重寫Context.unbindService( ServiceConnection conn) 關閉Service回調的方法 >onUnbind(Intent intent):解除訪問者與Service服務的綁定 >onDestory():關閉Service服務注意:onBind方法為抽象方法,在代碼中必須實現。將用戶端與Service服務綁定,目的就是為了實現兩者之間的通訊,而他們的通訊媒介就IBinder對象,訪問者可以通過IBinder對象調用Service子類的IBinder內部類中的成員方法,從而實現對Service服務的資料訪問。
<span style="font-family:Times New Roman;font-size:18px;">package com.example.servicetest1;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;public class MyBindService extends Service { private int count=0; private boolean threadFlag=true;//結束線程標誌 MyIBinder bind = new MyIBinder();//執行個體化一個Binder對象,用於被onBind方法返回給訪問者 /*0.Binder子類 * 其對象用於與訪問者通訊,訪問者通過調用IBinder子類中的方法擷取Service中的資料*/ public class MyIBinder extends Binder { //自訂成員方法,用於返回Service中的資料 public int getCount() { return count; } } /*1.onBind方法 * service用於返回一個IBinder對象給用戶端方便通訊 * 如果是訪問者通過Context.startService啟動該Service,則返回為空白 */ @Override public IBinder onBind(Intent arg0) { System.out.println("---MyService’s onBind invoked!---"); return bind; } /*2.onCreate方法 * 當Service啟動後,自動調用該方法,用於初始化 * */ public void onCreate() { System.out.println("---MyService’s onCreate invoked!---"); //建立一個線程,用於按一定時間間隔更新count的值 new Thread(){ public void run() { while(threadFlag)//預設為true { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } count++; } } }.start(); super.onCreate(); } /*3.onStartCommand方法 * 每次訪問者調用startService方法啟動該Service時都會回調該方法*/ public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("---MyService’s onStartCommand invoked!---"); return super.onStartCommand(intent, flags, startId); } /*4.onDestroy方法 * 當訪問者調用Context.stopService方法後,調用該方法關閉Service服務 * */ public void onDestroy() { System.out.println("---MyService’s onDestory invoked!---"); threadFlag=false; super.onDestroy(); } /*5.onUnbind方法 * 當訪問者調調用Context.unBind()方法後,調用該方法與Service解除綁定*/ public boolean onUnbind(Intent intent) { System.out.println("---MyService’s onUnbind invoked!---"); return super.onUnbind(intent); } }</span>注意:在綁定式Service服務中,我們主要是通過線程來處理耗時任務。這裡就牽扯到一個問題,就是當我們退出應用程式後,子線程卻還是在啟動並執行,它並沒有結束,這樣子線程就會成為一個孤兒線程,很容易被系統殺死,從而導致任務失敗。為瞭解決這個問題,我們為子線程設定一個條件標誌threadFlag,當程式調用onDestory結束service服務時,順便將子線程結束。
2.效果示範(1)非綁定式
(2)綁定式(3)介面效果
3.源碼分析(1)非綁定式 每當Service被建立時會回調onCreate()方法,每次Service被啟動時都會回調onStartCommand()方法,多次啟動一個已有的Service組件將不會再回調onCreate()方法,但每次啟動時都會回調onStartCommand()方法。(2)綁定式 綁定服務的執行過程:執行單擊事件方法根據Intent找到相應的Service類,並初始化該類調用Service的onCreate()方法調用該類的onBind()方法調用onServiceConnected()方法。 多次單擊綁定服務按鈕,並不會重複執行Binder 方法。一旦解除綁定,調用onunBind()方法,然後自動銷毀。
注意:a)未啟動Service而直接停止Service不起作用,但未綁定Service而先解除綁定Service則程式出錯,強制退出;b)若該Service處於綁定狀態下,該Service不會被停止即單擊停止按鈕不起作用,當單擊解除綁定Service按鈕時,它會先解除綁定隨後直接銷毀;c)若在解除之前,沒有單擊停止Service,則只解除綁定而不會銷毀。