ハイハイスクールアドベンチャー_.net_maui版
差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| ハイハイスクールアドベンチャー_.net_maui版 [2025/10/26 07:43] – [概要] araki | ハイハイスクールアドベンチャー_.net_maui版 [2025/10/26 09:29] (現在) – [Matrial You対応] araki | ||
|---|---|---|---|
| 行 78: | 行 78: | ||
| ==== Android版のパッケージングは鍵がいる ==== | ==== Android版のパッケージングは鍵がいる ==== | ||
| + | |||
| + | Android版も、ストアアプリにする予定じゃなくても、できるパッケージは黙ってれば aabになってしまうのです。 | ||
| + | これではサイドローディングできません。 | ||
| + | |||
| + | これもプロジェクトファイルに出力タイプを指定して apkにすることはできます。 | ||
| + | |||
| + | <code xml> | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | ただ、これで生成されるAPKはインストールできません。 | ||
| + | 無署名だからです。 | ||
| + | |||
| + | Androidもパッケージに署名がいるのですが、別にこちらは金を払って公式な署名をする必要はありません。 | ||
| + | オレオレ署名で問題なしです。 | ||
| + | |||
| + | まずはキーストアをつくります。 | ||
| + | |||
| + | <code bash> | ||
| + | $ keytool -genkey -v -keystore keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias keyalias | ||
| + | </ | ||
| + | |||
| + | keystore.jksとか keyaliasは適切なものにしてください。 | ||
| + | パスワード一回しか聞かれませんが、キーとストアの両方が一度にできます。 | ||
| + | |||
| + | キーができたら、プロジェクトファイルに署名のための設定を追加します。 | ||
| + | 但し、csproj本体にやっちゃうと、プロジェクトをgitなどで公開したくなったときに困るので、csproj.userの方に書いて、.gitignoreなどで公開除外することをお勧めします。 | ||
| + | |||
| + | <code xml> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | ご覧のようにパスワードべた書きになるので、間違って公開されないようにご注意ください。 | ||
| + | |||
| + | あとは普通にpublishしてやれば APKが得られます。 | ||
| ==== Matrial You対応 ==== | ==== Matrial You対応 ==== | ||
| + | |||
| + | Android Studioでは、基本的にMaterial You対応のランチャーアイコンを生成してくれません。 | ||
| + | 自分で手作業で対応を行う必要があります。 | ||
| + | |||
| + | 何もしなければ、ランチャーアイコンはカスタムアイコンになります。 | ||
| + | |||
| + | ところが、.NET MAUIは頼んでもないのにMatrial You対応のアイコンを生成します。 | ||
| + | 但し、モノクロアイコンにカスタムアイコンを持ってくるだけなので、カスタムアイコンがモノクロでない限りは何も表示されない間抜けな表示になってしまいます。 | ||
| + | |||
| + | できないならやらない、という Android Studioの方針はある意味正しいですが、基本的にPixel Launcher以外はMaterial You対応していないものばかりなので、この問題は発覚することはないのかもしれません。 | ||
| + | |||
| + | とはいえ、わたし自身がPixelユーザなのでこれは由々しき問題なのです。 | ||
| + | |||
| + | ハイハイスクールアドベンチャーのアイコンはいさこちゃん。 | ||
| + | ラスタ画像なので、mdpi, | ||
| + | |||
| + | 背景画像も適切に作ってくれます。 | ||
| + | |||
| + | ただモノクロアイコンだけは作ってくれないのに、adaptive iconに定義を突っ込んでくれます。 | ||
| + | これが問題。 | ||
| + | |||
| + | まずは、モノクロアイコン画像ファイルを用意し、Resources/ | ||
| + | 次に、ic_launcher.xml と ic_launcher_round.xml を用意し、Platforms/ | ||
| + | |||
| + | ハイハイスクールアドベンチャーの場合はMauiIconにisako_1024.pngを指定しているので、生成され参照されるのがisako_1024.xmlとisako_1024_round.xmlになります。 | ||
| + | |||
| + | <file xml isako_1024.xml> | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | isako_1024_round.xmlも内容は全く同じで基本的に問題はありません。 | ||
| + | 両方ないと、Pixel Launcherはモノクロアイコンを正しく扱えません。 | ||
| ==== 画面遷移は戻れない ==== | ==== 画面遷移は戻れない ==== | ||
| ==== Windows版の発行は自己内包型で ==== | ==== Windows版の発行は自己内包型で ==== | ||
| + | ===== 技術的なこと ===== | ||
| + | |||
| + | ==== リソースファイル ==== | ||
| + | |||
| + | プログラムが参照するファイルのうち、プログラムに同梱のものは、Windowsであればプログラム本体と同じ場所に、Linuxであれば、/ | ||
| + | ((MacOSやiOSがどうなっているのかは知らない。)) | ||
| + | |||
| + | また、プログラムの動作中に生成されるユーザデータなどの置き場所も環境に依存するのが普通です。 | ||
| + | |||
| + | これらの差分をフレームワークが吸収してくれると非常にプログラミングが楽になります。 | ||
| + | |||
| + | .NET MAUIでは、プログラムと同根のファイルは Resources/ | ||
| + | |||
| + | おおこりゃ楽ちん。 | ||
| + | と、思っていた時期もありました。 | ||
| + | |||
| + | Windows版が一通り動作したので、Androidでも動くか確かめようと思ったら、いきなり例外。 | ||
| + | fs.Length がサポートされていないと出てくるわけですよ。 | ||
| + | なんですと? | ||
| + | 調べてみると、Androidの場合、リソースファイルは圧縮されていたりなんだりで、普通のファイルと違って、Lengthをとったり、Seekしたりできない。 | ||
| + | やりたかったら、全部メモリストリームにコピーしてからやるか、リソースファイルを一旦ユーザのデータフォルダーにコピーしてからそっちを使えっていうじゃないですか。 | ||
| + | データファイルで最大のものは220KBのマップファイルで、まあ昨今のAndroid端末を考えればどうってこともないサイズ。 | ||
| + | 全部メモリ展開するっていうのもありかな、とちょっと思ったんですが、このゲームの基本的な構造は 500KB程度の M5 Stackや Raspberru Pi Picoなどでも動くように、けちけち使う分だけを展開するスタイル。 | ||
| + | Android版は当初、全部メモリに展開してたんですが、ソースを整理するときに全面的にけちけち戦略に書き直した経緯もあって、今更全部展開っていうのもな、と思い、ファイルをユーザデータ領域にコピーして使う方針に。 | ||
| + | <code csharp> | ||
| + | private static async Task CopyAssetToAppDataAsync(string filename) | ||
| + | { | ||
| + | // アセットを開く | ||
| + | using Stream input = await FileSystem.Current.OpenAppPackageFileAsync(filename); | ||
| + | // 保存先パスを決定 | ||
| + | string targetFile = Path.Combine(DataFolder, | ||
| + | // コピー | ||
| + | using FileStream output = File.Create(targetFile); | ||
| + | await input.CopyToAsync(output, | ||
| + | await output.FlushAsync(); | ||
| + | } | ||
| + | </ | ||
| + | アセットファイルの一覧は取れますか? | ||
| + | とAIに聞いたら「できません」というのでファイル名はプログラムで決め打ちでコピーするしかないですが、まあ必要なファイルはプログラム側でわかっているので、面倒でも列挙しておけばいいだけなので、そのようにします。 | ||
| + | なお、ご覧のようにこの操作は非同期操作です。 | ||
| + | この関数内では awaitを入れて一応順次動作するようにしていますが、呼び出し元でもこの処理をきちんと awaitしないとコピーが半端に終わってしまったりします。 | ||
| + | .NET自体が積極的に非同期を導入していて、そもそも非同期のサービスしかなかったりするものもあって、プログラム全体の流れをきちんと考えないとおかしな動作になることもあります。 | ||
ハイハイスクールアドベンチャー_.net_maui版.1761464585.txt.gz · 最終更新: by araki
