Android跨進程通信訪問其他應用程序的Activity
訪問其他應用程序的Activity
Activity既可以在進程內(同一個應用程序)訪問,也可以跨進程訪問。如果想在同一個應用程序中訪問Activity,需要指定Context對象和Activity的Class對象,代碼如下:
Intent intent = new Intent(this, Test.class); startActivity(intent);
Activity的跨進程訪問與進程內訪問略有不同。雖然它們都需要Intent對象,但跨進程訪問並不需要指定Context對象和Activity的 Class對象,而需要指定的是要訪問的Activity所對應的Action(一個字符串)。有些Activity還需要指定一個Uri(通過 Intent構造方法的第2個參數指定)。在android系統中有很多應用程序提供了可以跨進程訪問的Activity,例如,下面的代碼可以直接調用撥打電話的Activity。
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678"); startActivity(callIntent);
在調用撥號程序的代碼中使用了一個Intent.ACTION_CALL常量,該常量的定義如下:
public static final String ACTION_CALL = "android.intent.action.CALL";
這個常量是一個字符串常量,也是我們在這節要介紹的跨進程調用Activity的關鍵。如果在應用程序中要共享某個Activity,需要為這個 Activity指定一個字符串ID,也就是Action。也可以將這個Action看做這個Activity的key。在其他的應用程序中只要通過這個 Action就可以找到與Action對應的Activity,並通過startActivity方法來啟動這個Activity。
下面先來看一下如何將應用程序的Activity共享出來,讀者可按如下幾步來共享Activity:
1. 在AndroidManifest.xml文件中指定Action。指定Action要使用<action>標簽,並在該標簽的android:name屬性中指定Action
2. 在AndroidManifest.xml文件中指定訪問協議。在指定Uri(Intent類的第2個參數)時需要訪問協議。訪問協議需要使 用<data>標簽的android:scheme屬性來指定。如果該屬性的值是“abc”,那麽Uri就應該是“abc://Uri的主體 部分”,也就是說,訪問協議是Uri的開頭部分。
3. 通過getIntent().getData().getHost()方法獲得協議後的Uri的主體部分。這個Host只是個稱謂,並不一定是主機名。讀者可以將其看成是任意的字符串。
4. 從Bundle對象中獲得其他應用程序傳遞過來的數據。
5. 這一步當然是獲得數據後做進一步的處理了。至於如何處理這些數據,就得根據具體的需求決定了。
下面來根據這些步驟共享一個Activity。首先建立一個android工程(ActionActivity),工程的主Activity是Main。在 本例中我們會共享這個Main類。首先打開AndroidManifest.xml文件,添加一個<activity>標簽,並重新定義了 Main的相應屬性。AndroidManifest.xml文件的內容如下:
<!-- 重新配置Main --> <activity android:name=".Main" android:label="@string/app_name" > <intent-filter> <action android:name="net.blogjava.mobile.MYACTION" /> <data android:scheme="info" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
在配置AndroidManifest.xml時要註意,不能在同一個<activity>中配置多個動作,否則會覆蓋MAIN動作以使該程序無法正常啟動(雖然其他應用程序調用Main是正常的)。從上面的代碼可以看出,<action>標簽的android:name屬性值是 net.blogjava.mobile.MYACTION,這就是Main自定義的動作。<data>標簽指定了Url的協議。如果指定 了<data>標簽的android:scheme屬性值(info),則在調用Main時需要使用如下的URL: info://任意字符串
一般<category>標簽的android:name屬性值可以設成android.intent.category.DEFAULT。
下面來看看如何在Main類的onCreate方法中獲得其他應用程序傳遞過來的數據。
public class Main extends Activity implements OnClickListener { private EditText editText; @Override public void onClick(View view) { // 單擊按鈕,會顯示文本框中的內容(以Toast信息框形式顯示) Toast.makeText(this, editText.getText().toString(), Toast.LENGTH_LONG).show(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(this); editText = (EditText) findViewById(R.id.edittext); // 獲得其他應用程序傳遞過來的數據 if (getIntent().getData() != null) { // 獲得Host,也就是info://後面的內容 String host = getIntent().getData().getHost(); Bundle bundle = getIntent().getExtras(); // 其他的應用程序會傳遞過來一個value值,在該應用程序中需要獲得這個值 String value = bundle.getString("value"); // 將Host和Value組合在一下顯示在EditText組件中 editText.setText(host + ":" + value); // 調用了按鈕的單擊事件,顯示Toast信息提示框 onClick(button); } } }
從上面的程序可以看出,首先通過getIntent().getData()來判斷其他的應用程序是否傳遞了Uri(getData方法返回了一個Uri 對象)。如果運行該程序,Uri為null,因此,不會執行if語句裏面的代碼。當其他的應用程序傳遞了Uri對象後,系統會執行if語句裏面的代碼。當 運行ActionActivity後,在文本框中輸入“Running”,單擊“顯示文本框的內容”按鈕,會顯示如圖2所示的Toast提示信息框。
下面來看一下其他的應用程序是如何調用ActionActivity中的Main。新建一個android工程(InvokeActivity),並添加一個按鈕,按鈕的單擊事件方法代碼如下:
public void onClick(View view) { // 需要使用Intent類的第2個參數指定Uri Intent intent = new Intent("net.blogjava.mobile.MYACTION", Uri.parse("info://調用其他應用程序的Activity")); // 設置value屬性值 intent.putExtra("value", "調用成功"); // 調用ActionActivity中的Main startActivity(intent); }
在運行InvokeActivity之前,先要運行ActionActivity以便在android模擬器中安裝該程序。然後單擊InvokeActivity中的按鈕,就會顯示如圖3所示的效果。
當然,也可以使用startActivityForResult方法來啟動其他應用程序的Activity,以便獲得Activity的返回值。例如,可以將ActionActivity中Main類的onClick代碼修改為下面的形式。
public void onClick(View view) { Toast.makeText(this, editText.getText().toString(), Toast.LENGTH_LONG).show(); Intent intent = new Intent(); // 設置要返回的屬性值 intent.putExtra("result", editText.getText().toString()); // 設置返回碼和Intent對象 setResult(2, intent); // 關閉Activity finish(); }
然後在InvokeActivity中使用下面的代碼來調用Main。
intent = new Intent("net.blogjava.mobile.MYACTION", Uri.parse("info://調用其他應用程序的Activity")); // 傳遞數據 intent.putExtra("value", "調用成功"); startActivityForResult(intent, 1); // 1為請求碼
要想接收Activity返回的值,需要覆蓋onActivityResult事件方法,代碼如下:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Toast.makeText(this, "返回值:" + data.getExtras().getString("result"), Toast.LENGTH_LONG).show(); }
當單擊InvokeActivity中的相應按鈕後,並且Main關閉後,會顯示如圖4所示的Toast信息提示框。
從本節的介紹可以看出,跨進程訪問Activity(訪問其他應用程序中的Activity)主要是通過一個Action來完成的,如果要傳遞數據,還需 要指定一個Uri。當然,傳遞數據也可以通過Intent來完成。傳遞數據的過程可以是雙向的。如果要想從調用的Activity中返回數據,就需要使用 startActivityForResult方法來啟動Activity了。
Android跨進程通信訪問其他應用程序的Activity