Android筆記----Service組件

來源:互聯網
上載者:User

Android筆記----Service組件

Service簡介

跨進程調用Service(AIDL服務)

電話管理器

簡訊管理器

 

 

 

Service簡介

Service是Android四大組件中與Activity最相似的組件,它們都代表可執行檔程式。Service與Activity的區別在於: Service一直在後台運行,它沒有使用者介面,一旦Service被啟動起來之後,它與Activity一樣,也具有自己的生命週期。

Service組件也是可執行程式,它也有自己的生命週期。建立、配置Service與建立配置Activity的過程基本相似,下面介紹Service的開發過程。

1.1 開發Service

開發Service的步驟如下:

定義一個繼承Service的子類。

在AndroidManifest.xml檔案中配置該Service。

與Activity相似的是, Service中也定義了一系列生命週期的方法,如下所示:

onStartCommand():每當用戶端調用startService(Intent)方法啟動該Service時都會回調該方法。

IBinder onBind(Intent intent):該方法是Service子類必須實現的方法,通過返回的IBinder對象,與其他Service進行通訊。

onCreate():當該Service第一次被建立時回調該方法。

onDestroy():當該Service被關閉之前將會回調該方法。

onUnbind():當Service上綁定的所有用戶端都中斷連線時將會回調該方法。

配置Service使用,也可為元素配置子項目,用於說明該service可被哪些Intent啟動。

Android系統中, Service不能夠自己運行,需要通過一個Activity或者其他Context對象來調用,啟動Service有兩種方法:

通過Context的startService()方法:通過該方法啟動Service,訪問者與Service之間沒有關聯,即使訪問者退出了, Service仍在運行。

通過Context的bindService()方法:通過該方法啟動Service,訪問者與Service綁在了一起,訪問者一旦退出, Service也就終止。

 

例:Service使用:

MainActivity.java

