Android應用場景識別-音樂程序或音訊程序識別
阿新 • • 發佈:2018-12-14
0. 實現原理
獲取當前程序是音樂程序 && 當前程序是否佔有音訊服務焦點
1.上層呼叫方法
AudioManager audio = getSystemService(AudioManager.class);
(audio.isMusicActive() && audio.isAppInFocus(pkgName))
具體工具類呼叫如下
package com.android.lava.powersave.util; import java.lang.reflect.Method; import android.content.Context; import android.media.AudioManager; import android.util.Log; public class AudioManagerUtils { public static boolean isAudioAppRunning(Context mContext, String packageName) { boolean result = false; AudioManager mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); Class ownerClass = mAudioManager.getClass(); try { Class[] argsClass = new Class[1]; argsClass[0] = String.class; Method method = ownerClass.getMethod("isAppInFocus", argsClass); Object[] params = new Object[1]; params[0] = packageName; boolean isMusicActive = mAudioManager.isMusicActive(); if (isMusicActive) { boolean isAppInFocus = (Boolean) method.invoke(mAudioManager, params); result = isMusicActive && isAppInFocus; Log.d(AudioManagerUtils.class.getSimpleName(), packageName + ", isAudioAppRunning isMusicActive= " + isMusicActive + ", isAppInFocus = " + isAppInFocus + ", result = " + result); } } catch (Exception e) { e.printStackTrace(); } return result; } }
2.底層Framewoke實現
2.0 移植清單
-m media/java/android/media/AudioManager.java
-m media/java/android/media/IAudioService.aidl
-m services/core/java/com/android/server/audio/AudioService.java
-m services/core/java/com/android/server/audio/MediaFocusControl.java
2.1 AudioManager.java
media/java/android/media/AudioManager.java
package android.media; /** * AudioManager provides access to volume and ringer mode control. */ @SystemService(Context.AUDIO_SERVICE) public class AudioManager { /** * @hide * Check if the specified App obtains the focus. * @param packageName the package name of the App. * @return ture if the App obtains the focus. */ public boolean isAppInFocus(String packageName) { boolean isFocus = false; IAudioService service = getService(); try { isFocus = service.isAppInFocus(packageName); } catch (RemoteException e) { Log.e(TAG, "Can't call isAppInFocus() on AudioService due to " + e); } return isFocus; }
2.2 AudioService.java
media/java/android/media/IAudioService.aidl
package com.android.server.audio;
public class AudioService extends IAudioService.Stub
implements AccessibilityManager.TouchExplorationStateChangeListener,
AccessibilityManager.AccessibilityServicesStateChangeListener {
public boolean isAppInFocus(String name) {
return mMediaFocusControl.isAppInFocus(name);
}
2.3 IAudioService.aidl
media/java/android/media/IAudioService.aidl
/**
* Check whether the dolby client application is in audio focus or not.
* @param name the application's package name.
*/
boolean isAppInFocus(String name);
2.4 具體實現 MediaFocusControl.java
services/core/java/com/android/server/audio/MediaFocusControl.java
package com.android.server.audio;
public class MediaFocusControl implements PlayerFocusEnforcer {
protected boolean isAppInFocus(String name) {
boolean isInFocus = false;
synchronized (mAudioFocusLock) {
if (!mFocusStack.empty()) {
isInFocus = mFocusStack.peek().hasSamePackage(name);
}
}
return isInFocus;
}
3. SystemUI 中音樂程序的識別判斷方法 (參考或結合使用)
/**
* Get the current state of playback. One of the following:
* <ul>
* <li> {@link PlaybackState#STATE_NONE}</li>0
* <li> {@link PlaybackState#STATE_STOPPED}</li>1
* <li> {@link PlaybackState#STATE_PAUSED}</li>2
* <li> {@link PlaybackState#STATE_PLAYING}</li>3
* <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>4
* <li> {@link PlaybackState#STATE_REWINDING}</li>5
* <li> {@link PlaybackState#STATE_BUFFERING}</li>6
* <li> {@link PlaybackState#STATE_ERROR}</li>7
* </ul>
* <p>
* Need permission <uses-permission
* android:name="android.permission.MEDIA_CONTENT_CONTROL" />
* <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"
* /> <uses-permission
* android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
*/
public static HashMap<String, Integer> findMediaProcess(Context mContext) {
HashMap<String, Integer> result = new HashMap<String, Integer>();
if (!PowerSaveController.isSystemReady()) {
return result;
}
// TODO: use MediaSessionManager.SessionListener to hook us up to future
// updates
// in session state
MediaSessionManager mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
if (mMediaSessionManager != null) {
final List<MediaController> sessions = mMediaSessionManager.getActiveSessionsForUser(null, UserHandle.USER_ALL);
if (sessions != null && !sessions.isEmpty()) {
for (MediaController aController : sessions) {
if (aController == null)
continue;
// now to see if we have one like this
final String pkg = aController.getPackageName();
final PlaybackState state = aController.getPlaybackState();
int stateInt = state == null ? -11 : state.getState();
result.put(pkg, stateInt);
Log.d(TAG, "findMusicProcess music app = " + pkg + ", status = " + stateInt);
/*
* final PlaybackState state =
* aController.getPlaybackState(); if (state == null)
* continue; switch (state.getState()) { case
* PlaybackState.STATE_STOPPED: case
* PlaybackState.STATE_ERROR: continue; default: // now to
* see if we have one like this final String pkg =
* aController.getPackageName(); result.put(pkg,
* state.getState()); Log.d(TAG,
* "findMusicProcess music app = " + pkg + ", status = " +
* state.getState()); }
*/
}
}
}
return result;
}