带有相机的Android N中的FileUriExposedException [英] FileUriExposedException in Android N with Camera

查看:69
本文介绍了带有相机的Android N中的FileUriExposedException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MainActivity

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button mBtn;
    private Context context;
    private static final int SELECT_PICTURE_CAMARA = 101, SELECT_PICTURE = 201, CROP_IMAGE = 301;
    private Uri outputFileUri;
    String mCurrentPhotoPath;
    private Uri selectedImageUri;
    private File finalFile = null;
    private ImageView imageView;
    private PermissionUtil permissionUtil;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mBtn = (Button) findViewById(R.id.btn_img);
    imageView = (ImageView) findViewById(R.id.img_photo);
    permissionUtil = new PermissionUtil();
    mBtn.setOnClickListener(this);
    context = this;
}

@Override
public void onClick(View view) {
    selectImageOption();
}

private void selectImageOption() {
    final CharSequence[] items = {"Capture Photo", "Choose from Gallery", "Cancel"};

    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
    builder.setTitle("Add Photo!");
    builder.setItems(items, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int item) {
            if (items[item].equals("Capture Photo")) {                
                if (permissionUtil.checkMarshMellowPermission()) {
                    if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getCameraPermissions()))
                        onClickCamera();
                    else
                        ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getCameraPermissions(), SELECT_PICTURE_CAMARA);
                } else
                    onClickCamera();
            } else if (items[item].equals("Choose from Gallery")) {
                if (permissionUtil.checkMarshMellowPermission()) {
                    if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getGalleryPermissions()))
                        onClickGallery();
                    else
                        ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getGalleryPermissions(), SELECT_PICTURE);
                } else
                    onClickGallery();
            } else if (items[item].equals("Cancel")) {
                dialog.dismiss();
            }
        }
    });
    builder.show();
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (resultCode == RESULT_OK) {

        if (requestCode == SELECT_PICTURE) {

            selectedImageUri = data.getData();
            cropImage(selectedImageUri);

        } else if (requestCode == CROP_IMAGE) {
            /*if (data != null) {
                // get the returned data
                Bundle extras = data.getExtras();
                // get the cropped bitmap
                Bitmap selectedBitmap = extras.getParcelable("data");

                imageView.setImageBitmap(selectedBitmap);
            }*/

            Uri imageUri = Uri.parse(mCurrentPhotoPath);
            File file = new File(imageUri.getPath());
            try {
                InputStream ims = new FileInputStream(file);
                imageView.setImageBitmap(BitmapFactory.decodeStream(ims));
            } catch (FileNotFoundException e) {
                return;
            }

        } else if (requestCode == SELECT_PICTURE_CAMARA && resultCode == Activity.RESULT_OK) {
            cropImage(Uri.parse(mCurrentPhotoPath));

        }
    }
}

private void onClickCamera() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException ex) {
        }
        if (photoFile != null) {

            Uri photoURI;
            if (Build.VERSION.SDK_INT >= 24) {
                photoURI = FileProvider.getUriForFile(MainActivity.this,
                        BuildConfig.APPLICATION_ID + ".provider", photoFile);
            } else {
                photoURI = Uri.fromFile(photoFile);
            }

            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(takePictureIntent, SELECT_PICTURE_CAMARA);

        }
    }
}

private void onClickGallery() {
    List<Intent> targets = new ArrayList<>();
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_PICK);
    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
    List<ResolveInfo> candidates = getApplicationContext().getPackageManager().queryIntentActivities(intent, 0);

    for (ResolveInfo candidate : candidates) {
        String packageName = candidate.activityInfo.packageName;
        if (!packageName.equals("com.google.android.apps.photos") && !packageName.equals("com.google.android.apps.plus") && !packageName.equals("com.android.documentsui")) {
            Intent iWantThis = new Intent();
            iWantThis.setType("image/*");
            iWantThis.setAction(Intent.ACTION_PICK);
            iWantThis.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
            iWantThis.setPackage(packageName);
            targets.add(iWantThis);
        }
    }
    if (targets.size() > 0) {
        Intent chooser = Intent.createChooser(targets.remove(0), "Select Picture");
        chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
        startActivityForResult(chooser, SELECT_PICTURE);
    } else {
        Intent intent1 = new Intent(Intent.ACTION_PICK);
        intent1.setType("image/*");
        startActivityForResult(Intent.createChooser(intent1, "Select Picture"), SELECT_PICTURE);
    }
}

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";

    File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    if (Build.VERSION.SDK_INT >= 24) {
        mCurrentPhotoPath = String.valueOf(FileProvider.getUriForFile(MainActivity.this,
                BuildConfig.APPLICATION_ID + ".provider", image));
    } else {
        mCurrentPhotoPath = String.valueOf(Uri.fromFile(image));
    }

    return image;
}

