こんにちは、dodoと申します。
本件、私も興味が出て調べてみましたが、 File.setLastModified()が
使えないのはandroidの昔からの既知の問題のようです。
テストプロを作って試しましたが、手持ちのNexus 5(Android 6.0.1)でも
File.setLastModified()は常にfalseが返り、セットできませんでした。
そこで、不完全ではあるものの代替策を考えて試してみましたのでご紹介します。
androidのshell上にlinuxのtouch コマンドがあります。実際はtoyboxのシンボリックリンクですが、
このコマンドでファイルのタイムスタンプを変えることができます。
そこで、androidアプリからProcessクラスオブジェクトを介して
このコマンドを実行します。以下のようなメソッドを作成して
private String executeCommand(String command) {
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
process.waitFor();
String outText = output.toString();
Log.d(TAG, "out: " + outText);
return outText;
} catch (IOException e) {
Log.w(TAG, "IOException: " + e.getMessage());
} catch (InterruptedException e) {
Log.w(TAG, "InterruptedException: " + e.getMessage());
}
return "";
}
以下のように呼び出すと、/sdcard/Download/data.txt のタイムスタンプが現在日時に変わります。
executeCommand("/system/bin/touch /sdcard/Download/data.txt");
「不完全であるものの」と上で書いたのは、とりあえず以下のような理由があるからです。
1. /system/bin/touchコマンドはコマンドラインオプション指定でどうも問題があるようで、
例えば日時指定 "-t"を指定しても指定した日時でセットされない。
つまり、androidアプリからProcessクラスオブジェクトを介しても指定したい日時にセットできない。
2. 外部ストレージでマウントしたSDカードではファイルシステムが違う(exFATやFAT32?)
だろうから、ファイルシステムドライバーのキャッシュ方法の違いが顕在化して、
上記の方法でもダメかもしれない。
3. shellの環境が違うandroid端末もあるだろうから、/system/bin/touch が使えるとは限らない。
/system/bin/touch のソースコードを見たところ、linuxのシステムコール
utimensat() を使っているので、NDKでこのシステムコールを直に呼び出せば
touchコマンドに依存しないで日時設定できるようになると思います。(未確認です)
dodo
2017年9月15日金曜日 13時40分11秒 UTC+9 ケシポン:
File.setLastModifiedを使っているのですが、ファイルのタイムスタンプが変わりません。
他に方法などはあるのでしょうか?