SQLの窓

2015年06月01日


Storage Access Framework のガイドラインに基づく、Android 4.4 とそれ以降における 画像参照

Storage Access Framework
On Android 4.3 and lower, if you want your app to retrieve a file from another app, it must invoke an intent such as ACTION_PICK or ACTION_GET_CONTENT. The user must then select a single app from which to pick a file and the selected app must provide a user interface for the user to browse and pick from the available files.

On Android 4.4 and higher, you have the additional option of using the ACTION_OPEN_DOCUMENT intent, which displays a picker UI controlled by the system that allows the user to browse all files that other apps have made available. From this single UI, the user can pick a file from any of the supported apps.
要するに、ACTION_OPEN_DOCUMENT では全部用意しているので呼び出すだけで便利です。みたいな意味だと思います。画像関係のリソースを統一したインターフェィスを利用して選択できるはずです。 最初の表示は『最近』になりますが、以降は直前の表示になりました。 タイトル左端のメニューから対象を変更します。 画像はあらかじめ、Android Device Monitor(ツールバーの右から2番目 / HELP の左横) で該当場所にインポートしておきます。 画像の参照
package app.lightbox.winofsql.jp.storageaccess;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.FileDescriptor;
import java.io.IOException;


public class MainActivity extends Activity {

	// 画像呼び出しからの戻りコードの定義
	private static final int READ_REQUEST_CODE = 42;

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

		// ボタンのイベント
		Button button = (Button) this.findViewById(R.id.button);
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// On Android 4.4 and higher
				// ( Storage Access Framework )
				Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
				intent.addCategory(Intent.CATEGORY_OPENABLE);
				intent.setType("image/*");
				startActivityForResult(intent, READ_REQUEST_CODE);
			}
		});
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		// 意図した結果の場合の処理
		if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
			Uri uri = null;
			if (data != null) {
				// Uri が戻されます
				uri = data.getData();
				Log.i("lightbox", "Uri: " + uri.toString());

				// Storage Access Framework では、Bitmap の処理を
				// UI スレッドで行うべきでは無いとの記述があります
				// ( 使わなくともいちおうエミュレータでは動作しました )
				new AsyncTask<Uri, Void, Bitmap>() {

					// 非同期処理
					@Override
					protected Bitmap doInBackground(Uri... params) {
						Bitmap image = null;
						// Storage Access Framework にある Bitmap 取得処理です
						try {
							ParcelFileDescriptor parcelFileDescriptor =
									getContentResolver().openFileDescriptor(params[0], "r");
							FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
							image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
							parcelFileDescriptor.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
						return image;
					}

					// UI スレッド処理
					@Override
					protected void onPostExecute(Bitmap image) {
						super.onPostExecute(image);

						// Bitmap 取得に成功している場合は表示します
						if (image != null) {
							ImageView imageView = (ImageView) MainActivity.this.findViewById(R.id.imageView);
							imageView.setImageBitmap(image);
						}

					}
				}.execute(uri);

			}
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.menu_main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();

		if (id == R.id.action_settings) {
			return true;
		}

		return super.onOptionsItemSelected(item);
	}
}

Bitmap 作成の説明のところで、UI スレッドから実行すべきでは無いとのコメントがありました。AsyncTask を使用しなくでもエラーは出ませんでしたが、AsynTask 使っておいたほうが他で使う時に変更が少なくて済みますし、書いてある以上そのほうが安全なのでしょう。

画面定義

android:scaleType="fitStart" で、画像を ImageView の TOP に表示しています
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="New Button"
        android:id="@+id/button"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"/>

    <ImageView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/imageView"
        android:layout_below="@+id/button"
        android:layout_alignParentStart="true"
        android:scaleType="fitStart"/>

</RelativeLayout>




【1 Android Studioの最新記事】
posted by lightbox at 2015-06-01 19:11 | 1 Android Studio | このブログの読者になる | 更新情報をチェックする
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり