Android调用系统相机,需要注意的地方无非就是6.0之后的动态授权,7.0的系统对api 的限制需要使用Provider 等适配问题,大家网上一搜一大堆相关的文章。
但是最近做项目发现6.0,7.0 等适配问题都做了处理,但是拍完照片之后 onActivityResult 的结果码resultCode始终等于0,网上搜了很多答案有说是activity 启动模式为单例的,有说是没有权限的等等。 纠结了很久 ,最终发现是调用MediaStore.EXTRA_OUTPUT 设置自定义目录路径的问题 。代码如下:
/**
* 打开相机操作
*/
private void startCamera(Activity context) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = FileUtils.createOriImageFile();
if (file != null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
imgUriOri = Uri.fromFile(file);
} else {
imgUriOri = FileProvider.getUriForFile(context, "com.qh.insurance.file_provider", file);
}
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imgUriOri);
context.startActivityForResult(cameraIntent, Constants.PHOTO_REQUEST_CAMERA);
}
}
/**
* 创建拍照需要的文件
*
* @return
*/
public static File createOriImageFile() {
String imgNameOri = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String mTempPhotoPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/qhphoto/" + imgNameOri + ".jpeg";
File file =new File(mTempPhotoPath);
if (!file.exists())
{
file.getParentFile().mkdirs(); //注意此处创建文件调用getParentFile()再调用 mkdirs()
}
return file;
}
原因是在创建拍照文件的时候路 file不存在调用 file.mkdirs() , 最终创建的xxx.jpeg 是文件夹而非文件。
对于File类来说,他既可以表示一个文件,也可以表示一个文件夹,那么在声明情况下他会创建文件夹,什么情况下会创建文件
- 看下面例子
public static File createOriImageFile() {
String mTempPhotoPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/qhphoto/"+ "test.jpeg";
File file =new File(mTempPhotoPath);
if (!file.exists())
{
file.mkdirs();
}
return file;
}
这种情况下最终创建的test.jpeg 是文件夹,test.jpeg是文件夹的名字
2. 为什么会出现一个test.jpeg的文件夹:java默认情况下是创建一个文件就会想test.jpeg看成一个整体,成为一个文件的名字
那么怎么解决这个问题:你需要告诉它我要建一个文件, 所以你要告诉它所在的父目录代码如下:
public static File createOriImageFile() {
String mTempPhotoPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/qhphoto/"+ "test.jpeg";
File file =new File(mTempPhotoPath);
if (!file.exists())
{
file.getParentFile().mkdirs();
}
return file;
}
到此问题解决,成功获取了拍照后的文件。
本文主要是记录开发中遇到的坑,希望能够对你有帮助,如有问题,请大家指出斧正!
/**
* 打开讯飞语音识别
*/
@JavascriptInterface
public String xunFeiSpeech() {
String[] permissions = new String[]{Manifest.permission.RECORD_AUDIO};
if (PermissionUtil.hasPermissons(mainActivity, permissions)) {
mIatResults.clear();
//1. 创建SpeechRecognizer对象,第二个参数: 本地识别时传 InitListener
SpeechRecognizer mIat = SpeechRecognizer.createRecognizer(mainActivity, null); //语音识别器
//2. 设置听写参数,详见《 MSC Reference Manual》 SpeechConstant类
mIat.setParameter(SpeechConstant.DOMAIN, "iat");// 短信和日常用语: iat (默认)
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");// 设置中文
mIat.setParameter(SpeechConstant.ACCENT, "mandarin");// 设置普通话
// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
mIat.setParameter(SpeechConstant.VAD_BOS, "4000");
// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
mIat.setParameter(SpeechConstant.VAD_EOS, "2000");
mIat.setParameter(SpeechConstant.AUDIO_FORMAT_AUE, "speex");
mIat.setParameter(SpeechConstant.ASR_PTT, "0");// 不要标点
mIat.setParameter(SpeechConstant.SAMPLE_RATE, "16000");// 采样率16k
//3. 开始听写
mIat.startListening(new RecognizerListener() {
//一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;
//isLast等于true 时会话结束。
@SuppressLint("LongLogTag")
public void onResult(RecognizerResult results, boolean isLast) {
Log.e(TAG, results.getResultString());
System.out.println(results.getResultString());
String result = results.getResultString(); //为解析的
Log.e("没有解析的", result);
String text = JsonParser.parseIatResult(result);//解析过后的
Log.e("解析后的", text);
String sn = null;
// 读取json结果中的 sn字段
try {
JSONObject resultJson = new JSONObject(results.getResultString());
sn = resultJson.optString("sn");
} catch (JSONException e) {
e.printStackTrace();
}
mIatResults.put(sn, text);//没有得到一句,添加到
StringBuffer resultBuffer = new StringBuffer();
for (String key : mIatResults.keySet()) {
resultBuffer.append(mIatResults.get(key));
}
if (isLast) {
if (recognizerDialogManager != null) {
recognizerDialogManager.dismissRecognizerDialog();
}
//此处可调用js将识别结果传给h5
ToastUtil.getInstance().showToastLong(resultBuffer.toString());
Log.i("识别结果", resultBuffer.toString().toUpperCase());
String speechResult = resultBuffer.toString().toUpperCase();
if (TextUtils.isEmpty(speechResult)) {
return;
}
}
}
// 会话发生错误回调接口
@SuppressLint("LongLogTag")
public void onError(SpeechError error) {
if (recognizerDialogManager != null) {
recognizerDialogManager.dismissRecognizerDialog();
}
// 获取错误码描述
Log.e(TAG, "error.getPlainDescription(true)==" + error.getPlainDescription(true));
}
// 开始录音
public void onBeginOfSpeech() {
if (recognizerDialogManager != null) {
recognizerDialogManager.showRecognizerDialog();
}
}
//volume 音量值0~30, data音频数据
public void onVolumeChanged(int volume, byte[] data) {
if (recognizerDialogManager != null) {
recognizerDialogManager.setVoiceImage(volume);
}
Logger.i("volume", volume + "");
Logger.i("录音文件data", data.length + "");
}
// 结束录音
public void onEndOfSpeech() {
if (recognizerDialogManager != null) {
recognizerDialogManager.showWaiting();
}
}
// 扩展用接口
@SuppressLint("LongLogTag")
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
if (SpeechEvent.EVENT_SESSION_ID == eventType) {
String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
Log.d(TAG, "session id =" + sid);
}
}
});
recognizerDialogManager = new RecognizerDialogManager(mainActivity);
} else {
PermissionUtil.getAudioPermissions(mainActivity, Constants.REQUEST_PERMISSIONS_AUDIO);
}
return "此处要返回onResult() 方法返回的值";
}