录音检查,自测了小米,魅族,华为,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
网友评论