2016-11-16 2 views
1

"メディアを制御するための欠落許可" 私はこのコードに問題があります。それは、Android 5.xのといくつかのサムスンの携帯電話にoccuresでAbstractMethodError onClientSessionEventと

AbstractMethodError: abstract method "void android.media.RemoteController$OnClientUpdateListener.onClientSessionEvent 

@SuppressWarnings("deprecation") 
@TargetApi(Build.VERSION_CODES.KITKAT) 
public class NotificationRemoteControllerService extends NotificationService implements OnClientUpdateListenerExtended { 
private static final String TAG = "NRemoteContollerService"; 
public static boolean isMusicPlaying = false; 
MusicPlaybackState currenTplaybackState; 
// REMOTE CONTROLLER 
private int currentPlaybackState; 
private SimpleMusicMetadata simpleMusicMetadata; 
private RemoteController remoteController; 

private static String getStringMetadata(RemoteController.MetadataEditor metadataEditor, int key) { 
    return metadataEditor.getString(key, METADATA_DEFAULT_VALUE); 
} 

public static boolean isEnabled(Context context) { 
    ComponentName cn = new ComponentName(context, NotificationRemoteControllerService.class); 
    String flat = Settings.Secure.getString(context.getContentResolver(), "enabled_notification_listeners"); 
    return flat != null && flat.contains(cn.flattenToString()); 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 

    remoteController = new RemoteController(this, this); 
} 

RemoteController.OnClientUpdateListener myListener = new RemoteController.OnClientUpdateListener() { 
    @Override 
    public void onClientChange(boolean b) { 

    } 

    @Override 
    public void onClientPlaybackStateUpdate(int i) { 

    } 

    @Override 
    public void onClientPlaybackStateUpdate(int i, long l, long l1, float v) { 

    } 

    @Override 
    public void onClientTransportControlUpdate(int i) { 

    } 

    @Override 
    public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) { 

    } 
} 
/* ---------------------------------------------------------------------------------------- 

            REMOTE CONTROLLER 

    ---------------------------------------------------------------------------------------- */ 

@Override 
public void onDestroy() { 
    disableRemoteController(); 
    super.onDestroy(); 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    int artworkWidth; 
    int artworkHeight; 
    if (intent != null) { 
     artworkWidth = intent.getIntExtra(EXTRA_ALBUM_COVER_WIDTH, 
       DEFAULT_ATTRIBUTE_ALBUM_COVER_WIDTH); 
     artworkHeight = intent.getIntExtra(EXTRA_ALBUM_COVER_HEIGHT, 
       DEFAULT_ATTRIBUTE_ALBUM_COVER_HEIGHT); 
    } else { 
     artworkWidth = DEFAULT_ATTRIBUTE_ALBUM_COVER_WIDTH; 
     artworkHeight = DEFAULT_ATTRIBUTE_ALBUM_COVER_HEIGHT; 
    } 

    Log.e(TAG, "isMusicPlaying " + Boolean.toString(isMusicPlaying)); 
    if (simpleMusicMetadata == null) Log.e(TAG, "simpleMusic is Null!!"); 

    if (isMusicPlaying && simpleMusicMetadata != null) { 
     Log.e(TAG, "onStartCommand: eventbus.get " + simpleMusicMetadata.getTitle()); 
     EventBus.getDefault().post(simpleMusicMetadata); 
    } else { 
     remoteController.setArtworkConfiguration(artworkWidth, artworkHeight); 
     enableRemoteController(); 
    } 
    if (currenTplaybackState != null) { 
     Log.e(TAG, "PLAY_STATE" + currenTplaybackState.name()); 
     EventBus.getDefault().post(currenTplaybackState); 
    } 
    return START_STICKY; 
} 

private void postUpdateMetadata(RemoteController.MetadataEditor metadataEditor) { 
    String title = getStringMetadata(metadataEditor, METADATA_KEY_TITLE); 
    String artist = getStringMetadata(metadataEditor, METADATA_KEY_ARTIST); 
    String album = getStringMetadata(metadataEditor, METADATA_KEY_ALBUM); 

    Bitmap artwork = metadataEditor.getBitmap(MediaMetadataEditor.BITMAP_KEY_ARTWORK, null); 

    simpleMusicMetadata = new SimpleMusicMetadata(title, artist, album, artwork); 
    EventBus.getDefault().post(simpleMusicMetadata); 

} 

