Android_Service(2)前臺服務(service)和遠程服務(service)

1、前臺服務java

       service基本都是在後臺進行運行的,一直都是在默默地工做,不愛表現本身(沒有界面),但是這樣一個基層的工做人員(service)在Android系統的待遇(優先級)仍是比較差的,在系統內存不足的狀況下,就有可能回收掉正在後臺運行的service,所以service就會中止運行。若是但願service一直保持運行,不因系統內存不足而回收,該怎麼作呢?能夠先考慮使用前臺service,前臺service和普通service的區別在於,前臺service一直有一個正在運行的圖標在系統的狀態欄中顯示。但有一點要注意的是使用前臺service不表明service不能被殺死,在應用程序管理那裏能夠中止前臺service,狀態欄通知被刪除了也能解除service!
       那前臺service有什麼能夠用來幹什麼呢?一般來講,一個音樂的播放器能夠設置前臺service,在狀態欄中能夠顯示播放的歌曲相關的信息並能夠做爲啓動按鈕,打開音樂播放器,並且用戶也是明確知道音樂播放器在運行的。還有天氣相關的app也能夠用前臺service,在狀態欄中實時同步更新的天氣信息。android

       那麼咱們先來看看前臺service的效果吧:app

 

       效果圖能夠看到前臺service的界面,基本和一個通知信息界面差很少,而後點擊中止前臺service,狀態欄的圖標就消失了!此時前臺service也就關閉了!固然用戶想要中止前臺service,也跟普通service同樣,能夠在程序管理器那裏進行中止,具體看下面的效果圖!ide

 

       看完效果圖,咱們來看下代碼的實現,其實基本跟普通的service差很少,就是多了須要調用startForeground()方法,這個方法須要兩個參數:一個惟一標識通知的整數和給狀態欄的通知!若是須要刪除前臺service須要調用stopForeground()方法!函數

主界面的代碼:工具

 

[java] view plain copyui

 

 

  1. package com.liangdianshui.service2;  
  2.   
  3. import com.example.service2.R;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Intent;  
  7. import android.os.Bundle;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.widget.Button;  
  11.   
  12. public class MainActivity extends Activity implements OnClickListener {  
  13.   
  14.     private Button mBtStartFrontService;  
  15.     private Button mBtStopFrontService;  
  16.   
  17.     @Override  
  18.     protected void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.activity_main);  
  21.   
  22.         initView();  
  23.     }  
  24.   
  25.     private void initView() {  
  26.         mBtStartFrontService = (Button) findViewById(R.id.bt_start_front_server);  
  27.         mBtStopFrontService = (Button) findViewById(R.id.bt_stop_front_server);  
  28.         mBtStartFrontService.setOnClickListener(this);  
  29.         mBtStopFrontService.setOnClickListener(this);  
  30.     }  
  31.   
  32.     @Override  
  33.     public void onClick(View v) {  
  34.         // TODO Auto-generated method stub  
  35.         Intent intent2 = new Intent(MainActivity.this, MyService2.class);  
  36.         switch (v.getId()) {  
  37.         case R.id.bt_start_front_server:  
  38.             startService(intent2);  
  39.             break;  
  40.         case R.id.bt_stop_front_server:  
  41.             stopService(intent2);  
  42.             break;  
  43.         }  
  44.     }  
  45.   
  46. }  

Service類的代碼:this

 

 

