日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Android中使用ContentProvider进行跨进程方法调用

發(fā)布時(shí)間:2025/7/14 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android中使用ContentProvider进行跨进程方法调用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文同一時(shí)候發(fā)表在我的博客
點(diǎn)我進(jìn)入還能看到很多其它

需求背景

近期接到這樣一個(gè)需求,須要和別的 App 進(jìn)行聯(lián)動(dòng)交互,比方下載器 App 和桌面 App 進(jìn)行聯(lián)動(dòng)。桌面的 App 能直接顯示下載器 App 內(nèi)的下載任務(wù)進(jìn)度和狀態(tài)。

尋找解決方式

從需求上知道了,主要問(wèn)題在怎樣解決跨進(jìn)程的通信上邊。

  • AIDL

    AIDL 即 Android Interface Definition Language的縮寫(xiě),是專為 Android 中跨進(jìn)程通信接口的描寫(xiě)敘述語(yǔ)言。優(yōu)缺點(diǎn)非常明顯,長(zhǎng)處是穩(wěn)定,快。Android 專門用于跨進(jìn)程通信設(shè)計(jì)的。缺點(diǎn)是比較麻煩,AIDL 是通信的約定,參加通信的兩方都須要把這個(gè) AIDL 文件都加入自己的代碼中,然后創(chuàng)建 Service 來(lái)實(shí)現(xiàn)訪問(wèn)和被訪問(wèn)。

  • ContentProvider

    作為 Android 四大基礎(chǔ)組件之中的一個(gè)的 ContentProvider 本來(lái)它的作用僅僅是提供內(nèi)容性質(zhì)的跨進(jìn)程訪問(wèn)。可是在 API 11 (Android 3.0) 中,ContentProvider 加入了一個(gè)新的方法,能夠用來(lái)進(jìn)行跨進(jìn)程的方法調(diào)用,ContentProvider 中這種方法的定義例如以下:

    Bundle call(String method, String arg, Bundle extras)

    從易用性來(lái)講,這個(gè)沒(méi)有 AIDL 那么麻煩,并且擴(kuò)展性更強(qiáng),也沒(méi)有 Broadcast 過(guò)于依賴系統(tǒng),API 11 應(yīng)該就是主要是缺點(diǎn)了,別的缺點(diǎn)臨時(shí)沒(méi)發(fā)現(xiàn)。歡迎補(bǔ)充。

  • Broadcast

    廣播是最簡(jiǎn)單的:長(zhǎng)處是把分發(fā)消息的任務(wù)所有交給 Android 系統(tǒng)了;缺點(diǎn)也是由于全交給系統(tǒng)了,非常多地方不受控制。缺點(diǎn):

  • 盡管廣播能夠通過(guò)指定包名來(lái)進(jìn)行發(fā)送指向性消息,可是卻不能驗(yàn)證消息去向 App 的簽名。

  • 系統(tǒng)重新啟動(dòng)之后,在系統(tǒng)的廣播隊(duì)列里邊的消息就丟失了。
  • 實(shí)現(xiàn)

    為了簡(jiǎn)要,主要講講 ContentProvider 吧。

    ContentProvider

    首先是下載器 App 的 ContentProvider 代碼實(shí)現(xiàn)

    package cn.hiroz.downloader.realname;import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.util.Log;public class DownloaderContentProvider extends ContentProvider {@Overridepublic boolean onCreate() {return false;}@Overridepublic Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {return null;}@Overridepublic String getType(Uri uri) {return null;}@Overridepublic Uri insert(Uri uri, ContentValues contentValues) {return null;}@Overridepublic int delete(Uri uri, String s, String[] strings) {return 0;}@Overridepublic int update(Uri uri, ContentValues contentValues, String s, String[] strings) {return 0;}@Overridepublic Bundle call(String method, String arg, Bundle extras) {if ("DOWNLOAD".equals(method)) { // 當(dāng)調(diào)用我下載的時(shí)候Log.e("Downloader", "download: " + arg);// 調(diào)用桌面 App 的方法來(lái)更新?tīng)顟B(tài)updateStatus("download");} else ("PAUSE".equals(method)) { // 當(dāng)調(diào)用我暫停的時(shí)候Log.e("Downloader", "pause: " + arg);// 調(diào)用桌面 App 的方法來(lái)更新?tīng)顟B(tài)updateStatus("pause");}return null;}// 我們要調(diào)用的對(duì)方的 ContentProvider 的 URIprivate final Uri LAUNCHERCONTENTPROVIDER_URI = Uri.parse("content://cn.hiroz.launcher.LauncherContentProvider"); }private void updateStatus(String status) {getContext().getContentResolver().call(LAUNCHERCONTENTPROVIDER_URI, "UPDATE_STATUS", status, new Bundle());}

    在下載器 App 的 AndroidManifest.xml 中還須要加入 ContentProvider 的定義:

    <provider android:name="cn.hiroz.downloader.realname.DownloaderContentProvider"android:authorities="cn.hiroz.downloader.DownloaderContentProvider"android:exported="true"/>

    我特地加了authorities設(shè)置。這樣在交互時(shí)候訪問(wèn)的 ContentProvider 的 URI 會(huì)看起來(lái)不一樣。也不會(huì)暴露我真實(shí)的 ContentProvider 類

    然后是桌面 App 的 ContentProvider 代碼實(shí)現(xiàn)

    package cn.hiroz.launcher.realname;import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.util.Log;public class LauncherContentProvider extends ContentProvider {@Overridepublic boolean onCreate() {return false;}@Overridepublic Cursor query(Uri uri, String[] strings, String s, String[] strings2, String s2) {return null;}@Overridepublic String getType(Uri uri) {return null;}@Overridepublic Uri insert(Uri uri, ContentValues contentValues) {return null;}@Overridepublic int delete(Uri uri, String s, String[] strings) {return 0;}@Overridepublic int update(Uri uri, ContentValues contentValues, String s, String[] strings) {return 0;}@Overridepublic Bundle call(String method, String arg, Bundle extras) {// 當(dāng)被調(diào)用“更新?tīng)顟B(tài)”的時(shí)候if ("UPDATE_STATUS".equals(method)) {Log.e("Launcher", "update status: " + arg);}return null;}// 我們要調(diào)用的對(duì)方的 ContentProvider 的 URIprivate final Uri DOWNLOADERCONTENTPROVIDER_URI = Uri.parse("content://cn.hiroz.downloader.DownloaderContentProvider"); }public void download(String arg) {getContext().getContentResolver().call(DOWNLOADERCONTENTPROVIDER_URI, "DOWNLOAD", status, new Bundle());}public void pause(String arg) {getContext().getContentResolver().call(DOWNLOADERCONTENTPROVIDER_URI, "PAUSE", status, new Bundle());}}

    在桌面 App 的 AndroidManifest.xml 中還須要加入 ContentProvider 的定義:

    <provider android:name="cn.hiroz.launcher.realname.LauncherContentProvider"android:authorities="cn.hiroz.launcher.LauncherContentProvider"android:exported="true"/>

    然后在桌面 App 中。就能夠通過(guò) LauncherContentProvider 的 download 方法和 pause 方法來(lái)調(diào)用下載器 App 的功能了(這兩個(gè)方法寫(xiě)在這里不太合適,只是我僅僅是為了節(jié)省篇幅放一起了)。下載器 App 中被調(diào)用了方法,就會(huì)調(diào)用桌面 App 的更新?tīng)顟B(tài)。

    這里僅僅是演示了一個(gè)交互的過(guò)程,有很多其它問(wèn)題歡迎大家一起討論學(xué)習(xí)~~

    引申

    • 找不到 ContentProvider 的時(shí)候須要做一下空指針保護(hù)

    • 簽名校驗(yàn)

    總結(jié)

    以上是生活随笔為你收集整理的Android中使用ContentProvider进行跨进程方法调用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。