むちゃくちゃ試行錯誤したのでその覚書。
バージョンはUnity : 5.5.0b8 , Android : 5.1.1 と 6.0 。
Androidに画像を保存するには以下の手順が必要になる。
- 権限(android.permission.WRITE_EXTERNAL_STORAGE)を追加する
- Android6以上:requestPermissionsで動的に権限を取得
- それ以前:Assets/Plugins/Android/AndroidManifest.xmlに権限をつける
- 保存先パスの取得
- 機種ごとに異なる保存先のパスを取得する
- 保存する
- 今回はスクリーンショットを取得する
- メディアスキャンしてカメラロールなどで表示されるようにする
- これをしないと再起動しないと認識できない
権限追加
ここが一番の悩みどころだった。
その1
Android6より前のバージョン用に Assets の下に Plugins/Android フォルダを作り、その下に AndroidManifest.xml というファイルを作る。
これまで作っていなかったら Temp/StagingArea/AndroidManifest.xml をコピーして追記すると楽できる。
今回は以下を追記
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
その2
requestPermissionsを使う。
Assets/Plugins/Android に android-support-v4.jar を置いて、android.support.v4.app.ActivityCompat を使えばいけるかと思ったけど出来なかった。
最終的には以下の記事を参考にしてプラグインを導入。
ここはもう少し簡単に出来る方法を探してみたい。
パス取得
getExternalStorageDirectoryを使ってSDカードのルートディレクトリを取得する。
1 2 3 4 5 6 7 8 9 |
string path = ""; using (AndroidJavaClass jcEnvironment = new AndroidJavaClass ("android.os.Environment")) using (AndroidJavaObject joExDir = jcEnvironment.CallStatic<AndroidJavaObject> ("getExternalStorageDirectory")) { path = joExDir.Call<string>("toString")+"/jp.co.cname.app/"; } //フォルダがなければ作成 if (!Directory.Exists(path)) Directory.CreateDirectory(path); //ファイル名入力 path += System.DateTime.Now.Ticks.ToString ()+".png"; |
ファイル保存
スクリーンショットを取る専用関数もあるけどうまくいかなかった。
エラーも吐かず保存もされない。File関数を使うことで回避。
1 2 3 4 5 6 7 8 9 10 11 |
//専用関数を使う(うまくいかない) Application.CaptureScreenshot (path); //File関数を使う var tex = new Texture2D (Screen.width, Screen.height, TextureFormat.RGB24, false); tex.ReadPixels (new Rect(0, 0, Screen.width, Screen.height), 0, 0); using (FileStream BinaryFile = new FileStream(path, FileMode.Create, FileAccess.Write)) { using (BinaryWriter Writer = new BinaryWriter(BinaryFile)) { Writer.Write (tex.EncodeToPNG()); } } |
メディアスキャン
MediaScannerConnection.scanFile を使う。
過去にこれに苦しめられた経験があるけど今回は特に問題なかった。
1 2 3 4 5 6 7 8 9 10 11 12 |
void ScanMedia (string fileName){ if (Application.platform != RuntimePlatform.Android) return; #if UNITY_ANDROID using (AndroidJavaClass jcUnityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer")) using (AndroidJavaObject joActivity = jcUnityPlayer.GetStatic<AndroidJavaObject> ("currentActivity")) using (AndroidJavaObject joContext = joActivity.Call<AndroidJavaObject> ("getApplicationContext")) using (AndroidJavaClass jcMediaScannerConnection = new AndroidJavaClass ("android.media.MediaScannerConnection")) jcMediaScannerConnection.CallStatic ("scanFile", joContext, new string[] { fileName }, new string[] { "image/png" }, null); } Handheld.StopActivityIndicator(); #endif } |
これで晴れてUnityでスクショを保存できる。