获取应用播放音频的详细信息

Mad*_*han 0 media audio android

我正在开发一个需要在设备重新启动后恢复音频播放的应用程序。

我发现仅仅发送媒体播放按钮可能不会启动用户正在使用的同一个应用程序。(我已经 Spotify 运行,但在重新启动后发送播放按钮打开谷歌音乐)

有没有办法获取有关应用程序播放媒体的详细信息(重新启动之前)?

我需要类似应用程序名称/活动名称/包名称等的东西。(所以我可以在发送播放按钮之前启动同一个应用程序)

Mad*_*han 6

更新:以下方法要求您实施AccessibilityServiceGoogle Play 现在对其有严格要求和单独审查流程的方法,并且应用程序必须证明使用它的合理性。如果您实现以下内容,则您的应用可能会因滥用此 API 而被 Play 商店拒绝。


虽然不完美,但我找到了一种方法来识别当前播放音乐的应用程序。

我的方法是利用音乐播放器必须发布“正在进行的”通知以防止被系统杀死的事实,并且他们通常有一个广播接收器来处理媒体按钮。

从技术上讲,遵循 android 惯例的音乐应用程序必须为CATEGORY_MUSIC_APP(或已弃用的MediaStore.INTENT_ACTION_MUSIC_PLAYER)提供一个意图过滤器,以用于其至少一项活动,但我注意到当前版本的iHeartRadio 应用程序决定不打扰。

所以这是我的方法

  • 有一个无障碍服务注册到监控Android通知
    • (音乐播放器必须发布“正在进行的”通知,以防止在 CPU 或内存压力下被 android 杀死)。

无障碍服务必须至少 android:accessibilityEventTypes="typeNotificationStateChanged"由用户明确注册和启用。

服务必须按如下方式处理通知事件

@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
        if (accessibilityEvent.getEventType() ==
           AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
            String packageName = accessibilityEvent.getPackageName().toString();

            AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
            boolean musicPlaying = am.isMusicActive();

            if (!musicPlaying) {
                Log.i("NOTIFICATION", "no one is playing music. (anymore...)");
               return; // clear saved package
            }

            PackageManager pm = getPackageManager();    
            Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON);                
            i.setPackage(packageName);    

            List<ResolveInfo> a = pm.queryBroadcastReceivers(i, PackageManager.MATCH_ALL);

            if (a.size() > 0)
                Log.i("NOTIFICATION", "Music is played by: " + packageName);
                // save packageName to somewhere
            else
                Log.i("NOTIFICATION", "irrelevant notification from package: " + packageName);
        }
    }
Run Code Online (Sandbox Code Playgroud)

稍后当设备重新启动时,启动默认活动并按下播放按钮。

Intent i = new Intent(Intent.ACTION_VIEW);
i.addCategory(Intent.CATEGORY_DEFAULT); 
i.setPackage(savedPackage);
startActivity(i);

AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

 am.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY));
 am.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));

 // may be fire another intent for home/launcher. so user doesn't have to
Run Code Online (Sandbox Code Playgroud)

假设/警告

  • 音乐应用程序直接转到准备播放的活动(如果您尚未在该设备上登录他们的服务,iHeartRadio 会要求登录)
  • 音乐应用程序保存上次播放状态。如果不是这种情况,它可能会从曲目/播放列表的开头而不是用户停下来的地方开始播放。
  • 准确性可能会有所不同
    • Spotify 在用户离开活动或屏幕关闭时发布通知,并在播放状态更改时更新相同的通知(我们不会收到有关现有通知更改的通知。您不会收到播放开始的通知,直到 Spotify 活动暂停。)
    • Google 音乐在启动后立即发布通知,并且可能不会播放音乐(另一个应用程序可能正在播放音乐。可能会导致误报。)
    • iHeartRadio 导致连续多次通知更改。

您还可以Notification从事件中获取,并列出actions。如果title任何Action"Play"那么的应用程序是不是在玩音乐,只是张贴了通知,如谷歌音乐上面解释。

(选择开始“播放”意味着它现在没有播放。)此外,字符串“播放”不是标准的,可能因应用程序和/或语言而异。假设大多数应用程序的字符串相同或相似以支持辅助功能等。并确保您检查是否为actions空。如果通知使用自定义布局(例如:Spotify),则为 null。(也可能意味着盲人用户不能使用 Spotify,因为可访问性服务无法使用通知操作来控制它。)


更新:如果您不想将其构建到您自己的应用程序中, 您也可以使用Automate 之类的应用程序来处理此问题。