private void enableRemoteController() { 
    if (!EventBus.getDefault().isRegistered(this)) 
     EventBus.getDefault().register(this); 
    if (remoteController != null) { 
     try { 
      AudioManager manager = ((AudioManager) getApplicationContext().getSystemService(AUDIO_SERVICE)); 

      if (!manager.registerRemoteController(remoteController)) { 
       Log.e(TAG, "Failed to register remoteController."); 
      } 

     } catch (Exception e) { 
      Log.e(TAG, "enableRemoteController EXCEPTION"); 
      Log.e(TAG, e.getLocalizedMessage()); 
      Log.e(TAG, e.getMessage()); 

     } 
    } 

    setSynchronizationMode(RemoteController.POSITION_SYNCHRONIZATION_NONE); 
    currentPlaybackState = PLAYBACK_INVALID_STATE; 
} 

private void setSynchronizationMode(int sync) { 
    if ((sync != RemoteController.POSITION_SYNCHRONIZATION_NONE) && (sync != RemoteController.POSITION_SYNCHRONIZATION_CHECK)) { 
     throw new IllegalArgumentException("Unknown synchronization mode " + sync); 
    } 

    Class<?> iRemoteControlDisplayClass; 

    try { 
     iRemoteControlDisplayClass = Class.forName("android.media.IRemoteControlDisplay"); 
    } catch (ClassNotFoundException e1) { 
     throw new RuntimeException("Class IRemoteControlDisplay doesn't exist, can't access it with reflection"); 
    } 

    Method remoteControlDisplayWantsPlaybackPositionSyncMethod; 
    try { 
     remoteControlDisplayWantsPlaybackPositionSyncMethod = AudioManager.class.getDeclaredMethod("remoteControlDisplayWantsPlaybackPositionSync", iRemoteControlDisplayClass, boolean.class); 
     remoteControlDisplayWantsPlaybackPositionSyncMethod.setAccessible(true); 
    } catch (NoSuchMethodException e) { 
     throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() doesn't exist, can't access it with reflection"); 
    } 

    Object rcDisplay; 
    Field rcDisplayField; 
    try { 
     rcDisplayField = RemoteController.class.getDeclaredField("mRcd"); 
     rcDisplayField.setAccessible(true); 
     rcDisplay = rcDisplayField.get(remoteController); 
    } catch (NoSuchFieldException e) { 
     throw new RuntimeException("Field mRcd doesn't exist, can't access it with reflection"); 
    } catch (IllegalAccessException e) { 
     throw new RuntimeException("Field mRcd can't be accessed - access denied"); 
    } catch (IllegalArgumentException e) { 
     throw new RuntimeException("Field mRcd can't be accessed - invalid argument"); 
    } 

    AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 
    try { 
     remoteControlDisplayWantsPlaybackPositionSyncMethod.invoke(am, iRemoteControlDisplayClass.cast(rcDisplay), true); 
    } catch (IllegalAccessException e) { 
     throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() invocation failure - access denied"); 
    } catch (IllegalArgumentException e) { 
     throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() invocation failure - invalid arguments"); 
    } catch (InvocationTargetException e) { 
     throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() invocation failure - invalid invocation target"); 
    } 
} 


private void disableRemoteController() { 
    EventBus.getDefault().unregister(this); 
    if (remoteController != null) { 
     ((AudioManager) getApplicationContext().getSystemService(AUDIO_SERVICE)) 
       .unregisterRemoteController(remoteController); 
    } 
} 

private boolean sendMediaKeyEvent(int key) { 
    try { 
     KeyEvent downKeyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, key); 
     KeyEvent upKeyEvent = new KeyEvent(KeyEvent.ACTION_UP, key); 
     boolean downResult = remoteController.sendMediaKeyEvent(downKeyEvent); 
     boolean upResult = remoteController.sendMediaKeyEvent(upKeyEvent); 
     return downResult && upResult; 
    } catch (NullPointerException e) { 
     Log.e(TAG, "remoteController == null"); 
     return false; 
    } 
} 

private boolean sendNextKeyEvent() { 
    return sendMediaKeyEvent(MUSIC_KEY_NEXT); 
} 

private boolean sendPreviousKeyEvent() { 
    return sendMediaKeyEvent(MUSIC_KEY_PREVIOUS); 
} 

private boolean sendPlayKeyEvent() { 
    return sendMediaKeyEvent(MUSIC_KEY_PLAY); 
} 

private boolean sendPauseKeyEvent() { 
    return sendMediaKeyEvent(MUSIC_KEY_PAUSE); 
} 

@SuppressWarnings("unused") 
public void onEvent(MusicAction action) { 
    switch (action) { 
     case PREVIOUS: 
      sendPreviousKeyEvent(); 
      break; 
     case NEXT: 
      sendNextKeyEvent(); 
      break; 
     case PLAY_PAUSE: 
      if (isMusicPlaying) { 
       sendPauseKeyEvent(); 
      } else { 
       sendPlayKeyEvent(); 
      } 
      break; 
    } 
} 