[java] view plain copy加密

 

 

  1. package com.liangdianshui.service2;  
  2.   
  3. import com.example.service2.R;  
  4.   
  5. import android.app.Notification;  
  6. import android.app.PendingIntent;  
  7. import android.app.Service;  
  8. import android.content.Intent;  
  9. import android.os.Binder;  
  10. import android.os.IBinder;  
  11. import android.util.Log;  
  12.   
  13. public class MyService2 extends Service {  
  14.   
  15.     private static final String TAG = MyService2.class.getSimpleName();  
  16.   
  17.     private MyBinder mBinder = new MyBinder();  
  18.   
  19.     @Override  
  20.     public IBinder onBind(Intent intent) {  
  21.         // TODO Auto-generated method stub  
  22.         return mBinder;  
  23.     }  
  24.   
  25.     @Override  
  26.     public void onCreate() {  
  27.         // TODO Auto-generated method stub  
  28.         super.onCreate();  
  29.         Log.i(TAG, "onCreate");  
  30.         frontService();  
  31.     }  
  32.   
  33.     @Override  
  34.     public void onDestroy() {  
  35.         // TODO Auto-generated method stub  
  36.         super.onDestroy();  
  37.         Log.i(TAG, "onDestroy");  
  38.     }  
  39.   
  40.     @Override  
  41.     public int onStartCommand(Intent intent, int flags, int startId) {  
  42.         // TODO Auto-generated method stub  
  43.         Log.i(TAG, "onStartCommand");  
  44.         return super.onStartCommand(intent, flags, startId);  
  45.     }  
  46.   
  47.     class MyBinder extends Binder {  
  48.   
  49.         public void toDo() {  
  50.             Log.i(TAG, "toDo");  
  51.         }  
  52.     }  
  53.   
  54.     /** 
  55.      * 前臺服務 
  56.      */  
  57.     private void frontService() {  
  58.         Notification notification = new Notification(R.drawable.ic_launcher,  
  59.                 "Notification", System.currentTimeMillis());  
  60.         Intent notificationIntent = new Intent(this, MainActivity.class);  
  61.         PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,  
  62.                 notificationIntent, 0);  
  63.         notification  
  64.                 .setLatestEventInfo(this, "Title", "Content", pendingIntent);  
  65.         startForeground(1, notification);  
  66.         Log.d(TAG, "onCreate() executed");  
  67.     }  
  68. }  

       最後記得跟普通service同樣,在配置文件中聲明!操作系統

 

       Demo的下載地址:http://download.csdn.net/detail/two_water/9591717

      由於電腦有加密系統,因此只要把上面的類複製到對應的Java文件就能夠運行了。

2、遠程服務
       說到遠程服務(remote service),咱們怎麼建立遠程servie呢?
       其實在普通的service基礎上,咱們只要在配置文件中註冊Service的時候將它的android:process屬性指定成:remote就能夠了!
       注意:remote前面是有個冒號的!以下圖:

 

       以後咱們瞭解下Activity怎麼和遠程service進行通訊?爲何要了解這個呢?難道遠程服務不能像普通服務那樣和Activity那樣進行通訊嗎?

       其實遠程服務跟啓動遠程服務的程序不是同一個進程的,並且他們的包名也是不同的!(後面運行Demo的時候,看效果圖,打印的log信息能夠看到他們進程ID號不一樣,包名不一樣,具體在後面驗證)

       在Android中, 每一個應用程序都有本身的進程,當須要在不一樣的進程之間傳遞對象時,該如何實現呢? 顯然, Java中是不支持跨進程內存共享的。所以要傳遞對象, 須要把對象解析成操做系統可以理解的數據格式, 以達到跨界對象訪問的目的。在JavaEE中,採用RMI經過序列化傳遞對象。在Android中, 則採用AIDL(Android Interface Definition Language:接口描述語言)方式實現。

那麼什麼是AIDL呢?

       AIDL是一種接口定義語言,用於約束兩個進程間的通信規則,供編譯器生成代碼,實現Android設備上的兩個進程間通訊(IPC)。AIDL的IPC 機制和EJB所採用的CORBA很相似,進程之間的通訊信息,首先會被轉換成AIDL協議消息,而後發送給對方,對方收到AIDL協議消息後再轉換成相應 的對象。因爲進程之間的通訊信息須要雙向轉換,因此android採用代理類在背後實現了信息的雙向轉換,代理類由android編譯器生成,對開發人員 來講是透明的。

