如何在没有硬编码Activity类的服务库中从Notification启动主Activity

时间:2012-11-26 01:53:41

标签: android

我在服务中使用以下代码来打开main / launcher Activity,代码工作正常,直到我将此项目声明为库并创建了另外两个使用此库的项目。

所以在服务的onStartCommand中编写了这段代码。

 final Notification notification = new Notification(R.drawable.ic_launcher, null, 0);   

    String notifTitle = "Service";
    String notifMessage = "Running";

    final Intent notificationIntent = new Intent(this,   MainActivity.class);
    notificationIntent.putExtra("extra", "value");
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                            | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    notificationIntent.setAction("android.intent.action.MAIN");
    notificationIntent.addCategory("android.intent.category.LAUNCHER");

    final PendingIntent contentIntent = PendingIntent
                            .getActivity(this, 0, notificationIntent,0);



    notification.setLatestEventInfo(this, notifTitle, notifMessage, contentIntent);     
    startForeground(17, notification);

MainActivity.class是库的一部分,使用此库的两个项目的主要活动MainActivityA,MainActivityB扩展了库的MainActivity。

现在的问题是,当我点击服务通知时,应该启动MainActivityA或MainActivityB,但现在没有任何反应,但之前它在图书馆本身就是一个项目时起作用

任何想法都会很有用,

谢谢,

4 个答案:

答案 0 :(得分:1)

你正在硬编码你的意图

final Intent notificationIntent = new Intent(this,   MainActivity.class);

启动MainActivity.class而不是MainActivityA.class或MainActivityB.class。您必须将正确的类传递给您的服务,或者将意图更改为更通用,并让Intent框架发现您的活动(这可能是您的应用所独有的)。

我正在写一些关于意图过滤器的内容,但@ smith324打败了我。

我会考虑使用元数据而不是类似于:

的字符串资源
<meta-data android:name="com.foo.service.LaunchName" android:value="com.foo.MainActivityA"></meta-data>

这可以避免第三方字符串名称冲突,如果你添加额外的库,并且在我看来保持字符串文件更清洁开发人员,因为这更多的是你的类的连接而不是可能需要国际化/翻译的东西用户。

请参阅:How do you add user defined properties/values in to the Android manifest file?

答案 1 :(得分:1)

这是一个古老的问题,但我在尝试自己解决问题时遇到了这个问题。我想出了一种更简单的方法,无需配置任何字符串或传入任何参数。

String packageName = getPackageName();
Intent notificationIntent = getPackageManager().getLaunchIntentForPackage(packageName);

现在你有了添加额外内容的意图等等。

答案 2 :(得分:0)

有几种方法可以解决这个问题。

您可以在清单中的活动上声明一个Intent过滤器并广播Intent,但如果用户在其设备上安装了两个版本,则可能会出现问题。 (支持库中有一个本地广播,您可以使用docs

我个人会使用Android的资源系统动态加载类名。 Intents为您提供了设置ComponentName的能力,这与为Activity的类提供硬编码引用相同。

Intent i = new Intent();
String mPackage = ctx.getPackageName();
String mClass = ctx.getResources().getString(R.string.notification_class_name);
i.setComponent(new ComponentName(mPackage,mPackage+mClass));

库项目的值可以被使用它们的项目覆盖,因此在这两个项目中,您在strings.xml中都有一个与该应用程序的通知活动相对应的值。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="notification_class_name">.MainActivityA</string>
</resources>

然后,您可以将此Intent与pendingIntent一起使用,它将打开当前应用程序内的活动。

答案 3 :(得分:0)

要获取启动器活动,这是一种方式。

public static Class<?> GetLauncherActivity(Context context)
    {
        String packageName = context.getPackageName();
        Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
        String className = launchIntent.getComponent().getClassName();
        try
        {
            return Class.forName(className);
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
            return null;
        }
    }