android 7.0 拍照上传图片,Android调用系统相机、相册、剪裁图片并上传(常用于上传头像,兼容Android7.0)...

前言

在我们的日常开发当中,调用相机和从相册中选择照片裁剪并上传是很常见的功能,网上有很多框架,但是导入别人的库, 无疑增加了App的体积,因此这里讲一下如何使用系统自带的相机,相册,并裁剪,个人感觉还行

第一步 : FileProvider准备相关

在AndroidManifest.xml中增加provider节点,如下:

android:name="android.support.v4.content.FileProvider"

android:authorities="com.dream.takephotodemo"

android:grantUriPermissions="true"

android:exported="false">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/filepaths" />

其中: android:authorities 表示授权列表,填写你的应用包名,当有多个授权时,用分号隔开 android:exported 表示该内容提供器(ContentProvider)是否能被第三方程序组件使用,必须为false,否则会报异常:ava.lang.RuntimeException: Unable to get provider android.support.v4.content.FileProvider: java.lang.SecurityException: Provider must not be exported android:grantUriPermissions="true" 表示授予 URI 临时访问权限 android:resource 属性指向我们自及创建的xml文件的路径,文件名随便起

接下来,我们需要在资源(res)目录下创建一个xml目录,并建立一个以上面名字为文件名的xml文件,内容如下:

其中: external-path 代表根目录为: Environment.getExternalStorageDirectory() ,也可以写其他的,如: files-path 代表根目录为:Context.getFilesDir() cache-path 代表根目录为:getCacheDir() 其path属性的值代表路径后层级名称,为空则代表就是根目录,假如为“pictures”,就代表对应根目录下的pictures目录

第二步:使用FileProvider

在这之前,我们需要在AndroidManifest.xml中增加必要的读写权限:

1. 通过相机获取图片

/**

* 拍照

*/

private void takePhoto() {

//用于保存调用相机拍照后所生成的文件

if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

return;

}

captureFile = new File(rootFile, "temp.jpg");

//跳转到调用系统相机

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

//判断版本 如果在Android7.0以上,使用FileProvider获取Uri

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

Uri contentUri = FileProvider.getUriForFile(mContext, getPackageName(), captureFile);

intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);

} else {

//否则使用Uri.fromFile(file)方法获取Uri

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(captureFile));

}

startActivityForResult(intent, REQUEST_PERMISSION_CAMERA);

}

2. 通过相册获取图片

/**

* 从相册选择

*/

private void choosePhoto() {

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);

photoPickerIntent.setType("image/*");

startActivityForResult(photoPickerIntent, REQUEST_PERMISSION_WRITE);

}

3. 图片裁剪

/**

* 裁剪图片

*/

private void cropPhoto(Uri uri) {

cropFile = new File(rootFile, "avatar.jpg");

Intent intent = new Intent("com.android.camera.action.CROP");

intent.setDataAndType(uri, "image/*");

intent.putExtra("crop", "true");

intent.putExtra("aspectX", 1);

intent.putExtra("aspectY", 1);

intent.putExtra("outputX", 300);

intent.putExtra("outputY", 300);

intent.putExtra("return-data", false);//注意这里返回false,因为在部分手机上获取不到返回的数据

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cropFile));

intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());

intent.putExtra("noFaceDetection", true);

intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivityForResult(intent, CROP_REQUEST_CODE);

}

第三步:接收图片信息

我们在onActivityResult方法中获得返回的图片信息,在这里我们会先调用剪裁去剪裁图片,然后对剪裁返回的图片进行设置、保存、上传等操作

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if (resultCode == RESULT_OK) {

switch (requestCode) {

case REQUEST_PERMISSION_CAMERA:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

Uri contentUri = FileProvider.getUriForFile(mContext, getPackageName(), captureFile);

cropPhoto(contentUri);

} else {

cropPhoto(Uri.fromFile(captureFile));

}

break;

case REQUEST_PERMISSION_WRITE:

cropPhoto(data.getData());

break;

case CROP_REQUEST_CODE:

saveImage(cropFile.getAbsolutePath());

ivAvatar.setImageBitmap(BitmapFactory.decodeFile(cropFile.getAbsolutePath()));

break;

default:

break;

}

}

super.onActivityResult(requestCode, resultCode, data);

}

保存图片到本地

public String saveImage(String path) {

if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

return null;

}

Bitmap bitmap = BitmapFactory.decodeFile(path);

try {

FileOutputStream fos = new FileOutputStream(cropFile);

bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);

fos.flush();

fos.close();

return cropFile.getAbsolutePath();

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

至此,对Android7.0的兼容就结束了,注意在调用相机和裁剪时,传入的Uri需要使用FileProvider来获取

总结

拍照或从相册中选取时,我们首先要判断是否有拍照或读写SD卡的权限,如果没有则需要动态申请权限,这里我用的一个第三方库传送门,有了权限之后在进行下一步操作,还需要注意判断当前SD卡是否可用,做了这些判断之后,相信调用系统的拍照或者从相册中选择将会变得很简单

最后附上Demo地址传送门

如果大家对我的文章感兴趣的话,请为我点赞,谢谢!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值