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

【Android開発】ランタイム権限を使って外部ストレージにtxtファイルを作成・保存する方法

はじめに

このチュートリアルでは、Androidアプリでランタイム権限(実行時パーミッション)を使用して、外部ストレージにテキストファイル(txt)を作成・保存する方法を、手順を追って詳しく解説します。


ステップ1:新規プロジェクトの作成

まず、Android Studioで新しいプロジェクトを作成しましょう。メニューから「File」→「New Project」を選択し、必要な項目をすべて入力してプロジェクトを生成します。

ステップ2:レイアウトファイルの編集

次に、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">
   <EditText
      android:id = "@+id/enterText"
      android:hint = "Please enter text here"
      android:layout_width = "match_parent"
      android:layout_height = "wrap_content" />
   <Button
      android:id = "@+id/save"
      android:text = "Save"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content" />
</LinearLayout>

上記のレイアウトでは、テキスト入力用の EditText と保存用の Button を縦方向の LinearLayout で配置しています。ユーザーがボタンをタップすると、EditText に入力された内容が取得され、外部ストレージへ書き込まれる仕組みです。

ステップ3:MainActivity.java の編集

続いて、src/MainActivity.java に以下のコードを追加します。

package com.example.andy.myapplication;

import android.content.pm.PackageManager;
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.EditText;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
   private static final int PERMISSION_REQUEST_CODE = 100;
   Button save;

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

      final EditText enterText = findViewById(R.id.enterText);
      save = findViewById(R.id.save);
      save.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            if (!enterText.getText().toString().isEmpty()) {
               String state = Environment.getExternalStorageState();
               if (Environment.MEDIA_MOUNTED.equals(state)) {
                  if (Build.VERSION.SDK_INT >= 23) {
                     if (checkPermission()) {
                        File sdcard = Environment.getExternalStorageDirectory();
                        File dir = new File(sdcard.getAbsolutePath() + "/text/");
                        dir.mkdir();
                        File file = new File(dir, "sample.txt");
                        FileOutputStream os = null;
                        try {
                           os = new FileOutputStream(file);
                           os.write(enterText.getText().toString().getBytes());
                           os.close();
                        } catch (IOException e) {
                           e.printStackTrace();
                        }
                     } else {
                        requestPermission(); // 権限リクエスト処理
                     }
                  } else {
                     File sdcard = Environment.getExternalStorageDirectory();
                     File dir = new File(sdcard.getAbsolutePath() + "/text/");
                     dir.mkdir();
                     File file = new File(dir, "sample.txt");
                     FileOutputStream os = null;
                     try {
                        os = new FileOutputStream(file);
                        os.write(enterText.getText().toString().getBytes());
                        os.close();
                     } catch (IOException e) {
                        e.printStackTrace();
                     }
                  }
               }
            }
         }
      });
   }
   private boolean checkPermission() {
      int result = ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
      if (result == PackageManager.PERMISSION_GRANTED) {
         return true;
      } else {
         return false;
      }
   }

   private void requestPermission() {
      if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
      Toast.makeText(MainActivity.this, "Write External Storage permission allows us to create files. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
      } else {
         ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_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;
      }
   }
}

コードのポイント

このコードの主な処理の流れは以下の通りです。

  • ボタンクリック時に EditText の内容が空でないかをチェック
  • Environment.getExternalStorageState() で外部ストレージの状態(MEDIA_MOUNTED)を確認
  • API 23(Android 6.0)以降の場合は checkPermission() で権限の有無を判定し、未許可なら requestPermission() を呼び出して権限を要求
  • 権限が付与されていれば、外部ストレージ直下に「text」フォルダを作成し、その中に sample.txt として文字列を書き込み

onRequestPermissionsResult() では、ユーザーが権限ダイアログで選択した結果を受け取り、許可・拒否に応じてログを出力しています。

ステップ4:マニフェストファイルの編集

最後に、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>

ここでは、書き込み用の WRITE_EXTERNAL_STORAGE と読み取り用の READ_EXTERNAL_STORAGE の2つの権限を宣言しています。マニフェストでの宣言に加え、API 23 以降ではコード側で動的に権限をリクエストする必要がある点に注意してください。

アプリの実行と動作確認

それでは、アプリケーションを実行してみましょう。実際の Android 端末をパソコンに接続していることを前提とします。Android Studio からアプリを実行するには、プロジェクト内のアクティビティファイルを開き、ツールバーの「Run」アイコンをクリックします。接続済みのモバイルデバイスを選択すると、端末にアプリの初期画面が表示されます。

【Android開発】ランタイム権限を使って外部ストレージにtxtファイルを作成・保存する方法

次に、適当なテキストを入力して「Save」ボタンをタップしてみましょう。

【Android開発】ランタイム権限を使って外部ストレージにtxtファイルを作成・保存する方法

初回保存時には、外部ストレージへのアクセスを求めるランタイム権限ダイアログが表示されます。「許可」を選択すると、ファイルへの書き込みが実行されます。

結果を検証するには、端末の外部ストレージを開き、「text」フォルダが作成されているかを確認してください。フォルダ内に sample.txt が存在し、入力した内容が正しく保存されていれば成功です。

【Android開発】ランタイム権限を使って外部ストレージにtxtファイルを作成・保存する方法

補足:Android 10以降での注意点

Android 10(API 29)以降ではスコープドストレージが導入され、従来のように外部ストレージへ自由にアクセスすることが制限されました。targetSdkVersion を 29 以上に設定する場合は、マニフェストの application タグに android:requestLegacyExternalStorage="true" を一時的に指定するか、MediaStore API や Storage Access Framework(SAF)の利用を検討することをおすすめします。

  1. Androidスピナーに初期デフォルトテキストを表示させる方法【コード例付き】

    このチュートリアルでは、Androidアプリでスピナー(Spinner)ウィジェットを使い、ユーザーが何も選択していない初期状態に「デフォルトテキスト」を表示させる方法を解説します。「リストから選択してください」のようなガイド文をスピナーの初期値として設定したいケースで役立つテクニックです。実装の全体像実装のポイントは、スピナーに渡すデータリストの先頭(インデックス0)にガイド用テキストを追加することです。さらに選択イベント処理の中で、この先頭項目が選択されたときには通常の選択処理を行わないように分岐させます。以下、ステップ順に見ていきましょう。ステップ1:新規プロジェクトの作成Android

  2. AndroidでSDカードをデフォルトストレージにする方法|Adoptable Storageの設定手順と注意点

    スマートフォンの内部ストレージが少ない、または容量不足に悩まされるのは、誰にとっても避けたい問題です。毎日スマホを使い、撮影した写真や動画、インストールしたアプリなど、さまざまなデータを日々保存していくため、ストレージは確実に圧迫されていきます。近年のスマートフォンは128GB程度の大容量ストレージを搭載していることが多いものの、それでも容量不足に陥るケースは珍しくありません。しつこく表示される「空き容量が少なくなっています」という警告を解消するためにも、追加のストレージが必要になることは十分あり得ます。そこで登場するのが外部ストレージ(ポータブルストレージ)です。SDカードは容量不足を補うた