private void cropImage(Uri selectedImageUri) {
    Intent cropIntent = new Intent("com.android.camera.action.CROP");

    cropIntent.setDataAndType(selectedImageUri, "image/*");

    cropIntent.putExtra("crop", "true");
    cropIntent.putExtra("aspectX", 1);
    cropIntent.putExtra("aspectY", 1.5);
    cropIntent.putExtra("return-data", true);

    outputFileUri = Uri.fromFile(createCropFile());

    cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(cropIntent, CROP_IMAGE);
}

private File createCropFile() {
    File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    //  path = path + (timeStamp + "1jpg");
    File file = null;
    try {
        file = File.createTempFile(timeStamp, ".jpg", storageDir);
    } catch (IOException e) {
        e.printStackTrace();
    }

    mCurrentPhotoPath = String.valueOf(Uri.fromFile(file));
    return file;
}
}

PermissionUtil.java

package com.example.shwetachauhan.imagecropasoebi;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;

public class PermissionUtil {
    private String[] galleryPermissions = {
        "android.permission.WRITE_EXTERNAL_STORAGE",
        "android.permission.READ_EXTERNAL_STORAGE"
};

private String[] cameraPermissions = {
        "android.permission.CAMERA",
        "android.permission.WRITE_EXTERNAL_STORAGE",
        "android.permission.READ_EXTERNAL_STORAGE"
};

public String[] getGalleryPermissions(){
    return galleryPermissions;
}

public String[] getCameraPermissions() {
    return cameraPermissions;
}

public boolean verifyPermissions(int[] grantResults) {
    if(grantResults.length < 1){
        return false;
    }

    for (int result : grantResults) {
        if (result != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}

public boolean verifyPermissions(Context context, String[] grantResults) {
    for (String result : grantResults) {
        if (ActivityCompat.checkSelfPermission(context, result) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}

public boolean checkMarshMellowPermission(){
    return(Build.VERSION.SDK_INT> Build.VERSION_CODES.LOLLIPOP_MR1);
}

public boolean checkJellyBean(){
    return(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN);
}
}

  • 此代码用于从相机"或图库"中选择要裁剪的图像
  • 此代码适用于所有android操作系统,但是当我尝试在Android N设备上运行时,打开Camera会崩溃.在带有Gallery的Android N中可以正常使用.
  • 推荐答案

    我在 Android N设备中也遇到过同样的问题.但我解决了.

    这是我的代码,可以解决此问题:

    Here is my code which can solve the issue:

     public void launchCamera() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFileUri());
        } else {
            File file = new File(getPhotoFileUri().getPath());
            Uri photoUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", file);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
        }
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        if (intent.resolveActivity(getApplicationContext().getPackageManager()) != null) {
            startActivityForResult(intent, REQUEST_CAMERA);
        }
    }
    

    此后,您需要在res中创建一个 XML文件夹,然后在该文件夹中创建一个标记为 provider_paths.xml

    After this you need to create a XML folder in res, and in that folder you need to create a xml labeled provider_paths.xml

    provider_paths.xml

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
    </paths>
    

    稍后在清单中,您需要在应用标签中添加以下内容,并确保 compileSdkVersion> = 24

    Later in manifest you need to add the following inside the application tag and make sure that the compileSdkVersion >=24

    <provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/provider_paths"/>
    </provider>
    

    以下是两个参考链接,它们可以指导您更好地理解.

    Here are the two reference links which can guide you better for better understanding.

    链接:

    link1 -来自媒体合作

    link2 -来自inthecheesefactory

    link2 - from inthecheesefactory

    这篇关于带有相机的Android N中的FileUriExposedException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