那麼具體咱們是怎麼操做的呢?

  (1)在工程的src下,新創建一個文本文件,將要實現的函數放在這個文件中,後綴爲.aidl。(主要是一個接口,定義方法)

  (2)刷新工程後,就會發如今gen包下,有一個同名的java文件,這是aidl工具自動生成的,裏面,就有咱們要實現的函數。

  (3)Aidl定義好後,咱們就要實現咱們的remote service了。它也是繼承自service的。

  (4)Service實現後,要將它在mainfest.xml設置爲remote.注意,客戶端服務端在同個App中,android:process=":remote",表明在應用程序裏,當須要該service時,會自動建立新的進程。而若是是android:process="remote",沒有「:」分號的,則建立全局進程,不一樣的應用程序共享該進程。

  (5)最後,來實現咱們的客戶端,也就是Activity,來調用service。

       最後,咱們來看下代碼:

       首先須要新建一個AIDL文件,在這個文件中定義好Activity須要與Service進行通訊的方法。新建MyAIDL.aidl文件,代碼以下所示:

[java] view plain copy

 

 

  1. package com.liangdianshui.service3;  
  2.   
  3. interface MyAIDL {    
  4.     String combineString(String str1,String str2);    
  5.     int countChar(String str);  
  6. }    

       在服務類中,經過MyAIDL.Stub來實現MyAIDL.aidl中的兩個方法,而後在onBind()方法中將MyAIDLService.Stub的實現返回,其餘的跟普通service差很少!由於Stub其實就是Binder的子類,因此在onBind()方法中能夠直接返回Stub的實現。

[java] view plain copy

 

 

  1. package com.liangdianshui.service3;  
  2.   
  3. import com.liangdianshui.service3.MyAIDL.Stub;  
  4.   
  5. import android.app.Service;  
  6. import android.content.Intent;  
  7. import android.os.Binder;  
  8. import android.os.IBinder;  
  9. import android.os.Process;  
  10. import android.os.RemoteException;  
  11. import android.util.Log;  
  12.   
  13. public class MyService3 extends Service {  
  14.   
  15.     private static final String TAG = MyService3.class.getSimpleName();  
  16.   
  17.     MyAIDL.Stub mBinder = new Stub() {  
  18.   
  19.         @Override  
  20.         public String combineString(String str1, String str2)  
  21.                 throws RemoteException {  
  22.             // TODO Auto-generated method stub  
  23.             return str1 + str2;  
  24.         }  
  25.   
  26.         @Override  
  27.         public int countChar(String str) throws RemoteException {  
  28.             // TODO Auto-generated method stub  
  29.             return str.length();  
  30.         }  
  31.   
  32.     };  
  33.   
  34.     @Override  
  35.     public IBinder onBind(Intent intent) {  
  36.         // TODO Auto-generated method stub  
  37.         return mBinder;  
  38.     }  
  39.   
  40.     @Override  
  41.     public void onCreate() {  
  42.         // TODO Auto-generated method stub  
  43.         super.onCreate();  
  44.         Log.i(TAG, "onCreate");  
  45.         Log.i(TAG, "MyService3 process ID:" + Process.myPid());  
  46.     }  
  47.   
  48.     @Override  
  49.     public void onDestroy() {  
  50.         // TODO Auto-generated method stub  
  51.         super.onDestroy();  
  52.         Log.i(TAG, "onDestroy");  
  53.     }  
  54.   
  55.     @Override  
  56.     public int onStartCommand(Intent intent, int flags, int startId) {  
  57.         // TODO Auto-generated method stub  
  58.         Log.i(TAG, "onStartCommand");  
  59.         return super.onStartCommand(intent, flags, startId);  
  60.     }  
  61.   
  62. }  

       在MainActivity中,ServiceConnection中的代碼。能夠看到,這裏首先使用了MyAIDLService.Stub.asInterface()方法將傳入的IBinder對象傳換成了MyAIDLService對象,接下來就能夠調用在MyAIDLService.aidl文件中定義的全部接口!

