获取当前 android.intent.category.LAUNCHER 活动的实例

7

我创建了一个库项目,它在多个应用程序之间共享。我实现了一个简单的会话过期功能,可以在一定时间后将用户踢回登录界面。

登录界面活动是我的主要活动,因此在清单中它看起来像这样:

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.Sherlock.Light.DarkActionBar"
    android:name="com.blah.application.MyApplication" >
    <activity
        android:name="com.blah.activity.LoginScreenActivity"
        android:label="@string/title_activity_main"
        android:screenOrientation="portrait"
        android:configChanges="orientation|keyboardHidden"
        android:windowSoftInputMode="adjustPan">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

当会话过期时,我希望将用户踢回登录屏幕,但我不想硬编码活动的名称,因为它可能因使用库的特定应用程序而异。以下是之前我的做法:

Intent intent = new Intent(context, LoginScreenActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);

这种方法在应用的主活动不是LoginScreenActivity时无法正常工作。我不想硬编码“LoginScreenActivity.class”,而是想以编程方式确定主类的名称,然后将用户重定向到该活动...有人能帮帮我吗?
提前感谢!
编辑
我找到了一种实现相同结果的方法,但它绝对不是最好的。由于部署使用相同库的新应用程序需要一定的配置(字符串,布尔值等),因此我添加了一个字符串到特定应用程序的strings.xml文件中,为该应用程序定义了“main”活动名称:
<string name="mainClassName">com.blah.specificapp.activity.SpecificAppLoginScreenActivity</string>

然后,我可以通过名称获取该类的句柄,并将用户重定向到那里:

Class<?> clazz = null;

try 
{
    clazz = Class.forName(context.getString(R.string.mainClassName));
} 
catch (ClassNotFoundException e) 
{
    // TODO Auto-generated catch block
    e.printStackTrace();
}

if(clazz != null)
{
    Intent intent = new Intent(context, clazz);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    context.startActivity(intent);
}

我知道这个解决方案很糟糕,但它能够实现功能。就像我说的那样,每次添加新应用都需要进行一定量的配置,所以再添加一个字符串并不是很麻烦,只是不太优雅。如果有任何可以实现相同目标而不使用我的hack的建议,我将不胜感激。


一个应用程序可以有多个_main_活动... - K-ballo
没错,但如果我能得到这些列表,那么我就可以选择正确的一个。我正在寻找的类的名称将始终命名为“*LoginScreenActivity”。 - DiscDev
这听起来和硬编码class一样糟糕... - K-ballo
我同意。但我不可以硬编码这个类因为我不知道它的名字。或许我需要完全不同的方法……你有别的想法吗? - DiscDev
如果您正在使用Android 3+的_Navigation_元数据或_Support Library_中的等效元数据,您可以沿着堆栈向上查找并找出您的根Activity是什么。 - K-ballo
你能提供一个遍历堆栈到根活动的示例吗?我正在使用支持库,所以这对我来说是可用的,但是在搜索时我没有找到太多帮助。谢谢。 - DiscDev
2个回答

16

您可以使用PackageManager请求启动Intent,方法如下:

Intent launchIntent = PackageManager.getLaunchIntentForPackage(context.getPackageName());

这将返回一个Intent,您可以使用它来启动“主”活动(我假设是您的“登录”活动)。只需添加Intent.FLAG_ACTIVITY_CLEAR_TOP,您就可以顺利进行了。


1
大卫 - 你真是个天才。这正是我正在寻找的。刚试过了,它完全按照我想要的方式工作(将用户返回到“主”活动)。感谢你的帮助! - DiscDev
2
你也可以从活动上下文中获取 PackageManagergetApplication().getPackageManager().getLaunchIntentForPackage(getApplication().getPackageName()) - gkiko

0

你可以在你的Intent过滤器中使用MIME类型,这样怎么样?

    <activity android:name=".LoginActivity"
              android:exported="true" android:launchMode="singleTop" android:label="@string/MT">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT"/>
            <action android:name="com.foo.ACTION_LOGIN" />
            <data android:mimeType="application/x.foo.com.mobile.login" /> 
     </intent-filter>
    </activity>

然后按照以下方式启动活动:

Intent intent = new Intent();
intent.setAction("com.foo.ACTION_LOGIN");
intent.setType("application/x.foo.com.mobile.login");
startActivity(myIntent);

因此,意图将由与此操作/ MIME 类型配对注册的任何活动服务。我不确定,但我认为如果该活动托管在同一个应用程序中,它可能会被首选。


我尝试了你的方法,但是它抛出了一个异常: FATAL EXCEPTION: main android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.MAIN typ=application/com.blah.activity.main } intent.setAction("android.intent.action.MAIN"); intent.setType("application/com.blah.activity.main"); - DiscDev
我制作了一个示例应用程序并遇到了类似的问题。更改启动器活动的意图过滤器会破坏Android启动应用程序的能力。我想这是一种有缺陷的方法。很抱歉给你带来了错误的指引。 - EJK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接