我需要使用intent filter指定我的登录活动:
<activity
android:name=".view.LoginActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="com.example.sdk.LOGIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
我想这样做的原因是我正在开发一个我想在少数项目中使用的SDK,这是我能够弄清楚如何通知SDK的最佳方式,即登录活动,虽然它只在app模块中定义。
在我做了这样的声明后,我开始这样的登录活动(在库和应用程序中):
Intent intent = new Intent();
intent.setAction("com.example.sdk.LOGIN");
context.startActivity(intent);
有可能在同一设备上同时安装两个或多个依赖相同SDK的应用程序。如果我得到了正确的答案,在这种情况下,在每个应用程序中,Activity start将启动一个随机登录活动(可能在应用程序A中调用启动应用程序B的登录)。
欢迎重新使用与登录相关的逻辑的替代方法的建议,而不是依赖于意图过滤器。
答案 0 :(得分:2)
我找到了实现我想要的方法。
基本上我不会在我的库中硬编码包,而是使用以下命令从库启动登录活动:
private static final String INTENT_ACTION_PATTERN = "%s.LOGIN";
public void startLoginActivity() {
Intent intent = new Intent();
String intentAction = String.format(INTENT_ACTION_PATTERN, mContext.getPackageName());
intent.setAction(intentAction);
mContext.startActivity(intent);
}
我将使用一个约定,我将始终定义自定义意图过滤器以匹配我的应用程序包:
<activity
android:name=".view.LoginActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="com.example.myapp.LOGIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
答案 1 :(得分:1)
在这些应用程序中的每个应用程序中,Activity start将启动随机登录活动。
这不是真的。来自docs:
如果只有一个应用可以处理它,该应用会立即打开并获得意图。如果多个活动接受意图,系统会显示一个对话框,以便用户可以选择要使用的应用。
至于你的第二个问题:
有没有办法告诉应用程序A中的调用只在应用程序A中使用意图过滤器声明?
我假设您无法使用显式意图启动活动,因为您无法知道库模块中客户端的活动名称。
有没有 API,可以为您提供活动类,按其intent-filter
属性进行过滤。 PackageManager
API无法提供帮助。这意味着,您无法获取活动的类实例以显式启动活动。这反过来意味着,唯一的方法是隐式启动活动,正如已经说过的那样,它将通过对话框进行提示。
答案 2 :(得分:0)
这些是我做的步骤:
清单示例:
<activity
android:name="com.test.MainActivity">
<intent-filter>
<action android:name="test_action_that_should_be_unique"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
覆盖活动生命周期:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent == null)
return;
String action = intent.getAction();
if (action == null || !action.equals("test_action_that_should_be_unique"))
return;
Toast.makeText(this, "onCreate: test_action_that_should_be_unique", Toast.LENGTH_SHORT).show();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent == null)
return;
String action = intent.getAction();
if (action == null || !action.equals("test_action_that_should_be_unique"))
return;
Toast.makeText(this, "onNewIntent: test_action_that_should_be_unique", Toast.LENGTH_SHORT).show();
}
从其他应用程序测试新的自定义意图:
Intent intent = new Intent("test_action_that_should_be_unique");
startActivity(intent);
当然请检查上述null意图:
PackageManager packageManager = getActivity()。getPackageManager(); if(intent.resolveActivity(packageManager)!= null){ startActivity(意向); }
答案 3 :(得分:0)
我认为更好的解决方案是使用<meta-data>
中<application>
部分中的AndroidManifest
属性。客户可以在此处指定任何值,然后可以在库中读取它。因此,您的客户将指定其LoginActivity
的类名,然后将其用于通过显式Intent启动它。
<application ...>
...
<meta-data android:name="com.example.sdk.LOGIN_ACTIVITY" android:value=".view.LoginActivity" />
</application>
public void startLoginActivity(Context context) {
String packageName = context.getPackageName();
PackageManager pm = context.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo(packageName, PackgeManager.GET_META_DATA);
Bundle data = appInfo.metaData;
String activityName = data.getString("com.example.sdk.LOGIN_ACTIVITY");
if (activityName == null || activityName.isEmpty()) {
return;
}
ComponentName component = ComponentName.createRelative(packageName, activityName);
Intent intent = new Intent().setComponent(component);
context.startActivity(intent);
}