您的位置:首页 > 移动开发 > Android开发

关于android 7.0调用相机拍照崩溃问题

2017-11-08 15:36 323 查看
解决安卓7.0拍照,相册选择崩溃的问题(包括压缩图片在内)

因为项目需要调用相机拍照,自己的测试手机是5.0,按照正常的调用方法直接可以调用,在项目测试的时候,同事的7.0系统相机拍照就崩了,进入相册没有崩,以前就听过7.0的权限问题,今天刚好碰到了就自己试着去解决一下这个问题。顺便记录一下,同时要感谢我所转载的那篇文章的大神

1.在清单文件AndroidManifest.xml中建一个内容提供者(不用java代码创建,直接复制到清单文件下即可)

[html] view
plain copy

<!-- 适配android 7.0 拍照闪退的处理 ,其中authorities的值要和等下代码中使用的一致就行,其中resource内的文件就是拍照后的共享文件 -->  

        <provider  

            android:name="android.support.v4.content.FileProvider"  

            android:authorities="com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider"  

            android:exported="false"  

            android:grantUriPermissions="true">  

            <meta-data  

                android:name="android.support.FILE_PROVIDER_PATHS"  

                android:resource="@xml/file_paths" />  

        </provider>  

2.在res文件夹下面新建一个xml文件夹,然后在xml文件夹下面建立一个file_paths的xml文件作为provider的共享文件路径

[html] view
plain copy

<?xml version="1.0" encoding="utf-8"?>  

<resources xmlns:android="http://schemas.android.com/apk/res/android">  

    <paths>  

        <external-path path="" name="camera_photos" />  

        <files-path path="" name="photos" />  

    </paths>  

</resources>  

其中name:一个引用字符串,意思就是可以随便写。 

path:文件夹“相对路径”,完整路径取决于当前的标签类型。 

path可以为空,表示指定目录下的所有文件、文件夹都可以被共享。 

在这个文件中,为每个目录添加一个XML元素指定目录。paths 可以添加多个子路径:< files-path> 分享app内部的存储;< external-path> 分享外部的存储;< cache-path> 分享内部缓存目录。

< files-path > 

代表目录为:Context.getFi
16544
lesDir() 

代表目录为:Environment.getExternalStorageDirectory() 

代表目录为:getCacheDir() 

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 

如果对于path不理解的可以查询资料。

3.在代码中将原来的方法做判断,新增7.0的适配方法 

拍照

[java] view
plain copy

private void tackUploadingCamera() {  

        //创建File对象,用于存储选择的照片  

        File outputImage = new File(getDiskCacheDir(mContext), "test.jpg");  

        Log.i(tag, "拍照文件路径=============:" + outputImage.toString());  

        try {  

            if (outputImage.exists()) {  

                outputImage.delete();  

            }  

            outputImage.createNewFile();  

        } catch (Exception e) {  

            e.printStackTrace();  

        }  

          

        Log.i(tag, "拍照的照片:imageUri路径:" + imageUri);  

        //隐式意图启动相机,拍照后并把照片存储的url存储到intent中区  

        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");  

        //判断是否是7.0的系统  

        if (Build.VERSION.SDK_INT < 24) {  

            //拍照的照片路径  

            imageUri = Uri.fromFile(outputImage);//7.0这里会闪退,imgfile是图片文件路径  

            Log.i(tag, "7.0之前的系统,拍照的照片:imageUri路径:" + imageUri);  

            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  

        } else {  

            //7.0系统的操作  

            imageUri = FileProvider.getUriForFile(mContext, "com.chc.photo.fileprovider", outputImage);  

            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  

            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件  

            Log.i(tag,"android7.0动态添加权限");  

        }  

        // 启动相机程序的Activity,Cut_PHOTO 是我项目需要进行裁剪功能,拍完后进行裁剪,这个可以根据自己需求去自己设置  

        startActivityForResult(intent, Cut_PHOTO);  

    }  

注意:不要添加这个权限,我之前有这个权限的时候一直崩掉,删除就好了

[html] view
plain copy

<uses-permission android:name="android.permission.CAMERA" />-->  

public class PhotoUtils {

private String photoType, temp = "temp.jpg", path = "/sdcard/myCert/";//sd路径
private EditMyAccountActivity activity;
private SimpleDraweeView simpleDraweeView;

public PhotoUtils(EditMyAccountActivity activity) {
this.activity = activity;
}

public void takePhoto(String photoType, SimpleDraweeView simpleDraweeView) {
this.photoType = photoType;
this.simpleDraweeView = simpleDraweeView;
//        mainactivitys.setSimpleDraweeViewEnable(false);//禁止所有图片点击功能

Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
File file = new File(Environment.getExternalStorageDirectory(), temp);
uri = FileProvider.getUriForFile(activity, "com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider", file);
LogUtils.debug(uri.toString());
} else {
uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp));
}

takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
activity.startActivityForResult(takeIntent, Constants.TAKE_PHOTO);
}

