【PowerApps Tip's】オフライン対応

PowerApps はWebアプリケーションなのですが、実はオフライン（インターネット未接続）でも動くモノが作成可能です。今日はインターネットに接続できない状態でも動くアプリの作り方です。そのうち必要に迫られそうなので調査した結果のメモです。

# 公式情報
[オフライン対応キャンバス アプリを開発する](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/offline-apps) 

こちら↑を確認いただければ実装可能だと思います。これ以降は個人的な備忘の意味をかねて、ざっくりまとめていきます。

# ポイントとなる関数など
オフライン対応のアプリを作成する場合に必要になるモノを下記に列挙します。

### Connection シグナル
| プロパティ  |                        説明                      |
| :--------- | :----------------------------------------------- |
| .Connected | true ＝ オンライン<br />false ＝ オフライン(未接続) |
| .Metered   | true ＝ 従量制課金接続                             |

Connection.Connected の値を判定して、現在のインターネット接続状況を判断します。基本的に、オフライン対応する場合、このチェックが必須になります。

■参考URL
　https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/signals#connection

### SaveData と LoadData 関数
SaveData 関数が、そのアプリが実行されているローカル環境へデータをキャッシュしてくれます。LoadData 関数は、ローカル環境のキャッシュ情報からデータをアプリへ読み込んでくれます。保存できるデータ形式は Collection のみなので注意です。画面上に存在するオブジェクトなどを自由自在にキャッシュすることはできません。

また、下記の参考URLをご確認いただくとわかるのですが、キャッシュ可能な容量などは機種依存となるようです。そのため、膨大なデータを退避するといった利用方法はリスクが大きいと判断すべきかな、と思います。

■参考URL
　https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-savedata-loaddata

> これらの関数は、メモリ内コレクションで動作するために、利用可能なアプリのメモリの量によって制限されます。 使用可能なメモリは、デバイスとオペレーティング システム、PowerApps プレーヤーを使用して、メモリ、および画面とコントロールの観点から、アプリの複雑さによって異なります。

### Collection 変数
オフライン時に SaveData する際、必ずCollection 変数へ格納しておかなければなりません。

■参考URL
　https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/create-update-collection

# アーキテクチャの基本（個人的見解）
基本的に、PowerApps のアプリはオンライン（＝インターネット接続済み）の状態で利用される。ただし、地理の問題等で回線が切断されたり圏外になってオフラインになる可能性がある場合の対処として設計・実装する。（例えば海上だったり、山奥だったり、トンネルを通過するなど）

つまり、基本的にはオンライン → 状況によってオフラインになる可能性がある、といった場合の対処をする程度でとどめておくべきと個人的には考えている次第。はじめから「インターネット未接続の状態で動作するアプリ」が必要となるのであれば、PowerApps 以外の開発言語で専用アプリケーションを開発したほうが確実だと思います。

なお、オフライン時にデータを保存（SubmitFormなど）するケースも想定する必要があります。その場合に、前述の SaveData 関数を利用して一時的に確定したいデータをローカル保存し、オンライン状態になったら LoadData で読み込んで本来のデータソースへ反映する、という設計が必要になります。

# 検証してみた
<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">OffLine <a href="https://t.co/squskOEPER">pic.twitter.com/squskOEPER</a></p>&mdash; やま (@yamad365) <a href="https://twitter.com/yamad365/status/1127506087941365762?ref_src=twsrc%5Etfw">2019年5月12日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

データソースはSharePoint Online の簡単なカスタムリストなので説明は割愛。ボタンすぐ下にあるテーブルにデータソースの値を表示しています。さらに、その下においたテーブルに、ローカル保存したデータを表示しています。
アプリを起動して機内モードにすると、ローカル保存側にデータが退避されていくのが確認できます。

# 実装ポイント
ボタン押下時にオンラインの場合は素直にSubmitForm 、オフラインだった場合はCollection 変数にFormの値を退避したうえで、SaveData でローカル退避します。

``` Button.Onselect
If(
    Connection.Connected,
    SubmitForm(Form1),
    Collect(
        コレクション変数名,
        {
            text: DataCardValue1.Text,
            tel: DataCardValue2.Text
        }
    );
    SaveData(コレクション変数名,"ローカル保存用の名称");
    //Form再構築などは割愛
)
```
画面再描画のタイミングなどで退避してあるローカルデータを読み込めば、オフライン時に確定しようとしたデータが確認できます。※キャッシュが残っていれば、ですが。

``` Screen.OnVisible
If(Connection.Connected,"", LoadData(コレクション変数名,"ローカル保存用の名称")) 
```

# 補足情報
当方が検証した限りでは、例えば起動時にクラウドのデータソースを取得してくるようなアプリ（SharePoint Online のカスタムリストから自動生成したアプリで一覧が起動画面のような場合）はオフライン時は利用できません。それ以前に、スマートフォンのPowerAppsアプリをオフライン状態で起動した場合、それらの「インターネット接続ありき」で実装されたアプリは一覧に出てきません。

下記の動画、4分ごろから実際にオフライン（機内モード）にした状態で、PowerAppsアプリを起動したらどうなるか？が確認できますので、ご確認ください。

■参考URL
　[Build Offline PowerApps](https://www.youtube.com/watch?v=aIwbcCag9B4)

# まとめ
- Connection シグナルの[Connected]プロパティでオンラインか否か判断可能
- SaveData でローカルにデータ保存が可能
    - ローカル保存できるデータ量は機種に依存
- LoadData でローカルに保存したデータを読み込むコトが可能
- SaveData、LoadData どちらも Collection 変数**のみ**対応している

なおPowerApps自身に「オフラインからオンラインへ復帰した」というイベントは現状無いようです。なので、例えばタイマーで定期的にオンライン復旧しているか？というチェックを実施したり、（キャッシュに残ってるコトを期待して）アプリ再起動時の起動処理で手当てをしたり、といった設計が必要になってきます。ここらへんは、作成するアプリの要件に依存するかと思います。

しかし、なんにせよオフライン対応はめんどくさいですね。

それでは、皆さま。素晴らしい Power Platform Life を！