说明
本文章是为了满足,调用系统应用图库或者调用相机应用来得到图片的做法,
从根本上将就是从前面两个应用中提取文件路径(应用间通信),如果想完成二维码扫描之类的自定义相机,可以SufaceView+Camera类来完成。
拍照做法
简单来讲,先保证读写文件权限与打开相机权限,传递Uri对象(7.0以上通过FileProvider提供,别的通过Uri.fromFile就可以了)到相机中,然后就等拍照结果返回就可以了,如果裁剪的话,将新的Uri传递进去Crop系统裁剪界面。最后将返回结果处理就行了,具体看下面方法。
打开相机准备工作
申请权限,需要下面两个权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
在Android 6.0系统下,可以选择在清单文件中静态注册,在Android 6.0以上需要代码中动态申请,关于代
码中动态申请,可以参照:
http://blog.csdn.net/thanksforandroid/article/details/75105002
打开相机
File tempFile = new File(MineStudentFragment.this.getContext().getExternalCacheDir()
, PHOTO_FILE_NAME);
/**生成一个文件,放在内置SD卡上,PHOTO_FILE_NAME是自己取的名字。*/
if (Build.VERSION.SDK_INT >= 24) {
uriP = FileProvider.getUriForFile(MineStudentFragment.this.getContext()
, "mooc.zhihuiyuyi.com.mooc.provider"
, tempFile);
} else {
uriP = Uri.fromFile(tempFile);
}
/**http://blog.csdn.net/thanksforandroid/article/details/76512616*/
if (uriP != null) {
ForOpenCamera(uriP, REQUEST_PERMISSION_GALLERY_FIRST,Manifest.permission.WRITE_EXTERNAL_STORAGE);
} else {
ToastUtils.showShort(MineStudentFragment.this.getContext(), "未找到可用文件路径");
}
/**下面这个if - else 是为了给6.0网上系统动态申请写SD卡权限,ForOpenCamera()方法是自己写的*/
ForOpenCamera()方法
private void ForOpenCamera(Uri uriP, int permissionCode, String permission) {
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
MineStudentFragment.this.requestPermissions(new String[]{permission}, permissionCode);//没有就去申请,这里是因为当时是在Fragment中使用的,
return;
} else {
startCamera(uriP);
}
} else {
startCamera(uriP);
}
}
/**参数说明,这里传进来一个Uri,是为了有权限时候直接去调用startCamera,permissionCode是权限
申请码,方便动态申请权限之后,在权限回调中判断,permission,是你要申请的权限*/
假设用户没有权限,那么就回去申请,申请结果的回调如下:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch(requestCode){
case REQUEST_PERMISSION_GALLERY_FIRST:
/**这里之展示了一种case*/
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//表示给了权限了
startCamera(uriP);
} else {
//表示没有权限,不能下一步
ToastUtils.showLong(MineStudentFragment.this.getContext(), "您把数据访问禁止了,你将不能享受服务。修改权限可以去设置中修改!");
}
break;
}
}
接下来看看startCamera()方法
public void startCamera(Uri uriP) {
// 激活相机
mIntent1 = new Intent("android.media.action.IMAGE_CAPTURE");
mIntent1.putExtra(MediaStore.EXTRA_OUTPUT, uriP);
requestPermissions(mIntent1,
REQUEST_PERMISSION_CAREMA,
Manifest.permission.CAMERA,
PHOTO_REQUEST_CAREMA);
}
/**在这里获取打开相机的intent,然后调用自定义的requestPermissions()这个自定义方法*/
requestPermissions()方法:
private void requestPermissions(Intent intent, int permissionCode,
String permission, int requestCode) {
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
MineStudentFragment.this.requestPermissions(new String[]{permission}, permissionCode);
return;
} else {
startActivityForResult(intent, requestCode);
}
} else {
startActivityForResult(intent, requestCode);
}
}
/***也是检查有没有打开相机权限,如果没有的话,就去申请,有的话,就去打开相机了,requestCode是为了
得到相机的返回值*/
假设用户也没有打开相机权限,那么权限回调如下,这里也只取关于相机权限部分:
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_CAREMA:
/**这里只截取了一部分*/
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startActivityForResult(mIntent1, PHOTO_REQUEST_CAREMA);
} else {
ToastUtils.showLong(MineStudentFragment.this.getContext(), "您把相机权限禁止了,您将不能享受服务。修改权限可以去设置中修改!");
}
break;
}
}
正常走到现在,用户会进行拍照,当结果返回的时候:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/**这里为了理解,只展示相机结果的回调*/
if (requestCode == PHOTO_REQUEST_CAREMA) {
tempFile = new File(MineStudentFragment.this.getContext().getExternalCacheDir()
, PHOTO_FILE_NAME);
if (Build.VERSION.SDK_INT >= 24) {
if (getImageContentUri(MineStudentFragment.this.getContext(), tempFile) != null) {
crop(getImageContentUri(MineStudentFragment.this.getContext(), tempFile));
} else {
ToastUtils.showShort(MineStudentFragment.this.getContext(), "拍照失败,稍后重试!");
}
} else {
if (Uri.fromFile(tempFile) != null) {
crop(Uri.fromFile(tempFile));
} else {
ToastUtils.showShort(MineStudentFragment.this.getContext(), "拍照失败,稍后重试!");
}
}
}
/**这里加了这么多层的嵌套,是为了避免空指针。下一步进行剪切,调用自定义的crop方法,它需要传一个Uri路
径,但是这里又存在问题,在Android 7.0网上版本,所需要的路径,不能直接同过Uri.fromFile来获得,
所以这里又多了一个判断*/
看看图片剪切的方法:
private void crop(Uri uri) {
// 裁剪图片意图
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
// 裁剪框的比例,1:1
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// 裁剪后输出图片的尺寸大小
intent.putExtra("outputX", 250);
intent.putExtra("outputY", 250);
intent.putExtra("outputFormat", "JPEG");// 图片格式
intent.putExtra("noFaceDetection", true);// 取消人脸识别
intent.putExtra("return-data", true);
// 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CUT
startActivityForResult(intent, PHOTO_REQUEST_CUT);
}
这里也是有一个startActivityForResult,接下来看看裁剪图片的返回结果的处理
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PHOTO_REQUEST_CUT) {
// 返回剪切后的数据,这里为了展示,也只是保留一部分需要的一部分
if (data != null && data.getParcelableExtra("data") != null) {
mStream = new ByteArrayOutputStream();
mBitmap = data.getParcelableExtra("data");
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, mStream);
/**图片可以应用了*/
/**接下来就是上传到服务器*/
File files = creatFile(mBitmap);//变成文件
putNET_Photo(files);
} else {
ToastUtils.showShort(MineStudentFragment.this.getContext(), "未知的错误发生了");
}
}
}
createFile()方法是将Bitmap转换成文件的方法,这里多说一下,其实到这里拍照已经结束了
private File creatFile(Bitmap bitmap) {
File cache = new File(getActivity().getCacheDir() + File.separator + CACHE_DIR);
BufferedOutputStream bos = null;
File file = null;
if (!cache.exists()) {
cache.mkdirs();
}
try {
file = new File(cache, USER_ICON_NAME);
bos = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
相册
简单来讲, 就是先打开相册,选择完之后传递会数据过来 ,生成图片就好了。
准备工作
需要权限如下:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
打开系统相册
mIntent2 = new Intent(Intent.ACTION_PICK);
mIntent2.setType("image/*");
requestPermissions(mIntent2,
REQUEST_PERMISSION_GALLERY,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
PHOTO_REQUEST_GALLERY);
针对于7.0以上,所以还是有动态获取权限,requestPermissions方法,
private void requestPermissions(Intent intent, int permissionCode,
String permission, int requestCode) {
if (Build.VERSION.SDK_INT >= 23) {
if(ContextCompat.checkSelfPermission(getContext(), permission)!= PackageManager.PERMISSION_GRANTED) {
MineStudentFragment.this.requestPermissions(new String[]{permission}, permissionCode);
return;
} else {
startActivityForResult(intent, requestCode);
}
} else {
startActivityForResult(intent, requestCode);
}
}
/**此方法和上述相机哪里申请第二个权限的时候一样,不需要重写,只需要调用即可*/
权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_GALLERY:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startActivityForResult(mIntent2, PHOTO_REQUEST_GALLERY);
} else {
ToastUtils.showLong(MineStudentFragment.this.getContext(), "您把数据访问禁止了,你将不能享受服务。修改权限可以去设置中修改!");
}
break;
}
}
/**这里直截取了一部分。*/
用户选完相片之后,看看对于结果的处理:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PHOTO_REQUEST_GALLERY) {
// 从相册返回的数据
if (data != null && data.getData() != null) {
// 获取图片的全路径
Uri uri_1 = data.getData();
LogUtils.d("MineStudentFragment", "得到图片的全路径是:" + uri_1.toString());
crop(uri_1);
} else {
ToastUtils.showShort(MineStudentFragment.this.getContext(), "选择相册失败,稍后重试!");
}
}
}
/**接下来就是调用crop方法,然后的处理就是和前面拍照一样了*/
####说明:
前面的权限结果回调方法还有Activity结果的回调方法,其实是在一块的,这里为了好理解,而分开了,这里也涉及到了权限动态申请还有FileProvider,这些 可以参考博客,
http://blog.csdn.net/thanksforandroid/article/details/75105002
http://blog.csdn.net/thanksforandroid/article/details/76512616