关于android6.0的拍照调不起裁剪程序,并提示“文件无效,无法加载”

来源:互联网 发布:经营网络棋牌室赚钱吗 编辑:程序博客网 时间:2024/06/07 00:24

在这里统一的记录一下:

第一点,有一些手机没有sd卡(说是这样),就是那种getExternalStorage()得不到的情况,这种情况下当然是无法把拍的照片或者相册取出来的存进这个路径的,这是一个坑,我是这么解决的:

//App一些信息的存储文件夹路径private static final String appDirectoryPath = File.separator+"mnt"+File.separator+"sdcard"+File.separator+"HousingEstate";
定义一个自己的路径,前面的/mnt/sdcard好像是所有手机(我测试过的)都能找到这个路径,然后后面加上名字,之后创建目录,作为所有的该app的图片所在目录,注意的是,我这里是在继承自Application类(程序启动时加载)的一个工具类里定义的,这样只要程序一启动我就能得到它,不过,我原来是在这个类的
@Overridepublic void onCreate() {    super.onCreate();}

里面创建目录的,本来是可行的,可是放在android6.0上之后也不行了说是找不到file,于是就放在需要他的时候现去创建吧,我在这里是把它放在个人资料展示页创建的,因为这里要用到上传头像。

File rootDirectory = new File(TheApplication.getAppRootDirectoryPath());if (rootDirectory.exists()){    if (rootDirectory.isDirectory())        rootDirectory.delete();}rootDirectory.mkdirs();file = new File(rootDirectory.getPath(),"portrait.jpg");

第二点,在6.0以下所有测试的手机都完美执行上传头像功能(相册方式和相机方式都行),可到了android6.0之后,大坑来了!

首先,权限问题,具体可以参考我的另一篇博客点击打开链接。

本想着权限也配好了,一切都ok了,没想到啊没想到,神奇的事情发生了,首先,相册选取方式上传图片一点毛病都没有,就是拍照方式,能调起拍照程序,可是点击确认的时候却提示“文件无效,无法加载”,我以为又是权限问题,检查了好多遍,也查阅了好多遍,用到的权限都配置了,可就是不行,现在一想,权限没配置导致的后果是能调起拍照,但是点击确认键无效,和这个情况也不符啊。然后我以为是路径错误,各种跑断点,这一跑不要紧,结果发现,只要是跑断点结束后就能调起裁剪程序了,EXM?这是什么鬼?还有延迟?然后后来我又试了试在照完之后等待一会(具体多长时间并不确定),然后就好了,问了同事,发现onActivityForResult中的返回intent(也就是data)为空,于是推断会不会是这个原因,结果查看资料后发现,如果你调起拍照程序的时候没有写putExtra(MediaStore.EXTRA_OUTPUT, imageUri);这一句,那么他不会返回空,而是返回一个缩略图的地址(并不明白),如果指定了输出路径则返回的data就是null,所以和这个没关系。于是我断定肯定这中间有什么地方耗时了,在还没有准备好所需要的一切资源时就去调裁剪程序了,这时他肯定找不到资源啊,然后就各种尝试,最后发现了问题所在,先看一下调起相册和相机的代码:

fromGallery.setText("图库");                fromGallery.setOnClickListener(new View.OnClickListener() {                    @Override                    public void onClick(View v) {                        //如果选择的是相册                        try {                            if (file.exists()) {                                file.delete();                            }                            file.createNewFile();                        } catch (IOException e) {                            e.printStackTrace();                        }                        imageUri = Uri.fromFile(file);                        Intent intent = new Intent(Intent.ACTION_PICK);                        intent.setType("image/*");                        startActivityForResult(intent, GALLERY_REQUEST_CODE);                        mAlertDialog.dismiss();                    }                });                TextView fromCamera = (TextView) view.findViewById(R.id.cancle);                fromCamera.setText("相机");                fromCamera.setOnClickListener(new View.OnClickListener() {                    @Override                    public void onClick(View v) {                        //如果选择的是拍照(不能执行注释代码,否则会出现6.0调不出裁剪程序,并且无错误信息,只提示文件无效,无法加载”)//                        try {//                            if (file.exists()) {//                                file.delete();//                            }//                            file.createNewFile();////                        } catch (IOException e) {//                            e.printStackTrace();//                        }                        imageUri = Uri.fromFile(file);//                        Log.d("AAAAA", "Uri: "+imageUri.toString());                        Intent camera = new Intent("android.media.action.IMAGE_CAPTURE");                        camera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);                        startActivityForResult(camera, CAMERA_REQUEST_CODE);                        mAlertDialog.dismiss();                    }                });
对于拍照的异常,我已经在注释里写了,我想的是,file.delete()或者file.createNewFile()方法是耗时的,所以在还没有创建好的时候就去存放所拍的照片就会出错,而之所以相册的没事,是因为调起相册根本不需要指定输出路径,只是裁剪的时候会用到,等到了那个时候,中间这段时间足以让文件删除和创建工作都做好了,所以不会出错。总之,我发现,try-catch语句里面的代码根本可以不需要用,即便是相册,他不需要先去创建文件,指定输出路径后,他自己输出的时候会自动创建的,你只需要给他指定路径就好了。

再附上接收并调起裁剪程序的代码:

Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(imageUri, "image/*");// 裁剪框的比例,11intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);// 裁剪后输出图片的尺寸大小,如果不设置这个可能ImageView显示不完整导致显示黑色的intent.putExtra("outputX", 800);intent.putExtra("outputY", 600);intent.putExtra("scale", true);intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(intent, CROP_REQUEST_CODE);
最后在onActivityForResult方法中显示裁剪后的图片:

String path = file.getPath();bitmap = BitmapFactory.decodeFile(path);mPortrait.setImageBitmap(bitmap);
整个流程的file只需要在Activity初始化的时候实例化一次即可,并不需要创建和多次实例化!

最后,提一下怎么创建自定义效果的AlertDialog:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
final AlertDialog mAlertDialog = builder.create();
mAlertDialog.show();
//你自己定义的AlertDialog的内容布局
View view = View.inflate(this, R.layout.alert_dialog, null);
TextView title = (TextView) view.findViewById(R.id.title);
title.setText("你自己的标题");
TextView content = (TextView) view.findViewById(R.id.content);
content.setText("你自己的提示框信息");
TextView fromGallery = (TextView) view.findViewById(R.id.confirm);
fromGallery.setText("按钮1");
fromGallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something.
}
});
TextView fromCamera = (TextView) view.findViewById(R.id.cancle);
fromCamera.setText("按钮1");
fromCamera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//do something.
}
});
mAlertDialog.getWindow().setContentView(view);
//写成new ColorDrawable(0x00000000)的形式而不是null,如果是null有的手机会是黑色背景
mAlertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x00000000));
//2/3等于0了!!!
// Log.d("SD", "onClick: " + 2 / 3 * TheApplication.screenWidth + "||" + 1 / 3 * TheApplication.screenHeight);
Log.d("SD", "onClick: " + (int) ((float) 2 / 3) * TheApplication.screenWidth + "||" + (int) (float) 1 / 3 * TheApplication.screenHeight);
//这里指定成屏幕宽度的3分之2,高度的3分之1
mAlertDialog.getWindow().setLayout((int) (((float) 2 / 3) * TheApplication.screenWidth), (int) ((float) 1 / 3 * TheApplication.screenHeight));
//对于getWindow的修改都应该放在show之后!!








0 1
原创粉丝点击