Получение имени приложения с изменением аудиофокуса

Кажется, я не могу найти ничего, связанного с выяснением того, какое приложение получило аудиофокус. Я могу правильно определить из своего приложения, какой это был тип изменения фокуса, но не из какого-либо другого приложения. Есть ли способ определить, какое приложение получило фокус?

"Что я хочу сделать?"

Мне удалось записать внутренний звук, будь то музыка или голос. Если я в настоящее время записываю звук независимо от источника, я хочу определить, какое приложение взяло на себя фокус, чтобы определить, что моему приложению нужно делать дальше.

В настоящее время я использую AudioManager.OnAudioFocusChangeListener. чтобы мое приложение прекратило запись внутренних звуков после изменения фокуса, но я хочу, чтобы имя приложения получило фокус.


person zaggler    schedule 24.07.2015    source источник
comment
просто мысли вслух ... как насчет того, чтобы получить топ текущих задач? конечно, приложение, которое только что получило аудио-фокус, должно быть там довольно высоко.   -  person alvi    schedule 26.07.2015
comment
К вашему сведению, функция getRecentTasks() строго ограничена в Android L. Это похоже на неправильный подход, то есть на то, что Android не хочет предоставлять приложениям, возможно, по соображениям безопасности. Возможно, есть лучший подход, что бы вы сделали, если бы узнали имя приложения?   -  person Trevor Carothers    schedule 27.07.2015


Ответы (3)


Короткий ответ. Хорошего решения не существует... и Android, вероятно, так и задумал.

Объяснение. Глядя на исходный код, AudioManager не имеет API (даже скрытых API) для проверки того, у кого есть Audio Focus. AudioManager оборачивает вызовы AudioService, который сохраняет реальное состояние звука. API, который AudioService предоставляет через свою заглушку, когда AudioManager привязывается к нему, также не имеет API для запроса текущего Audio Focus. Таким образом, даже с помощью разрешений на уровне отражения/системы вы не сможете получить нужную информацию.

Если вам интересно, как отслеживаются изменения фокуса, вы можете посмотреть на MediaFocusControl, экземпляр которого является переменной-членом AudioService здесь.

Непроверенная хакерская эвристика: вы можете получить полезную информацию, просмотрев UsageStats временные метки. Затем, когда у вас есть приложения, которые использовались в течение, скажем, ~ 500 мс после потери AudioFocus, вы можете сверить их с приложениями с разрешениями на аудио. Вы можете подписаться на эту публикацию, чтобы получить разрешения для любого установленного приложения.

Это явно эвристика и может потребовать некоторой настройки. Также требуется, чтобы пользователь предоставил вашему приложению разрешения на доступ к статистике использования. Пробег может варьироваться.

person Trevor Carothers    schedule 27.07.2015
comment
Если вы нацеливаетесь только на леденец, он может перехватить медиа-уведомление и таким образом получить пакет. - person JohanShogun; 27.07.2015
comment
Спасибо за информацию, действительно все было полезно. Я был очень занят работой и кое-чем другим, чтобы вернуться к этой теме. MediaFocusControl было чем-то, во что я копался раньше, но мне пришлось вернуться к нему, чтобы освежить свой разум. Я изучил UsageStats и с тем, что предложил @JohanShogun, у меня есть рабочее решение, которое, похоже, пока работает хорошо. Еще раз, спасибо за вашу помощь, я ценю это! - person zaggler; 01.08.2015
comment
Круто, я никогда не использовал UsageStats, рад, что у них есть практическое применение. - person Trevor Carothers; 01.08.2015
comment
Я думаю, что невозможно получить статистику, когда пользователь управляет воспроизведением только через уведомление. - person Vlad; 24.09.2020

Глядя на класс MediaContorller (новый в леденце, доступен в библиотеке сравнения для более старых версий).

Вот эти два метода, которые выглядят интересно:

https://developer.android.com/reference/android/media/session/MediaController.html#getPackageName()

https://developer.android.com/reference/android/media/session/MediaController.html#getSessionActivity()

getPackageName предположительно возвращает имя пакета текущего сеанса: http://androidxref.com/5.1.1_r6/xref/frameworks/base/media/java/android/media/session/MediaController.java#397

getSessionActivity дает вам PendingIntent с активностью для запуска (если она предоставлена), где вы также можете получить пакет.

Используется вместе с вашим аудиослушателем и широковещательным приемником для определения состояния телефона, чтобы определить, звонит ли телефон в данный момент, вы можете использовать это, чтобы получить более точное определение, чем у вас есть в настоящее время. Как указал выше Тревор Карозерс, нет никакого способа получить общее приложение с фокусом на аудио.

person JohanShogun    schedule 29.07.2015
comment
Я нашел ваш пост довольно интересным, который напомнил MediaController, с которым я действительно мог бы работать. Я использовал решение UsageStats (@Trevor Carothers) вместе с MediaController, чтобы прийти к решению, которое, похоже, работает нормально на данный момент. Еще раз, спасибо, я ценю вашу помощь и время! - person zaggler; 01.08.2015
comment
MediaController показывает только имя пакета моего приложения и активность - person Vlad; 24.09.2020
comment
Хорошо, я сделал это, используя NotificationListenerService и прочитав дополнительные уведомления в методе onNotificationPosted(notification: StatusBarNotification). Но getPackageName бесполезен, а getSessionActivity для меня всегда null - person Vlad; 24.09.2020

Вы можете использовать dumpsys audio, чтобы узнать, кто использует аудиофокус. И вы также можете ознакомиться с результатами dumpsys media_session.

А если вы хотите узнать, кто играет музыку, вы можете выбрать dumpsys media.audio_flinger. Для себя я переключаюсь на эту команду.

person liudongmiao    schedule 19.08.2017
comment
Требуется android.permission.DUMP с уровнем защиты системы - person Vlad; 24.09.2020