美文网首页
判断国产机型6.0以下是否有录音相机权限

判断国产机型6.0以下是否有录音相机权限

作者: kunio | 来源:发表于2020-07-13 19:48 被阅读0次

录音检查,自测了小米,魅族,华为,OPPO,vivo的机型,但是同一机型不同型号之间或许也会存在差异性,没办法将所有机型全部囊括

废话不多说,直接上代码:

package com.kunio.permission;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Build;

/**
 * 对于6.0以下运行时权限校验,对于录音和拍照进行校验
 */
class AndroidBeforeMChecker {
    static boolean checkPermission(Context context, String permission) {
        if (context == null || permission == null) {
            return false;
        }
        try {
            switch (permission) {
                case Manifest.permission.RECORD_AUDIO:
                    return RecordAudioPermissionCheck.check(context);
                case Manifest.permission.CAMERA:
                    return CameraPermissionCheck.check(context);
                default:
                    return true;
            }
        } catch (Throwable e) {
            return false;
        }
    }

    private static class RecordAudioPermissionCheck {
        private static final int[] RATES = new int[]{8000, 11025, 22050, 44100};

        static boolean check(Context context) {
            AudioRecord audioRecord = null;
            try {
                int[] params = findAudioParameters();
                if (params == null) return !existMicrophone(context);

                audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, params[0], params[1], params[2], params[3]);
                int state = audioRecord.getState();
                if (state != AudioRecord.STATE_INITIALIZED) return !existMicrophone(context);

                int recordState = audioRecord.getRecordingState();
                if (recordState != AudioRecord.RECORDSTATE_STOPPED) return true;

                audioRecord.startRecording();
                if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
                    // 部分OPPO、vivo、小米在录音权限拒绝对时候会走到这里,此时audioRecord.getRecordingState()值为1
                    return false;
                }
                byte[] buffer = new byte[params[3]];
                int len = audioRecord.read(buffer, 0, params[3]);
                if (len <= 0){
                    // 华为5.x手机在权限拒绝之后,这里面读出来的长度是0,4.x的部分手机直接会默认有权限,其它的没验证
                    return false;
                }
                // 有言论说华为的4.4机型上面的判断都会失效,但是内部所读的全部为0,但是因为资源原因,此处未加测试
                if (ishuawei) {
                    int i = 0, j = len - 1;
                    while (i <= j) {
                        if (buffer[i] != 0 || buffer[j] != 0) {
                            return true;
                        }
                        i++;
                        j--;
                    }
                    return false;
                }
            } catch (Throwable e) {
                return !existMicrophone(context);
            } finally {
                if (audioRecord != null) {
                    // 有的vivo手机调用此函数时,也会引发系统授权弹窗弹起
                    audioRecord.release();
                }
            }
            return true;
        }

        private static boolean existMicrophone(Context context) {
            PackageManager packageManager = context.getPackageManager();
            return packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE);
        }

        private static int[] findAudioParameters() {
            for (int rate : RATES) {
                for (int channel : new int[]{AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO}) {
                    for (int format : new int[]{AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT}) {
                        int buffer = AudioRecord.getMinBufferSize(rate, channel, format);
                        if (buffer != AudioRecord.ERROR_BAD_VALUE) {
                            return new int[]{rate, channel, format, buffer};
                        }
                    }
                }
            }
            return null;
        }
    }


    private static class CameraPermissionCheck {
        static boolean check(Context context) {
            Camera camera = null;
            try {
                int cameraCount = Camera.getNumberOfCameras();
                if (cameraCount <= 0) return true;

                camera = Camera.open(cameraCount - 1);
                Camera.Parameters parameters = camera.getParameters();
                camera.setParameters(parameters);
                camera.setPreviewCallback(PREVIEW_CALLBACK);
                camera.startPreview();
                return true;
            } catch (Throwable e) {
                PackageManager packageManager = context.getPackageManager();
                return !packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
            } finally {
                if (camera != null) {
                    camera.stopPreview();
                    camera.setPreviewCallback(null);
                    camera.release();
                }
            }
        }

        private static final Camera.PreviewCallback PREVIEW_CALLBACK = new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
            }
        };
    }
}

借鉴:
https://www.jianshu.com/p/7d255fa8247d
https://github.com/yanzhenjie/AndPermission

相关文章

网友评论

      本文标题:判断国产机型6.0以下是否有录音相机权限

      本文链接:https://www.haomeiwen.com/subject/elezcktx.html