Android应用场景识别-音乐进程或音频进程识别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/su749520/article/details/82996790

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;
    }

猜你喜欢

转载自blog.csdn.net/su749520/article/details/82996790
今日推荐