Android -Services 使用簡介
Android Services 四大組件之一,主要用於後臺長時間運行。沒有界面。這裏講解兩種services的啟動還有AIDL通信方式。
1.startservices
a.建立繼承services的類,復寫方法(本地服務)
public class MyServices extends Service { private static final String TAG="TestTag"; @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stubreturn null; } @Override public void onCreate() { Log.i(TAG, "onCreate"); super.onCreate(); } @Override public void onStart(Intent intent, int startId) { Log.i(TAG, "onStart"); super.onStart(intent, startId); } @Overridepublic void onDestroy() { Log.i(TAG, "onDestroy"); super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } }
b.聲明AndroidManifest
<service android:name=".MyServices"/>
c.啟動關閉
switch(v.getId()){ case R.id.btnStart: startService(intent); break; case R.id.btnStop: stopService(intent); break; }
後記:
服務生命周期:context.startService() ->onCreate()- >onStart()- >onStartCommand()->Service running ->context.stopService() ->onDestroy() ->Service stop
如果Service還沒有運行,則android先調用onCreate()然後調用onStartCommand(),每次調用startService(Intent)的時候,都會調用執行onStartCommand();
如果Service已經運行,則只調用onStartCommand()。
2.bindservices
服務鏈接(ServiceConnection)或直接獲取Service中狀態和數據信息
服務鏈接能夠獲取Service的對象,因此綁定Service的組件可以調用Service中的實現的函數
使用Service的組件通過Context.bindService()建立服務鏈接,通過Context.unbindService()停止服務鏈接
如果在綁定過程中Service沒有啟動,Context.bindService()會自動啟動Service
同一個Service可以綁定多個服務鏈接,這樣可以同時為多個不同的組件提供服務
a.創建BindService繼承Service
public class BindService extends Service { private static final String TAG="BindService"; private BindServiceX myBinderServiceX=new BindServiceX(); public class BindServiceX extends Binder{ public BindService getBindService() { return BindService.this; } } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub Log.i(TAG, "onBind"); return myBinderServiceX; } @Override public void onCreate() { Log.i(TAG, "onCreate"); super.onCreate(); } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.i(TAG, "onDestroy"); super.onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); return super.onStartCommand(intent, flags, startId); } public void ShowLog(){ Log.i(TAG, "BindService=>ShowLog"); } }
b.聲明AndroidManifest
<service android:name=".BindService"/>
c.啟動使用
public void onClick(View v) { Intent intentBind = new Intent(MainActivity.this, BindService.class); switch (v.getId()) { case R.id.btnStartBindService: bindService(intentBind, conn, Context.BIND_AUTO_CREATE); break; case R.id.btnStopBindService: if (isConn) { unbindService(conn); //不可以多次調用 isConn=false; } break; }
後記:
AndroidServiceActivity綁定方法,Context.BIND_AUTO_CREATE表明只要綁定存在,就自動建立Service;同時也告知Android系統,這個Service的重要程度與調用者相同,除非考慮終止調用者,否則不要關閉這個Service。
如果service沒被創建,那麽調用一次onCreate(),然後調用onBind(),多次綁定時,不會多次調用onBind()。
通過unbindService()函數取消綁定Servcie時,onUnbind()函數將被調用,
如果onUnbind()函數的返回true,則表示在調用者綁定新服務時,
onRebind()函數將被調用
取消綁定僅需要使用unbindService()方法,並將ServiceConnnection傳遞給unbindService()方法需註意的是,unbindService()方法成功後,系統並不會調用onServiceDisconnected(),因為onServiceDisconnected()僅在意外斷開綁定時才被調用
3.AIDL IPC通信 services
Android系統中,各個應用都運行在自己的進程中,進程之間一般無法直接進行通信,為了實現進程通信(interprocess communication,簡稱IPC),android提供了AIDL Service;
Android需要AIDL(Android Interface Definition Language)來定義遠程接口,這種接口定義語言並不是一種真正的變成語言,只是定義兩個進程之間的通信接口;
與Java接口相似,但是存在如下幾點差異:
-
AIDL定義接口的源代碼必須以.aidl結尾;
-
AIDL用到的數據類型,除了基本類型、String、List、Map、CharSequence之外,其它類型全部都需要導包,即使它們在同一個包中也需要導包;
AIDL的步驟:
a.創建AIDL文件
package com.example.zcx.servicesdemo; // Declare any non-default types here with import statements //interface ICat { // /** // * Demonstrates some basic types that you can use as parameters // * and return values in AIDL. // */ // void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, // double aDouble, String aString); //} interface ICat { String getColor(); double getWeight(); }
b.服務端編寫
public class AidlService extends Service { String[] colors = new String[] { "紅色", "黃色", "黑色" }; double[] weights = new double[] { 2.3, 3.1, 1.58 }; private String color; private double weight; private CatBinder catBinder; Timer timer = new Timer(); @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會直接傳給客戶端的ServiceConnected對象的ServiceConnected * ()方法的第二個參數;在綁定遠程Service的情況下 * ,只將catBinder對象的代理傳給客戶端的ServiceConnected對象的ServiceConnected()方法的第二個參數 */ return catBinder; } @Override public void onDestroy() { timer.cancel(); } /** * 繼承Stub,也就是實現了ICat接口,並實現了IBinder接口 * * @author pengcx * */ public class CatBinder extends ICat.Stub { @Override public String getColor() throws RemoteException { return color; } @Override public double getWeight() throws RemoteException { return weight; } } }
androidmanifest:
<service android:name=".AidlService" android:process=":remote"> <intent-filter> <action android:name="org.crazyit.aidl.AIDL_SERVICE" /> </intent-filter> </service>
c.客戶端使用
首先需要建立aidl,註意要在相同的包名下,否則報錯: java.lang.SecurityException: Binder invocation to an incorrect interface
// ICat.aidl package com.example.zcx.servicesdemo; // Declare any non-default types here with import statements //interface ICat { // /** // * Demonstrates some basic types that you can use as parameters // * and return values in AIDL. // */ // void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, // double aDouble, String aString); //} interface ICat { String getColor(); double getWeight(); }
編寫客戶端:
public class MainActivity extends AppCompatActivity { private ICat catService; private Button getButton; private EditText colorEditText, weightEditText; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { catService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { // 獲取遠程Service的onBinder方法返回的對象代理 catService = ICat.Stub.asInterface(service); Log.d("zcx","catService"); } }; public static Intent getExplicitIntent(Context context, Intent implicitIntent) { // Retrieve all services that can match the given intent PackageManager pm = context.getPackageManager(); List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); // Make sure only one match was found if (resolveInfo == null || resolveInfo.size() != 1) { return null; } // Get component info and create ComponentName ResolveInfo serviceInfo = resolveInfo.get(0); String packageName = serviceInfo.serviceInfo.packageName; String className = serviceInfo.serviceInfo.name; ComponentName component = new ComponentName(packageName, className); // Create a new intent. Use the old one for extras and such reuse Intent explicitIntent = new Intent(implicitIntent); // Set the component to be explicit explicitIntent.setComponent(component); return explicitIntent; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getButton = (Button) findViewById(R.id.getbutton); colorEditText = (EditText) findViewById(R.id.coloredittext); weightEditText = (EditText) findViewById(R.id.weightedittext); // 創建所需要綁定的Service的Intent Intent intent = new Intent(); intent.setAction("org.crazyit.aidl.AIDL_SERVICE"); //intent.setPackage(getPackageName()); Intent eintent = new Intent(getExplicitIntent(this,intent)); Log.e("zcx","eintent = "+eintent); // 綁定遠程的服務 Log.e("zcx"," "+bindService(eintent, conn, Service.BIND_AUTO_CREATE)); getButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 獲取並顯示遠程service的狀態 try { colorEditText.setText(catService.getColor()); weightEditText.setText(catService.getWeight() + ""); } catch (RemoteException e) { e.printStackTrace(); } } }); } @Override protected void onDestroy() { super.onDestroy(); // 解除綁定 this.unbindService(conn); } }
Android -Services 使用簡介