SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

Xamarin.Android ファイルの保存

【 Xamarin 記事一覧 】

ファイルの保存には、各アプリ独自の領域を使用する「内部保存」と、SDカードなどの「外部保存」という2つの概念があります。

1 内部保存

アプリの内部保存は「/data/data/パッケージ名/files/」を使用します。
この領域を使用した場合、アプリを削除した際にファイルも全て削除されます。
内部保存領域のパスは、System.Environment.GetFolderPathにSystem.Environment.SpecialFolder.Personalを指定することで取得できます。

以下は、内部保存の一例です。

namespace AndroidApplication1 {
    [Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]
    public class Activity1 : Activity {

        protected override void OnCreate(Bundle bundle) {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);

            //  /data/data/パッケージ名/files
            var path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            var fileName = path + "/sample.txt";

       //Saveボタンを押した際の処理
            FindViewById<Button>(Resource.Id.ButtonSave).Click+= (s, a) =>{
                try {
                    //保存
                    System.IO.File.WriteAllText(fileName, "本日は晴天なり");
                    Toast.MakeText(this, "保存しました", ToastLength.Short).Show();
                } catch (Exception ex) {
                    //エラー
                    Toast.MakeText(this, ex.Message, ToastLength.Short).Show();
                }
            };

       //Readボタンを押した際の処理
            FindViewById<Button>(Resource.Id.ButtonRead).Click += (s, a) => {
                try {
                    //読込み
                    var str = System.IO.File.ReadAllText(fileName);
                    Toast.MakeText(this, str,ToastLength.Short).Show();
                } catch (Exception ex) {
                    //エラー
                    Toast.MakeText(this, ex.Message, ToastLength.Short).Show();
                }
            };
        }
    }
}


2 外部保存

(1)外部メディアのパス

Android端末では外部メディアのマウントディレクトリが端末により異なります。このため、必ず外部メディアの場所(マウントディレクトリ)を確認する必要があります。

外部メディアの場所は、EnvironmentクラスのExternalStorageDirectoryを使用して取得することができます。

var sdPath = Android.OS.Environment.ExternalStorageDirectory;

(2)パーミッション

外部保存領域へファイルを保存するには、マニフェストファイルへのパーミッション(WRITE_EXTERNAL_STORAGE)の追加が必要になります。

(3)メディア状態(使用の可否)

SDカードは抜き差しができるので、常に書き込みが可能であるとは限りません。
EnvironmentクラスのExternalStorageStateにより、メディアの状態を識別することができます。
Environmentクラスには外部メディアの状態を表す定数が用意されていますが、代表的なものは次の4つです。

var sdCardState = Android.OS.Environment.ExternalStorageState;
switch (sdCardState) {
    case Android.OS.Environment.MediaMounted:
        Toast.MakeText(this, "マウント済み", ToastLength.Short).Show();
        break;
    case Android.OS.Environment.MediaMountedReadOnly:
        Toast.MakeText(this, "読取専用", ToastLength.Short).Show();
        break;
    case Android.OS.Environment.MediaRemoved:
        Toast.MakeText(this, "挿入されていない", ToastLength.Short).Show();
        break;
    case Android.OS.Environment.MediaUnmounted:
        Toast.MakeText(this, "マウントされていない", ToastLength.Short).Show();
        break;
    default:
        Toast.MakeText(this, "その他", ToastLength.Short).Show();
        break;
}

オブジェクトブラウザで確認すると、上記以外にもEnvironmentの状態を表すプロパティを見ることができます。

(4)ファイルの保存・読込みサンプル

外部保存の一例として、SDカードへのファイルの保存・読込みのサンプルを記載します。
※Saveを押す(ファイル保存)前にReadを押す(ファイル読出)とエラーが発生しています(左図)





namespace AndroidApplication1{
    [Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]
    public class Activity1 : Activity{

        protected override void OnCreate(Bundle bundle){
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);

            //SDカード内のファイル名を作成
            var fileName = Android.OS.Environment.ExternalStorageDirectory + "/sample.txt";
       
       //Saveボタンを押した際の処理
            FindViewById<Button>(Resource.Id.ButtonSave).Click += (s, a) =>{
                var sdCardState = Android.OS.Environment.ExternalStorageState;
                if (sdCardState == Android.OS.Environment.MediaMounted) {
                    try {
                        //ファイル保存
                        System.IO.File.WriteAllText(fileName, "本日は晴天なり");
                        Toast.MakeText(this, "ファイルを保存しました", ToastLength.Short).Show();
                    } catch (Exception ex) {
                        //エラー
                        Toast.MakeText(this, ex.Message, ToastLength.Short).Show(); 
                    }
                } else {
                    Toast.MakeText(this, "SDカードの準備ができていません", ToastLength.Short).Show(); 
                }
            };
       //Readボタンを押した際の処理
            FindViewById<Button>(Resource.Id.ButtonRead).Click += (s, a) => {
                try {
                    //ファイル読み込み
                    var str = System.IO.File.ReadAllText(fileName);
                    Toast.MakeText(this, str, ToastLength.Short).Show(); 
                } catch (Exception ex) {
                    //エラー
                    Toast.MakeText(this, ex.Message, ToastLength.Short).Show(); 
                }
            };
        }
    }
}

【 Xamarin 記事一覧 】