« Android 版はファイル名の大文字小文字を区別するように | メイン | システムのパス »

2016年12月20日

吉里吉里Z 開発:: ストレージアクセスフレームワーク(SAF) のパス

    

・ディレクトリ選択 ( ACTION_OPEN_DOCUMENT_TREE ) の場合、URI で返ってくるのは、外部ストレージの時 content://com.android.externalstorage.documents/tree/primary: + フォルダパス。
・ファイル選択 ( ACTION_OPEN_DOCUMENT ) の場合は、content://com.android.externalstorage.documents/document/primary: + ファイルパス。

primary の後のコロンとスラッシュは文字列で取得するとエスケープされている。

ディレクトリ選択で取得した URI で DocumentFile.fromTreeUri を使って開き、DocumentFile.listFiles でファイルリストを取得した場合の URI はどうなるか?
「content://com.android.externalstorage.documents/tree/primary: + フォルダパス + document/primary: + ファイルパス」になる。
長い上に単純にファイル名を結合したものではなく、パス部分すべてが結合された状態になる。
DocumentFile.getUri で取得すると上記のようになる。
DocumentFile.getName でディスプレイ名を取得して、/ を間に入れて無理やり文字列結合した場合 DocumentFile.isDocumentUri で false となる。
ディスプレイ名を使って URI を取得したいときは、ツリーの DocumentFile に対して DocumentFile.findFile で検索する必要があるようだ。

外部ストレージの場合、URI の最後 / (%2F) 以降がファイル名 = ディスプレイ名となっているが、GoogleDrive の場合は異った。
URI が REST のような末尾 /acc=1;doc=1 になっている。
DocumentFile.getName すればファイル名が得られる。
ただ、得られる名前は DocumentsProvider の実装依存でもあるので、必ずファイル名とも限らない。


吉里吉里2/Z のファイルパスは、ディレクトリのパス + / + ファイル名を期待した作りになっている。
TVPGetPlacedPath 内でファイル名をテーブルから検索して、見付かった場合に パス + ファイル名 で強制的に結合される。
これらを踏まえて Android版で SAF を使用したファイルアクセスをどうするか。

1. iTVPStorageMedia を拡張して(一部プラグインに影響する破壊的変更)、パスとファイル名の結合をメディアストレージに依存する実装に変える。
2. GetLocallyAccessibleName で、最後の / 以降はディスプレイ名が使われているという前提で、/ でパスとファイル名を分離し、期待するパスを生成する。

簡単に思いつくのはこの2つ。
1 は一部互換性を破壊しつつも、SAF のようなシステムを考慮したスマートな仕様に思える。ただし、このようなシステムがどの程度あるのか疑問で、この特殊な例のためだけに変更するのが良いかどうか。
2 はやや泥臭いが互換性は破壊せず、GetLocallyAccessibleName と言うメソッドも意図した動作をするように実装される。

2番で行く。


投稿者 Takenori : 2016年12月20日 22:56




comments powered by Disqus
Total : Today : Yesterday : なかのひと