Search code examples
androidlocal-storageandroid-cameraresolutionblurry

Android Low picture quality after shot


I have a button that triggers an image capture :

private void capturePicture() {
    if(ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Tiến hành gọi Capture Image intent
        startActivityForResult(intent, 100);
    } else ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, 200);
}

Right after I take the shot, I see the capture and the resolution is very low. It is saved in the local storage and when it is displayed in the app it's not in its original quality.

private void loadImageFromStorage(String path, int position, Device device)
{

    try {
        File f=new File(path,device.getSerial()+".jpg");
        Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
        imvDeviceImage.setImageBitmap(b);
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }

}

An here is for the permission

 if(ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        startActivityForResult(intent, 100);
    } else ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, 200);

After shooting In the app


Solution

  • Use File provider option for the same.

    In the manifest file add the provider description :

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

    add the permission :

      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    add a path file( i have made image_path.xml, added in the description of file provider) under res/xml folder. (if xml is not there, make one folder named xml.)

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

    Add dangerous permission request procedure for devices above lollipop, since WRITE_EXTERNAL_STORAGE is a dangerous permission.

    In the class, in which you initiate Camera :

    Declare a contant to pass in camera intent:

    private int ACTION_REQUEST_CAMERA = 8765;
      private String CAPTURE_IMAGE_FILE_PROVIDER = "YOUR_PACKAGE.fileprovider";
    

    Now, you can pass the uri instead in the camera intent.

        public void launchCamera() {
    // check for dangerous permission 
            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                File path = new File(activity.getFilesDir(), "Gallery/MyImages/");
                if (!path.exists()) path.mkdirs();
                File image = new File(path, "image_capture.jpg");
                Uri imageUri = FileProvider.getUriForFile(activity.getApplicationContext(), CAPTURE_IMAGE_FILE_PROVIDER, image);
                Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                providePermissionForProvider(cameraIntent, imageUri);
                startActivityForResult(cameraIntent, ACTION_REQUEST_CAMERA);
            } else {
                //if permission is not provided
                new PermissionsMarshmallow(activity);
            }
        }
    

    ::Edited :

    forgot to add this function :

     private void providePermissionForProvider(Intent intent, Uri uri) {
        List<ResolveInfo> resInfoList = activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            activity.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }
    

    In the onActivityResult function :

    //get the file from the uri path  , it is the same declared in the path file in xml folder. in this case it is Gallery/MyImages/
         File path = new File(activity.getFilesDir(), "Gallery/MyImages/");
                        if (!path.exists()) path.mkdirs();
                        File imageFile = new File(path, "image_capture.jpg");
    
                        Uri stringUri = Uri.fromFile(imageFile);
    
                        Bitmap bitmapFromMedia = MediaStore.Images.Media.getBitmap(activity.getContentResolver(), stringUri);
    

    Hope this helps. let me know if you opt for this procedure and are stuck somewhere.