Android打开相册vs拍照获取图片的原理实现
2016-10-18 20:01
501 查看
前言:这几天在做用户登陆注册的逻辑时,遇到了要修改用户的头像问题的解决。在此把实现的原理以及实现过程中遇到的问题分享个大家...留下些许脚印
在手机的app里我们常常可用看到在个人中心页面有修改头像的功能 : 你可以选择拍照或从相册 选取图片来源。
1,拍照or从相册选择都是通过intent 的startActivityForResulr(intent,requestCode)方法来启动,在onActivityResutl()回调方法中获取图片存储路径。
2.拍照实现原理:当用户选择拍照时其可正常拍照或自拍方式来获取它想要的图片。这种方式是把拍下来的照片存储在SD卡里,通过调用系统相机创建一个Intent对象为其所在一个打开相机的action。然后在onActivityResutl()方法里获取到刚刚保存的图片的SD卡路径。然后跟即此图片路径你可以获取到他的bimmap或Picasso,Universal Image Loader.....等其他图片处理框架来设置到我们的ImageView控件上即可显示
3.从相册选择:此方式是通过Intent来打开系统相机。首先实列化一个Intent对象变设置其打开相机的action,调用startActivityForResulr(intent,requestCode)方法即可打开相册。然后在onActivityResutl()方法里通过getContentReslover()内容解析者来获取图片存储的cursor游标然后解析游标获取图片的路径,拿到图片路径后你就可以根据图片路径设置图片的显示啦。
所遇问题:
(1),在拍照时因为要把图片存储在SD卡里所以要手动用代码判断手机里是否挂载了SD卡。代码如下:
代码如下:
添加后可以看到此提示信息:
4.重写activity的onRequestPermissionsResult()方法监听用户对权限的选择,在授予权限的if分支里进行拍照或打开相册的业务操作
点击始终允许即可显示你拍照的图片。关于Android6.0系统的权限添加相关资料大家可参考:http://www.open-open.com/lib/view/open1446693346826.html
5,最后帖上完整的代码:
6,当手机系统为Android7.0. 打开相机拍照时应用会挂掉,报android.os.FileUriExposedException: file:///storage/emulated.. exposed beyond app through Intent.getData()
解决方案大家参照此篇文章:http://www.cnblogs.com/netcorner/p/6542373.html
在手机的app里我们常常可用看到在个人中心页面有修改头像的功能 : 你可以选择拍照或从相册 选取图片来源。
1,拍照or从相册选择都是通过intent 的startActivityForResulr(intent,requestCode)方法来启动,在onActivityResutl()回调方法中获取图片存储路径。
2.拍照实现原理:当用户选择拍照时其可正常拍照或自拍方式来获取它想要的图片。这种方式是把拍下来的照片存储在SD卡里,通过调用系统相机创建一个Intent对象为其所在一个打开相机的action。然后在onActivityResutl()方法里获取到刚刚保存的图片的SD卡路径。然后跟即此图片路径你可以获取到他的bimmap或Picasso,Universal Image Loader.....等其他图片处理框架来设置到我们的ImageView控件上即可显示
3.从相册选择:此方式是通过Intent来打开系统相机。首先实列化一个Intent对象变设置其打开相机的action,调用startActivityForResulr(intent,requestCode)方法即可打开相册。然后在onActivityResutl()方法里通过getContentReslover()内容解析者来获取图片存储的cursor游标然后解析游标获取图片的路径,拿到图片路径后你就可以根据图片路径设置图片的显示啦。
所遇问题:
(1),在拍照时因为要把图片存储在SD卡里所以要手动用代码判断手机里是否挂载了SD卡。代码如下:
//首先判断手机是否插入SD卡 String state = Environment.getExternalStorageState();//获取外部存储设备的存储状态 if (state.equals(Environment.MEDIA_MOUNTED)){ //打开系统相机的相关代码.... }else{ Toast.makeText(getActivity(), "请确保已插入SD卡", Toast.LENGTH_SHORT).show(); }(2),当用户的手机系统为 android 6.0或6.0以上的系统时,需要用代码的方式动态的判断用户是否添加了读写SD卡的权限【拍照把图片写入SD卡,从相册选择相当于从SD里读取数据】,即便你在清单文件里添加了但如果你不用代码动态方式提示用户授权此权限,那头像就读取不到。而在6.0以下的系统里只需在AndroidMainfest.xml文件里添加即可。由此可见Google在不断的加强系统对安装应用的权限管理。这也是出于一种安全性的考虑。
代码如下:
//6.0系统对权限加强里管理。so 使用代码方式来实现 设置权限[6.0以下系统只需在清单文件里添加] if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //申请WRITE_EXTERNAL_STORAGE权限 this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},22);//权限,请求码 }
添加后可以看到此提示信息:
4.重写activity的onRequestPermissionsResult()方法监听用户对权限的选择,在授予权限的if分支里进行拍照或打开相册的业务操作
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == WRITE_EXTERNAL_STORAGE_REQUEST_CODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户授予了此权限 } else { // 用户拒绝了此权限 } } }
点击始终允许即可显示你拍照的图片。关于Android6.0系统的权限添加相关资料大家可参考:http://www.open-open.com/lib/view/open1446693346826.html
5,最后帖上完整的代码:
//弹出对话框让用户选择头像来源(拍照vs相册) private void showPhotoSelectDialog(){ final AlertDialog.Builder builder = new AlertDialog.Builder(this); View view = UIUtils.inflater(R.layout.zdy_dailog); builder.setView(view); TextView paizhaoText = (TextView)view.findViewById(R.id.zdy_text1); TextView fromxzheText = (TextView)view.findViewById(R.id.zdy_text2); final AlertDialog theDialog = builder.create(); paizhaoText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { theDialog.dismiss(); fromPaizhao(); } }); fromxzheText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { theDialog.dismiss(); fromXianche(); } }); theDialog.show(); } private String image_from_sd_paizhao_or_xianche__path;//图片sd路径 private boolean isuploadImage;//标记用户是否上传图片 private String path; //sd卡路径 /** * 注意: * 1.拍照和打开相册Android6.0系统后要动态授予应用写和读SD卡的权限,否则拍照失败/从相册获取图片失败或应用崩溃 * 2.需重写onRequestPermissionsResult方法监听用户对权限的授予情况(拒绝vs允许),在允许的方法里执行相应的拍照或打开相册功能 * 3.经测试,在允许了其中一个权限后下次再点击就无需申请了 */ private static int WRITE_SD_CODE = 1; private static int READ_SD_CODE = 2; @TargetApi(Build.VERSION_CODES.M) private void fromPaizhao() { //6.0以上系统(拍照时)动态申请写sd卡权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},WRITE_SD_CODE);//权限,请求码 }else { paizhao(); Log.v("TAG", "拍照....."); } } @TargetApi(Build.VERSION_CODES.M) private void fromXianche() { //6.0以上系统(打开相册时)动态申请读sd卡权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},READ_SD_CODE); }else { xianche(); Log.v("TAG", "相册...."); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); Log.v("TAG", "权限requestCode:" + requestCode); if (requestCode == WRITE_SD_CODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { paizhao(); Log.v("TAG", "授予权限"); }else { Log.v("TAG", "拒绝权限"); } }else if(requestCode==READ_SD_CODE){ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { xianche(); Log.v("TAG", "授予权限"); }else { Log.v("TAG", "拒绝权限"); } } } /** * 解决android7.0拍照应用挂掉问题:http://www.cnblogs.com/netcorner/p/6542373.html * 1.安卓7.0遇到 android.os.FileUriExposedException: file:///storage/emulated.. exposed beyond app through Intent.getData() * 2.注意:4..2.2的系统拍照要用Uri.fromFile(file)(oppo手机测试结果),否则在拍照完成点击OK确认后在onActivityResult()方法里执行的是放弃拍照的if分支 * 故要做系统版本判断 */ private void paizhao(){ Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); path = Environment.getExternalStorageDirectory().getPath() + "/"; //将当前的拍照时间作为图片的文件名称 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); String filename = simpleDateFormat.format(new Date()) + ".jpg"; image_from_sd_paizhao_or_xianche__path = path + filename; File file = new File(image_from_sd_paizhao_or_xianche__path); //****************************************************************** Uri photoURI; //解决三星7.x或其他7.x系列的手机拍照失败或应用崩溃的bug.解决4.2.2(oppo)/4.x系统拍照执行不到设置显示图片的bug if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N){ //7.0以下的系统用 Uri.fromFile(file) photoURI = Uri.fromFile(file); }else { //7.0以上的系统用下面这种方案 photoURI = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider",file); } //****************************************************************** intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);//将图片文件转化为一个uri传入 startActivityForResult(intent, 100); } //打开相册 private void xianche(){ Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, 200); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode){ case 100://拍照 if (resultCode==this.RESULT_OK){ if(image_from_sd_paizhao_or_xianche__path!=null) { //UIL框架加载本地sd卡图片路径为 String imageFilePath = "file://" + image_from_sd_paizhao; //Picssao用file来封装文件 File file = new File(image_from_sd_paizhao_or_xianche__path); Picasso.with(this).load(file).into(circleImageView); isuploadImage = true; Log.v("TAG", "拍照获取的图片sd卡路径:" + image_from_sd_paizhao_or_xianche__path); } }else{ ToastUtils.show("放弃拍照"); } break; case 200://从相册 if(resultCode==this.RESULT_OK) { //内容解析者来操作内容提供最对数据的4方法 if (data!=null) { Uri uri = data.getData(); if (uri!=null) { Cursor cursor = getContentResolver().query(uri, null, null, null, null); //选择的就只是一张图片,所以cursor只有一条记录 if (cursor != null) { if (cursor.moveToFirst()) { image_from_sd_paizhao_or_xianche__path = cursor.getString(cursor.getColumnIndex("_data"));//获取相册路径字段 File file = new File(image_from_sd_paizhao_or_xianche__path); Picasso.with(this).load(file).into(circleImageView); isuploadImage = true; Log.v("TAG", "打开相册获取的图片sd卡路径:" + image_from_sd_paizhao_or_xianche__path); } } } } }else{ ToastUtils.show("放弃从相册选择"); } break; } }
6,当手机系统为Android7.0. 打开相机拍照时应用会挂掉,报android.os.FileUriExposedException: file:///storage/emulated.. exposed beyond app through Intent.getData()
解决方案大家参照此篇文章:http://www.cnblogs.com/netcorner/p/6542373.html
相关文章推荐
- Android打开相册vs拍照获取图片的原理实现
- Android实现类似QQ头像点击打开相册或者拍照,并获取裁剪后的图片
- Android 相册选择照片或拍照获取图片系统6.0及7.0实现
- Android拍照和从相册获取图片(解决android7.0打开相机崩溃的问题),同时也解决了拍完照后图片方向不正的问题
- android 调用系统相册选取照片或者打开相机拍照获取图片
- Android 拍照或者从相册获取图片的实现
- android 调用系统相册选取照片或者打开相机拍照获取图片
- Android 拍照或者从相册获取图片的实现
- android 调用系统相册选取照片或者打开相机拍照获取图片,返回时回到手机桌面,然后才会跳转到当前activity
- Android实现拍照及从相册获取图片
- android 调用系统相册选取照片或者打开相机拍照获取图片,返回时为什么会回到home界面或者到前一个界面,然后才会跳转到当前activity
- android 调用系统相册选取照片或者打开相机拍照获取图片,返回时回到手机桌面,然后才会跳转到当前activity
- Android获取本地相册图片和拍照获取图片的实现方法
- Android拍照和从相册获取图片(解决android7.0打开相机崩溃的问题),同时也解决了拍完照后图片方向不正的问题
- Android 实现拍照 获取相册 图片压缩 图片旋转 图片转存
- android 拍照或从相册获取图片 返回 bitmap
- Android调用相册拍照控件实现系统控件缩放切割图片
- Android 调用相册 拍照 实现系统控件缩放 切割图片
- Android调用相机实现拍照并裁剪图片,调用手机中的相册图片并裁剪图片
- Android开发,调用相册图片或者调用相机进行拍照获取图片