7.0 Compatible Camera Album Use

Posted by ryanbutler on Sat, 08 Jun 2019 02:31:56 +0200

scene

Many applications have the requirement of setting up the next avatar, which requires camera album. But when 6.0, run-time privilege detection is added. When 7.0, it restricts the building of shared files in the application, which is the file://URI used in the previous camera album can not be used.

Because in applications 7.0 and above, the Strict Mode API policy enforced by the android framework prohibits the disclosure of file://URI outside your application. If an intent containing the file URI leaves your application, the application fails and a FileUriExposedException exception is reported. If you want to share files between applications, you should send a content://URI and grant temporary access to the URI. The simplest way to do this authorization is to use the FileProvider class.

The logic of code execution

Because it is to help understand, so the code is organized from the business logic, along with the use of the camera album code preparation, in advance prepared things are mentioned when need to use. Utils indicates that the code is used in the tool class, Activity indicates that the code is used in Activeness when calling the camera album, and Project represents the configuration code of the project when the code is used.

Select Camera Album (Utils)

Through the bullet window, the user can choose whether to open the camera or the album. Note that when opening the camera here, the user has the right to detect.

chooseDialog = new AlertDialog.Builder(activity).setItems(
                new String[]{"camera", "Album"},
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        switch (arg1) {
                            case 0:
                                //- Check whether there is permission to open the camera
                                if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                                    //To request permission
                                    ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, 111);
                                } else {
                                    selectPicFromCamera();
                                }
                                break;
                            case 1:
                                selectPicFromLocal();
                            default:
                                break;
                        }
                    }
                }).create();
        chooseDialog.show();

Turn on the camera (Utils)

Note that android version judgment should be made. If Build.VERSION.SDK_INT >= Build.VERSION_CODES.N, use FileProvider to obtain Uri.

 /**
     * Turn on the camera
     */
    public void selectPicFromCamera() {
        if (!CommUtils.isExitsSdcard()) {
            Toast.makeText(mActivity, "No SD card", Toast.LENGTH_SHORT).show();
            return;
        }
        //User Head Cache Directory
        mFileUri.getParentFile().mkdirs();
        Uri imgUri = Uri.fromFile(mFileUri);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //Create a content-type Uri through FileProvider
            imgUri = FileProvider.getUriForFile(mActivity, "zxl.fengye.mallstore.fileprovider", mFileUri);
        }
        //--Call System Camera
        Intent intentCamera = new Intent();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //Add this sentence to indicate that the file represented by the Uri is temporarily authorized for the target application
        }
        intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        //Save the photo results in Uri of photo_file, not in the album
        intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
        mActivity.startActivityForResult(intentCamera, 2);
    }

FileProvider(Project)

You can see that we use FileProvider when we turn on the camera, and then we need to set up something in the project so that we can use FileProvider in our code.

  • 1. Add provider to manifest

Note that authorities must be unique, otherwise the application may not be installed on the target phone. Usually use project package name + self-defined name

<!-- compatible android7.0 -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="zxl.fengye.mallstore.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
  • 2. Create corresponding xml files under resource files

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path
            name="external"
            path="" />
        <files-path
            name="files"
            path="" />
        <cache-path
            name="cache"
            path="" />
    </paths>
</resources>

The root directory represented by <files-path/>: Context.getFilesDir()
The root directory represented by <external-path/>: Environment.getExternal Storage Directory ()
The root directory represented by <cache-path/>: getCacheDir()
name, by the way, will not be used in the code, but will be in the uri obtained;
Paths are directories that are allowed to be accessed. Null means that all directories and files in the corresponding root directory can be accessed.
ok, the configuration for FileProvider is complete. Next look

Open the photo album (Utils)

 /**
     * Open Album
     */
    private void selectPicFromLocal() {
        Intent intent1 = new Intent("android.intent.action.PICK");
        intent1.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
        mActivity.startActivityForResult(intent1, 1);
    }

Album Camera Callback (Activity)

We open the camera or album through Start Activity ForResult, so after taking or selecting a picture, we need to process it in Activity.

Here fileUri and fileCropUri are global variables, representing the location of the photographed image and the location of the cut image respectively:

  private File fileUri = new File(CommUtils.getSDPath() + "/FengYe/img/", System.currentTimeMillis() + ".png");
  private File fileCropUri = new File(CommUtils.getSDPath() + "/FengYe/imgCrop/", System.currentTimeMillis() + ".png");
  • Note that android version judgment is required in both album and camera callbacks. Because when Build.VERSION.SDK_INT >= Build.VERSION_CODES.N, you need to use FileProvider to get Uri.

