val intent = Intent() .addCategory(Intent.CATEGORY_OPENABLE) .setType("*/*") .setAction(Intent.ACTION_GET_CONTENT) startActivityForResult(Intent.createChooser(intent, "Select a file."), REQUEST_CODE)
でファイルオープンのActivityが起動します。
setType("image/*")
とかすると、画像だけを選択させることができます。
結果は onActivityResult()
で
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == 1 && resultCode == Activity.RESULT_OK) { val uri = data?.getData() ?: return ... } }
のように Uri がとれます。
Uri からは ContentResolver
を介して InputStream
が取れます。
val strm = contentResolver.openInputStream(uri)
で、ストリームから読み出せばいいんですが、ファイルパスや File
オブジェクトしか受け付けないAPIを呼ぶときに困ります。
Uri を path に変換する方法は、調べると↓等がみつかります。
ここでいくつか紹介されている方法を試しましたが、Androidのバージョンや機種によって正しく動作しない場合がありました。
確実なのはアプリ内のキャッシュに一度コピーしてそれを渡す方法です。
val tmpFile = File(cacheDir, "temp.data") Files.copy(strm, tmpFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
参照するファイルのサイズが大きくなければこれで問題なさそうです。
同様にセーブダイアログも
val intent = Intent() .addCategory(Intent.CATEGORY_OPENABLE) .setAction(Intent.ACTION_CREATE_DOCUMENT) .putExtra(Intent.EXTRA_TITLE, fileName) startActivityForResult(Intent.createChooser(intent, "Select save destination."), 1)
のように出すことができます。
デフォルトのファイル名を指定する場合、 putExtra(Intent.EXTRA_TITLE, fileName)
のようにします。
こちらもファイルオープン時と同様に Uri
が取得できますので、OutputStream
を使って書き込みができます。