Open4

[.NET MAUI] アプリ固有のデータをダウンロード

GomitaGomita

アプリにバンドルしたファイルの読み込みでは、車種データ「cartype.json」をアプリにバンドルしているため、仮にもし車種が増えた場合は「cartype.json」を再作成してアプリをビルドし直す必要が生じる。

実際には考えにくいケースではあるが、車種が頻繁に更新されるとして、アプリ起動時に「cartype.json」をWebサーバからダウンロードしてデバイス内に保存し、アプリをビルドし直すことなく(ユーザーがアプリのバージョンアップすることなく)データだけ更新できるようにしたい。

GomitaGomita

事前に、更新版の車種データ「cartype_ver2.json」を自前のWebサーバにホストしておく。

cartype_ver2.json
[
    { "Name": "コンパクト" },
    { "Name": "ミニバン" },
    { "Name": "セダン" },
    { "Name": "ワゴン" },
    { "Name": "SUV" },
    { "Name": "スポーツ" },
    { "Name": "商用" },
    { "Name": "軽自動車" },
    { "Name": "ハッチバック" },
    { "Name": "クロスカントリー" }
]

アプリケーションが読み書き可能なデータディレクトリのパスは、FileSystem.Current.AppDataDirectoryで取得可能。このディレクトリ内にWebサーバからダウンロードした「cartype_ver2.json」を保存してから読み込むようにする。WebサーバからのダウンロードはWebCleint.DownloadFileを使用する。このクラスは非推奨(obsolete)だが、手っ取り早くURLからファイルをダウンロードするには便利だ。

MainPage.xaml.cs
+using System.Net;
...
    private async void MainPage_Loaded(object sender, EventArgs e)
    {
+        string dataDir = FileSystem.Current.AppDataDirectory;
+        string filePath = Path.Combine(dataDir, "cartype.json");
+        WebClient wc = new WebClient();
+        wc.DownloadFile("https://www.xuldev.org/maui/cartype_ver2.json", filePath);
+        string json = File.ReadAllText(filePath);
-        string json = await ReadTextFile("Data/cartype.json");

見事、Webサーバからダウンロードした「cartype_ver2.json」のデータを反映して車種のリストが更新された!

また、Webサーバ上の「cartype_ver2.json」の内容をちょっと変更してから、iOSシミュレーター上でアプリを終了〜再度起動すると、車種リストが最新の内容に更新された!!

GomitaGomita

非推奨のWebClientクラスを、HttpClientに置き換える。
HttpClientクラスは標準ではHTTPSプロトコルのみ対応しており、http:// のURLへGetAsyncなどでアクセスしようとするとSystem.Net.Http.HttpRequestException: The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.例外スローして止まってしまう。例外はtry ~ catchしないとコンソールに表示されないので、これに気づくのにかなりの時間を要してしまった。
業務アプリではHTTPへの接続も必要なため、許可する方法は調査が必要。。。

MainPage.xaml.cs
        string dataDir = FileSystem.Current.AppDataDirectory;
        string filePath = Path.Combine(dataDir, "cartype.json");

 -       WebClient wc = new WebClient();
 -       wc.DownloadFile("http://www.xuldev.org/maui/cartype_ver2.json", filePath);
+        using (var client = new HttpClient())
+        {
+            string url = "https://www.xuldev.org/maui/cartype_ver2.json";    // HTTPS必須!
+            var response = await client.GetAsync(url);
+            response.EnsureSuccessStatusCode();
+            var body = await response.Content.ReadAsStringAsync();
+            File.WriteAllText(filePath, body);
+        }

        string json = File.ReadAllText(filePath);
        var lst = JsonSerializer.Deserialize<List<CarType>>(json);
        CarTypeList.ItemsSource = lst;
GomitaGomita

HTTPへの接続

Apple社としてはHTTP通信は非推奨であり、ATS(App Transport Security)を無効化する必要がある。こちらに書いてある方法で無事解決した。
https://www.wired-cat.com/entry/2020/05/02/213858

ソリューションのツリーからPlatforms > iOS > Info.plist Platforms > MacCatalyst > Info.plistをプロパティリストエディターで開いて、NSAppTransportSecurityの辞書を追加し、その配下にNSAllowsArbitraryLoadsのブール値「はい」を追加する。