一介の開発者の戯言

最近カメラアプリを作っています。
撮影した画像をサムネイル表示しているのですが写真を上書きしたときにサムネイルが更新されません。

色々なサンプルソースを見るとサムネイルを作るときにMediaStore.Images.Mediaにデータを挿入するようになっています。
MediaStore.Images.Mediaにデータがないとサムネイルが作られないから挿入しているようです。
しかし挿入だけだと同じファイルを複数登録してしまうことになり、Android自体の速度低下等を招きかねないので既に存在していたらアップデートするか削除して挿入するかにした方がいいと思います。

画像を更新してからMediaStore.Images.Mediaを更新してみましたがサムネイルは更新されませんでした。
削除してから挿入してみたらContentResolver.deleteをしてからContentResolver.insertを行うと対象のファイルが0バイトになるので
ContentResolver.deleteで対象ファイルが削除されるようです。
そこでContentResolver.deleteを行ってから画像ファイルを保存してContentResolver.insertを行ってみたところ、サムネイルがちゃんと更新されました。
以下がサンプルソースです。

	private String TAG = "Thumbnail Sample";
	private void writePicture(String fname, byte[] data)
	{
		//対象ファイルの削除
		removeThumb(fname);

		//画像ファイルの保存
		try{
			FileOutputStream outfile = new FileOutputStream(fname);
			outfile.write(data);
			outfile.close();
		}catch(Exception e){
			Log.e(TAG,e.getStackTrace()[0].getFileName()
				+"("+e.getStackTrace()[0].getLineNumber()+")"
				+e.getStackTrace()[0].getMethodName()
				+" "+e.toString());
		}

		//サムネイルの削除対象に登録
		makeThumb(fname);
	}

	/**
	 * ContentResolverへ画像ファイル(jpeg)を登録し、サムネイル作成対象にします
	 * @param fname 登録する画像ファイルのフルパス
	 */
	private void makeThumb(String fname)
	{
		long now = System.currentTimeMillis();
		try{
			ContentValues values = new ContentValues();
			ContentResolver cr = getContext().getContentResolver();
			values.put(Images.Media.MIME_TYPE, "image/jpeg");
			values.put("_data", fname);
			values.put(Images.Media.DATE_ADDED,now);
			values.put(Images.Media.DATE_TAKEN,now);
			values.put(Images.Media.DATE_MODIFIED,now);
			cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
		}catch(Exception e){
			Log.e(TAG,e.getStackTrace()[0].getFileName()
				+"("+e.getStackTrace()[0].getLineNumber()+")"
				+e.getStackTrace()[0].getMethodName()
				+" "+e.toString());
		}
	}

	/**
	 * ContentResolverから画像ファイルを削除します
	 * @param fname 削除する画像ファイルのフルパス
	 */
	private void removeThumb(String fname)
	{
		ContentResolver cr = getContext().getContentResolver();
		try{
			String where = MediaStore.Images.Media.DATA+"=?";
			String[] selectionArgs = { fname };
			cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, where, selectionArgs);
		}catch(Exception e){
			Log.e(TAG,e.getStackTrace()[0].getFileName()
				+"("+e.getStackTrace()[0].getLineNumber()+")"
				+e.getStackTrace()[0].getMethodName()
				+" "+e.toString());
		}
	}

解決したので自前でサムネイルを作らなくて済みます。
ただしサムネイルはまだ無い為getThumbnailを実行してから作り始めるので時間が掛かります。
別スレッドで取得させた方が使い勝手が向上します。

コメント

コメントを受け付けておりません。