Android 7.0 take photos and upload

On Android 7.0 mobile phone, call the system camera with the old method to take photos and keep throwing. FileUriExposedException is abnormal. This is because Android 7.0 forces a policy called StrictMode to be enabled, and App cannot expose URI of file: / /. If you use Intent to open an external App with such a URI (for example, open the system camera to take a picture), you will throw a FileUriExposedException exception. Official FileProvider, solution.
The specific steps are as follows:
1. Create the folder XML in the res directory, and create the file [paths.xml file. The location is as follows:

Arbitrary xml file name
The contents of the xml file are as follows:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--<files-path/> //The root of the delegate: Context.getFilesDir()
        <external-path/> //Root directory represented: Environment.getExternalStorageDirectory()
         <cache-path/> //Root directory represented: getCacheDir()
         <root-path/> //External SD card
         -->
    <external-path
        name="external_files"
        path="">
    </external-path>
</resources>

2. In the Manifest.xml file, under the application tab:

<provider
     android:name="android.support.v4.content.FileProvider"
     android:authorities="com.xxx.fileprovider"
     android:exported="false"
     android:grantUriPermissions="true">
     <meta-data
           android:name="android.support.FILE_PROVIDER_PATHS"
           android:resource="@xml/image_paths" />
</provider>

xxx content is optional, preferably package name, and cannot be the same as other projects

3. Get Uri method:

private Uri getPhotoUri() {
        Uri imageUri = null;
        String sdDir = Environment.getExternalStorageDirectory().getAbsolutePath();
        String fileName = "new_photo.jpg";
        String path = sdDir + String.format("/%s/%s",
                "AAAA", fileName);
        File file = new File(path);
        file.getParentFile().mkdirs();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            try {
                imageUri = FileProvider.getUriForFile(this,
                        "com.xxx.fileprovider", file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            imageUri = Uri.fromFile(file);
        }
        return imageUri;
    }

4. System camera call method:

private void jumpToTakePhoto() {
        myUri = getPhotoUri();//myUri is the global Uri variable
        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//Photograph
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoUri());
        cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//Add flag here
        startActivityForResult(cameraIntent, TAKEPHOTO_CODE);
    }

5. Apply for permission and take photos:

private void getPermissionAndTakePhoto(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Android version greater than 6.0, dynamic application permission
            int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
            if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]
                        {Manifest.permission.CAMERA//Camera permissions
                                , Manifest.permission.WRITE_EXTERNAL_STORAGE//Storage permission
                        }, REQUEST_CARME_STATE);
            } else {
                jumpToTakePhoto();//Permission has been applied, take photos directly
            }
        } else {
            jumpToTakePhoto();//Android version is less than 6.0, take photos directly
        }
    }

Permission application result processing:

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == REQUEST_CARME_STATE && grantResults.length == 1 &&
                grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            jumpToTakePhoto();//Permission application succeeded, take photos
        }
    }

6. After taking photos, return to the display:

@Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Uri result=null;
        if (TAKEPHOTO_CODE == requestCode) {
            if (resultCode == RESULT_OK) {
                try {
                    if(bitmap!=null){
                        bitmap.recycle();//Recycle and release the image resources, otherwise the OOM will be abnormal when shooting again
                    }
                    //When photographing returns, obtain the file from the path and turn it into Bitmap, and display it to imageView
                    bitmap= BitmapFactory.decodeStream(getContentResolver().openInputStream(getPhotoUri()));

                    imageView.setImageBitmap(bitmap);

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }

The first time I did it, it was all pictures. Some of the pictures didn't show, which was embarrassing...

Tags: Android xml FileProvider Mobile

Posted on Thu, 26 Mar 2020 11:35:22 -0400 by Lexas