Android 录音和摄像头权限适配

Posted Shawn_Dut

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 录音和摄像头权限适配相关的知识,希望对你有一定的参考价值。

  最近在研究权限适配的相关内容,整理以前的权限博客如下:
  android permission权限与安全机制解析(上)
  android permission权限与安全机制解析(下)
  Android 悬浮窗权限各机型各系统适配大全
  这篇博客主要是介绍录音权限和摄像头权限的适配,android permission权限与安全机制解析(下)这篇博客中我介绍到了 6.0 之后危险权限的相关处理步骤,而录音和摄像头权限正好是属于危险权限,所以需要去单独申请,申请的步骤在这篇博客中就不介绍了,上面那篇博客中已经介绍的很详细,这里主要是介绍在不同版本如何去检测权限的授予与否。
  转载请注明出处:http://blog.csdn.net/self_study/article/details/52965045
  PS:对技术感兴趣的同鞋加群544645972一起交流。

录音权限

6.0之前

  6.0 之前的检测方法我最刚开始的想法是依照悬浮窗权限的适配方案,使用 AppOpsManager 去检测,但是实际情况是,6.0 版本之下的机型很多判断都不准确,所以无奈在网上找到了一种粗暴的解决方案:

public class AudioPermissionCheckUtils 
    private static final String TAG = "AudioPermissionCheckUtils";

    // 音频获取源
    public static int audiosource = MediaRecorder.AudioSource.MIC;
    // 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
    public static int sampleRateInHz = 44100;
    // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
    public static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
    // 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
    public static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    // 缓冲区字节大小
    public static int bufferSizeInBytes = 0;

    /**
     * 判断是是否有录音权限
     */
    public static boolean checkAudioPermission(final Context context) 
        bufferSizeInBytes = 0;
        bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
                channelConfig, audioFormat);
        AudioRecord audioRecord =  new AudioRecord(audioSource, sampleRateInHz,
                channelConfig, audioFormat, bufferSizeInBytes);
        //开始录制音频
        try
            // 防止某些手机崩溃,例如联想
            audioRecord.startRecording();
        catch (IllegalStateException e)
            e.printStackTrace();
            AVLogUtils.e(TAG, Log.getStackTraceString(e));
        
        /**
         * 根据开始录音判断是否有录音权限
         */
        if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING
                && audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED) 
            AVLogUtils.e(TAG, "audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING : " + audioRecord.getRecordingState());
            return false;
        

        if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) 
            //如果短时间内频繁检测,会造成audioRecord还未销毁完成,此时检测会返回RECORDSTATE_STOPPED状态,再去read,会读到0的size,所以此时默认权限通过
            return true;
        

        byte[] bytes = new byte[1024];
        int readSize = audioRecord.read(bytes, 0, 1024);
        if (readSize == AudioRecord.ERROR_INVALID_OPERATION || readSize <= 0) 
            AVLogUtils.e(TAG, "readSize illegal : " + readSize);
            return false;
        
        audioRecord.stop();
        audioRecord.release();
        audioRecord = null;

        return true;
    

这个解决方案一目了然,就是直接调用 AudioRecord 去录音,如果发现录音的文件大小不正确,比如为0,再结合此时的录音状态,那么可以基本判定录音权限的开启与否。

6.0 及之后

  6.0 之后,系统提供了相关 API,权限检测就很简单了:

int hasCameraPermission;
hasCameraPermission = checkSelfPermission(Manifest.permission.CAMERA);
Toast.makeText(this, "camera granted : " + (hasCameraPermission == PackageManager.PERMISSION_GRANTED), Toast.LENGTH_SHORT).show();

只要返回的值为 PackageManager.PERMISSION_GRANTED 就可以判定已经授权改权限。

摄像头权限

6.0之前

  同录音权限,在 6.0 之前的版本使用 AppOpsManager 在很多机型上会有适配问题,所以在这里依旧粗暴的采用下面这种方案:

public class CameraPermissionCheckUtils 
    private static final String TAG = "CameraPermissionCheckUtils";

    public static boolean checkCameraPermission(Context context) 
        boolean canUse = true;
        Camera mCamera = null;
        try 
            mCamera = Camera.open(0);
            mCamera.setDisplayOrientation(90);
         catch (Exception e) 
            AVLogUtils.e(TAG, Log.getStackTraceString(e));
            canUse = false;
        
        if (canUse) 
            mCamera.release();
            mCamera = null;
        
        return canUse;
    

但是貌似在少数机型和手机上依旧会有判断错误的情况存在,而且由于这个函数会调用 Camera.open 函数,所以造成在少些手机上会卡顿一下。

6.0 及之后

  6.0 之后就直接使用系统 API 进行判断就可以了:

int hasAudioPermission;
hasAudioPermission = checkSelfPermission(Manifest.permission.RECORD_AUDIO);
Toast.makeText(this, "audio granted : " + (hasAudioPermission == PackageManager.PERMISSION_GRANTED),
        Toast.LENGTH_SHORT).show();

同样,只要判断返回结果为 PackageManager.PERMISSION_GRANTED 就可以判定 app 已被授权摄像头权限。

源码下载

  https://github.com/zhaozepeng/AndroidAudioCameraPermission

以上是关于Android 录音和摄像头权限适配的主要内容,如果未能解决你的问题,请参考以下文章

Android 悬浮窗权限各机型各系统适配大全

Android 悬浮窗各机型各系统适配大全

android录音采用的双麦克风还是单麦克风

适配:Android11存储

Android 13 适配指南

Android Q R的适配-隐私权限