1. 程式人生 > >android Service之三:傳遞基本型資料的遠端服務

android Service之三:傳遞基本型資料的遠端服務

讓其他應用程式複用本程式的服務。這樣的服務叫遠端(remote)服務,實際上是程序間通訊(RPC)。

如果是呼叫不需要資料互動的遠端服務(startservice呼叫),跟無需資料互動的我本地服務呼叫是類似的

如果呼叫遠端服務進行資料互動,這時需要使用android介面描述語言(AIDL)來定義遠端服務的介面,而不是上述那樣簡單的java介面。副檔名為aidl而不是java。可用上面的ICountService改動而成ICountSerivde.aidl,eclipse會自動生成相關的java檔案。

package com.easymorse; interface ICountService {
int getCount(); }

編寫服務(Service)類,稍有差別,主要在binder是通過遠端獲得的,需要通過樁(Stub)來獲取。樁物件是遠端物件的本地代理。

ICountService.Stub繼承自IBinder介面和ICountService介面

package com.easymorse; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log;
publicclass CountService extends Service { privateboolean threadDisable; privateint count; private ICountService.Stub serviceBinder =new ICountService.Stub() { @Override publicint getCount() throws RemoteException { return count; } }; @Override
public IBinder onBind(Intent intent) { return serviceBinder; } @Override publicvoid onCreate() { super.onCreate(); new Thread(new Runnable() { @Override publicvoid run() { while (!threadDisable) { try { Thread.sleep(1000); } catch (InterruptedException e) { } count++; Log.v("CountService", "Count is "+ count); } } }).start(); } @Override publicvoid onDestroy() { super.onDestroy(); this.threadDisable =true; Log.v("CountService", "on destroy"); } }

配置檔案AndroidManifest.xml和上面的類似, 只是ServiceConnection中返回的IBinder是代理物件,不能使用強轉,改用Stub.asInterface()

在Activity中使用服務的差別不大,只需要對ServiceConnection中的呼叫遠端服務的方法時,要捕獲異常。

private ServiceConnection serviceConnection =new ServiceConnection() { @Override publicvoid onServiceConnected(ComponentName name, IBinder service) { countService = ICountService.Stub.asInterface(service); ; try { Log.v("CountService", "on serivce connected, count is "+ countService.getCount()); } catch (RemoteException e) { thrownew RuntimeException(e); } } @Override publicvoid onServiceDisconnected(ComponentName name) { countService =null; } };

這樣就可以在同一個應用程式中使用遠端服務的方式和自己定義的服務互動了。

如果是另外的應用程式使用遠端服務,需要做的是複製上面的aidl檔案和相應的包構到應用程式中,其他呼叫等都一樣。

下面是一個傳引數的例子(string是可以作為基本資料型別傳遞的):

  在AIDL中定義服務介面
   為了展示遠端服務例項,我們將編寫一個股票報價服務。此服務將提供一種方法來獲取股票代號並返回價格。要在Android 中編寫遠端服務,第一步是在 AID檔案中定義服務的介面。 
   股票報價服務的 AIDL 定義 

Java程式碼  收藏程式碼
  1. //This file is IStockQuoteService.aidl  
  2. package com.androidbook.stockquoteservice;  
  3. interface IStockQuoteService  
  4. {  
  5.     double getQuote(String ticker);  
  6. }  
在服務類中實現AIDL介面
  上邊我們為股票報價服務定義了 AIDL 檔案並生成了繫結檔案。現在我們將提供該服務的實現。要實現服務的介面,需要編寫一個類來擴充套件 android.app.Service 並實現 IStockQuoteService介面。我們將編寫的類 命名為 StockQuoteService。為了將服務向客戶端公開,StockQuoteService 需要提供onBind()方法 的實現,我們還需要將一些配置資訊新增到 AndroidManifest.xml檔案中。  下面給出 我們服務類得實現。 
