[.NET MAUI] アプリ固有のデータをダウンロード
アプリにバンドルしたファイルの読み込みでは、車種データ「cartype.json」をアプリにバンドルしているため、仮にもし車種が増えた場合は「cartype.json」を再作成してアプリをビルドし直す必要が生じる。
実際には考えにくいケースではあるが、車種が頻繁に更新されるとして、アプリ起動時に「cartype.json」をWebサーバからダウンロードしてデバイス内に保存し、アプリをビルドし直すことなく(ユーザーがアプリのバージョンアップすることなく)データだけ更新できるようにしたい。
事前に、更新版の車種データ「cartype_ver2.json」を自前のWebサーバにホストしておく。
[
{ "Name": "コンパクト" },
{ "Name": "ミニバン" },
{ "Name": "セダン" },
{ "Name": "ワゴン" },
{ "Name": "SUV" },
{ "Name": "スポーツ" },
{ "Name": "商用" },
{ "Name": "軽自動車" },
{ "Name": "ハッチバック" },
{ "Name": "クロスカントリー" }
]
アプリケーションが読み書き可能なデータディレクトリのパスは、FileSystem.Current.AppDataDirectoryで取得可能。このディレクトリ内にWebサーバからダウンロードした「cartype_ver2.json」を保存してから読み込むようにする。WebサーバからのダウンロードはWebCleint.DownloadFileを使用する。このクラスは非推奨(obsolete)だが、手っ取り早くURLからファイルをダウンロードするには便利だ。
+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シミュレーター上でアプリを終了〜再度起動すると、車種リストが最新の内容に更新された!!
非推奨の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への接続も必要なため、許可する方法は調査が必要。。。
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;
HTTPへの接続
Apple社としてはHTTP通信は非推奨であり、ATS(App Transport Security)を無効化する必要がある。こちらに書いてある方法で無事解決した。
ソリューションのツリーからPlatforms > iOS > Info.plist
Platforms > MacCatalyst > Info.plist
をプロパティリストエディターで開いて、NSAppTransportSecurity
の辞書を追加し、その配下にNSAllowsArbitraryLoads
のブール値「はい」を追加する。