public class MainActivity extends Activity{Button start , stop;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 擷取程式介面中的start、stop兩個按鈕start = (Button) findViewById(R.id.start);stop = (Button) findViewById(R.id.stop);//建立啟動Service的Intentfinal Intent intent = new Intent();//為Intent設定Action屬性intent.setAction(com.boby.service.FIRST_SERVICE);start.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0){//啟動指定SerivcestartService(intent);}});stop.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0){//停止指定SerivcestopService(intent);}});}}

 

在設定檔中配置Service:

 

 

1.2 綁定本地Service並與之通訊

當程式通過startService()和stopService()啟動、關閉Service時,Service與訪問者之間基本上不存在太多關聯,因此Service和訪問者之間也無法進行通訊、資料交換。

如果要Service和訪問者交換資料需要進行方法調用或者資料交換。則應該使用bindService()和unbindService()啟動和關閉服務。

通過Context的bindService(Intent service,ServiceConnection conn, int flags),當訪問者與Service之間串連成功時將回調該ServiceConnection對象的onSerciceConnected(ComponentName name,IBinder service)方法,當訪問者與Service之間中斷連線時將回調ServiceConnection的onSerciceDisconnected(ComponentName name)方法。

當開發Service類時,該Service類必須提供一個IBinder onBind(Intent intent)方法,在綁定本地Service的情況下,onBind(Intent intent)方法返回的IBinder對象將會傳遞給onSerciceConnected(ComponentName name,IBinder service)方法中的service參數,這樣訪問者就可以通過該IBinder對象與Service進行通訊。

 

例:Activity綁定本地Service:

MainActivity.java

public class MainActivity extends Activity{Button bind , unbind , getServiceStatus;// 保持所啟動的Service的IBinder對象BindService.MyBinder binder;// 定義一個ServiceConnection對象private ServiceConnection conn = new ServiceConnection(){// 當該Activity與Service串連成功時回調該方法@Overridepublic void onServiceConnected(ComponentName name, IBinder service){System.out.println(--Service Connected--);// 擷取Service的onBind方法所返回的MyBinder對象binder = (BindService.MyBinder) service;}// 當該Activity與Service中斷連線時回調該方法@Overridepublic void onServiceDisconnected(ComponentName name){System.out.println(--Service Disconnected--);}};@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 擷取程式介面中的start、stop、getServiceStatus按鈕bind = (Button) findViewById(R.id.bind);unbind = (Button) findViewById(R.id.unbind);getServiceStatus = (Button) findViewById(R.id.getServiceStatus);//建立啟動Service的Intentfinal Intent intent = new Intent();//為Intent設定Action屬性intent.setAction(com.boby.service.BIND_SERVICE);bind.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View source){//綁定指定SerivcebindService(intent , conn , Service.BIND_AUTO_CREATE);}});unbind.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View source){//解除綁定SerivceunbindService(conn);}});getServiceStatus.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View source){// 擷取、並顯示Service的count值Toast.makeText(MainActivity.this, Serivce的count值為: + binder.getCount(), 4000).show();}});}}

 

在設定檔中配置Service:

  

 

1.3 Service的生命週期

應用程式中啟動Service的方式不同, Service的生命週期也略有差異。

 

跨進程調用Service(AIDL服務)

2.1 AIDL服務簡介

跨進程訪問(AIDL服務)Android系統中的進程之間不能共用記憶體,因此,需要提供一些機制在不同進程之間進行資料通訊。

為了使其他的應用程式也可以訪問本應用程式提供的服務,Android使用一種介面定義語言(Interface Definition Language,IDL)來公開服務的介面。因此,可以將這種可以跨進程訪問的服務稱為AIDL(Android Interface Definition Language)服務。

Android的遠程Service調用,需要先定義一個遠程調用的介面,然後提供該介面的實作類別。

用戶端訪問本地Service時, Service只是將一個回調對象(IBinder對象)通過onBind()方法返回給用戶端。遠程Service的onBind()方法只是將IBinder對象的代理傳給用戶端的ServiceConnection的onServiceConnected方法的第二個參數。當用戶端擷取了遠程Service的IBinder對象的代理後,就可以通過該IBinder對象去回調遠程Service的屬性或方法了。

 

2.2 建立AIDL服務的步驟
建立AIDL服務要比建立普通的服務複雜一些,具體步驟如下:
(1)在Eclipse Android工程的Java包目錄中建立一個副檔名為aidl的檔案。該檔案的文法類似於Java代碼,但會稍有不同。
(2)如果aidl檔案的內容是正確的,ADT會自動產生一個Java介面檔案(*.java)。
(3)建立一個服務類(Service的子類)。
(4)實現由aidl檔案產生的Java介面。
(5)在AndroidManifest.xml檔案中配置AIDL服務,尤其要注意的是,標籤中android:name的屬性值就是用戶端要引用該服務的ID,也就是Intent類的參數值。

 

2.3 將資料暴露給用戶端

上一步定義好一個AIDL介面之後,接下來定義一個Service的實作類別,該Service的onBind()方法所返回的IBinder對象應該是ADT所產生的ICat.Stub的子類的執行個體。

 

AndroidManifest.xml


 

例:跨進程調用Service:

AidlService.java

public class AidlService extends Service{private CatBinder catBinder;Timer timer = new Timer();String[] colors = new String[]{紅色, 黃色,黑色};double[] weights = new double[]{2.3, 3.1,1.58};private String color;private double weight;// 繼承Stub,也就是實現額ICat介面,並實現了IBinder介面public class CatBinder extends Stub{@Overridepublic String getColor() throws RemoteException{return color;}@Overridepublic double getWeight() throws RemoteException{return weight;}}@Overridepublic void onCreate(){super.onCreate();catBinder = new CatBinder();timer.schedule(new TimerTask(){@Overridepublic void run(){// 隨機地改變Service組件內color、weight屬性的值。int rand = (int)(Math.random() * 3);color = colors[rand];weight = weights[rand];System.out.println(-------- + rand);}} , 0 , 800);}@Overridepublic IBinder onBind(Intent arg0){/* 返回catBinder對象 * 在綁定本地Service的情況下,該catBinder對象會直接 * 傳給用戶端的ServiceConnection對象 * 的onServiceConnected方法的第二個參數; * 在綁定遠程Service的情況下,只將catBinder對象的代理 * 傳給用戶端的ServiceConnection對象 * 的onServiceConnected方法的第二個參數; */return catBinder;}@Overridepublic void onDestroy(){timer.cancel();}}

 

2.4 用戶端訪問AIDLService

AIDL介面定義了兩個進程間的通訊介面,因此用戶端也需要剛才定義的AIDL介面,因此開發用戶端的第一步就是將Service端的AIDL介面檔案複製到用戶端應用中。複製到用戶端後ADT工具會為AIDL介面產生相應的實現。

用戶端綁定遠程Service,需要以下兩步:

建立ServiceConnection對象。

以ServiceConnection對象為參數,調用Context的bindService()方法遠程調用Service。

綁定遠程Service的ServiceConnection並不能直接擷取Service的onBind()方法所返回的對象,只能返回onBind()方法所返回的對象的代理。所以, ServiceConnection的on ServiceConnected方法中需要通過如下代碼處理:

 

AidlClient.java

public class AidlClient extends Activity{private ICat catService;private Button get;EditText color, weight;private ServiceConnection conn = new ServiceConnection(){@Overridepublic void onServiceConnected(ComponentName name, IBinder service){// 擷取遠程Service的onBind方法返回的對象的代理catService = ICat.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name){catService = null;}};@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);get = (Button) findViewById(R.id.get);color = (EditText) findViewById(R.id.color);weight = (EditText) findViewById(R.id.weight);// 建立所需綁定服務的IntentIntent intent = new Intent();intent.setAction(com.boby.aidl.action.AIDL_SERVICE);// 綁定遠程服務bindService(intent, conn, Service.BIND_AUTO_CREATE);get.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0){try{// 擷取、並顯示遠程Service的狀態color.setText(catService.getColor());weight.setText(catService.getWeight() + );}catch (RemoteException e){e.printStackTrace();}}});}@Overridepublic void onDestroy(){super.onDestroy();// 解除綁定this.unbindService(conn);}}

 

電話管理器

電話管理TelephonyManager是一個管理手機通訊狀態、電話網路資訊的服務類,該類提供了大量的getXxx()方法來擷取電話網路的相關資訊。

在程式中擷取TelephonyManager,只需調用如下代碼即可:

 

 

例:監聽手機來電:

MonitorPhone.java

public class MonitorPhone extends Activity{TelephonyManager tManager;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 取得TelephonyManager對象 tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);// 建立一個通話狀態監聽器PhoneStateListener listener = new PhoneStateListener(){@Overridepublic void onCallStateChanged(int state, String incomingNumber){switch (state){// 無任何狀態case TelephonyManager.CALL_STATE_IDLE:break;case TelephonyManager.CALL_STATE_OFFHOOK:break;// 來電鈴響時case TelephonyManager.CALL_STATE_RINGING:OutputStream os = null;try{os = openFileOutput(phoneList, MODE_APPEND);}catch (FileNotFoundException e){e.printStackTrace();}PrintStream ps = new PrintStream(os);// 將來電號碼記錄到檔案中ps.println(new Date() + 來電: + incomingNumber);ps.close();break;default:break;}super.onCallStateChanged(state, incomingNumber);}};//監聽電話通話狀態的改變 tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);}}

註:在DDMS中的File Explorer面板的data/data/com.boby/files目錄下,看到一個phoneList檔案,匯出該檔案,並查看其內容,記錄了來自另一個模擬器的電話呼入。

 

 

簡訊管理器

SmsManager是Android提供的另一個非常常見的服務, SmsManager提供了系統sendXxxMessage()方法用於傳送簡訊。簡訊通常是普通的常值內容,也就是調用sendTextMessage()方法進行發送即可。

例:兩個模擬器互發簡訊:

下面的程式中用到了一個PendingIntent對象,是對Intent的封裝,一般通過調用PendingIntent的getActivity()、getService()、getBroadcastReceiver()靜態方法來擷取PendingIntent對象。

PendingIntent通常會傳給其他應用組件,從而由其他應用程式來執行PendingIntent所封裝的”Intent”。

 

例:

SendSms.java

public class SendSms extends Activity{EditText number , content;Button send;SmsManager sManager;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 擷取SmsManagersManager = SmsManager.getDefault();// 擷取程式介面上的兩個文字框和按鈕number = (EditText) findViewById(R.id.number);content = (EditText) findViewById(R.id.content);send = (Button) findViewById(R.id.send);// 為send按鈕的單擊事件綁定監聽器send.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0){// 建立一個PendingIntent對象PendingIntent pi = PendingIntent.getActivity(SendSms.this, 0, new Intent(), 0);// 傳送簡訊sManager.sendTextMessage(number.getText().toString(), null, content.getText().toString(), pi, null);// 提示簡訊發送完成Toast.makeText(SendSms.this, 簡訊發送完成, 8000).show();}});}}

 



 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.