问题出现场景
此情况出现在Android程序将相机所拍照片存至手机的过程,主要原因是存储照片的操作反馈的数据为空,在代码中没有合理处理的原因。当使用APP时,出现了闪退现象。究于此,文章进行问题分析和解决。
出现问题的代码
相机拍照请求代码:
REQUEST_CODE_CAMERA = 1
//实例化一个intent,并指定action
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//指定一个图片路径对应的file对象
uri = Uri.fromFile(ImageUtil.getImageFile());
// 将所拍照片写至 uri 对应的文件路径
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
//启动activity
startActivityForResult(intent, REQUEST_CODE_CAMERA);
拍照后结果处理代码:
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//此处直接认为请求反馈回来的有数据,进行后续处理了。
if(requestCode == 1) {
if(resultCode == RESULT_OK) {
Toast.makeText(getApplicationContext(), "图片已保存",
Toast.LENGTH_SHORT).show();
}
}
}
原因分析
1 先根据Android程序的运行逻辑来看
下面代码展示了Android相机拍照过程中的关键代码,通过代码逻辑可看出:
Android系统框架Camera应用程序在默认情况下,即不需要指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);照相机有自己默认的存储路径,拍摄的照片将被写入到对应路径,且仅返回一个响应代码RESULT_OK,如果想访问原始图片,可以通过getIntent().getStringExtra(MediaStore.EXTRA_OUTPUT),得到原始图片位置,然后进行访问图片。如果指定了目标uri,data就没有反馈数据,如果没有指定uri,则data就返回有数据,且为bitmap!
综上,出错原因可能为我们没有在onActivityResult 方法中的data 进行空值判断。
// First handle the no crop case -- just return the value. If the
// caller specifies a "save uri" then write the data to it's
// stream. Otherwise, pass back a scaled down version of the bitmap
// directly in the extras.
if (mSaveUri != null) { //存在mSaveUri,即指定了目标uri
OutputStream outputStream = null;
try {
outputStream = mContentResolver.openOutputStream(mSaveUri);
outputStream.write(data);
outputStream.close();
setResult(RESULT_OK); //直接返回RESULT_OK,并没有指定intent
finish();
} catch (IOException ex) {
// ignore exception
} finally {
Util.closeSilently(outputStream);
}
} else {
Bitmap bitmap = createCaptureBitmap(data);
// 返回RESULT_OK,并包含一个Intent对象,其中Extra中科key为data,value为一个bitmap
setResult(RESULT_OK, new Intent("inline-data").putExtra("data", bitmap));
finish();
}
其他原因
问题一
我们自定义的存储路径不存在,且我们也没有在保存前判断路径是否存在,来新建路径,导致照片无法存储,如自定义存储路径是/mnt/sdcard/pics/,而手机SD 卡下在拍照前没有名为pics
的文件夹,那么部分手机拍照后图片不会保存,导致我们无法获得照片,大多数手机的相机遇到文件夹不存在的情况都会自己创建出不存在的文件夹,而个别手机却不会创建,其代表机型为:三星I8258、华为H30-T00、红米等。解决的方法就是在指定存储路径前先判断路径中的文件夹是否都存在,不存在先创建再调用相机。
问题二
照片可以存储,但是名字不对 file:///mnt/sdcard/123 1.jpg,由于Uri 的fromFile 方法会将路径中的空格用“%20”取代。其实对于大多数的手机这都不算事,手机在解析存储路径的时候都会将“%20”替换为空格,这样实际上最终的照片名字还是我们当初指定的名字:123 1.jpg,遗憾的是个别手机(如酷派7260)系统自带的相机没有将“%20”读成空格,拍照后的照片的名字是123%201.jpg,我们用路径“file:///mnt/sdcard/123 1.jpg”就不能找到该图像了。
根据以上分析,对应的解决方案如下:
(1)如果我们指定了路径,就不要使用data 来获取照片,起码在使用前要做空判断,即使用 onActivityResult 中返回的(data)做空判断。
(2)指定拍照路径时,先检查路径中的文件夹是否都存在,不存在时先创建文件夹再调用相机拍照。
(3)指定拍照存储路径时,照片的命名中不要包含空格等特殊符号。
【文章借鉴了这位前辈的文章:https://blog.csdn.net/zimo2013/article/details/16916279】