skip to Main Content

I’m trying to use MediaStore API to save an image but it always save the file with this name
1637955326427.jpg and the size of the file is 0 B.
this is the code that i use:

 OutputStream fos;
            ContentResolver resolver = getBaseContext().getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "fileName.jpg");
            contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
            Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
            try {
                fos = resolver.openOutputStream(Objects.requireNonNull(imageUri));
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),list.get(0).getDocfile().getUri());
                if(bitmap!=null){
                    bitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);

                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

list.get(0).getDocFile() return a DocumentFile also i tested this on API 28
Thanks in advance

NOTICE this image already exist on the External Storage, just need to copy it.

EDIT: I delete this code fos = resolver.openOutputStream(imageUri); was duplucate. I do realy apologize. the file work fine but steal wrong name.

2

Answers


  1. Chosen as BEST ANSWER

    I delete this code fos = resolver.openOutputStream(imageUri); was duplicate. the image work fine but steal wrong name.

    About the Wrong name and extension, i think that MediaStore doesn't work fine with Android 9 and lower, because i tested the same code on Android 11 and it's working fine


  2. First lets take a look at getting write permissions for an existing image. Please note that the photopath does not necessarily exist yet but should point to the location you want your file to be saved.

    if (!requestPhotoWritePermission(this, getImageUriFromFS(this, new File(photoPath)))) {
            return;
        } else {
            takePicture();
        }
    

    This will form an overwrite request with the default camera

    public static Uri getImageUriFromFS(Context c, File file) {
        long id = getFilePathToImageID(file, c);
        Uri fromUri = ContentUris.withAppendedId( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,id);
        return fromUri;
    }
    
    
    
    public static long getFilePathToImageID(File imagePath, Context context)
    {
        Uri mainUri;
        Cursor cursor1 = context.getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[]{MediaStore.Images.Media._ID},
                MediaStore.Images.Media.DATA + "=? ",
                new String[]{imagePath.getAbsolutePath()}, null);
        long id = 0;
        if (cursor1 != null && cursor1.moveToFirst()) {
    
            id = cursor1.getLong(cursor1.getColumnIndex(MediaStore.MediaColumns._ID));
            cursor1.close();
        }
        return id;
    }
    
    public static boolean requestPhotoWritePermission(Activity activity, Uri fromUri) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    
            boolean hasPermission = true;
            if (activity.checkUriPermission(fromUri, Binder.getCallingPid(), Binder.getCallingUid(),
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION) != PackageManager.PERMISSION_GRANTED) {
                hasPermission = false;
            }
    
            List<Uri> uriList = new ArrayList<>();
            uriList.add(fromUri);
    
            if (!hasPermission) {
                PendingIntent pi = MediaStore.createWriteRequest(activity.getContentResolver(), uriList);
                try {
                    activity.startIntentSenderForResult(pi.getIntentSender(), REQUEST_OVERWRITE_PERMISSION_CODE, null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    e.printStackTrace();
                }
                return false;
            }
            return true;
        }
        return true;
    }
    

    This will persist the permission to overwrite or create a new picture via the camera intent

    Then in your activity:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 53) {
            if (resultCode == RESULT_OK) {
                //you'll want to take your picture here and possibly store the uri to your photo for later retrieval
                takePicture();
            }
     }
    

    This will take a picture if the permission request is accepted

    To Take a picture using the default intent with a provider:

    1. Declare your provider in the manifest

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

    1.5: xml File paths file:

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path
        name="internal_images"
        path="files/Pictures" />
    <external-files-path
        name="internal_images_alternate"
        path="Pictures" />
    <external-path
        name="external"
        path="Documents" />
    <external-files-path
        name="external_files"
        path="Documents" />
    <cache-path
        name="cache"
        path="Documents" />
    <external-cache-path
        name="external_cache"
        path="Documents" />
    <files-path
        name="files"
        path="Documents" />
    </paths>
    

    The above will give you permission to save to the documents folder. Replace as required.

    1. Utilize the provider to take the picture

      public static File dispatchTakePictureIntent(Activity activity, String photoPath) {
      
           Intent takePictureIntent = getCameraIntentWithUpdatedPackages(activity);
           Uri photoURI = Uri.fromFile(new File(photoPath));
      
           Uri photoUri = FileProvider.getUriForFile(activity.getApplicationContext(), activity.getApplicationContext().getPackageName() + ".provider", new File(photoPath));
      
           activity.grantUriPermission(photoURI.getAuthority(), photoUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
           takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
           //disable strict mode policies
           StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
           StrictMode.setVmPolicy(builder.build());
           activity.startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
           return new File(photoPath);
      
      
       return null;
      

      }

    EDIT:
    I forgot something

     public static Intent getCameraIntentWithUpdatedPackages(Context context) {
        List<ResolveInfo> resolveInfo = new ArrayList<>();
    
        final Intent capturePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        PackageManager pm = context.getPackageManager();
        resolveInfo = pm.queryIntentActivities(capturePhoto, 0);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    //             For Android 11 we need to add specific camera apps
            // due them are not added during ACTION_IMAGE_CAPTURE scanning...
    //            resolveInfo.addAll(getCameraSpecificAppsInfo(context));
        }
        capturePhoto.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    
        return capturePhoto;
    }
    

    EDIT: Update by the name (in onActivityResult after requesting an overwrite permission)

    Uri fromUri = MediaUtils.getImageUriFromFS(this, new File(from));
                    ContentResolver contentResolver = getContentResolver();
                    ContentValues contentValues = new ContentValues();
    
                    contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 1);
                    contentResolver.update(fromUri, contentValues, null, null);
                    contentValues.clear();
                    contentValues.put(MediaStore.Files.FileColumns.DISPLAY_NAME, new File(to).getName());
                    contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0);
                    contentResolver.update(fromUri, contentValues, null, null);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search