MediaScannerConnectionを使って画像をギャラリーに反映させる


アプリ内で保存した画像をギャラリーに反映させる方法を説明します。

カメラアプリや画像加工アプリを作成してSDカードなどのストレージに画像ファイルを保存した場合、そのままではギャラリーアプリからその画像を確認することができません。

今回の記事の方法でその画像ファイルをギャラリーの反映させることができます。

カメラアプリを作成したい場合や、SDカードに保存する場合は以下の記事が参考になります。

それでは続きでサンプルソースと共に説明します。

MediaScannerConnection

MediaScannerConnectionクラスはMediaScannerServiceと接続する役割を持ち、メディアファイルをMediaContent Providerに登録することができます。

このMediaScannerConnectionクラスのメソッドであるMediaScannerConnection#scanFileを使うことで任意の画像ファイルをMediaContent Providerに登録し、ギャラリーに反映させることができます。

scanFileメソッドはAPIレベル1から存在します。APIレベル8から同じscanFileという名前ですが、引き数が異なるものが追加されました。

APIレベル8で追加されたメソッドの方が呼び出しが簡単&複数のファイを指定することができて便利です。

最近の端末はAndroid2.2以上が多いのでまずはAPIレベル8で追加された方のscanFileメソッドを説明します。

scanFileメソッド(APIレベル8)

  • static void scanFile(Context context, String[] paths, String[] mimeTypes, MediaScannerConnection.OnScanCompletedListener callback)

定義を見てもらえば分かりますが、クラスメソッドなのでMediaScannerConnectionクラスのインスタンスを生成する必要がありません(後述するAPIレベル1からのscanFileメソッドはインスタンスメソッド)。

第2引数にギャラリーに反映させたいファイルのパスを、第3引数に対象とするメディアの種類のMineTypeを指定します。共に配列ですので複数指定することができます。

※第3引数のMimeTypeはnullを指定することも可能で、その場合は拡張子からタイプを推測してくれます。

MediaScannerConnection.OnScanCompletedListenerは1つのメソッドだけを持ったインタフェースです。スキャンが終わった際に呼ばれます。

  • abstract void onScanCompleted(String path, Uri uri)

以下のサンプルではSDカード直下のrotate.jpgをスキャンしてギャラリーに反映させています。

String[] paths = {Environment.getExternalStorageDirectory().toString()+ "/rotate.jpg"};
String[] mimeTypes = {"image/jpeg"};
MediaScannerConnection.scanFile(getApplicationContext(),
								paths,
				        	    mimeTypes,
				        	    mScanCompletedListener);
OnScanCompletedListener mScanCompletedListener = new OnScanCompletedListener() {
	@Override
	public void onScanCompleted(String path, Uri uri) {
		Log.d("MediaScannerConnection", "Scanned " + path + ":");
		Log.d("MediaScannerConnection", "-> uri=" + uri);
	}
};

上記のサンプルを実行してスキャンした際のログです。

onScanCompletedのpathにはスキャンしたファイルのパス、uriにはContentProviderのURIが入ります。URIがnullの場合はスキャンに失敗したということを表します。

scanFileメソッド(APIレベル1)

  • void scanFile(String path, String mimeType)

次にAPIレベル1から使えるscanFileメソッドです。こちらはインスタンスメソッドなのでまずはMediaScannerConnectionクラスのインスタンスを生成する必要があります。

コンストラクタの第2引数にはMediaScannerConnectionClientクラスを指定します。

このMediaScannerConnectionClientクラスには

  • onScanCompleted
  • onMediaScannerConnected

が定義されており、それぞれスキャンが完了した時、MediaScannerServiceへの接続が完了した時に呼び出されます。

ギャラリーへの反映の手順は手順は以下の通りです。

  1. MediaScannerConnectionクラスのインスタンスの生成
  2. MediaScannerServiceへ接続
  3. MediaScannerServiceへ接続が完了したらscanFileメソッドでスキャンを指示
  4. スキャンが完了したらMediaScannerServiceへ接続への接続を解除する

MediaScannerConnectionクラスのインスタンスの生成とMediaScannerConnection#connectでMediaScannerServiceへ接続を実施

mMediaScannerConnection = new MediaScannerConnection(getApplicationContext(),
													mScannerConnectionCluent);
mMediaScannerConnection.connect();

接続完了時に呼ばれるMediaScannerConnectionClient#onMediaScannerConnectedでMediaScannerConnection#scanFileを実行する。APIレベル8で追加されたscanFileと異なりは入れるではなく、1つのファイルしか指定することができません。

※第3引数のMimeTypeはnullを指定することも可能で、その場合は拡張子からタイプを推測してくれます。

MediaScannerConnectionClient mScannerConnectionCluent = new MediaScannerConnectionClient() {
	@Override
	public void onScanCompleted(String path, Uri uri) {
		Log.d("MediaScannerConnection", "Scanned " + path + ":");
		Log.d("MediaScannerConnection", "-> uri=" + uri);
		mMediaScannerConnection.disconnect();
	}

	@Override
	public void onMediaScannerConnected() {
		Log.d("MediaScannerConnection", "onMediaScannerConnected ");
        String path = Environment.getExternalStorageDirectory().toString()+ "/rotate.jpg";
        String mimeType = "image/jpeg";
        mMediaScannerConnection.scanFile(path, mimeType);
	}
};

補足

「今回は画像ファイルをスキャンし、ギャラリーに反映させるためにMediaScannerConnectionクラスを利用したけど、音声ファイルなども同様にスキャンしてContentProviderに登録することが可能だよ。」