After we get the uri of the picture, we need to tailor the picture photoUtils. start PhotoZoom (new uri).

    private Uri cropImageUri;
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 1 && data != null) { // Album
            if (!CommUtils.isExitsSdcard()) {
                Toast.makeText(UserInfoActivity.this, "No SD card", Toast.LENGTH_SHORT).show();
                return;
            }
            Uri newUri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                cropImageUri = Uri.fromFile(fileCropUri);
                newUri = Uri.parse(photoUtils.getPath(UserInfoActivity.this, data.getData()));
                newUri = FileProvider.getUriForFile(this, "zxl.fengye.mallstore.fileprovider", new File(newUri.getPath()));
            } else {
                newUri = Uri.parse("file://" + photoUtils.getPath(UserInfoActivity.this, data.getData()));
            }
            photoUtils.startPhotoZoom(newUri);
        } else if (requestCode == 2) {      //Photograph
            Uri imgUri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                //Create a content-type Uri through FileProvider
                imgUri = FileProvider.getUriForFile(UserInfoActivity.this, "zxl.fengye.mallstore.fileprovider", fileUri);
            } else {
                imgUri = Uri.fromFile(fileUri);
            }
            photoUtils.startPhotoZoom(imgUri);
        } else if (requestCode == 3 && data != null) {// post-crop
            Bitmap bitmap = (Bitmap) data.getExtras().get("data");
            uploadPic(bitmap, handler);
        }

    }

Get the file path (Utils)

photoUtils.getPath(UserInfoActivity.this, data.getData()) is used in the album camera callback. It should be noted that the selected image after Android 4.4 no longer returns to the real Uri, but the encapsulated Uri. Therefore, over 4.4, the Uri should be parsed.

List the differences of file paths before and after 4.4:

// 4.4 above content://com.android.providers.media.documents/document/image:3952
 // 4.4 The following content://media/external/images/media/3951
  • The following method of obtaining file path is written by a foreign developer. Most of them are reprinted in China, and some of them can not be used after modification. The code posted here is also transferred on the Internet. I can't confirm whether it is the original, but there is no problem in using it in my project.
@SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    //This method is automatically used in Android version 4.4 or below
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

Utils

After we take or select a picture through a camera or album, we need to tailor it. Especially now the mobile camera is getting better and better, the photos are getting bigger and bigger, and it's easy to take several M.

Android version judgment is also required here. When Build.VERSION.SDK_INT >= Build.VERSION_CODES.N, we need to grant URI temporary access intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION).

/**
     * Compatible with Android 7.0
     * @param uri
     */
    public void startPhotoZoom(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        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", true);
        mActivity.startActivityForResult(intent, 3);
    }

Activity after clipping pictures

As we have seen in the callback of the camera album, the clipped callback is processed, and the upload operation should vary according to the interface, so it is not stated here. So far, the relevant code and logic have been expressed.

 if (requestCode == 3 && data != null) {// post-crop
     Bitmap bitmap = (Bitmap) data.getExtras().get("data");
     uploadPic(bitmap, handler);
 }

Source code

This is the terrible source code zone. First, go to the tool class ChoosePhotoUtils.

public final class ChoosePhotoUtils {
    private AlertDialog chooseDialog;
    private Activity mActivity;
    private File mFileUri;
    private File mFileCropUri;

    public ChoosePhotoUtils(final Activity activity, File fileUri, File fileCropUri) {
        this.mActivity = activity;
        this.mFileUri = fileUri;
        this.mFileCropUri = fileCropUri;

        chooseDialog = new AlertDialog.Builder(activity).setItems(
                new String[]{"camera", "Album"},
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        switch (arg1) {
                            case 0:
                                //- Check whether there is permission to open the camera
                                if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                                    //To request permission
                                    ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, 111);
                                } else {
                                    selectPicFromCamera();
                                }
                                break;
                            case 1:
                                selectPicFromLocal();
                            default:
                                break;
                        }
                    }
                }).create();
        chooseDialog.show();
    }

    /**
     * Open Album
     */
    private void selectPicFromLocal() {
        Intent intent1 = new Intent("android.intent.action.PICK");
        intent1.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
        mActivity.startActivityForResult(intent1, 1);
    }


    /**
     * Turn on the camera
     */
    public void selectPicFromCamera() {
        if (!CommUtils.isExitsSdcard()) {
            Toast.makeText(mActivity, "No SD card", Toast.LENGTH_SHORT).show();
            return;
        }
        //User Head Cache Directory
        mFileUri.getParentFile().mkdirs();
        Uri imgUri = Uri.fromFile(mFileUri);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //Create a content-type Uri through FileProvider
            imgUri = FileProvider.getUriForFile(mActivity, "zxl.fengye.mallstore.fileprovider", mFileUri);
        }
        //--Call System Camera
        Intent intentCamera = new Intent();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //Add this sentence to indicate that the file represented by the Uri is temporarily authorized for the target application
        }
        intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        //Save the photo results in Uri of photo_file, not in the album
        intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
        mActivity.startActivityForResult(intentCamera, 2);
    }

    /**
     * Compatible with Android 7.0
     * @param uri
     */
    public void startPhotoZoom(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        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", true);
        mActivity.startActivityForResult(intent, 3);
    }

    /**
     * Android4.4 After that, the selected image no longer returns to the real Uri, but the encapsulated Uri. Therefore, above 4.4, the Uri should be parsed, that is, the above method of PhotoUtils.getPath().
     *
     * @param context Context object
     * @param uri     Uri of the current photo album
     * @return String corresponding to Uri after parsing
     */
    //  4.4 above content://com.android.providers.media.documents/document/image:3952
    //  4.4 The following content://media/external/images/media/3951
    @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    //This method is automatically used in Android version 4.4 or below
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

}

