一行代码实现安卓照片选取上传服务器,并适配安卓7.0无法调起相机的问题

识字粗堪供赋役,不须辛苦慕公卿。这篇文章主要讲述一行代码实现安卓照片选取上传服务器,并适配安卓7.0无法调起相机的问题相关的知识,希望能为你提供帮助。


【一行代码实现安卓照片选取上传服务器,并适配安卓7.0无法调起相机的问题】最近在开发时需要实现头像更换功能,这里就要用到拍照和相册选取功能了。但是在安卓7.0的手机上遇到无法打开相机的问题。下面就针对7.0做了一些处理优化。


1,原因分析
??Android??升级到7.0后对权限又做了一个更新即不允许出现以file://的形式调用隐式APP,需要用共享文件的形式:content:// URI
2,解决方案
下面是打开系统相机的方法,做了android各个版本的兼容:


public void takePhoto()
File imgFile = new File(imgPath);
if (!imgFile.getParentFile().exists())
imgFile.getParentFile().mkdirs();

Uri imgUri = null;
if (Build.VERSION.SDK_INT < 24)
// 从文件中创建uri
imgUri = Uri.fromFile(imgFile);
else
//兼容android7.0 使用共享文件的形式
ContentValues contentValues = new ContentValues(1);
contentValues.put(MediaStore.Images.Media.DATA, imgFile.getAbsolutePath());
imgUri = mActivity.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);



Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
mActivity.startActivityForResult(intent, REQ_TAKE_PHOTO);



上面只是简单的一段代码,下面我把优化之后,并且支持一下功能
1,适配7.0拍照
2,相册选取图片
3,可以设置是否进行裁剪
4,通过glide实时显示选中的图片
5,如果用户拒绝了权限,可以给提示框进到用户跳到权限设置页
下面是效果图



下面贴出主要实现代码


public class LQRPhotoSelectUtils

public static final int REQ_TAKE_PHOTO = 10001;
public static final int REQ_SELECT_PHOTO = 10002;
public static final int REQ_ZOOM_PHOTO = 10003;

private Activity mActivity;
//拍照或剪切后图片的存放位置(参考file_provider_paths.xml中的路径)
private String imgPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + String.valueOf(System.currentTimeMillis()) + ".jpg";
//FileProvider的主机名:一般是包名+".fileprovider",严格上是build.gradle中defaultConfig中applicationId对应的值+".fileprovider"
private String AUTHORITIES = "packageName" + ".fileprovider";
private boolean mShouldCrop = false; //是否要裁剪(默认不裁剪)
private Uri mOutputUri = null;
private File mInputFile;
private File mOutputFile = null;

//剪裁图片宽高比
private int mAspectX = 1;
private int mAspectY = 1;
//剪裁图片大小
private int mOutputX = 800;
private int mOutputY = 480;
PhotoSelectListener mListener;

/**
* 可指定是否在拍照或从图库选取照片后进行裁剪
* < p>
* 默认裁剪比例1:1,宽度为800,高度为480
*
* @param activity上下文
* @param listener选取图片监听
* @param shouldCrop 是否裁剪
*/
public LQRPhotoSelectUtils(Activity activity, PhotoSelectListener listener, boolean shouldCrop)
mActivity = activity;
mListener = listener;
mShouldCrop = shouldCrop;
AUTHORITIES = activity.getPackageName() + ".fileprovider";
imgPath = generateImgePath();


/**
* 可以拍照或从图库选取照片后裁剪的比例及宽高
*
* @param activity 上下文
* @param listener 选取图片监听
* @param aspectX图片裁剪时的宽度比例
* @param aspectY图片裁剪时的高度比例
* @param outputX图片裁剪后的宽度
* @param outputY图片裁剪后的高度
*/
public LQRPhotoSelectUtils(Activity activity, PhotoSelectListener listener, int aspectX, int aspectY, int outputX, int outputY)
this(activity, listener, true);
mAspectX = aspectX;
mAspectY = aspectY;
mOutputX = outputX;
mOutputY = outputY;


/**
* 设置FileProvider的主机名:一般是包名+".fileprovider",严格上是build.gradle中defaultConfig中applicationId对应的值+".fileprovider"
* < p>
* 该工具默认是应用的包名+".fileprovider",如项目build.gradle中defaultConfig中applicationId不是包名,则必须调用此方法对FileProvider的主机名进行设置,否则Android7.0以上使用异常
*
* @param authorities FileProvider的主机名
*/
public void setAuthorities(String authorities)
this.AUTHORITIES = authorities;


/**
* 修改图片的存储路径(默认的图片存储路径是SD卡上 Android/data/应用包名/时间戳.jpg)
*
* @param imgPath 图片的存储路径(包括文件名和后缀)
*/
public void setImgPath(String imgPath)
this.imgPath = imgPath;


/**
* 拍照获取
*/
public void takePhoto()
File imgFile = new File(imgPath);
if (!imgFile.getParentFile().exists())
imgFile.getParentFile().mkdirs();

Uri imgUri = null;

//if (Build.VERSION.SDK_INT > = 24) //这里用这种传统的方法无法调起相机
//imgUri = FileProvider.getUriForFile(mActivity, AUTHORITIES, imgFile);
//else
//imgUri = Uri.fromFile(imgFile);
//
/*
* 1.现象
在项目中调用相机拍照和录像的时候,android4.x,Android5.x,Android6.x均没有问题,在Android7.x下面直接闪退
2.原因分析
Android升级到7.0后对权限又做了一个更新即不允许出现以file://的形式调用隐式APP,需要用共享文件的形式:content:// URI
3.解决方案
下面是打开系统相机的方法,做了android各个版本的兼容:
* */

if (Build.VERSION.SDK_INT < 24)
// 从文件中创建uri
imgUri

    推荐阅读