質問: 0; i < 10; i++) { // 存在チェック if (!to .exists()) { if (!to .mkdirs()) { LogWriter.writeLog(LogWriter.sReleaseMode, "ディレクトリの作成に失敗しました"); return; } } ``` ### よろしくお願いいたします。
回答: いろいろ要点がありそうです。 まず、ファイル移動は時間のかかる作業になります。Androidのライフサイクルによるイベントメソッド(onCreateのような)は、迅速に処理を終えないとアプリが落ちてしまいます。小さなファイル1個を読み書きする程度なら問題ないのですが、10個のファイルだと別スレッドを設けないと、落ちる可能性が高いと思います。 別スレッドを作るには、ThreadやAsyncTaskを使う方法がありますが、AsyncTaskを使うならばこの辺を参考にすればいいでしょうか。doInBackgroundというメソッドが非同期で動作するスレッドの本体になるので、この中にファイル移動のループ処理を実装すればいいでしょう。 次に、内部ストレージから読み出すためには、前回の質問のようにRuntime Premissionによって読み取りの許可を得る必要があります。File#listFilesで一覧を取得しようとするのは間違いではないのですが、許可を得ていないとlistFilesの戻り値がnullになってしまうので、この時点でコケてしまいます。 その上で、内部ストレージのパスを得るのは、 ``` File from = new File(Environment.getExternalStorageDirectory() + "/sample/A"); ``` (11/08 23:46 訂正) **パスの直接記述は推奨されません**。うっかり直接記述で回答してしまいましたが、内部ストレージのパスを得るにはEnvironment.getExternalStorageDirectory()を用いるべきなので、訂正しました。 (訂正おわり) のようにすればいいでしょう。区切り記号の/は自動的には挿入されないので、ディレクトリー名の文字列を単純に繋ぐだけではだめです。これで得られた変数fromから ``` File[] files = from.listFiles(); ``` のようにすれば、filesという変数にこのディレクトリーに入っているファイル一覧が得られるでしょう。 次に、外部ストレージ(以下、SDカード)のパッケージ専用ディレクトリーのパスを得るには、Context#getExternalFilesDirsを用いましょう。SDカードのパス名は`/storage//`という構成になっています。UUIDはSDカードごとに異なる一意の値になるので、SDカードを差し替えると別の値になります。ここを決め打ちしてしまうと、「今差しているSDカードでしか動かないプログラム」になってしまいます。それでは多分困るでしょう。 ここは ``` File sdcarddir = null; File[] dirs = getExternalFilesDirs(null); for (File dir : dirs) { if (Environment.isExternalStorageRemovable(dir)) { sdcarddir = new File(dir + "/sample/B"); break; } } ``` のようにすれば、sdcarddirという変数に`/storage//Android/data/<パッケージ名>/files/sample/B`というパスが得られるでしょう。ちなみに、Environment.isExternalStorageRemovableというのは、取り外し可能メディアであるかを判別するためのメソッドです。これを用いて、簡易的にSDカードかどうかを判定しています。本当はもっと念を入れて確認した方が良いようですが、まあ試験的にやってみる程度なら。 getExternalFilesDirsの引数をnullにすると、パッケージ名の下にさらにfilesディレクトリーがくっつくのですが、パッケージ名の直下に置かれるディレクトリーには役割があるので、特殊な事情でもない限りはそれに従うのが良策と思います。 で、最後にファイル移動ですが、一般的にはFile#renameToというメソッドを使う方法がありますが、「内部ストレージからSDカード」のような異なるメディア間の移動には使えないようなので(常識なのかな?)、単純に「コピー元ファイルの内容を全部読み取ってコピー先ファイルに書き出す」みたいな作業になってしまうのではないでしょうか。このサイトの「java.io.Fileクラスを使用してコピーする」として紹介されているような感じでしょうか。ここは他にもいろいろ方法はありそうですが。 実際に軽く作ってみましたが、上記のような方針で思ったような結果は得られるようです。(実現できないことを回答してしまうほど恥ずかしいことはない。) ものすご〜〜〜〜く長い回答で申し訳ないのだけど、この辺の要点を一つ一つクリアしながら作成してみてはいかがでしょうか。一気にゴールを目指そうとしないことです。アプリ開発は基礎知識の積み重ねですから。