public void handlePhoto(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Constants.TAKE_PHOTO:
if (resultCode == -1) {
cropPhoto();
}
break;
case Constants.CROP_PHOTO:
LogUtils.debug("case:Crop");
if (data != null && data.getExtras() != null) {
/*  Bundle extras = data.getExtras();
Bitmap image = extras.getParcelable("data");*/
Bitmap image = null;
try {
image = BitmapFactory.decodeStream(activity.getContentResolver().openInputStream(Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp))));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (image != null) {
savePhoto(image, photoType);//保存在SD卡中
}
} else {
if (data == null) {
LogUtils.debug("data==null");
} else if (data.getExtras() == null) {
LogUtils.debug("data.getExtras()==null");
}
//                    mainactivitys.setSimpleDraweeViewEnable(true);
activity.showDialog("剪裁时发生错误,请重试");
}
break;
}
}

private void cropPhoto() {
LogUtils.debug("cropPhoto");
Uri uri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
File file = new File(Environment.getExternalStorageDirectory(), temp);
uri = FileProvider.getUriForFile(activity, "com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider", file);
} else {
uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp));
}

Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1.26);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
int width=PublicUtil.getwidthPixels(activity);
int height=PublicUtil.getheightPixels(activity);
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 300);
intent.putExtra("return-data", true);
//uritempFile为Uri类变量,实例化uritempFile
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp)));
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
LogUtils.debug("CropEnd");
activity.startActivityForResult(intent, Constants.CROP_PHOTO);
}

private void savePhoto(Bitmap mBitmap, String imageName) {
LogUtils.debug("savePhoto");
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用
return;
}
FileOutputStream jpgOut = null;
File file = new File(path);
file.mkdirs();// 创建文件夹
Log.e("创建文件夹", "OK!!!");
String jpgFileName = path + imageName;//图片名字
try {
jpgOut = new FileOutputStream(jpgFileName);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, jpgOut);// 把数据写入文件
//关闭流
jpgOut.flush();
jpgOut.close();
compressToTragetSize(mBitmap, jpgFileName);
setPhoto();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//            try {
//                if (jpgOut != null) {
//                    //关闭流
//                    jpgOut.flush();
//                    jpgOut.close();
//                }
//                compressToTragetSize(mBitmap, jpgFileName);
//                setPhoto();
//            } catch (IOException e) {
//                LogUtils.debug("写入失败!");
//                e.printStackTrace();
//            }
}

}

private void setPhoto() {
/* LogUtils.debug("setPhoto");
File temp = new File(path + photoType);
Uri photoUri = Uri.fromFile(temp);*/

/*  switch (photoType) {
case Constants.ID_FRONT:
LogUtils.debug(photoType);
*//* mFrontPhoto.setImageURI("/sdcard/myCert/" + photoType);
mFrontPhoto.setImageURI(photoUri);*//*
mFrontPhoto.setImageBitmap(bitmap);
break;
case Constants.ID_BACK:
LogUtils.debug(photoType);
//                mBackPhoto.setImageURI(photoUri);
mBackPhoto.setImageBitmap(bitmap);
break;
case Constants.YINGYE:
LogUtils.debug(photoType);
//                LogUtils.debug(temp.exists() ? "yes" : "NO");
//                mHandedPhoto.setImageURI(photoUri);
mHandedPhoto.setImageBitmap(bitmap);
break;
case Constants.DIAN:

break;
}*/

//        Bitmap bitmap = getSmallBitmap(path + photoType, 172, 252);
//        simpleDraweeView.setImageBitmap(bitmap);

Bitmap bitmap = getSmallBitmap(path + photoType, 172, 252);
Uri photoUri = Uri.parse(MediaStore.Images.Media.insertImage(activity.getContentResolver(), bitmap, null, null));
Fresco.getImagePipeline().evictFromCache(photoUri);
simpleDraweeView.setImageURI(photoUri);

//        simpleDraweeView.setImageBitmap(getSmallBitmap(path + photoType, 172, 252));
}

private void compressToTragetSize(Bitmap image, String fileName) {
File file = new File(fileName);
double size = file.length();
/* if (file.exists()) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
size = fis.available();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}*/
Log.e("文件字节大小", size + "");
while ((size / 1024d) > 450d) {
int compressSzie = (int) (100d / ((size / 1024d) / 450d));
compressSzie = 100 - compressSzie;
Log.e("kb", (size / 1024d) + "");
Log.e("倍数", ((size / 1024d) / 450d) + "");
Log.e("压缩比率", compressSzie + "");
FileOutputStream b = null;
try {
file.delete();//删除原文件
b = new FileOutputStream(fileName);
image.compress(Bitmap.CompressFormat.JPEG, 98, b);// 把数据写入文件

} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (b != null) {
//关闭流
b.flush();
b.close();
size = new File(fileName).length();
}
} catch (IOException e) {
LogUtils.debug("写入失败!");
e.printStackTrace();
}
}
}
}

/**
* 计算图片的缩放值
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}

/**
* 根据路径获得突破并压缩返回bitmap用于显示
*
* @param filePath
* @return
*/
public Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;  //只返回图片的大小信息
BitmapFactory.decodeFile(filePath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息