1. 程式人生 > >Android跨進程通信訪問其他應用程序的Activity

Android跨進程通信訪問其他應用程序的Activity

null activit finish 打開 撥打 內容 click 很多 color

訪問其他應用程序的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