直接通過Binder的onTransact完成跨進程通信

来源:https://www.cnblogs.com/ganchuanpu/archive/2018/07/04/9263850.html
-Advertisement-
Play Games

1.具體代碼: 服務端實現: 可以看到onTransact有四個參數 code , data ,replay , flags code 是一個整形的唯一標識,用於區分執行哪個方法,客戶端會傳遞此參數,告訴服務端執行哪個方法; data客戶端傳遞過來的參數; replay伺服器返回回去的值; flag ...


1.具體代碼:

服務端實現:

public class IPCService extends Service {
 
    private static final String DESCRIPTOR = "IPCService";
    private final String[] names = { "B神", "艹神", "基神", "J神", "翔神" };
    private MyBinder mBinder = new MyBinder();
 
    private class MyBinder extends Binder {
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            switch (code) {
            case 0x001: {
                data.enforceInterface(DESCRIPTOR);
                int num = data.readInt();
                reply.writeNoException();
                reply.writeString(names[num]);
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

可以看到onTransact有四個參數 
code , data ,replay , flags

  • code 是一個整形的唯一標識,用於區分執行哪個方法,客戶端會傳遞此參數,告訴服務端執行哪個方法;
  • data客戶端傳遞過來的參數;
  • replay伺服器返回回去的值;
  • flags標明是否有返回值,0為有(雙向),1為沒有(單向)。

客戶端實現:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 
    private EditText edit_num;
    private Button btn_query;
    private TextView txt_result;
    private IBinder mIBinder;
    private ServiceConnection PersonConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mIBinder = null;
        }
 
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIBinder = service;
        }
    };
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
 
