編輯:關於Android編程
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使用
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; @Override public 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的Intent final Intent intent = new Intent(); //為Intent設置Action屬性 intent.setAction(com.boby.service.FIRST_SERVICE); start.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { //啟動指定Serivce startService(intent); } }); stop.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { //停止指定Serivce stopService(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連接成功時回調該方法 @Override public void onServiceConnected(ComponentName name , IBinder service) { System.out.println(--Service Connected--); // 獲取Service的onBind方法所返回的MyBinder對象 binder = (BindService.MyBinder) service; } // 當該Activity與Service斷開連接時回調該方法 @Override public void onServiceDisconnected(ComponentName name) { System.out.println(--Service Disconnected--); } }; @Override public 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的Intent final Intent intent = new Intent(); //為Intent設置Action屬性 intent.setAction(com.boby.service.BIND_SERVICE); bind.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { //綁定指定Serivce bindService(intent , conn , Service.BIND_AUTO_CREATE); } }); unbind.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { //解除綁定Serivce unbindService(conn); } }); getServiceStatus.setOnClickListener(new OnClickListener() { @Override public 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 { @Override public String getColor() throws RemoteException { return color; } @Override public double getWeight() throws RemoteException { return weight; } } @Override public void onCreate() { super.onCreate(); catBinder = new CatBinder(); timer.schedule(new TimerTask() { @Override public void run() { // 隨機地改變Service組件內color、weight屬性的值。 int rand = (int)(Math.random() * 3); color = colors[rand]; weight = weights[rand]; System.out.println(-------- + rand); } } , 0 , 800); } @Override public IBinder onBind(Intent arg0) { /* 返回catBinder對象 * 在綁定本地Service的情況下,該catBinder對象會直接 * 傳給客戶端的ServiceConnection對象 * 的onServiceConnected方法的第二個參數; * 在綁定遠程Service的情況下,只將catBinder對象的代理 * 傳給客戶端的ServiceConnection對象 * 的onServiceConnected方法的第二個參數; */ return catBinder; } @Override public 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() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 獲取遠程Service的onBind方法返回的對象的代理 catService = ICat.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { catService = null; } }; @Override public 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); // 創建所需綁定服務的Intent Intent intent = new Intent(); intent.setAction(com.boby.aidl.action.AIDL_SERVICE); // 綁定遠程服務 bindService(intent, conn, Service.BIND_AUTO_CREATE); get.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { try { // 獲取、並顯示遠程Service的狀態 color.setText(catService.getColor()); weight.setText(catService.getWeight() + ); } catch (RemoteException e) { e.printStackTrace(); } } }); } @Override public void onDestroy() { super.onDestroy(); // 解除綁定 this.unbindService(conn); } }
電話管理器
電話管理TelephonyManager是一個管理手機通信狀態、電話網絡信息的服務類,該類提供了大量的getXxx()方法來獲取電話網絡的相關信息。
在程序中獲取TelephonyManager,只需調用如下代碼即可:
例:監聽手機來電:
MonitorPhone.java
public class MonitorPhone extends Activity { TelephonyManager tManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 取得TelephonyManager對象 tManager = (TelephonyManager) getSystemService (Context.TELEPHONY_SERVICE); // 創建一個通話狀態監聽器 PhoneStateListener listener = new PhoneStateListener() { @Override public 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; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 獲取SmsManager sManager = 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() { @Override public 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(); } }); } }
Hi,大家好,今天給大家分享一下Android中onInterceptTouchEvent與onTouchEvent,,記得樓主以前剛開始找工作的時候,被人問了關於And
Android LaunchMode詳解越是做的時間越長,基礎知識就忘的越干淨,最近做一個項目中,發現啟動的幾個Activity居然重疊了,我ri~~,再不回憶一下就要退
下面是效果展示:復制代碼 代碼如下:<?xml version=1.0 encoding=utf-8?><LinearLayout xmlns:andr
效果圖思路:就是先設置Gridlayout的行列數,然後往裡面放置一定數目的自定義日歷按鈕控件,最後實現日歷邏輯就可以了。步驟:第一步:自定義日歷控件(初步)第二步:實現