是否可以在try/catch中启动活动?

DaJ*_*ams 0 service android try-catch android-intent android-activity

我有一个服务,假设启动Android音乐应用程序,基本上使音乐应用程序弹出屏幕.我试图这样做的方式是:

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
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

logcat会显示Hello,但由于某种原因,音乐无法启动.但是当我把它移到另一个地方时,它确实开始了.有没有办法这样做,或者我必须以另一种方式做到这一点?我希望用户点击图标后弹出音乐应用程序.这就是我做if c.equals("音乐")部分的原因.它在try中的原因是因为这一行:

CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));
Run Code Online (Sandbox Code Playgroud)

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

ada*_*amp 7

这里有很多关于Intents的误解,活动和BroadcastReceivers之间的区别,以及为这样的事情设置Android的一般方式.让我们看看我们是否可以清除其中一些内容.:)

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

但这比那更糟糕.即使你有精确的活动名称来发送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);
Run Code Online (Sandbox Code Playgroud)

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

  • 我们想要发起一个"主要"行动而不是更专业的行动
  • 我们希望它成为用户通常从Launcher启动的Activity(主屏幕)
  • 我们希望它成为一个宣传自己能够播放音乐的应用程序
  • 我们希望它在新任务中启动,或者如果该应用程序的任务已经存在,请将其置于最前面.

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

总而言之,您还提到过您正在从服务开始活动.它通常被认为是糟糕的用户体验设计,如果这种情况无处不在,而不是响应用户采取的行动,所以请记住这一点.