[java] view plain copy

 

 

  1. package com.liangdianshui.service3;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.ComponentName;  
  5. import android.content.Intent;  
  6. import android.content.ServiceConnection;  
  7. import android.os.Bundle;  
  8. import android.os.IBinder;  
  9. import android.os.Process;  
  10. import android.util.Log;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14.   
  15. public class MainActivity extends Activity implements OnClickListener {  
  16.   
  17.     private final static String TAG = MainActivity.class.getSimpleName();  
  18.   
  19.     private Button mBtStartRemoteService;  
  20.     private Button mBtStopRemoteService;  
  21.     private Button mBtBindRemoteService;  
  22.     private Button mBtUnbindRemoteService;  
  23.   
  24.     private MyAIDL mAIDL;  
  25.   
  26.     private ServiceConnection mConnection = new ServiceConnection() {  
  27.   
  28.         @Override  
  29.         public void onServiceConnected(ComponentName name, IBinder service) {  
  30.             // TODO Auto-generated method stub  
  31.             mAIDL = MyAIDL.Stub.asInterface(service);  
  32.             try {  
  33.                 int result = mAIDL.countChar("liangdianshui");  
  34.                 String str = mAIDL.combineString("liangdianshui", "hello");  
  35.                 Log.d(TAG, "countChar: " + result);  
  36.                 Log.d(TAG, "combineString : " + str);  
  37.             } catch (Exception e) {  
  38.                 e.printStackTrace();  
  39.             }  
  40.         }  
  41.   
  42.         @Override  
  43.         public void onServiceDisconnected(ComponentName name) {  
  44.             // TODO Auto-generated method stub  
  45.   
  46.         }  
  47.   
  48.     };  
  49.   
  50.     @Override  
  51.     protected void onCreate(Bundle savedInstanceState) {  
  52.         super.onCreate(savedInstanceState);  
  53.         setContentView(R.layout.activity_main);  
  54.   
  55.         initView();  
  56.   
  57.         Log.i(TAG, "MainActivity process ID:" + Process.myPid());  
  58.     }  
  59.   
  60.     private void initView() {  
  61.         // TODO Auto-generated method stub  
  62.         mBtStartRemoteService = (Button) findViewById(R.id.bt_start_remote_server);  
  63.         mBtStopRemoteService = (Button) findViewById(R.id.bt_stop_remote_server);  
  64.         mBtBindRemoteService = (Button) findViewById(R.id.bt_bind_remote_server);  
  65.         mBtUnbindRemoteService = (Button) findViewById(R.id.bt_unbind_remote_server);  
  66.         mBtStartRemoteService.setOnClickListener(this);  
  67.         mBtStopRemoteService.setOnClickListener(this);  
  68.         mBtBindRemoteService.setOnClickListener(this);  
  69.         mBtUnbindRemoteService.setOnClickListener(this);  
  70.     }  
  71.   
  72.     @Override  
  73.     public void onClick(View v) {  
  74.         // TODO Auto-generated method stub  
  75.         Intent intent3 = new Intent(MainActivity.this, MyService3.class);  
  76.         switch (v.getId()) {  
  77.         case R.id.bt_start_remote_server:  
  78.             startService(intent3);  
  79.             break;  
  80.         case R.id.bt_stop_remote_server:  
  81.             //點擊後會發現不能中止遠程service,由於遠程service和本程序不在同一個進程  
  82.             stopService(intent3);  
  83.             break;  
  84.         case R.id.bt_bind_remote_server:  
  85.             bindService(intent3, mConnection, BIND_AUTO_CREATE);  
  86.             break;  
  87.         case R.id.bt_unbind_remote_server:  
  88.             unbindService(mConnection);  
  89.             break;  
  90.         }  
  91.     }  
  92.   
  93. }  

       運行咱們的程序,並點擊「開啓遠程Server」,看下打印出來的Log:

 

       不難發現,它們的進程ID不一樣了,並且包名也是不同的,包名後面還跟上了:remote標識。

 

       其實遠程service跟普通service開啓和關閉基本是同樣的,就是綁定服務那裏不一樣,由於是創建在不一樣進程間的通訊!那咱們來看下綁定遠程服務和解綁的效果圖吧:

 

       能夠看出,打印出來的log信息,把遠程服務的方法的結果打印出來了!

 

        Demo的下載地址:http://download.csdn.net/detail/two_water/9592054

           由於電腦有加密系統,因此只要把上面的類複製到對應的java文件就能夠運行了。

相關文章
相關標籤/搜索