CarAppFocusManager使用

CarAppFocusManager是android.car.jar中的类,用于管理车机系统的应用焦点,如导航或语音命令的激活状态。它确保系统中通常只运行一个此类应用实例,并能处理音频焦点的设置和监听,实现应用间的互斥操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CarAppFocusManager

位于android.car.jar中。

官方介绍

CarAppFocusManager allows applications to set and listen for the current application focus like active navigation or active voice command. Usually only one instance of such application should run in the system, and other app setting the flag for the matching app should lead into other app to stop.

主要是为了处理车机系统中音频焦点的管理和互斥操作。

使用

public class ECAudioFocusManager {

    private Car mCar;
    private CarAudioManager mCarAudioManager = null;

    private AudioFocusListener audioFocusListener = null;

    private CarAppFocusManager mAppFocusManager;
    private AppFocusOwnershipCallback mAppFocusCallback;

    ECAudioFocusManager() {
        mCar = Car.createCar(ECManager.getInstance().getContext(), new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                try {
                    mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
                } catch (CarNotConnectedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        });
        mCar.connect();
		
        audioFocusListener = new AudioFocusListener();

        if (mCar.isConnected()) {
            AppFocusChangedListener mListener = new AppFocusChangedListener();
            mAppFocusCallback = new AppFocusOwnershipCallback();
            try {
                mAppFocusManager = (CarAppFocusManager) mCar.getCarManager(Car.APP_FOCUS_SERVICE);
                mAppFocusManager.addFocusListener(mListener, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION);
                mAppFocusManager.addFocusListener(mListener, CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND);
            } catch (CarNotConnectedException e) {
                Log.e(" carAppFocusManager init error : " + e.getMessage());
            }
        }
    }

	/**
	 * 先申请APP焦点
	 * 最大重试次数十次
	 * 重试着抢焦点也是为了增加抢到的几率
	 */
    private void doRequestAppFocus(int appFocusType) {

        Log.d("doRequestAppFocus type : " + appFocusType);

        if (isOwningFocus(appFocusType)) {
            doRequestFocus(player);
            return;
        }

        int status = CarAppFocusManager.APP_FOCUS_REQUEST_FAILED;
        int retryCnt = 10;
        while (status == CarAppFocusManager.APP_FOCUS_REQUEST_FAILED && retryCnt-- > 0) {
            try {
                status = mAppFocusManager.requestAppFocus(appFocusType, mAppFocusCallback);
                Log.d("doRequestAppFocus --- status : " + status);

                if (status != CarAppFocusManager.APP_FOCUS_REQUEST_SUCCEEDED && retryCnt > 1) {
                    Thread.sleep(500);
                }
            } catch (CarNotConnectedException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
	
	/**
	 * 再申请声音焦点
	 * 最大重试次数十次
	 * 重试着抢焦点也是为了增加抢到的几率
	 */
    private void doRequestFocus(AudioPlayer player) {
        Log.d("doRequestFocus name : " + player.getName());

        if (player.getVrPlayFlag()) {
            return;
        }

        int status = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        int retryCnt = 10;
        while (status != AudioManager.AUDIOFOCUS_REQUEST_GRANTED && retryCnt-- > 0) {
            try {
                status = mCarAudioManager.requestAudioFocus(audioFocusListener, player.getAudioAttributes(), player.getDurationHint(), 0);
                Log.d("requestAudioFocus --- name : " + player.getName() + ",  status : " + status);

                if (status != AudioManager.AUDIOFOCUS_REQUEST_GRANTED && retryCnt > 1) {
                    Thread.sleep(500L);
                }
            } catch (CarNotConnectedException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        boolean result = status == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
        player.setVrPlayFlag(result);
    }
	
	/**
	 * 释放APP焦点
	 */
    private void doAbandonAppFocus(int appFocusType) {
        Log.d("doAbandonAppFocus type : " + appFocusType);

        try {
            mAppFocusManager.abandonAppFocus(mAppFocusCallback, appFocusType);
        } catch (SecurityException e) {
            Log.e("doAbandonAppFocus error : " + e.getMessage());
        }
    }

	/**
	 * 释放声音焦点
	 */
    private void doAbandonFocus(AudioPlayer player) {
        Log.d("doAbandonFocus name : " + player.getName());

        player.setVrPlayFlag(false);
        mCarAudioManager.abandonAudioFocus(audioFocusListener, player.getAudioAttributes());
    }

	/**
	 * 声音焦点的监听回调
	 * 在这里可以根据自己所申请的焦点类型的变化进行监听
	 */
    class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener {
        @Override
        public void onAudioFocusChange(int focusChange) {
            Log.d("onAudioFocusChange focusChange = " + focusChange);
            switch (focusChange) {
                case AudioManager.AUDIOFOCUS_GAIN:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS:
                    break;
                case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                    break;
                case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
                    break;
                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                    break;
            }
        }
    }

	/**
	 * APP焦点的监听回调
	 * 在这里可以根据自己所申请的焦点类型的变化进行监听
	 */
    private class AppFocusChangedListener
            implements CarAppFocusManager.OnAppFocusChangedListener {

        @Override
        public void onAppFocusChanged(int appType, boolean active) {
            Log.d(" onAppFocusChanged: " + appType + " appActive: " + active);
            switch (appType) {
                case CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION:
                    if (active) {
                        doRequestFocus(mTTSPlayer);
                    } else {
                        doAbandonFocus(mTTSPlayer);
                    }
                    break;
                case CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND:
                    if (active) {
                        doRequestFocus(mVRPlayer);
                    } else {
                        doAbandonFocus(mVRPlayer);
                    }
                    break;
            }
        }
    }

	/**
	 * APP焦点获得或者丢失的监听回调
	 * onAppFocusOwnershipLost 该类型的APP焦点丢失,一般需要当前应用停止该类型音频的播放
	 * onAppFocusOwnershipGranted 该类型的APP焦点的授予获得,一般需要当前应用申请该类型APP焦点成功后回调
	 */
    private class AppFocusOwnershipCallback
            implements CarAppFocusManager.OnAppFocusOwnershipCallback {

        @Override
        public void onAppFocusOwnershipLost(int appType) {
            Log.d(" onAppFocusOwnershipLost: " + appType);
            mAppFocusManager.abandonAppFocus(mAppFocusCallback, appType);
            if (appType == CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION) { 
                doAbandonFocus(mTTSPlayer);
            } else if (appType == CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND) {
                doAbandonFocus(mVRPlayer);
            }
        }

        @Override
        public void onAppFocusOwnershipGranted(int appType) {
            Log.d(" onAppFocusOwnershipGranted: " + appType);
            if (appType == CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION) {
                doRequestFocus(mTTSPlayer);
            } else if (appType == CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND) {
                doRequestFocus(mVRPlayer);
            }
        }
    }

	/**
	 * 判断该类型的APP焦点是否拥有
	 * 一般借用此方法可以避免重复申请APP焦点
	 */
    private boolean isOwningFocus(int appType) {
        boolean owningFocus = false;
        try {
            owningFocus = mAppFocusManager.isOwningFocus(mAppFocusCallback, appType);
        } catch (CarNotConnectedException e) {
            Log.e("isOwningFocus error : " + e.getMessage());
        }
        return owningFocus;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值