Get details of app playing audio(获取应用程序播放音频的详细信息)
问题描述
我正在开发一个应用程序,该应用程序需要在设备重新启动后恢复音频播放。
我发现,简单地发送媒体播放按钮可能无法启动用户正在使用的同一个应用程序。(我正在运行Spotify,但在重启后发送播放按钮可打开Google Music)
是否有方法获取有关应用播放媒体的详细信息(重新启动前)?
我需要类似应用程序名称/活动名称/包名称等内容。 (这样我就可以在发送播放按钮之前启动相同的应用程序)
推荐答案
更新2:使用queryBroadcastReceivers
接口,可能受package visibility filtering on Android 11 and higher影响。这意味着您必须声明QUERY_ALL_PACKAGES
权限,并且在发布到Play Store时必须证明其使用的合理性。Android T似乎deprecate this API in favor of a slightly different one,但当前调用应该仍然有效。
AccessibilityService
,Google Play现在对此有严格的要求和单独的审查流程,应用程序必须证明使用它的合理性。如果你实现以下内容,你的应用很可能会因为滥用此API而被Play Store拒绝。
虽然不完美,但我找到了一种方法来识别正在播放音乐的应用程序。
我的方法是利用这样一个事实,即音乐播放器必须发布正在进行的通知,以防止被系统终止,并且他们通常有一个Broadcast Receiver来处理媒体按钮。
从技术上讲,遵循Android约定的音乐应用程序必须至少为CATEGORY_MUSIC_APP(或不推荐的MediaStore.INTENT_ACTION_MUSIC_PLAYER)设置意图过滤器,但我注意到iHeartRadio app的当前版本决定不麻烦了。
以下是我的方法
- 注册Accessibility Service以监控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);
}
}
稍后重新启动设备时,启动默认活动并按"播放"按钮。
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
假设/注意事项
- 音乐应用程序直接转到可以播放的活动(如果您尚未在该设备上登录iHeartRadio的服务,则会要求登录)
- 音乐应用保存上次播放状态。如果不是这样,它可能会从曲目/播放列表的开头开始播放,而不是从用户停止的位置开始播放。
- 准确性可能会有所不同
- Spotify在用户离开活动或屏幕关闭时发布通知,并在播放状态更改时更新相同的通知(现有通知更改不会通知我们。在暂停Spotify活动之前,您不会收到播放开始的通知。)
- 谷歌音乐在启动后立即发布通知,可能没有播放音乐(另一款应用可能正在播放音乐。可能导致误报。)
- iHeartRadio导致连续更改多个通知。
还可以从事件中获取Notification
,并列出actions
。如果任何Action
的title
是"Play"
,则该应用程序不会播放音乐,而只是像上面解释的谷歌音乐那样发布通知。
(可以选择开始‘播放’意味着它现在不在播放。)此外,Play字符串不是标准字符串,可能会因应用程序和/或语言而异。假设字符串对大多数应用程序相同或相似,以支持可访问性等。并确保检查actions
是否为空。如果通知使用自定义布局(例如:Spotify),则为空。(这也可能意味着盲人用户无法使用Spotify,因为辅助功能服务无法使用通知操作对其进行控制。)
更新: 如果您不想将其内置到您自己的应用程序中,也可以使用Automate这样的应用程序来处理此问题。
这篇关于获取应用程序播放音频的详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:获取应用程序播放音频的详细信息
- 想使用ViewPager,无法识别android.support.*? 2022-01-01
- 在测试浓缩咖啡时,Android设备不会在屏幕上启动活动 2022-01-01
- 用 Swift 实现 UITextFieldDelegate 2022-01-01
- Android - 拆分 Drawable 2022-01-01
- 如何检查发送到 Android 应用程序的 Firebase 消息的传递状态? 2022-01-01
- Android - 我如何找出用户有多少未读电子邮件? 2022-01-01
- 使用自定义动画时在 iOS9 上忽略 edgesForExtendedLayout 2022-01-01
- MalformedJsonException:在第1行第1列路径中使用JsonReader.setLenient(True)接受格式错误的JSON 2022-01-01
- android 4中的android RadioButton问题 2022-01-01
- Android viewpager检测滑动超出范围 2022-01-01