0

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

}

logcatはHelloを表示しますが、何らかの理由で音楽が開始されません。しかし、私がそれを別の場所に移動すると、それは始まります。この方法でそれを行う方法はありますか、それとも別の方法で行う必要がありますか?ユーザーがアイコンをクリックすると、音楽アプリケーションがポップアップするようにしたい。そのため、if c.equals( "Music")の部分を実行しました。それが試行の中にある理由は、この行のためです:

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

エラーが発生し、迅速な修正は、try/catchステートメントで囲まれるようにすることでした。

4

1 に答える 1

8

ここでは、Intents、アクティビティと BroadcastReceivers の違い、および Android がこのようなものに設定される一般的な方法について、多くの誤解があります。その一部をクリアできるかどうか見てみましょう。:)

Intent を作成し、特定のパッケージをターゲットにしてstartActivity. com.android.music.MediaButtonIntentReceiverしかし、Activity ではないcomponent をターゲットにしようとしています。startActivityこのインテントでの呼び出しは失敗する可能性があります。

それだけよりも悪いです。パッケージのインテントを送信する正確なアクティビティ名があったとしてcom.android.musicも、別の音楽アプリをインストールしているユーザーはどうなるでしょうか? 多くの OEM は、デバイスに独自の音楽プレーヤーのバリアントを出荷しています。つまり、そのパッケージ名を明示的にターゲットにすると、デバイスで失敗します。たとえば、Nexus 端末に同梱されている Google Play Music では、com.google.android.music上記で指定したパッケージではなく、パッケージ名が使用されます。

ローカライズされたアプリ ラベル文字列の一致に基づくフィルタリングも、問題を引き起こします。「Music」という単純なタイトルのアプリを探していますが、この文字列は特定の音楽アプリとロケールの両方によって異なります。たとえば、Google Play Music では「Google Play Music」という文字列が使用されますが、他の言語に翻訳された「Music」も、この正確な文字列とは一致しません。

最後に、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 に次のことを伝えることです。

  • より専門的なものではなく、「メイン」のアクションを開始したい
  • ユーザーが通常ランチャー (ホーム画面) から起動するアクティビティにしたい
  • 音楽を再生できることを宣伝するアプリにしたい
  • 新しいタスクで起動するか、そのアプリのタスクが既に存在する場合は、それを前面に表示します。

より少ないコード行で、より一般的な方法でこれを達成することができました。これは、エッジ ケースに対してより抵抗力があり、音楽アプリのユーザーの好みにも自動的に従います。(インテントに一致するアプリが複数ある場合、ユーザーはどのアプリを開始するかを尋ねられ、それを次回のデフォルトとして設定する機会が与えられます。)

そうは言っても、サービスからアクティビティを開始していることにも言及しました。これがユーザーのアクションに応じて発生するのではなく、どこからともなく発生する場合は、通常、ユーザー エクスペリエンスの設計が不十分であると見なされるため、注意してください。

于 2012-12-01T21:08:24.960 に答える