Activeness, UserInfo Activity for Reuse

public class UserInfoActivity extends BaseActivity {

    @Bind(R.id.iv_title_left)
    ImageView ivTitleLeft;
    @Bind(R.id.tv_title)
    TextView tvTitle;
    @Bind(R.id.iv_title_right)
    ImageView ivTitleRight;
    @Bind(R.id.tv_score2award)
    TextView tvScore2award;
    @Bind(R.id.user_img_camera)
    SimpleDraweeView userImgCamera;
    @Bind(R.id.user_ing_info)
    TextView userImgInfo;
    @Bind(R.id.nick_key)
    TextView nickKey;
    @Bind(R.id.nick_value)
    EditText nickValue;
    @Bind(R.id.tel_key)
    TextView telKey;
    @Bind(R.id.tel_value)
    TextView telValue;
    @Bind(R.id.psw_key)
    TextView pswKey;
    @Bind(R.id.psw_value)
    ImageView pswValue;
    @Bind(R.id.address_key)
    TextView addressKey;
    @Bind(R.id.address_value)
    EditText addressValue;
    @Bind(R.id.address_manger_key)
    TextView addressMangerKey;
    @Bind(R.id.address_manger_value)
    ImageView addressMangerValue;
    @Bind(R.id.sex_key)
    TextView sexKey;
    @Bind(R.id.sex_value_women)
    RadioButton sexValueWomen;
    @Bind(R.id.sex_value_man)
    RadioButton sexValueMan;
    @Bind(R.id.viewGorp_ll)
    LinearLayout viewGrop;
    @Bind(R.id.box_all)
    LinearLayout boxAll;
    private String imgName;
    private File outputImage;
    private File fileUri = new File(CommUtils.getSDPath() + "/FengYe/img/", System.currentTimeMillis() + ".png");
    private File fileCropUri = new File(CommUtils.getSDPath() + "/FengYe/imgCrop/", System.currentTimeMillis() + ".png");
    private ChoosePhotoUtils photoUtils;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_info);
        ButterKnife.bind(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        initView();
        loadData();
    }

    private boolean isEdit = false;

    private void initView() {
        tvTitle.setText("personal data");
        ivTitleRight.setVisibility(View.GONE);
        tvScore2award.setVisibility(View.VISIBLE);
        tvScore2award.setText("complete");
        tvScore2award.setTextColor(getResources().getColor(R.color.colorBlack));
        userImgCamera.getBackground().setAlpha(100);//0-255 transparency value
    }

    /**
     * Initialize data loading
     */
    private int userId = UserInfoUtils.getUserInfoBean().getUserId();

    private void loadData() {
        if (!CommUtils.isNetWorkConnected(UserInfoActivity.this)) {
            ToastUtil.showShort(UserInfoActivity.this, "Please check the network", Gravity.CENTER);
            return;
        }
        //Internet Request Personal Information
        ...
    }

    /**
     * Modify nicknames and other information
     */
    private void resetNickOrSex() {
        if (!CommUtils.isNetWorkConnected(UserInfoActivity.this)) {
            ToastUtil.showShort(UserInfoActivity.this, "Please check the network", Gravity.CENTER);
            return;
        }
       //Modify Personal Information Upload
       ...
    }

    @OnClick({R.id.viewGorp_ll, R.id.iv_title_left, R.id.tv_score2award, R.id.user_img_camera, R.id.tel_value, R.id.psw_value, R.id.address_manger_value})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.viewGorp_ll:
                CommUtils.hideKeyboard(UserInfoActivity.this);
                break;
            case R.id.iv_title_left:
                finish2Main();
                break;
            case R.id.tv_score2award:
                telValue.setMaxEms(6);
                telValue.setFilters(new InputFilter[]{new InputFilter.LengthFilter(11)});
                resetNickOrSex();
                break;
            case R.id.user_img_camera:
                photoUtils = new ChoosePhotoUtils(UserInfoActivity.this, fileUri, fileCropUri);
                break;
            case R.id.tel_value:
                startActivityForResult(new Intent(UserInfoActivity.this, ResetTelActivity.class), 10101);
                break;
            case R.id.psw_value:
                startActivity(new Intent(UserInfoActivity.this, ResetPswActivity.class));//Different ui s
                break;
            case R.id.address_manger_value:
                Intent intent1 = new Intent(UserInfoActivity.this, MangerAddressActivity.class);
                startActivity(intent1);
                break;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 111:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //Agree!
                    photoUtils.selectPicFromCamera();
                } else {
                    //refuse
                    Toast.makeText(this, "Pro, camera rights are denied.\n Please open it in the settings", Toast.LENGTH_LONG).show();
                }
                break;
            default:
                break;
        }
    }

    private void finish2Main() {
        Bundle bundle = new Bundle();
        bundle.putString("nick", UserInfoUtils.getUserInfoBean().getNickName());
        bundle.putString("img", UserInfoUtils.getUserInfoBean().getHeadImg());
        UserInfoActivity.this.setResult(RESULT_OK, UserInfoActivity.this.getIntent().putExtra("nickImg", bundle));
        UserInfoActivity.this.finish();
    }

    @Override
    public void onBackPressed() {
        finish2Main();
    }

    //Head image processing - -----------------------------------------------------------------------------------------------------------------------------------------------------------

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case mConstants.IMG_MSG:
                    Bundle data = msg.getData();
                    String imgPath = (String) data.get("thumPath");
                    resetUserImg(imgPath);
                    break;
                default:
                    break;

            }
        }
    };

    private Uri cropImageUri;

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 1 && data != null) { // Album
            if (!CommUtils.isExitsSdcard()) {
                Toast.makeText(UserInfoActivity.this, "No SD card", Toast.LENGTH_SHORT).show();
                return;
            }
            Uri newUri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                cropImageUri = Uri.fromFile(fileCropUri);
                newUri = Uri.parse(photoUtils.getPath(UserInfoActivity.this, data.getData()));
                newUri = FileProvider.getUriForFile(this, "zxl.fengye.mallstore.fileprovider", new File(newUri.getPath()));
            } else {
                newUri = Uri.parse("file://" + photoUtils.getPath(UserInfoActivity.this, data.getData()));
            }
            photoUtils.startPhotoZoom(newUri);
        } else if (requestCode == 2) {      //Photograph
            Uri imgUri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                //Create a content-type Uri through FileProvider
                imgUri = FileProvider.getUriForFile(UserInfoActivity.this, "zxl.fengye.mallstore.fileprovider", fileUri);
            } else {
                imgUri = Uri.fromFile(fileUri);
            }
            photoUtils.startPhotoZoom(imgUri);
        } else if (requestCode == 3 && data != null) {// post-crop
            Bitmap bitmap = (Bitmap) data.getExtras().get("data");
            uploadPic(bitmap, handler);
        }
        //Update the modified Tel
        if (requestCode == 10101 && data != null) {
            String phone = data.getStringExtra("phone");
            if (!TextUtils.isEmpty(phone)) {
                String start = phone.substring(0, 2);
                String end = phone.substring(8, 11);
                telValue.setText(start + "******" + end);
            }
        } else {
            loadData();
        }

    }

    /**
     * -----------Upload pictures
     */
    /**
     * Return json data
     */
    public void uploadPic(Bitmap bitmap, final Handler handler) {
        if (!CommUtils.isNetWorkConnected(UserInfoActivity.this)) {
            CommUtils.showSafeToast(UserInfoActivity.this, "Please check the network");
            return;
        }
        //Upload pictures
        ...
    }

    /**
     * Modify user profile http:
     *
     * @param img
     */
    private void resetUserImg(final String img) {
        if (!CommUtils.isNetWorkConnected(UserInfoActivity.this)) {
            CommUtils.showSafeToast(UserInfoActivity.this, "Please check the network");
            return;
        }
        //Modify the user's Avatar
        ...
    }

}

Topics: Android FileProvider Google network