public static int state; 

private void updatePlaybackState(int state) { 
    MusicPlaybackState playbackState; 

    if (state == STATE_PLAYING 
      || state == STATE_BUFFERING 
      || state == STATE_FAST_FORWARDING 
      || state == STATE_REWINDING 
      || state == STATE_SKIPPING_TO_NEXT) { 
     isMusicPlaying = true; 
     playbackState = MusicPlaybackState.PLAYING; 

    } else if (state == STATE_PAUSED) { 
     isMusicPlaying = false; 
     playbackState = MusicPlaybackState.PAUSED; 

    } else { 
     isMusicPlaying = false; 
     playbackState = MusicPlaybackState.STOPPED; 
    } 
    Log.e(TAG, "playing state: " + playbackState.name()); 
    EventBus.getDefault().post(playbackState); 
    currenTplaybackState = playbackState; 
    currentPlaybackState = state; 
} 

@Override 
public void onClientSessionEvent(String s, Bundle bundle) { 

} 


@Override 
public void onClientChange(boolean noClient) { 
    Log.e(TAG, "onClientChange: " + Boolean.toString(noClient) + ", " + Boolean.toString(isMusicPlaying)); 
    if (!noClient && isMusicPlaying) { 
     EventBus.getDefault().post(VisibilityBus.VISIBLE); 
    } else { 
     EventBus.getDefault().post(VisibilityBus.GONE); 
    } 
} 

@Override 
public void onClientPlaybackStateUpdate(int i) { 
    Log.e(TAG, "onClientPlaybackStateUpdate: " + i); 
    updatePlaybackState(i); 
} 

@Override 
public void onClientPlaybackStateUpdate(int i, long l, long l1, float v) { 
    Log.e(TAG, "onClientPlaybackStateUpdate: " + i); 
    updatePlaybackState(i); 
} 

@Override 
public void onClientTransportControlUpdate(int i) { 
} 

@Override 
public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) { 
    postUpdateMetadata(metadataEditor); 
} 


} 

問題を私は

 remoteController = new RemoteController(this, new RemoteController.OnClientUpdateListener() { 

     public void onClientSessionEvent(String string, Bundle bundle) { } 

     @Override 
     public void onClientChange(boolean b) { 

     } 

     @Override 
     public void onClientPlaybackStateUpdate(int i) { 

     } 

     @Override 
     public void onClientPlaybackStateUpdate(int i, long l, long l1, float v) { 

     } 

     @Override 
     public void onClientTransportControlUpdate(int i) { 

     } 

     @Override 
     public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) { 

     } 
    }); 
} 

に変更しようとしていましたが、「メディアを制御する権限がありません」があります。 どのように私はそれを動作させるためにこのメソッドを追加する必要がありますか?

+0

をすぐ確認するために、あなたの 'NotificationRemoteControllerService'は実際には[NotificationListenerService](HTTPSを拡張します。 android.com/service/notification/NotificationListenerService.html)、 'NotificationService'と呼ばれるクラスはありませんか?あなたの 'isEnabled'呼び出しは' enableRemoteController() 'を呼び出すと実際にtrueを返しますか?あなたが取得している 'メディアを制御する権限がありません'のスタックトレースを投稿できますか? – ianhanniballake

+0

NotificationServiceはNotificationListenerServiceを継承します。 isEnabledはtrueを返します。 「メディアを制御する権限がありません」は、enableRemoteControllerのキャッチからです。 – Patryk

+0

私はOnClientUpdateListenerを拡張しようとしていましたが、このメソッドを拡張インタフェースに追加しましたが、AbstractMethodErrorを持っています – Patryk

答えて

0

は、ドキュメントによると、あなたのAndroidManifest.xml

<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/> 

にこの権限を追加://開発者:

public static final String MEDIA_CONTENT_CONTROL 
Added in API level 19 
Allows an application to know what content is playing and control its playback. 
Not for use by third-party applications due to privacy of media consumption 
Constant Value: "android.permission.MEDIA_CONTENT_CONTROL" 
+0

私はすでにマニフェストでそれを持っています。 – Patryk

+0

システムアプリケーションの場合にのみ動作します。「サードパーティ製アプリケーションでは使用しない」と引用した場合もあります。 – ianhanniballake

+0

@ianhanniballake:それは警告として投稿しましたが、彼は試してみることができると考えました。 – SoulRayder

関連する問題