Android
 Computer >> コンピューター >  >> プログラミング >> Android

Androidでランタイム権限を使って外部ストレージの画像ファイルを読み込む方法

この記事では、Androidアプリにおいてランタイムパーミッション(実行時権限)を取得しながら、外部ストレージに保存された画像ファイルを読み込んで表示する方法を、ステップごとに解説します。

Android 6.0(API 23)以降では、外部ストレージへのアクセスなど、ユーザーのプライバシーに関わる機能には実行時にユーザーの許可を得る必要があります。本チュートリアルでは、その基本的な実装パターンを学ぶことができます。

ステップ1:新規プロジェクトを作成する

Android Studioを開き、File → New Project を選択して新しいプロジェクトを作成します。必要な項目(プロジェクト名、パッケージ名、保存先など)を入力してプロジェクトを完成させましょう。

ステップ2:レイアウトファイル(activity_main.xml)を編集する

res/layout/activity_main.xml に以下のコードを追加します。

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "https://schemas.android.com/apk/res/android"
    xmlns:tools = "https://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = ".MainActivity"
    android:orientation = "vertical">
   <Button
      android:id = "@+id/read"
      android:text = "read"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content" />
   <ImageView
      android:id = "@+id/imageView"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content" />
</LinearLayout>

このレイアウトには、画像読み込み用のButtonと、読み込んだ画像を表示するためのImageViewを配置しています。ボタンがタップされると、外部ストレージから画像データを取得し、ImageViewに表示される仕組みです。

ステップ3:MainActivity.javaを実装する

src/MainActivity.java に以下のコードを記述します。

package com.example.andy.myapplication;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
public class MainActivity extends AppCompatActivity {
    private static final int PERMISSION_REQUEST_CODE = 100;
    Button read;
    ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = findViewById(R.id.imageView);
        read = findViewById(R.id.read);
        read.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String state = Environment.getExternalStorageState();
                if (Environment.MEDIA_MOUNTED.equals(state)) {
                    if (Build.VERSION.SDK_INT >= 23) {
                        if (checkPermission()) {
                            File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/images.jpeg");
                            if (dir.exists()) {
                                Log.d("path", dir.toString());
                                BitmapFactory.Options options = new BitmapFactory.Options();
                                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                                Bitmap bitmap = BitmapFactory.decodeFile(String.valueOf(dir), options);
                                imageView.setImageBitmap(bitmap);
                            }
                        } else {
                            requestPermission(); // 権限をリクエスト
                        }
                    } else {
                        File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/images.jpeg");
                        if (dir.exists()) {
                            Log.d("path", dir.toString());
                            BitmapFactory.Options options = new BitmapFactory.Options();
                            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                            Bitmap bitmap = BitmapFactory.decodeFile(String.valueOf(dir), options);
                            imageView.setImageBitmap(bitmap);
                        }
                    }
                }
            }
        });
    }
    private boolean checkPermission() {
        int result = ContextCompat.checkSelfPermission(MainActivity.this,
                android.Manifest.permission.READ_EXTERNAL_STORAGE);
        if (result == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            return false;
        }
    }
    private void requestPermission() {
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
            Toast.makeText(MainActivity.this,
                    "ストレージへのアクセス許可が必要です。アプリ設定から権限を有効にしてください。",
                    Toast.LENGTH_LONG).show();
        } else {
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[] {android.Manifest.permission.READ_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_CODE);
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.e("value", "Permission Granted, Now you can use local drive .");
                } else {
                    Log.e("value", "Permission Denied, You cannot use local drive .");
                }
                break;
        }
    }
}

コードのポイント

  • checkPermission()ContextCompat.checkSelfPermission() を使って、すでに READ_EXTERNAL_STORAGE 権限が付与されているかを確認します。
  • requestPermission():権限がない場合に ActivityCompat.requestPermissions() で許可ダイアログを表示します。過去に拒否されている場合は、Toastで設定画面からの許可を促します。
  • onRequestPermissionsResult():ユーザーが選択した結果を受け取り、許可・拒否に応じた処理を行います。
  • BitmapFactory.decodeFile():指定したパスの画像ファイルをデコードし、BitmapとしてImageViewにセットします。ARGB_8888を指定することで高画質な描画が可能です。

ステップ4:AndroidManifest.xmlに権限を宣言する

manifest.xml に以下のコードを追加します。

<?xml version = "1.0" encoding = "utf-8"?>
<manifest xmlns:android = "https://schemas.android.com/apk/res/android"
    package = "com.example.andy.myapplication">
    <uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE"/>
    <application
        android:allowBackup = "true"
        android:icon = "@mipmap/ic_launcher"
        android:label = "@string/app_name"
        android:roundIcon = "@mipmap/ic_launcher_round"
        android:supportsRtl = "true"
        android:theme = "@style/AppTheme">
        <activity android:name = ".MainActivity">
            <intent-filter>
                <action android:name = "android.intent.action.MAIN" />
                <category android:name = "android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

マニフェストファイルでは、READ_EXTERNAL_STORAGE(読み取り)と WRITE_EXTERNAL_STORAGE(書き込み)の両方の権限を宣言しておきます。これにより、実行時の権限リクエストが正しく機能します。

アプリを実行してみよう

それでは実際にアプリを起動してみましょう。Android端末をPCに接続した状態で、Android StudioのツールバーにあるRunアイコンをクリックします。接続したモバイルデバイスを選択すると、端末にアプリの初期画面が表示されます。

Androidでランタイム権限を使って外部ストレージの画像ファイルを読み込む方法

初期画面で「read」ボタンをタップすると、初回は権限の許可ダイアログが表示されます。許可を選択すると、外部ストレージから画像が読み込まれ、以下のようにImageViewに表示されます。

Androidでランタイム権限を使って外部ストレージの画像ファイルを読み込む方法

まとめ

このように、Android 6.0以降のランタイムパーミッションに対応することで、ユーザーの同意を得た上で安全に外部ストレージへアクセスできます。権限チェック → リクエスト → 結果ハンドリングという一連の流れは、他の危険なパーミッション(カメラ、位置情報など)でも同様のパターンで実装できるので、ぜひ覚えておきましょう。

  1. SDカードのフォルダ・ファイルにAndroidの書き込み権限を設定する方法【サンプルコード付き】

    本記事では、AndroidアプリからSDカード(外部ストレージ)上のフォルダやファイルに対して書き込みを行うために必要なアクセス許可(パーミッション)の設定方法を、サンプルコード付きで解説します。「テキストを入力して外部ストレージに保存し、あとで読み出す」というシンプルなアプリを題材に、レイアウト・Javaコード・マニフェストの実装手順を順番に見ていきましょう。 実装の全体像 外部ストレージへの読み書きを実現するには、主に次の3つの要素が必要です。 マニフェストでの権限宣言:READ_EXTERNAL_STORAGE と WRITE_EXTERNAL_STORAGE を宣言する ストレージ

  2. Rubyでファイルを読み書きする方法を実例つきで徹底解説

    Rubyでファイルの読み書きができるようになると、ファイルからデータを抽出したり、新しいファイルを作成したり、必要な情報を素早く見つけたりできるようになります。この記事では、Rubyにおけるファイル操作の基本を、実際のコード例とともにわかりやすく解説します。 この記事で学べること Rubyでファイルを読み込む方法 Rubyでファイルに書き込む方法 覚えておきたいFileクラスのメソッド ディレクトリ操作の基礎 FileUtilsモジュールの使い方 まとめ それでは始めましょう! Rubyでファイルを読み込む方法 Rubyでファイルを読み込む基本的な流れは、次の3ステップです。 op