[OutSystems]File Pluginでファイルを保存するパス

モバイルアプリケーションで、端末内のファイルを操作するための公式プラグインFile Plugin。
File Pluginで操作対象となるパスについて確認してみます。

# 確認環境
Personal Environment(Version 11.12.0 (Build 30002))
Service Studio (Version 11.11.7)
[File Plugin](https://www.outsystems.com/forge/component-overview/1633/file-plugin)（Version 3.0.1）

iOS (Version 14.6)
Android (Version 9)
　
# まとめ
ドキュメントと実験によると以下の通り。

|  | iOS | Android |
|:-:|:-|:-|
| 内部・一時  | cordova.file.tempDirectory | cordova.file.cacheDirectory |
| 内部・永続  | cordova.file.dataDirectory | cordova.file.dataDirectory  |
| 外部・一時  | 無し  | cordova.file.externalCacheDirectory  |
| 外部・永続 | 無し  | cordova.file.externalDataDirectory |

cordova.file.tempDirectory
　file:///var/mobile/Containers/Data/Application/\<UUID\>/tmp/
cordova.file.cacheDirectory
　file:///storage/emulated/0/Android/data/\<App Identifier\>/cache/
cordova.file.dataDirectory（iOS）
　file:///var/mobile/Containers/Data/Application/\<UUID\>/Library/NoCloud/
cordova.file.dataDirectory（Android）
　file:///storage/emulated/0/Android/data/\<App Identifier\>/files/

# 保存先の分類

## 内部／外部
端末自身の記憶領域に保存する（内部）か、SDカードに保存するか（外部）の違いのようです。
（SDカードは持っていないので、外部記憶領域についてはテストできず、Cordova Pluginの記述に依存しています）
iOSには、この分類がなく、全て内部扱いになります。

内部／外部の指定に使うために、StorageTypeというStatic EntityがFile Pluginに。
File Pluginの各Actionには、StorageTypeIdというパラメータがあるので、そこに、StorageTypeのIdを指定する仕組み。
デフォルト値は内部を指定。

## 一時／永続
文字通り、保存するディレクトリ／ファイルが一時的なものか、永続的なものか。
一時的といっても、すぐに消えるわけではなく、OSが削除することがあるというもの。
iOSにはiCloud同期の機能がありますが、永続を選んだ場合でも、iCloud同期が行われない場所に保存されるようです。

一時／永続の指定に使うために、StoragePersistencyというStatic Entityがあります。
File Pluginの各Actionには、StoragePersistencyIdというパラメータがあるので、そこに、StoragePersistencyIdを指定する仕組みです。ただし、ファイル保存のActionだけは、Input ParameterにはStoragePersistencyIdがなく、SaveFile（永続）とSaveTempraryFile（一時）にActionレベルで別れてます。

引数にStoragePersistencyIdがある場合、デフォルト値は永続が指定される。

# 保存したファイルのパス
下のサンプル実装/作成したファイルのパスを確認するを使って、実際の保存先パスを確認してみました。
## iOS
以下のルートパスに作成されました。
UUIDの部分は実際にはGUIDらしきものが入っています。UUIDとしているのは、file pluginのドキュメントの記述によっています。
ただ、OutSystemsのDeviceInfo APIで取得した端末のUUIDとは別の値でした。

一時保存領域のルートパス：
file:///var/mobile/Containers/Data/Application/\<UUID\>/tmp/

永続保存領域のルートパス：
file:///var/mobile/Containers/Data/Application/\<UUID\>/Library/NoCloud/

実際のパスは、「ルートパス/ディレクトリ/ファイル」の形式。
ディレクトリ／ファイルの位置に日本語を使うとURLエンコードされた形式になりました。

## Android
ルートパスは以下の通り。

一時保存領域のルートパス：
file:///storage/emulated/0/Android/data/\<App Identifier\>/cache/

永続保存領域のルートパス：
file:///storage/emulated/0/Android/data/\<App Identifier\>/files/

実際のパスは、「ルートパス/ディレクトリ/ファイル」の形式。
ディレクトリ／ファイルの位置に日本語を使うとURLエンコードされた形式になりました。

# サンプル実装
## プラグイン利用可否の判定
Pluginモジュールには、そのプラグインを利用できる状況かどうかを判定するためのCheck<プラグイン名> Actionを用意することになっています。FilePluginでは、CheckFilePlugin Actionですね。パラメータはありません。

プラグインを利用できない端末であれば例えば、OnReadyで判定して別の画面に遷移させたり、ユーザーがリクエストしたときにエラーメッセージを表示したりします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/def3883a-be4c-4767-d850-d0a5f89ae799.png)

FilePluginの各Actionは、実は処理の先頭で内部的にCheckFilePlugin Actionを呼んでいるようです。

## ディレクトリ作成
CreateDirectory Actionを使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/8b34cab0-636c-be5c-a89a-8b0d8330fb55.png)

StoragePersistencyIdで保存先を一時／永続のどちらにするか指定する。
　ここで指定した保存先によって、ファイル・ディレクトリのルートパスが決定される。
ルートパスからの相対パスをPathに入力（例：""、"/フォルダ名"）。
Nameに作成するフォルダの名前を指定する。

以上の指定により、「一時／保存のルートパス/Path/Name」というパスにディレクトリが作成される。

Androidの場合には、StorageTypeIdにExternalを指定することによって、SDカードへの保存も可能。

## ファイル作成
ファイル作成は、なぜかInput Parameter「StoragePersistencyId」でなく別のActionを割り当てることで永続と一時を切り分けている。

一時ファイルを作成するのはSaveTemporaryFile、永続ファイルを作成するのはSaveFile Action。
パラメータはどっちのActionも同じなので、SaveTemporaryFileで説明します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/3a23c829-76fe-8401-3485-2cd33b62349d.png)
Name, Path, StorageTypeIdはディレクトリ作成と同じなのでそちらを参照。
BinaryDataはファイルの中身をバイナリ形式で渡します。ここではテストなので、NullBinary()でからのバイナリを渡しています。

## 一覧
ディレクトリを指定して、配下のファイル・ディレクトリをリストアップするAction。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/84915d9e-2d03-8253-5f84-fd72251a674d.png)
Pathを空文字列で渡せば、ルートフォルダ直下の一覧がとれます。

Output Parameterは

- DirectoryList：指定パスにあるディレクトリ名（Text型）のリスト
- FileList：指定パスにあるファイル名（Text型）のリスト

## 作成したファイルのパスを確認する
File Pluginを使って保存したファイルが実際にどこにあるかを確認するのがここでの目的。
ファイルについては、実際のパスをURL形式で返してくれるActionがあります。
GetFileUri Actionがそれです。ここでは、ListDirectoryで取得したファイル名の一覧をループして、Uriを取得する場合の例。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/12de4acd-226d-4356-0c3f-824349085b11.png)

# 公式ドキュメント
[File Plugin](https://success.outsystems.com/Documentation/11/Extensibility_and_Integration/Mobile_Plugins/File_Plugin)
File Pluginが内部で使っている[Cordova Plugin](https://github.com/OutSystems/cordova-plugin-file)