【问题标题】:Is it possible to start an activity inside of a try/catch?是否可以在 try/catch 中启动活动?
【发布时间】:2012-12-01 19:05:47
【问题描述】:

我有一个服务是用来启动安卓音乐应用程序的,基本上是让音乐应用程序在屏幕上弹出。我尝试这样做的方式是:

public void onStart(Intent intent, int startId) 
{
    // TODO Auto-generated method stub
    super.onStart(intent, startId);
    System.out.println("LOGS STARTED");
    ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
    List l = am.getRunningAppProcesses();
    Iterator i = l.iterator();
    PackageManager pm = this.getPackageManager();
    while(i.hasNext()) 
    {
        ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo)(i.next());
        try 
        {
            CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));
            Log.w("LABEL", c.toString());
            if(c.equals("Music"))
            {
                System.out.println("HELLO \n");
                                    Intent in = new Intent();
                in.setClassName("com.android.music", "com.android.music.MediaButtonIntentReceiver");
                startActivity(in);
            }
         }
        catch(Exception e) 
        {
            //Name Not FOund Exception
        }
    }

}

logcat 确实显示 Hello,但由于某种原因,音乐不会开始。但是当我将它移到另一个位置时,它确实开始了。有没有办法以这种方式做到这一点,还是我必须以另一种方式做到这一点?我希望用户单击图标后弹出音乐应用程序。这就是为什么我做了 if c.equals("Music") 部分。之所以在try里面是因为这行:

CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));

会得到一个错误,快速解决方法是让它被 try/catch 语句包围。

【问题讨论】:

  • 只是猜测...“com.android.music.MediaButtonIntenrtReceiver”->“com.android.music.MediaButtonIntentReceiver”
  • 绝对有可能。如果音乐不响,那就是别的问题了……
  • @Thomas 我不想播放音乐,我只想弹出应用程序,但它不会弹出。
  • try catch 不是“快速修复”。这是您控制预期和意外错误的方式。很可能你会因为你在你的 catch 块中什么都不做而得到一个你隐藏的错误。要么在你的 catch 上设置一个断点并检查异常,要么将其删除并检查 logcat 是否有错误。然后用确切的问题编辑您的问题。
  • try-catch 块与您的其余代码没有任何关系。正如 dougcunha 所说,您在 in.setClassName("com.android.music", "com.android.music.MediaButtonIntenrtReceiver"); 行上有错字 - IntenrtReceiver 应该是 IntentReceiver

标签: android android-intent service android-activity try-catch


【解决方案1】:

这里有很多关于 Intent、Activity 和 BroadcastReceivers 之间的区别以及 Android 为此类事情设置的一般方式的误解。让我们看看我们是否可以清除其中的一些。 :)

您已经创建了一个 Intent,并尝试将其定位到特定包,然后调用 startActivity。但是你试图定位组件com.android.music.MediaButtonIntentReceiver,它不是一个活动。使用此 Intent 调用 startActivity 可能会失败。

这比这更糟糕。即使你有准确的活动名称来发送com.android.music 包的意图,安装了不同音乐应用程序的用户怎么办?许多 OEM 在设备上发布了他们自己的音乐播放器变体,这意味着在他们的设备上明确定位该软件包名称将失败。例如,Nexus 设备上的 Google Play 音乐使用包名称 com.google.android.music,而不是您在上面指定的包。

基于匹配本地化应用标签字符串的过滤也会给您带来问题。您正在寻找一个标题为“音乐”的应用程序,但此字符串会因特定的音乐应用程序和区域设置而异。例如,Google Play 音乐使用字符串“Google Play 音乐”,而翻译成其他语言的“音乐”也不会匹配这个确切的字符串。

最后,您只需要使用 ActivityManager 查看正在运行的应用进程。这会给您带来问题,因为如果应用程序当时没有运行怎么办? Android 可以在后台终止应用程序进程以获取资源,用户不需要知道这一点。您正在编写的代码会为您的用户意外中断。

那你能做什么?

意图是通用的。不要使用特定的人类可读标签字符串来抓取特定包的运行进程列表,而是告诉 Android 你在语义上尝试做什么。您想启动音乐应用。

Intent musicIntent = new Intent(Intent.ACTION_MAIN)
        .addCategory(Intent.CATEGORY_LAUNCHER)
        .addCategory(Intent.CATEGORY_APP_MUSIC)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(musicIntent);

逐行进行,我们在这里所做的就是告诉 Android:

  • 我们希望启动“主要”操作,而不是更专业的操作
  • 我们希望它是用户通常会从启动器(主屏幕)启动的 Activity
  • 我们希望它是一款宣传自己能够播放音乐的应用
  • 我们希望它在新任务中启动,或者如果该应用的任务已经存在,请将其置于最前面。

现在,我们通过更少的代码行设法以更通用的方式实现了这一点,这种方式更能抵抗极端情况,并且还会自动遵循用户对音乐应用的偏好。 (如果有多个应用程序与 Intent 匹配,系统会询问用户他们想要启动哪个应用程序,并有机会将其设置为下次的默认值。)

话虽如此,您还提到您正在从服务启动活动。如果这种情况突然发生而不是响应用户采取的操作,通常会被认为是糟糕的用户体验设计,因此请记住这一点。

【讨论】:

  • +1(投票)我同意你的看法@adamp。非常感谢您分享这些详细信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-12
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
相关资源
最近更新 更多