0

MusicPlayingService(拡張MediaBrowserServiceCompat)とサービスを制御するウィジェットを持つ音楽プレーヤーアプリがあります。 MusicPlayingServiceも「MediaSessionCompat.Callback」を実装し、現在のMediaSessionからのすべてのコールバックを処理MusicStateManagerへの参照(MusicServicesのonCreateに作成)している:私のウィジェットは、送信された保留中のインテントの束をmSession.setCallback(MusicStateManager);サービスが停止するとWidgetのPendingIntentが失われる

public class MusicPlayingService extends MediaBrowserServiceCompat implements 
    AudioManager.OnAudioFocusChangeListener { 

@RequiresPermission(Manifest.permission.READ_PHONE_STATE) 
@Override 
public void onCreate() { 
    super.onCreate(); 
    Log.d(TAG, "MusicPlayingService started"); 

    ..... 

    mPlayerStateManager = new MusicStateManager(this); 

    ..... 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    Log.d(TAG, "onStartCommand"); 
    MediaButtonReceiver.handleIntent(mPlayerStateManager.getSession(), intent); 
    return START_STICKY; 
} 

を持っていますMusicPlayingServiceに送信し、MusicStateManagerで処理します。すべて素晴らしいです。

public class MusicStateManager extends MediaSessionCompat.Callback { 

.... 

public MusicStateManager(@NonNull MusicStateManager argService) { 
    Log.d(TAG, "setting service"); 
    mPlayerService = argService; 

    ComponentName mediaButtonReceiver = new ComponentName(mPlayerService, HeadsetReceiver.class); 
    mSession = new MediaSessionCompat(mPlayerService, SESSION_TAG, mediaButtonReceiver, null); 
    mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | 
      MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); 

    Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 
    PendingIntent pendingMediaButtonIntent = PendingIntent.getBroadcast(mPlayerService, 0, mediaButtonIntent, 0); 
    mSession.setMediaButtonReceiver(pendingMediaButtonIntent); 

    Intent toggleIntent = new Intent(NotificationPlayer.toggleAction); 
    PendingIntent pendingToggleIntent = PendingIntent.getBroadcast(mPlayerService, 0, toggleIntent, 0); 
    mSession.setMediaButtonReceiver(pendingToggleIntent); 

    mSession.setCallback(this); 
    mSession.setActive(true); 

} 

    /** 
    * Callback method called from MusicStateManager whenever the music is about to play. 
    */ 
    public void onPlay() { 
     Log.d(TAG, "onPlay"); 

     ....... 
    } 

    @Override 
    public void onCustomAction(String action, Bundle extras) { 
     Log.d(TAG, "received action: " + action); // NoI18N 

     if (ACTION_TOGGLE.equals(action)) { 
      mPlayerService.toggle(); 
     } 
    } 

物がございます。私が強制的にアプリケーションを停止すると、音楽サービスがシャットダウンします(明らかに)。ウィジェットのボタンを押すとサービスが再開します(LogCatのさまざまなLog.d(...)から見ることができます)。しかし、ウィジェットのPendingIntentは失われ、決して処理されません。

これはユーザには奇妙な意味を持ちますが、ほとんどの場合、ウィジェットのボタンは機能します(サービスが実行されているとき)。しかし、私はこの問題をデバッグし、私のPendingIntentに何が起こるか見ることができますどのように任意のアイデアあなたがそれらを再度押すと、彼らが動作する場合(初回のサービスを始めたが、意図を処理するために失敗したため。

+0

コードには、ウィジェットのPendingIntentsを設定する場所は含まれません。また、 'setMediaButtonReceiver'を複数回呼び出すと、以前に設定した値が上書きされ、[メディアボタンからの再生を再開]するだけです(https://developer.android.com/reference/android/support/v4/)。 media/session/MediaSessionCompat.html#setMediaButtonReceiver(android.app.PendingIntent))。これは呼び出されず、ウィジェットの動作もまったく変更されません。ウィジェットコードと、起動された 'BroadcastReceiver.onReceive()'や 'Service.onStartCommand()'を含めることができますか? – ianhanniballake

+0

私はあなたが求めたものすべてを追加していました。しかし、私がPendingIntentsをコピー/ペーストしようとしていたとき、私はcontextとしてapplicationContextを使用していることに気付きました。これは問題であることが判明しました!私がデバッグするのが難しい理由は、アプリケーションが起動されたときにMusicServiceも起動し、LogCatからMusicServiceが正しく起動したように見えたためです。 –

+0

さて、あなたのウィジェットの 'RemoteViews'で' PendingIntent'が何を使用しているのかまだわかりません - 私は[setOnClickPendingIntent](https://developer.android.com/reference/android/widget/RemoteViews .html#setOnClickPendingIntent(int、%20android.app.PendingIntent))。 – ianhanniballake

答えて

0

0を作成する最良の方法メディア再生用のは、MediaButtonReceiver.buildMediaButtonPendingIntent()です。これにより、正しいコールバックをトリガーする定数PlaybackStateCompat.ACTION_を渡すことができます。

PendingIntent playPendingIntent = MediaButtonReceiver 
    .buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_PLAY); 

あなたがすでにonStartCommand()に正しいMediaButtonReceiver.handleIntent()コールを持っていますが、あなたはsetPlaybackState()を呼び出すことによって、正しい行動を可能にするあなたのMediaSessionCompatを作成するときにも確認する必要がありそうです:

// Ideally, you should keep a reference to this Builder to update it, 
// rather than create it from scratch each time 
PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder() 
    .setActions(PlaybackStateCompat.ACTION_PLAY | 
       PlaybackStateCompat.ACTION_PLAY_PAUSE); 
mSession.setPlaybackState(playbackStateBuilder.build()); 

によってMediaSessionCompatとして、デフォルトではメディアボタンは使用できません。インスタンシエーションから直接ACTION_PLAYを確実にサポートすることで、最初のMediaButtonReceiver.handleIntent()が正しくMediaSessionCompat.Callbackを呼び出すようにします。

関連する問題