0

MusicPlayingService (확장자 : MediaBrowserServiceCompat)가있는 뮤직 플레이어 앱과 서비스를 제어하는 ​​위젯이 있습니다. MusicPlayingService는 "MediaSessionCompat.Callback"을 구현하고 현재 MediaSession에서 모든 콜백을 처리하는 MusicStateManager에 대한 참조합니다 (MusicServices에서 onCreate에서 만든)가 : mSession.setCallback(MusicStateManager);위젯의 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; 
} 

내 위젯은 전송 보류 텐트의 무리가 있습니다 으로 이동하여 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를 복사/붙여 넣으 려 할 때 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를 만들 때 당신은 또한 확인해야합니다 : 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()); 

을하여 기본값은 미디어 버튼을 허용하지 않습니다. 인스턴스화를 통해 ACTION_PLAY을 직접 지원함으로써 가장 먼저 MediaButtonReceiver.handleIntent()MediaSessionCompat.Callback으로 올바르게 호출되도록 할 수 있습니다.