preface

Wrote a demo, simple logic is: add a line of text or watermark on a picture, and save to the system album, that is, the picture library on our mobile phone. There is no problem in the front editing pictures to add watermarks, but there is a problem in the back saving to the system album: no pictures can be displayed.

The problem

Three steps to save system albums before Android 10:

  • Save the picture to your phone
  • Insert the image into your phone’s gallery
  • Broadcast updates

The code is as follows:

public static void savePhotoAlbum(Context context, Bitmap bmp) {
    // Save the image first
    File appDir = new File(Environment.getExternalStorageDirectory(), "Boohee");
    if(! appDir.exists()) { appDir.mkdir(); } String fileName = System.currentTimeMillis() +".jpg";
    File file = new File(appDir, fileName);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        bmp.compress(CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
	}
    
    // Next, insert the file into the system gallery
    try {
        MediaStore.Images.Media.insertImage(context.getContentResolver(),
				file.getAbsolutePath(), fileName, null);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    // Finally notify gallery update
    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));
}
Copy the code

Problem: The image is not displayed, that is, not updated to the system gallery.

A careful observer will notice that there are two deprecated methods in the previous code:

 MediaStore.Images.Media.insertImage(context.getContentResolver(),
				file.getAbsolutePath(), fileName, null);
Copy the code
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path)));
Copy the code

To solve the problem

Here is a solution to the above problem and compatible with Android10 version:

    /** * Add watermark and save to system album */
    private void imgMerge(a) {
        new Thread(() -> {
            try {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
                File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "newFile.jpg");
                if(! file.exists()) { file.createNewFile(); }// Add watermark text position.
                Bitmap newBitmap = addTextWatermark(bitmap, "Test the demo sample");
                // Save to system album
                savePhotoAlbum(newBitmap, file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
    
    /** * save to album **@paramSRC Source image *@paramFile File to be saved */
    private void savePhotoAlbum(Bitmap src, File file) {
        if (isEmptyBitmap(src)) {
            return;
        }
        // Save to file first
        OutputStream outputStream;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(file));
            src.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
            if (!src.isRecycled()) {
                src.recycle();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // Update the gallery again
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, file.getName());
            values.put(MediaStore.MediaColumns.MIME_TYPE, getMimeType(file));
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
            ContentResolver contentResolver = getContentResolver();
            Uri uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,  values);
            if (uri == null) {
                return;
            }
            try {
                outputStream = contentResolver.openOutputStream(uri);
                FileInputStream fileInputStream = new FileInputStream(file);
                FileUtils.copy(fileInputStream, outputStream);
                fileInputStream.close();
                outputStream.close();
            } catch(IOException e) { e.printStackTrace(); }}else {
            MediaScannerConnection.scanFile(
                    getApplicationContext(),
                    new String[]{file.getAbsolutePath()},
                    new String[]{"image/jpeg"},
                    (path, uri) -> {
                        // Scan Completed}); }}Copy the code

Sending a broadcast and inserting a MediaProvider to add images to an album are officially deprecated. Using the above method on Android 10 and later will effectively solve the problem of not showing images.

Make a note!