How to pick image for crop from camera or gallery in Android 7.0?

后端 未结 9 2198
礼貌的吻别
礼貌的吻别 2020-12-01 04:56

Pick image for crop from gallery and camera it\'s done for below Android 7.0 but in Android Nought it crashes in camera. I use fileprovider for it but doesn\'t work.

相关标签:
9条回答
  • 2020-12-01 05:23

    Have you added this in Manifest.xml??

    <application
            ........
        <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>
    </application>
    

    this has to be there in your manifest.. for effect in the naugut android 7.0.

    Again you need to add provider_paths.xml file in 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>
    
    0 讨论(0)
  • 2020-12-01 05:27

    You can easily use this library which will be helpful to clean your project from boilerplate code for image pick and crop.

    0 讨论(0)
  • 2020-12-01 05:28

    Following solution works for me. I've tested with Gallery, Google drive, Photos etc.

    Sample is in Kotlin language.

    ImagePickUtils.kt

    fun getImageUri(context: Context, contentURI: String): Uri {
        var conUri = Uri.parse(contentURI)
        var filePath = ""
        if (DocumentsContract.isDocumentUri(context, conUri)) {
            val wholeID = DocumentsContract.getDocumentId(conUri)
    
            // Split at colon, use second item in the array
            val id = wholeID.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
    
            val column = arrayOf(MediaStore.Images.Media.DATA)
    
            // where id is equal to
            val sel = MediaStore.Images.Media._ID + "=?"
    
            val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    column, sel, arrayOf(id), null) ?: return conUri
    
            val columnIndex = cursor.getColumnIndex(column[0])
    
            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex)
            }
            cursor.close()
    
            if (filePath.isNotEmpty()) {
                filePath = filePath.replace(" ".toRegex(), "%20")
                conUri = Uri.parse("file://$filePath")
            }
        }
        return conUri
    }
    

    onActivityResult of Activity / Fragment:

    if (data != null) {
        val imagePath: Uri
        if (data.data != null) {
               val mImageUri = data.data
               imagePath = getImageUri(this@HomeActivity, mImageUri.toString())
               Log.i(TAG+" Image actual path", imagePath.toString())
        }
    }
    

    Hope this would help you.

    0 讨论(0)
  • 2020-12-01 05:28
    Intent pickImageIntent = new Intent("com.android.camera.action.CROP");
    Uri contentUri = imageUri;
    pickImageIntent.setDataAndType(contentUri, "image/*");
    pickImageIntent.putExtra("crop", "true");
    pickImageIntent.putExtra("aspectX", 1);
    pickImageIntent.putExtra("aspectY", 1);
    pickImageIntent.putExtra("outputX", 400);
    pickImageIntent.putExtra("outputY", 400);
    pickImageIntent.putExtra("return-data", true);
    startActivityForResult(pickImageIntent, RESULT_CROP);
    
    0 讨论(0)
  • 2020-12-01 05:29
        Uri uri = FileProvider.getUriForFile(this, getPackageName() + Configs.FILE_PROVIDER_NAME, inFile);
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        intent.setDataAndType(uri, "image/*");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outFile));
    

    You should notice that the uri for EXTRA_OUTPUT should not be modified by FileProvider. And your paths.xml should like this

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_sd" path="."/>
    <external-files-path name="external_app" path="."/>
    <files-path name="files" path="."/>
    <cache-path name="cache" path="."/>
    

    Because you create crop file under getExternalFilesDir. So <external-files-path> is necessary.

    0 讨论(0)
  • 2020-12-01 05:35

    I have two source for crop,one is gallery and the other one is camera

    the method gallery:

    //take a photo from gallery
    public void gallery() {
        //set UUID to filename
        String PHOTO_FILE_NAME = UUID.randomUUID().toString()+".jpg";
        Utils.putValue(this, Constants.UserPortraitFilePath,PHOTO_FILE_NAME);
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, PHOTO_REQUEST_GALLERY);
    }
    

    the method camera:

        //take a photo from camera
    public void camera() {
        //check sdcard is usable or not
        if (Utils.hasSdcard()) {
            //set UUID to filename
            String PHOTO_FILE_NAME = UUID.randomUUID().toString()+".jpg";
            Utils.putValue(this,Constants.UserPortraitFilePath,PHOTO_FILE_NAME);
            Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
            //set file location to DreamGo/Image
            File path = Environment.getExternalStorageDirectory();
            File dir = new File(path, "DreamGo/Image");
            if(!dir.exists())
                dir.mkdirs();
            //Android N need use FileProvider get file 
            //uri because StrictMode System
            //getUriForFile(content,provider author,file)
            Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider",
                    new File(dir.getAbsolutePath(), PHOTO_FILE_NAME));
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
        }else {
            showToast("no storage device");
        }
    }
    

    the crop method:

        //Android N crop image
    public void crop(Uri uri) {
        context.grantUriPermission("com.android.camera",uri,
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        //Android N need set permission to uri otherwise system camera don't has permission to access file wait crop
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        intent.putExtra("crop", "true");
        //The proportion of the crop box is 1:1
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        //Crop the output image size
        intent.putExtra("outputX", 800);
        intent.putExtra("outputY", 800);
        //image type
        intent.putExtra("outputFormat", "JPEG");
        intent.putExtra("noFaceDetection", true);
        //true - don't return uri |  false - return uri
        intent.putExtra("return-data", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
    }
    

    the onActivityResult method :

    private static final int PHOTO_REQUEST_CAMERA = 0;//camera
    private static final int PHOTO_REQUEST_GALLERY = 1;//gallery
    private static final int PHOTO_REQUEST_CUT = 2;//image crop
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        String PHOTO_FILE_NAME = Utils.getValue(this, Constants.UserPortraitFilePath);
        File path = Environment.getExternalStorageDirectory();
        File dir = new File(path, "DreamGo/Image");
        if(!dir.exists())
            dir.mkdirs();
        switch (requestCode)
        {
            case PHOTO_REQUEST_GALLERY:
                if (data != null){
                    //file from gallery
                    File sourceFile = new File(getRealPathFromURI(data.getData()));
                    //blank file DreamGo/Image/uuid.jpg
                    File destFile = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
                    Log.e("photo",data.getData().getPath());
                    try {
                        //copy file from gallery to DreamGo/Image/uuid.jpg
                        // otherwise crop method can't cut image without write permission
                        copyFile(sourceFile,destFile);
                        //Android N need use FileProvider to get file uri
                        Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider", destFile);
                        //cut image
                        crop(photoURI);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case PHOTO_REQUEST_CAMERA:
                //whether sdcard is usable has been checked before use camera
                File tempFile = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
                Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider", tempFile);
                crop(photoURI);
                break;
            case PHOTO_REQUEST_CUT:
                try {
                    if(data!=null) {
                        file = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
                        icon.loadImage("file://" + file.getAbsolutePath());
                    }else {
                        showToast("a error happened when cut picture");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }
    }
    

    the realted code:

    //copy sourceFile to destFile
    public void copyFile(File sourceFile, File destFile) throws IOException {
        if (!sourceFile.exists()) {
            return;
        }
        FileChannel source = new FileInputStream(sourceFile).getChannel();
        FileChannel destination = new FileOutputStream(destFile).getChannel();
        if (destination != null && source != null) {
            destination.transferFrom(source, 0, source.size());
        }
        if (source != null) {
            source.close();
        }
        if (destination != null) {
            destination.close();
        }
    }
    
    //file uri to real location in filesystem
    public String getRealPathFromURI(Uri contentURI) {
        Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
        if (cursor == null) {
            // Source is Dropbox or other similar local file path
            return contentURI.getPath();
        } else {
            cursor.moveToFirst();
            int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            return cursor.getString(idx);
        }
    }
    
    public static final String getValue(Context context, String key) {
        return getSharedPreference(context).getString(key, "");
    }
    public static final boolean putValue(Context context, String key,
                                         String value) {
        value = value == null ? "" : value;
        SharedPreferences.Editor editor = getSharedPreference(context).edit();
        editor.putString(key, value);
        boolean result = editor.commit();
        if (!result) {
            return false;
        }
        return true;
    }
    
    0 讨论(0)
提交回复
热议问题