        // 綁定遠程Service
        Intent service = new Intent("android.intent.action.IPCService");
        service.setPackage("com.jay.ipcserver");
        bindService(service, PersonConnection, BIND_AUTO_CREATE);
        btn_query.setOnClickListener(this);
    }
 
    private void bindViews() {
        edit_num = (EditText) findViewById(R.id.edit_num);
        btn_query = (Button) findViewById(R.id.btn_query);
        txt_result = (TextView) findViewById(R.id.txt_result);
    }
 
    @Override
    public void onClick(View v) {
        int num = Integer.parseInt(edit_num.getText().toString());
        if (mIBinder == null) {
            Toast.makeText(this, "未連接服務端或服務端被異常殺死", Toast.LENGTH_SHORT).show();
        } else {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            String _result = null;
            try {
                _data.writeInterfaceToken("IPCService");
                _data.writeInt(num);
                mIBinder.transact(0x001, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readString();
                txt_result.setText(_result);
                edit_num.setText("");
            } catch (RemoteException e) {
                e.printStackTrace();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }
    }
}

2.transact和onTransact的區別

談transact 和onTransact需要先聊聊iBinder

IBinder是什麼呢?首先要明白,Android的遠程調用(就是跨進程調用)就是通過IBinder實現的,下麵是對android開發文檔的翻譯。

  IBinder是遠程對象的基本介面,是為高性能而設計的輕量級遠程調用機制的核心部分。但它不僅用於遠程調用,也用於進程內調用。這個介面定義了與遠程對象交互的協議。不要直接實現這個介面,而應該從Binder派生。

  IBinder的主要API是transact(),與它對應另一方法是Binder.onTransact()。第一個方法使你可以向遠端的IBinder對象發送發出調用,第二個方法使你自己的遠程對象能夠響應接收到的調用。IBinder的API都是同步執行的,比如transact()直到對方的Binder.onTransact()方法調用完成後才返回。調用發生在進程內時無疑是這樣的,而在進程間時,在IPC的幫助下,也是同樣的效果。   通過transact()發送的數據是Parcel,Parcel是一種一般的緩衝區,除了有數據外還帶有一些描述它內容的元數據。元數據用於管理IBinder對象的引用,這樣就能在緩衝區從一個進程移動到另一個進程時保存這些引用。這樣就保證了當一個IBinder被寫入到Parcel併發送到另一個進程中,如果另一個進程把同一個IBinder的引用回發到原來的進程,那麼這個原來的進程就能接收到發出的那個IBinder的引用。這種機制使IBinder和Binder像唯一標誌符那樣在進程間管理。   系統為每個進程維護一個存放交互線程的線程池。這些交互線程用於派送所有從另外進程發來的IPC調用。例如:當一個IPC從進程A發到進程B,A中那個發出調用的線程(這個應該不線上程池中)就阻塞在transact()中了。進程B中的交互線程池中的一個線程接收了這個調用,它調用Binder.onTransact(),完成後用一個Parcel來做為結果返回。然後進程A中的那個等待的線程在收到返回的Parcel後得以繼續執行。實際上,另一個進程看起來就像是當前進程的一個線程,但不是當前進程創建的。   Binder機制還支持進程間的遞歸調用。例如,進程A執行自己的IBinder的transact()調用進程B的Binder,而進程B在其Binder.onTransact()中又用transact()向進程A發起調用,那麼進程A在等待它發出的調用返回的同時,還會用Binder.onTransact()響應進程B的transact()。總之Binder造成的結果就是讓我們感覺到跨進程的調用與進程內的調用沒什麼區別。   當操作遠程對象時,你經常需要查看它們是否有效,有三種方法可以使用:   1 transact()方法將在IBinder所在的進程不存在時拋出RemoteException異常。   2 如果目標進程不存在,那麼調用pingBinder()時返回false。   3 可以用linkToDeath()方法向IBinder註冊一個IBinder.DeathRecipient,在IBinder代表的進程退出時被調用。   要實現IBinder來支持遠程調用,應從Binder類派生一個類。Binder實現了IBinder介面。但是一般不需要直接實現此類,而是跟據你的需要由開發包中的工具生成,這個工具叫AIDL。你通過AIDL語言定義遠程對象的方法,然後用AIDL工具生成Binder的派生類,然後就可使用之。然而,可是,但是,當然,你也可以直接從Binder類派生以實現自定義的RPC調用,或只是實例化一個原始的Binder對象直接作為進程間共用的令牌來使用。

  

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • if (textField == _phoneTF) { //支持刪除 if (range.length == 1 && string.length == 0) { return YES; } else if (_phoneTF.text.length ... ...
  • 1> 索引 雖然索引的目的在於提高資料庫的性能,但這裡有幾個情況需要避免使用索引。使用索引時,應重新考慮下列準則: 2> 事務 對於事務,就是資料庫的一次原子性的執行操作。原子性的執行操作為數據的整體性執行帶來的可靠安全性。在SQLite中,如果我們預設事務(會為每個插入和更新都創建一次事務,並且在 ...
  • 1.使用系統為我們提供了幾個抽象的標簽 ①include:重用 ②viewstub:按需載入 註意: ③merge:減少佈局層數 ...
  • 最近有小伙伴說,7.0適配整了一波,現在又要來適配8.0,真是一波未平一波又起 但是作為開發者來說,學無止境,不跟上時代的步伐,肯定會被時代所淘汰... 話說Android P已經在路上了,你準備好了嗎? 適配屬性 1、通知渠道(Channeld) 當然,適配8.0的第一步自然是把targeSdk升 ...
  • 1.首先下載Eclipse for android,點擊進入。下載這個版本可以省去ADT配置() 2.下載符合你電腦的版本 2.現在Android SDK,地址:http://tools.android-studio.org/index.php/sdk 3.啟動Eclipse,選擇windows>p ...
  • 前言 大家好,給大家帶來 的概述,希望你們喜歡 前言 如果你想學習Android開發,那你就要瞭解Java編程,這是基礎,也是重點,如果沒學Java語法就先學習,再來學Android,別問可不可以先學Android,都告訴了,先學Java對吧! Android開發的基本瞭解 Android開發主要了 ...
  • 1.筆者常用三方庫 名稱作用說明 <small>AFNetworking <small>基於HTTP/HTTPS 聯網請求 <small> <small>SDWebImage <small>圖片非同步載入和緩存 <small> image圖像沒做壓縮處理 <small> FMDB <small>SQL ...
  • 版權聲明:未經博主允許不得轉載 AsyncTask 瞭解AsyncTask非同步,需要瞭解一下非同步任務(多線程),什麼是線程,可以這麼說線程好比邊吃飯邊看電視,AsyncTask是為了方便後臺線程中操作更新UI,本質為Handler非同步消息處理機制。 學習AsyncTask需要知道它的參數,它要實現的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...