做了一个拍照及从相册调用图片作为头像的功能:
一开始代码写好在Android6.0系统上正常运行,换了Android8.0 9.0就闪退了,那问题就是版本不兼容问题了,
一、首先在onCreate方法中加入了以下代码,判断系统大于6.0
//android 7.0系统以上解决拍照的问题
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.detectFileUriExposure();
}
}
二、解决了这个之后,能打开相机了,但是,,,拍照完毕后以及从相册选取完照片后,不能调取剪裁,于是在onActivityResult回调方法中及剪裁方法cropPhoto中 又加了几行代码
//处理手机不兼容问题
try {
head = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile));
verifyStoragePermissions(this);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
uritempFile=uri;
并且千万千万要注释掉这下面两条代码:
// head = extras.getParcelable("data");
//intent.putExtra("return-data", true);
下面是比较完整的代码:
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case CROP_PHOTO1:
if (resultCode == RESULT_OK) {
cropPhoto(data.getData()); //裁剪图片
}
break;
case CROP_PHOTO2:
if (resultCode == RESULT_OK) {
File temp = new File(Environment.getExternalStorageDirectory() +"/"+
spUserName+"_head.jpg");
cropPhoto(Uri.fromFile(temp)); //裁剪图片
}
break;
case SAVE_PHOTO:
if (data != null) {
Bundle extras = data.getExtras();
// head = extras.getParcelable("data");
//处理手机不兼容问题
try {
head = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile));
verifyStoragePermissions(this);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (head != null) {
String fileName=setPicToView(head); //保存在SD卡中
//保存头像地址到数据库中
DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("head",
fileName,spUserName);
iv_photo.setImageBitmap(head); //用ImageView显示出来
//发送广播更新“我”的界面中的头像
Intent intent = new Intent(
UpdateUserInfoReceiver.ACTION.UPDATE_USERINFO);
intent.putExtra(
UpdateUserInfoReceiver.INTENT_TYPE.TYPE_NAME,
UpdateUserInfoReceiver.INTENT_TYPE.UPDATE_HEAD);
intent.putExtra("head", fileName);
sendBroadcast(intent);
}
}
break;
}
/**
* 调用系统的裁剪功能
*/
public void cropPhoto(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
//aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 150);
intent.putExtra("outputY", 150);
//intent.putExtra("return-data", true);
//处理手机不兼容问题
uritempFile=uri;
startActivityForResult(intent, SAVE_PHOTO);
}
三、运行之后,还是闪退,出现日志
java.io.FileNotFoundException: /storage/emulated/0/ (Permission denied)
查询资料后,还是权限问题,安卓7.0系统以后写入SD卡权限失败问题,添加动态权限使APP可以访问手机存储权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//验证是否许可权限
for (String str : permissions) {
if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
}
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
builder.detectFileUriExposure();
}
}
三、很不幸,还没有完。如果你的手机是小米MIUI系统的话,小米miui系统调用系统裁剪图片功能camera.action.CROP后会崩溃或重新打开app
在剪裁方法cropPhoto中
//处理手机不兼容问题及小米手机不兼容问题
if (Build.MODEL.contains("MI")) {
uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + spUserName+"_head.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", false); // no face detection
}else {
//处理手机不兼容问题
uritempFile=uri;
}
上代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//验证是否许可权限
for (String str : permissions) {
if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
}
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
builder.detectFileUriExposure();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case CROP_PHOTO1:
if (resultCode == RESULT_OK) {
cropPhoto(data.getData()); //裁剪图片
}
break;
case CROP_PHOTO2:
if (resultCode == RESULT_OK) {
File temp = new File(Environment.getExternalStorageDirectory().getPath()+"/"+ spUserName+"_head.jpg");
cropPhoto(Uri.fromFile(temp)); //裁剪图片
}
break;
case SAVE_PHOTO:
if (data != null) {
Bundle extras = data.getExtras();
// head = extras.getParcelable("data");
//处理手机不兼容问题及小米手机不兼容问题
try {
head = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (head != null) {
String fileName=setPicToView(head); //保存在SD卡中
//保存头像地址到数据库中
DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("head",
fileName,spUserName);
iv_photo.setImageBitmap(head); //用ImageView显示出来
//发送广播更新“我”的界面中的头像
Intent intent = new Intent(
UpdateUserInfoReceiver.ACTION.UPDATE_USERINFO);
intent.putExtra(
UpdateUserInfoReceiver.INTENT_TYPE.TYPE_NAME,
UpdateUserInfoReceiver.INTENT_TYPE.UPDATE_HEAD);
intent.putExtra("head", fileName);
sendBroadcast(intent);
}
}
break;
case CHANGE_NICKNAME: //个人资料修改界面回传过来的昵称数据
if (data != null) {
new_info = data.getStringExtra("nickName");
if (TextUtils.isEmpty(new_info)) {
return;
}
tv_nickName.setText(new_info);
//更新数据库中的昵称字段
DBUtils.getInstance(UserInfoActivity.this).updateUserInfo(
"nickName", new_info, spUserName);
}
break;
case CHANGE_SIGNATURE: //个人资料修改界面回传过来的签名数据
if (data != null) {
new_info = data.getStringExtra("signature");
if (TextUtils.isEmpty(new_info)) {
return;
}
tv_signature.setText(new_info);
//更新数据库中的签名字段
DBUtils.getInstance(UserInfoActivity.this).updateUserInfo(
"signature", new_info, spUserName);
}
break;
}
}
/**
* 调用系统的裁剪功能
*/
public void cropPhoto(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
//aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 150);
intent.putExtra("outputY", 150);
//intent.putExtra("return-data", true);
//处理手机不兼容问题及小米手机不兼容问题
if (Build.MODEL.contains("MI")) {
uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + spUserName+"_head.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", false); // no face detection
}else {
//处理手机不兼容问题
uritempFile=uri;
}
startActivityForResult(intent, SAVE_PHOTO);
}
private String setPicToView(Bitmap mBitmap) {
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { //检测sd是否可用
return "";
}
FileOutputStream b = null;
File file = new File(path);
file.mkdirs(); //创建文件夹
String fileName = path + spUserName+"_head.jpg"; //图片名字
try {
b = new FileOutputStream(fileName);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b); //把数据写入文件
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
//关闭流
b.flush();
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return fileName;
}
未完待续……
在模拟器上,相册选取照片出现 editing is not supported for this image,还未解决……