一、創建Service
1.創建一個myService類,來繼承Service。重寫其中的方法,包括:onCreate(),onStartCommend(),onDestroy(),onBind()方法是自動重載的。
1.1 onCreate():創建Service的時候調用,只調用一次。
1.2 onStartCommend():執行Service的時候調用,執行幾次,調用幾次。
1.3 onDestroy():在銷燬Service的時候調用,只調用一次。
1.4 onBind():在bindService的時候調用。只調用一次。
1.2 myService代碼如下:
package com.wangpei.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * 作者:WangPei on 2015/7/9 09:48 * 郵箱:[email protected] */ public class myService extends Service { private static final String TAG = "myInfo"; //需要返回Binder實例 private MyBinder myBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { return myBinder; } @Override public void onCreate() { Log.i(TAG,"onCreate is excute"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG,"onStartCommand is excute"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG,"onDestroy is excute"); super.onDestroy(); } class MyBinder extends Binder{ public void startDownload(){ //模擬下載任務 Log.i(TAG,"startDownload is excute"); } } }
二、startService AND stopService
2.1 startService
2.1.1 代碼如下:
1
2
|
Intent
startIntent = new Intent(MainActivity. this ,myService. class ); startService(startIntent); |
2.1.2 調用myService類中的方法順序如下:
onCreate() ---> onStartCommend() ---先創建Service,然後在執行。
2.2 stopService 代碼如下:
2.2.1 代碼如下:
Intent stopIntent = new Intent(MainActivity.this,myService.class); stopService(stopIntent);
2.2.2 調用myService類中的方法順序如下:
onDestroy() --直接被銷燬。
三、bindService AND unBindService
3.1 創建ServiceConnection:
//初始化myService中的binder private myService.MyBinder myBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myBinder = (myService.MyBinder) service; //啓動下載任務 myBinder.startDownload(); } @Override public void onServiceDisconnected(ComponentName name) { } };
3.1.1 onServiceConnected()方法,是在Activity和Service建立連接的時候,進行調用。
3.1.1 onServiceDisconnected()方法,onServiceDisconnected()方法不是解除關聯的時候調用,而是發生異常時調用的。
3.2 bindService 代碼如下:
Intent bindIntent = new Intent(MainActivity.this,myService.class); bindService(bindIntent,connection,BIND_AUTO_CREATE);
3.2.1 BIND_AUTO_CREATE:意思是在綁定Service的時候,進行自動創建。
3.3 unBindService 代碼如下:
unbindService(connection);
3.4 注意 如果同時startService和bindService,必須要stopService和unBindService,才能onDestroy()該Service。
3.5 額外的東西
樓主文中是有說明Service和Activity是如何通信的;首先在自定義的Service類中覆蓋onBind(Intent intent)方法,返回一個Binder子類的對象,在自定義的Binder子類中可以定義一些方法;然後再Activity創建個ServiceConnection對象,並實現其onServiceConnected(ComponentName name, IBinder service) 方法,在這個方法中將傳入的IBinder對象強轉爲在Service中定義的Binder子類,這樣就拿到了Service中的某個對象的引用了,想怎通信都行;但要使onServiceConnected方法被回調,還需要調用bindService方法,把ServiceConnection的對象當作參數傳過去......
四、Service AND Thread 的關係
4.1 Service
4.1.1 Service旨在後臺運行,並且Service也是在主線程中運行的。
4.1.2 Service就不同了,所有的Activity都可以與Service進行關聯,然後可以很方便地操作其中的方法,即使Activity被銷燬了,之後只要重新與Service建立關聯,就又能夠獲取到原有的Service中Binder的實例。
4.1.3 使用Service來處理後臺任務,Activity就可以放心地finish,完全不需要擔心無法對後臺任務進行控制的情況。
4.1.4 我們可以在Service中再創建一個子線程,然後在這裏去處理耗時邏輯就沒問題了。
4.1.5 較爲標準的Service寫法:
private MyBinder myBinder;
@Override
public Binder onBind(Intent intent){
return myBinder;
}
@Override public int onStartCommand(Intent intent, int flags, int startId) { new Thread(new Runnable() { @Override public void run() { // 開始執行後臺任務 } }).start(); return super.onStartCommand(intent, flags, startId); } class MyBinder extends Binder { public void startDownload() { new Thread(new Runnable() { @Override public void run() { // 執行具體的下載任務 } }).start(); } }
4.2 Thread
4.2.1 Thread是在子線程中運行的,旨在不影響主線程的運行。
4.2.2 Activity很難對Thread進行控制,當Activity被銷燬之後,就沒有任何其它的辦法可以再重新獲取到之前創建的子線程的實例;
五、前臺Service
5.1 需要在通知欄顯示,點擊之後,可以跳轉到Activity。優點,可以保持持續的運行。比如說墨跡天氣,它的Service在後臺更新天氣數據的同時,還會在系統狀態欄一直顯示當前天氣的信息。具體實現如下:
public class MyService extends Service { public static final String TAG = "MyService"; private MyBinder mBinder = new MyBinder(); @Override public void onCreate() { super.onCreate(); //先定義通知 Notification notification = new Notification(R.drawable.ic_launcher, "有通知到來", System.currentTimeMillis()); //跳轉意圖 Intent notificationIntent = new Intent(this, MainActivity.class); //將意圖轉換爲等待意圖 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); //初始化通知 notification.setLatestEventInfo(this, "這是通知的標題", "這是通知的內容", pendingIntent); //然後調用startForeground()方法就可以讓MyService變成一個前臺Service,並會將通知的圖片顯示出來。 startForeground(1, notification); Log.d(TAG, "onCreate() executed"); } ......... }
六、遠程Service
6.1 遠程Service介紹:
在註冊service的時候,添加屬性:remote即可激活遠程service。遠程service,是不同有主進程的service。直接可以在內部執行耗時操作,並且不影響主進程的使用。但是,有一個弊端。遠程service沒有辦法和Activity進行綁定。因爲,遠程service是不同於應用程序主進程的進程,他們之間無法建立連接的。
那麼如何,才能使Activity和遠程service建立連接呢?這裏我們需要使用AIDL。接口定義語言來實現跨進程通信技術。
6.2 AIDL(android interface definition language)的使用:
6.2.1 使用方法,先建立一個後綴爲AIDL的文件,這是一個接口文件。然後進行編譯。系統會自動生成一個java文件。然後我們就可以進行使用了。
// IMyAidlInterface.aidl package com.wangpei.service; // Declare any non-default types here with import statements interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ int plus(int a, int b); String toUpperCase(String str); }
6.2.2 然後進行編譯,系統會自動生成一個相應的java文件。此時,我們就可以使用它了。
在MyService中進行使用(對aidl中的方法,進行重寫。):
package com.wangpei.service; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /** * 作者:WangPei on 2015/7/9 09:48 * 郵箱:[email protected] */ public class myService extends Service { private static final String TAG = "myInfo"; private MyBinder myBinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { return mBinder; } IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public int plus(int a, int b) throws RemoteException { return a+b; } @Override public String toUpperCase(String str) throws RemoteException { if(str != null){ return str.toUpperCase(); }else { return null; } } }; @Override public void onCreate() { Log.i(TAG,"onCreate is excute"); // Log.i(TAG,"myService thread is :"+Thread.currentThread().getName()); /** * 前臺Service的使用 */ // Notification notification = new Notification(R.drawable.ic_launcher,"這是通知的內容",System.currentTimeMillis()); // Intent notificationIntent = new Intent(this,MainActivity.class); // PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0); // notification.setLatestEventInfo(this,"這是通知的標題","這是主要內容",pendingIntent); // startForeground(1,notification); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG,"onStartCommand is excute"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG,"onDestroy is excute"); super.onDestroy(); } class MyBinder extends Binder{ public void startDownload(){ Log.i(TAG,"startDownload is excute"); } } }
6.2.3 最後在Activity中進行調用,即可,使用Aidl中,所定義的方法。
private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // myBinder = (myService.MyBinder) service; // myBinder.startDownload(); iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { int result = iMyAidlInterface.plus(9,15); String str = iMyAidlInterface.toUpperCase("wang pei"); Log.i(TAG,result+""); Log.i(TAG,str); } catch (RemoteException e) { e.printStackTrace(); } }