[翻译]使用intent的activity之间的交互

原文:Intentを用いたActivity間のやりとり

翻译前的废话:因为不熟悉intent-filter和intent,调bug时浪费了很多时间,这篇也就是在官方文档的技术上,有个浅显但是实用的解释。

调用activity

intent与startActivity

从当前activity去调用其他activity的过程是,创建intent、作为参数传入startActibity()来调用。intent分为Explicit intents(明确的intent)与 Implicit intents(隐性的intent),相关详细内容请直接参考官方文档。
隐性的intent,比如想打开指定的url的情况:(译注:总之就是没有指明本app中activity名的情况

Uri uri = Uri.parse("http://www.bar.com/hoge");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

调用activity时的数据设定

startActivity()之前可以设定intent中的Extra。这次以明确的intent为例:

/**调用端*/
import android.content.Intent;
...
Intent intent = new Intent(this, SubActivity.class);
intent.putExtra("foo", someData);
startActivity(intent);
/**被调用端*/
import android.content.Intent;
...
Intent intent = getIntent();
String someData = intent.getStringExtra("foo"); // someData是String的情况
SomeData someData = (SomeData) intent.getSerializableExtra("foo"); // Serializable用implement封装后,自定义格式的数据也可以传递
Bundle args = intent.getExtras(); // 传递的Extra通过Map形式全部取得

被其他actibity调用

intent-filter

通过前面说的startActivity()、隐性的intent形式被调用的场合,必须在AndroidManifest.xml里定义intent-filter:


    
        
        
        
        
    

想接受隐性的intent的场合一定要设定android.intent.category.DEFAULT的category。原因是把隐性的intent传递进startActivity()或者startActivityForResult()以调用其他activity时,默认作为CATEGORY_DEFAULT来处理,要是intent-filter里没有对应的category系统就认为是不合适的intent而不进行处理。

Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and startActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If you do not declare this category in your intent filter, no implicit intents will resolve to your activity.

通过隐性的intent被调用的区别

通过隐性的intent被调用的场合,应该有指定intent里的URL,取出这个URL并判断会比较好:

Intent intent = getIntent();
Uri uri = intent.getData();
if uri == null {
  Log.d("test", "这是app里明确的Intent");
} else {
  Log.d("test", uri.toString());
}

(译注:p.s. Uri uri = intent.getData(); 注意根据activity的lauchMode,除了standard以外另外三个属性会可能调用onNewIntent()而不是onCreate()来更新activity)

Try to override onNewIntent. The problem is that getIntent
returns the Intent that started the Activity, but not the most recent one. But you can override it using setIntent method.

因此需要重载onNewIntent():

@Override
protected void onNewIntent(Intent intent) { 
  super.onNewIntent(intent); 
  setIntent(intent);
}

限制调用activity

因为安全的原因要限制其他的activity的调用,或者需要确认那些启动调用的activity。就会使用下面的两种方式。

android:exported设定false

AndroidManifest.xml的activity的设定里,android:exported设定false的话,其他activity的component无法调用该activity:

AndroidManifest.xml

API Guides的官方说明:

android:exported
Whether or not the activity can be launched by components of other applications — "true" if it can be, and "false" if not. If "false", the activity can be launched only by components of the same application or applications with the same user ID.

Activity.getCallingActibity()取得启动调用的activity

使用Activity.getCallingActivity()的话,就可以知道startActivityForResult()的调用元。(startActivity()的话就还是不知道哦。) (译注:getCallingActivity()返回依旧是null。宝宝就在这里调了好久~

参考文档

Intents and Intent Filters
activity

你可能感兴趣的:([翻译]使用intent的activity之间的交互)