IStockQuoteService 服務實現。 
Java程式碼  收藏程式碼
  1. package com.androidbook.stockquoteservice;  
  2. import android.app.Service;  
  3. import android.content.Intent;  
  4. import android.os.IBinder;  
  5. import android.os.RemoteException;  
  6. import android.util.Log;  
  7. public class StockQuoteService extends Service {  
  8.     private static final String TAG = "StockQuoteService";  
  9.     public class StockQuoteServiceImpl extends IStockQuoteService.Stub {  
  10.         @Override  
  11.         public double getQuote(String ticker) throws RemoteException {  
  12.             Log.v(TAG, "getQuote() called for " + ticker);  
  13.             return 20.0;  
  14.         }  
  15.     }  
  16.     @Override  
  17.     public void onCreate() {  
  18.         super.onCreate();  
  19.         Log.v(TAG, "onCreate called");  
  20.     }  
  21.     @Override  
  22.     public void onDestroy() {  
  23.         super.onDestroy();  
  24.         Log.v(TAG, "onDestory() called");  
  25.     }  
  26.     @Override  
  27.     public void onStart(Intent intent, int startId) {  
  28.         super.onStart(intent, startId);  
  29.         Log.v(TAG, "onStart() called");  
  30.     }  
  31.     @Override  
  32.     public IBinder onBind(Intent intent) {  
  33.         Log.v(TAG, "onBind() called");  
  34.         return new StockQuoteServiceImpl();  
  35.     }  
  36. }  

    在這個服務類中大家可以看到我們實現了 onBind() 方法。從AIDL檔案生成的 Stub類是抽象類並且它實現了 IStockQuoteService介面。在我們的服務實現中,有一個擴充套件了 Stub類得內部類,名為 StockQuoteServiceImpl。此類充當著遠端服務實現,而且 onBind()方法會返回此類的例項。到此,我們有了一個有效的 ADIL服務,但是外部的客戶端還無法連線到它。 
     要將服務向客戶端公開,需要在AndroidManifest.xml檔案中新增服務宣告,而這一次我們需要一個Intent 過濾器來公開服務,如下。 



   從客戶端應用程式呼叫服務
   當客戶端與服務通訊時,它們之間必須有一個協議或契約。在Android中,這個契約就是AIDL。所以,使用服務的第一步是,獲取服務的 AIDL檔案並將其複製到客戶端專案中。當將AIDL檔案複製到客戶端專案時,AIDL 編譯器將建立一個介面定義檔案,這個檔案與我們在服務端定義的檔案相同。這會向客戶端公開所有的方法、引數並返回服務的型別。我們建立一個新專案並複製AIDL檔案。 
    (1)建立一個新的Android專案, 將其命名為 StockQuoteClient。使用不同的包名稱比如 com.androidbook.stockquoteclient。在Create Activity欄位中使用 MainActivity注意不要把IStockQuoteService.aidl檔案放到這包中,這個包只有一個MainActivity 類。 
    (2)在此專案中新建一個包 com.androidbook.stockquoteservice,放在src目錄下。 
    (3)將IStockQuoteService.aidl檔案從 StockQuoteService 專案也就是我們服務端得專案複製到新建的包中。複製過來之後,AIDL編譯器會自動生成關聯的java檔案。 
     重新生成的服務介面充當著客戶端與服務之間的契約。下一步是獲取服務的引用,以便呼叫getQuote()方法。對於遠端服務,必須呼叫 bindService()方法,而不是 startService()方法。 

    客戶端佈局檔案 
Xml程式碼  收藏程式碼
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <Button  
  8.     android:id="@+id/bindBtn"  
  9.     android:layout_width="wrap_content"  
  10.     android:layout_height="wrap_content"  
  11.     android:text="Bind"/>  
  12. <Button  
  13.     android:id="@+id/callBtn"  
  14.     android:layout_height="wrap_content"  
  15.     android:layout_width="wrap_content"  
  16.     android:text="Call Again"/>  
  17. <Button  
  18.     android:id="@+id/unbindBtn"  
  19.     android:layout_width="wrap_content"  
  20.     android:layout_height="wrap_content"  
  21.     android:text="UnBind"/>  
  22. </LinearLayout>  


  MainActivity類 
