在Android應用開發中,我們會碰到跨進程通信的情況,例如:你用QQ通訊錄打電話的時候會調用系統的撥號應用、某些新聞客戶端可以將新聞分享到QQ、微信等應用,這些都是跨進程通信的情況。簡而言之,就是一個應用調用了另一個應用,並傳遞了一定的數據。在Android中有Activity、Content Provider、BroadcastReceiver、Service四大組件,巧的是Android進程間通信也離不開這四大組件(也有說是AIDL機制,但是現在還分不清Service和AIDL的區別(/ □ \) ),組件間通信的核心機制是Intent,通過Intent可以開啟一個Activity或者Service。
對於這四大組件,最常用也是最容易理解的就是Activity了,因為Activity是看得見摸得到的,所以跨進程通信也就先從Activity先講起來。
Activity既可以在同一個進程內訪問,也可以跨進程訪問,是否跨進程訪問的主要區別在於Intent是顯示Intent還是隱式Intent。
Intent類型:
1、顯示Intent——直接指定要啟動的Activity類,一般用於同一個進程內的不同組件間通信,其格式為new Intent(this,Target.class);
//顯示Intent,一般用於啟動同一進程中的Activity Intent intent = new Intent(this,OtherActivity.class); startActivity(intent);
2、隱式Intent——一般用於跨進程通信,注冊在AndroidManifest.xml文件中,其格式為intent.setAction(String action)。
// 隱式Intent Intent intent = new Intent(); // 設置Action,啟動系統撥號界面,ACTION_CALL其實是字符串常量"android.intent.action.CALL" intent.setAction(Intent.ACTION_CALL); startActivity(intent);
既然知道了Activity間跨進程通信的主要取決於隱式Intent,那么,我們該如何實現隱式Intent呢?答案是正如上面所說,在AndroidManifest.xml文件中注冊就行了。下面就又到了直接上代碼的環節,代碼注釋中會穿插一些要注意內容。
創建一個OtherActivity的Android項目,將布局文件稍稍修改下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <!-- 實際開發中不建議將內容直接寫在text內 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是被另一個Activity跨進程召喚的" /> </RelativeLayout>
接着,修改OtherActivity項目的AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lsj.otheractivity" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- 一個<activity>包括:零個或多個<intent-filter> --> <!-- 它主要是作為匹配的標准,能否匹配成功由<action>、<category>、<data>三個tag共同決定的。 --> <activity android:name="com.lsj.otheractivity.MainActivity" android:label="@string/app_name" > <!-- 一個<intent-filter>包括:一個或多個<action> 零個或多個<category> 零個或一個<data> --> <intent-filter> <!-- <action>是實現隱式Intent啟動另一進程中的Activity的關鍵 --> <!-- 想要啟動這個這個Activity,只要往setAction中添加此處<action>標簽中的字符串常量即可 --> <action android:name="com.lsj.otherActivity" /> <!-- 如果有自定義action時,記得添加下面這句 ,不然會報錯--> <category android:name="android.intent.category.DEFAULT" /> <action android:name="android.intent.action.MAIN" /> <!-- <category>用於指定Activity的分類特征,此處代表此Activity是這個程序的啟動界面 --> <category android:name="android.intent.category.LAUNCHER" /> <!-- <data>標簽不會用,暫時忽略 --> </intent-filter> </activity> </application> </manifest>
接着,在創建一個Activity的Android項目,在其MainActivity中添加如下代碼:
// 新建一個Intent對象 Intent intent = new Intent(); // 設置Intent對象的Action,Action為OtherActivity配置文件中注冊的action值 intent.setAction("com.lsj.otherActivity"); // 啟動Activity startActivity(intent);
先安裝好OtherActivity,然后安裝並運行Activity,你會發現OtherActivity已經被打開了。這就實現了Activity間跨進程通信,對於傳遞數據,可以用bundle或者intent。putExtras()來實現。
對於前面講到的設置action可能會有這么個疑惑,如果一個Intent對應多種匹配結果該怎么處理呢?系統會根據組件的不同而不同對待,如果是service那么這些service都可以啟動並處理消息;如果是Activity則會彈出一個對話框讓用戶進行選擇。
參考:android多進程通信
作者:登天路