MediaStoreを使ってDCIMディレクトリに画像を保存する

事の発端
Environment.getExternalStorageDirectory()がDeprecated!!!
頼むぜ,google・・・。
それ今から辞めたら影響度でかくない?
API level 1のときからだぜ?
今,30とか31だぜ?APIがYO!!!

ここに書いてある通りなんだけど・・・
qiita.com

アプリ内データはgetExternalFilesDir()とかで代替できるんだけども,今まで普通にアクセスしてた写真フォルダとかにはアクセスできなくなってくるわけなんですよ。
というわけで四苦八苦しながら解決いたしました。

MainActivity.java

package jp.co.hogehoge.mediastoretest;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Bitmap bmp;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView = findViewById(R.id.imageView);
        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic);

        button = findViewById(R.id.button);
        button.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        if (view == button) {

            ContentValues contentValues = new ContentValues();
             // ファイル名
            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "sample2.jpg");
            // MIMETYPEの設定
            contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
            // 書込み用にロックする
            contentValues.put(MediaStore.Images.Media.IS_PENDING, 1);
            //保存フォルダ ->DCIMディレクトリのtestに格納される(フォルダも自動で作ってくれる)
            //Environment.DIRECTORY_DCIMをEnvironment.DIRECTORY_PICTURESにすればPicturesディレクトに保存される
            contentValues.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM+"/test/");
            ContentResolver resolver = getApplicationContext().getContentResolver();
            
            Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
            Uri item = resolver.insert(collection, contentValues);

            try {
                OutputStream outPutStream = getContentResolver().openOutputStream(item);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                //ByteArrayOutputStreamに変換する
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
                //ストリームからバイトにして
                byte[] bytes = byteArrayOutputStream.toByteArray();
                // OutPutStreamに流し込む
                outPutStream.write(bytes);
                outPutStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            contentValues.clear();
            // ロックの開放
            contentValues.put(MediaStore.Images.Media.IS_PENDING, 0);
            resolver.update(item, contentValues, null, null);
        }
    }

}

AndroidManifest.xml

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

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        android:background="@drawable/ic"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="128dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

BUTTONを押すと・・・。
f:id:iinebot:20210622192544p:plain


DCIMのテストディレクトリに保存されました!
f:id:iinebot:20210622192604p:plain


参考

akira-watson.com

www.fixes.pub

matsudamper.hatenablog.com