Java程式碼  收藏程式碼
  1. package com.androidbook.stockquoteclient;  
  2. import com.androidbook.stockquoteservice.IStockQuoteService;  
  3. import android.app.Activity;  
  4. import android.content.ComponentName;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.ServiceConnection;  
  8. import android.os.Bundle;  
  9. import android.os.IBinder;  
  10. import android.os.RemoteException;  
  11. import android.util.Log;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.widget.Button;  
  15. import android.widget.Toast;  
  16. public class MainActivity extends Activity {  
  17.     protected static final String TAG = "StockQuoteClient";  
  18.     private IStockQuoteService stockService = null;  
  19.     private Button bindBtn;  
  20.     private Button callBtn;  
  21.     private Button unbindBtn;  
  22.     @Override  
  23.     public void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         setContentView(R.layout.main);  
  26.         bindBtn = (Button) findViewById(R.id.bindBtn);  
  27.         bindBtn.setOnClickListener(new OnClickListener() {  
  28.             @Override  
  29.             public void onClick(View v) {  
  30.                 bindService(new Intent(IStockQuoteService.class.getName()),  
  31.                         serConn, Context.BIND_AUTO_CREATE);  
  32.                 bindBtn.setEnabled(false);  
  33.                 callBtn.setEnabled(true);  
  34.                 unbindBtn.setEnabled(true);  
  35.             }  
  36.         });  
  37.         callBtn = (Button) findViewById(R.id.callBtn);  
  38.         callBtn.setOnClickListener(new OnClickListener() {  
  39.             @Override  
  40.             public void onClick(View v) {  
  41.                 callService();  
  42.             }  
  43.         });  
  44.         callBtn.setEnabled(false);  
  45.         unbindBtn = (Button) findViewById(R.id.unbindBtn);  
  46.         unbindBtn.setOnClickListener(new OnClickListener() {  
  47.             @Override  
  48.             public void onClick(View v) {  
  49.                 unbindService(serConn);  
  50.                 bindBtn.setEnabled(true);  
  51.                 callBtn.setEnabled(false);  
  52.                 unbindBtn.setEnabled(false);  
  53.             }  
  54.         });  
  55.     }  
  56.     private void callService() {  
  57.         try {  
  58.             double val = stockService.getQuote("SYH");  
  59.             Toast.makeText(this"Value from service is " + val,  
  60.                     Toast.LENGTH_LONG).show();  
  61.         } catch (RemoteException e) {  
  62.             Log.e("MainActivity", e.getMessage(), e);  
  63.         }  
  64.     }  
  65.     private ServiceConnection serConn = new ServiceConnection() {  
  66.         // 此方法在系統建立服務連線時呼叫  
  67.         @Override  
  68.         

    相關推薦

    android Service傳遞基本型資料遠端服務

    讓其他應用程式複用本程式的服務。這樣的服務叫遠端(remote)服務,實際上是程序間通訊(RPC)。 如果是呼叫不需要資料互動的遠端服務(startservice呼叫),跟無需資料互動的我本地服務呼叫是類似的 如果呼叫遠端服務進行資料互動,這時需要使用android

    Hive命令hive的資料匯入匯出

    Hive 資料的匯入匯出: 一 Hive資料匯出   1、匯出資料到本地檔案系統:      insert overwrite local directory '/software/data/data1' select * f

    maven構建docker映象三部曲推送到遠端倉庫(內網和阿里雲)

    在上一章《maven構建docker映象三部曲之二:編碼和構建映象》的實戰中,我們將spring boot的web工程構建成docker映象並在本地啟動容器成功,今天我們把docker-maven-plugin外掛的推送功能也用上,這樣編譯、構建、推送都能一

    Android Service的啟動終止,以及資料傳遞的簡單案例

    生命週期方法簡單介紹 startService() 作用:啟動Service服務  手動呼叫startService()後,自動呼叫內部方法:onCreate()、onStartCommand() 

    資料hdfs詳解put許可權剖析與常用命令

    –無論是對於hdfs的讀和寫,對於使用者來說都是無感知的、透明的操作,使用者並不關心資料如何讀出來如何寫進去的,只要返回一個結果告訴使用者資料讀出來了或寫進去了,至於怎麼讀怎麼寫,使用者並不關心 補充: 讀:hdfs dfs -ls / = hdfs dfs

    Android電源管理PowerManager.WakeLock原始碼詳讀

    PowerManager.WakeLock 有加鎖和解鎖兩種狀態,加鎖的方式有兩種,一種是永久的鎖,這樣的鎖除非顯式的放開,是不會解鎖的,所以這種鎖用起來要非常的小心。第二種鎖是超時鎖,這種鎖會在鎖住後一段時間自動解鎖。         在建立了PowerManager.W

    Android問題集錦轉載Javah 常見錯誤記錄-NDK與JNI除錯

    測試檔案:hello-jni/src/com/example/hellojni/HelloJni.java/** * 該檔案來自 Android NDK Sample - HelloJni, 為了便於說明問題,我作了一些修改。 */ package com.example

    Linux作業系統備份通過二進位制拷貝(dd)方式實現Linux作業系統資料的備份

    今天我們介紹另外一種粗曠,但是相對簡單的備份方法:通過dd命令二進位制拷貝方式備份作業系統資料。dd拷貝的方式不能線上實施,因為dd是二進位制的塊拷貝,若拷貝過程中有寫檔案操作,會導致檔案系統不一致(如某個節點建立到一半被dd拷貝走了),因此,這種方式必須進入記憶體操作系的單使用者模式下操作,實施

    android開發為listview繫結資料種方式

    第一種,使用simple adapter simpleadapter 是最簡單的一種方式,但是其資料來源必須是map型別。 1.生成 SimpleAdapter()物件 2.設定資料來源 3.設定每個item的佈局 4.設定SimpleAdapter(Context con

    Android系統資訊獲取 IMSI號和IMEI解釋

    IMSI號: IMSI是國際移動使用者識別碼的簡稱(International Mobile Subscriber Identity)  它是在公眾陸地行動電話網(PLMN)中用於唯一識別移動使用者的一個號碼。在GSM網路,這個號碼通常被存放在SIM卡中 IMSI共有15位,其結構如下:  MCC

    Qt總結磁碟檔案操作、遍歷資料夾和檔案目錄,並過濾和獲取檔案資訊、字尾名、字首名(

    前言 本節內容主要包括磁碟容量檢測、磁碟內指定或特定檔案的操作 話不多說,先上效果圖 共分為兩個部分,第一部分是檢測磁碟容量,第二部分是篩選磁碟內指定檔案(test.txt)或特定檔案(.txt / .png型別檔案) 獲取磁碟容量關鍵函式:【fileapi.h】 

    資料探勘模型介紹決策樹

    1. 適用的場景 (1)分析對某種響應可能性影響最大的因素,比如判斷具有什麼特徵的客戶流失概率更高; (2)為其他模型篩選變數。決策樹找到的變數是對目標變數影響很大的變數。所以可以作為篩選變數的手段。 注: 1)決策樹篩選的變數之間的獨立性可能不夠,因為決策樹每次選擇變數時

    玩轉大資料系列資料報表與展示

    經過了資料採集與資料同步、資料分析和處理,我們應該考慮將處理好的資料做成報表或者大屏展示給老闆們看,以便老闆們可以更加精準地做出戰略決策,為業務的發展指明方向。 提到資料報表,不得不說說Quick BI。Quick BI提供海量資料實時線上分析服務,支援拖拽式操作、提供了豐富的視覺化效果,可以幫助您輕鬆自如

    虛擬機器安裝XP系統圖解安裝VM Tools和共享資料

         上一篇演示了新建虛擬機器和xp系統的安裝,本篇將是這個系列的結尾階段:安裝VM Tools 和共享資料夾。      安裝VM Tools能夠使的虛擬機器和實體機之間能夠自由拖動檔案,最重要

    ANDROID音訊系統散記resample-2

    這篇是承接上一篇提到的底層resample處理,以Samsung的tiny alsa-lib為例說明。 tiny alsa-lib 這個tiny alsa-lib位於android2.3.1-gingerbread/device/samsung/crespo/libau

    Android系統應用---SystemUI狀態列電池圖示的顯示和Android電池管理的探討

    電池圖示顯示 電池圖示是SystemUI顯示中不可缺少的一部分,它顯示在SystemUI的電池和訊號組合區域。 從佈局來看,電池的顯示屬於status_bar.xml,包含了system_icons.xml佈局 <includelayout="@layout/

    R語言與資料分析分類演算法2

    上期與大家分享的傳統分類演算法都是建立在判別函式的基礎上,通過判別函式值來確定目標樣本所屬的分類,這類演算法有個最基本的假設:線性假設。今天繼續和大家分享下比較現代的分類演算法:決策樹和神經網路。這兩個演算法都來源於人工智慧和機器學習學科。 首先和小夥伴介紹下資料探勘領域比

    【OpenCV學習筆記】Mat初始建立方法----要求資料連續儲存

    int rows=15; // int cols=40; int size=rows*cols; vector<int>Va(size); vector<Vec<int, 8>>Vb(size); vector<Vec4i>V

    Android O 前期預研Android Vehicle HAL

    Android Automotive Android Automotive 是Android Oreo中的一個新的特色功能,從AOSP的程式碼上來看,Android O中已經包含有了從Application到Framework 到HAL的整體框架,這一章節,我

    影象語義分割從頭開始訓練deeplab v2系列【pascal-context資料集】

    在之前的部落格已經講過deeplab v2原始碼解析與基於VOC2012資料集的訓練,本部落格基於pascal-context資料集進行fine tuning txt檔案:檔案中有資料集的名字列表的txt檔案,此處不同於原始碼,在pascal-con