//动态权限
implementation 'pub.devrel:easypermissions:2.0.1'
在清单文件中注册内容提供器, android:authorities 属性的值要和FileProvider.getUriForFile(MainActivity.this,VERA_FILEPROVIDER,outputImage)中第二个参数的值一样
创建@xml/file_paths
申请权限的代码:
String[] perms={
Manifest.permission.CAMERA,Manifest.permission.INTERNET,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE
};
if (EasyPermissions.hasPermissions(this,perms)){
init();
}else{
EasyPermissions.requestPermissions(this,getString(R.string.permission),RC_CEMERA_AND_LOCATION,perms);
}
private void takePhoto() {
// 创建file对象,用于存储拍照后的对象
File outputImage=new File(getExternalCacheDir(),"output_image.jpg");
try{
if (outputImage.exists())outputImage.delete();
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT>=24){
// FileProvider是一种特殊的内容提供器,使用了和内容提供器类似的机制来保护数据,可以选择性的将封装过的Uri共享给外部,从而提高应用的安全性。
mImageUri= FileProvider.getUriForFile(MainActivity.this,VERA_FILEPROVIDER,outputImage);
}else{
mImageUri=Uri.fromFile(outputImage);
}
// 启动相机程序
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定调用相机拍照后的照片存储的地址
intent.putExtra(MediaStore.EXTRA_OUTPUT,mImageUri);
startActivityForResult(intent,TAKE_PHOTO_RC);
}
private void choosePhoto() {
Intent intent=new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent,CHOOSE_PHOTO);
}
在onActivityResult()中处理:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case TAKE_PHOTO_RC:
if (resultCode==RESULT_OK){
try {
Bitmap bitmap= BitmapFactory.decodeStream(getContentResolver().openInputStream(mImageUri));
mImage.setImageBitmap(bitmap);
// 保存到相册
ImgUtil.saveImageToGallery(this,bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
case CHOOSE_PHOTO:
if (resultCode==RESULT_OK){
if (Build.VERSION.SDK_INT>=19){
handleImageOn19(data);
}else{
handleImageBefore10(data);
}
}
}
}
private void handleImageBefore10(Intent intent) {
Uri uri=intent.getData();
String imagePath=getImagePath(uri,null);
displayImage(imagePath);
}
@TargetApi(19)
private void handleImageOn19(Intent intent) {
String imagePath=null;
Uri uri=intent.getData();
if (DocumentsContract.isDocumentUri(this,uri)){
// 如果是document类型的uri,通过document id处理
String docId=DocumentsContract.getDocumentId(uri);
if (uri.getAuthority().equals("com.android.providers.media.documents")){
String id=docId.split(":")[1];//解析出数字格式的id
String selection=MediaStore.Images.Media._ID+"="+id;
imagePath=getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
}else if (uri.getAuthority().equals("com.android.providers.downloads.documents")){
Uri contentUri= ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(docId));
imagePath=getImagePath(contentUri,null);
}
}else if ("content".equalsIgnoreCase(uri.getScheme())){
// 如果是content类型的uri,则使用普通方式处理
imagePath=getImagePath(uri,null);
}else if ("file".equalsIgnoreCase(uri.getScheme())){
// 如果是file类型的uri,直接获取图片路径
imagePath=uri.getPath();
}
displayImage(imagePath);
}
private void displayImage(String imagePath) {
if (imagePath!=null){
Bitmap bitmap=BitmapFactory.decodeFile(imagePath);
mImage.setImageBitmap(bitmap);
}else{
Toast.makeText(this, "failed", Toast.LENGTH_SHORT).show();
}
}
private String getImagePath(Uri uri, String selection) {
String path=null;
// 通过Uri和selection来获取真实的图片路径
Cursor cursor=getContentResolver().query(uri,null,selection,null,null);
if (cursor!=null){
if (cursor.moveToFirst()){
path=cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
public class ImgUtil {
public static void saveImageToGallery(Context context, Bitmap bitmap){
// 首先保存图片
File appDir = new File(Environment.getExternalStorageDirectory(), "vgmap");
if (!appDir.exists()){
appDir.mkdirs();
}
String filename=System.currentTimeMillis()+".jpg";
File file=new File(appDir,filename);
try {
FileOutputStream fileOutputStream=new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG,100,fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 其次把文件插入到系统图库
try {
MediaStore.Images.Media.insertImage(context.getContentResolver(),file.getAbsolutePath(),filename,null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 最后通知图库更新
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse(file.getAbsolutePath())));
}
}
package com.example.anew;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.example.anew.utils.ImgUtil;
import pub.devrel.easypermissions.EasyPermissions;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int TAKE_PHOTO_RC = 2;
private static final int CHOOSE_PHOTO = 3;
private Button mBtnTakephoto;
private ImageView mImage;
private Button mBtnChoosePhoto;
private static final int RC_CEMERA_AND_LOCATION = 1;
private static final String VERA_FILEPROVIDER = "VERA_FILEPROVIDER";
// 照片所在的uri地址
private Uri mImageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnTakephoto = (Button) findViewById(R.id.btn_takephoto);
mImage = (ImageView) findViewById(R.id.image);
mBtnChoosePhoto = (Button) findViewById(R.id.btn_choose_photo);
mBtnTakephoto.setOnClickListener(this);
mBtnChoosePhoto.setOnClickListener(this);
String[] perms={
Manifest.permission.CAMERA,Manifest.permission.INTERNET,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE
};
if (EasyPermissions.hasPermissions(this,perms)){
init();
}else{
EasyPermissions.requestPermissions(this,getString(R.string.permission),RC_CEMERA_AND_LOCATION,perms);
}
}
private void init() {
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_takephoto:
takePhoto();
break;
case R.id.btn_choose_photo:
choosePhoto();
break;
}
}
private void choosePhoto() {
Intent intent=new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent,CHOOSE_PHOTO);
}
private void takePhoto() {
// 创建file对象,用于存储拍照后的对象
File outputImage=new File(getExternalCacheDir(),"output_image.jpg");
try{
if (outputImage.exists())outputImage.delete();
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT>=24){
// FileProvider是一种特殊的内容提供器,使用了和内容提供器类似的机制来保护数据,可以选择性的将封装过的Uri共享给外部,从而提高应用的安全性。
mImageUri= FileProvider.getUriForFile(MainActivity.this,VERA_FILEPROVIDER,outputImage);
}else{
mImageUri=Uri.fromFile(outputImage);
}
// 启动相机程序
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定调用相机拍照后的照片存储的地址
intent.putExtra(MediaStore.EXTRA_OUTPUT,mImageUri);
startActivityForResult(intent,TAKE_PHOTO_RC);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case TAKE_PHOTO_RC:
if (resultCode==RESULT_OK){
try {
Bitmap bitmap= BitmapFactory.decodeStream(getContentResolver().openInputStream(mImageUri));
mImage.setImageBitmap(bitmap);
// 保存到相册
ImgUtil.saveImageToGallery(this,bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
case CHOOSE_PHOTO:
if (resultCode==RESULT_OK){
if (Build.VERSION.SDK_INT>=19){
handleImageOn19(data);
}else{
handleImageBefore10(data);
}
}
}
}
private void handleImageBefore10(Intent intent) {
Uri uri=intent.getData();
String imagePath=getImagePath(uri,null);
displayImage(imagePath);
}
@TargetApi(19)
private void handleImageOn19(Intent intent) {
String imagePath=null;
Uri uri=intent.getData();
if (DocumentsContract.isDocumentUri(this,uri)){
// 如果是document类型的uri,通过document id处理
String docId=DocumentsContract.getDocumentId(uri);
if (uri.getAuthority().equals("com.android.providers.media.documents")){
String id=docId.split(":")[1];//解析出数字格式的id
String selection=MediaStore.Images.Media._ID+"="+id;
imagePath=getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
}else if (uri.getAuthority().equals("com.android.providers.downloads.documents")){
Uri contentUri= ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(docId));
imagePath=getImagePath(contentUri,null);
}
}else if ("content".equalsIgnoreCase(uri.getScheme())){
// 如果是content类型的uri,则使用普通方式处理
imagePath=getImagePath(uri,null);
}else if ("file".equalsIgnoreCase(uri.getScheme())){
// 如果是file类型的uri,直接获取图片路径
imagePath=uri.getPath();
}
displayImage(imagePath);
}
private void displayImage(String imagePath) {
if (imagePath!=null){
Bitmap bitmap=BitmapFactory.decodeFile(imagePath);
mImage.setImageBitmap(bitmap);
}else{
Toast.makeText(this, "failed", Toast.LENGTH_SHORT).show();
}
}
private String getImagePath(Uri uri, String selection) {
String path=null;
// 通过Uri和selection来获取真实的图片路径
Cursor cursor=getContentResolver().query(uri,null,selection,null,null);
if (cursor!=null){
if (cursor.moveToFirst()){
path=cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
}