×
ラベル dev の投稿を表示しています。 すべての投稿を表示
ラベル dev の投稿を表示しています。 すべての投稿を表示

目次 [隠す]

blogger ロゴ

今年の六月に入って以降、新規に書いたブログ記事がGoogleインデックスに登録されないトラブルが発生していました。

解決方法が分かったので備忘録を兼ね一連の対応をまとめました。

※他のブログサービスやホームページによるケースは未検証です。同様に解決できるかはご自身の責任でお願いいたします。

今回のトラブルと対処方法の概要

利用ブログ

Blogger(Google提供のブログサービス)

トラブル内容

Googleインデックスに新しいブログ記事が登録されない。

トラブル原因

Google Search Consoleで表示されるエラー名は「リダイレクトエラー」。

対処方法

URLから記号(ハイフン)を削除した。

今回のトラブルと対処方法の詳細

トラブル原因

Google Search Consoleで「カバレッジ」のエラーを表示してみると「リダイレクトエラー」が発生していた。

説明画像1

試しに、Google Search Consoleの「URL検査」で、エラーに該当する「ashitano-tarinai-futari.html」という記事を検査する。

説明画像2

やはり「リダイレクトエラー」とメッセージがあるが、それ以上の情報は無い。

Search Consoleヘルプでリダイレクトエラーの詳細について確認する。

リダイレクト エラー: リダイレクト チェーンが長すぎる、リダイレクト ループが発生している、リダイレクト URL が最終的に URL の最大長を超えた、リダイレクト チェーンに不正または空の URL がある、のいずれかのタイプのリダイレクト エラーに Google が遭遇しました。Lighthouse などのウェブ デバッグツールを使用して、リダイレクトに関する詳細情報を入手してください。

該当URLのリダイレクトを「リダイレクトチェック」で調べてみるが、リダイレクトを必要としないページのため問題なし。

リダイレクトチェック(ohotuku.jp)

この他、いくつか「リダイレクトエラー」に関するブログを読んでみたがいずれも該当せず。

リダイレクトエラー のエラー原因と改善方法 - 株式会社ココログラフ

リダイレクトエラーとは、リダイレクト処理でエラーが発生している場合に表示されます。リダイレクトは、指定のWebサイトに来訪したユーザーを自動的に指定した別ページに転送する処理のことを指します。ページの

blog card

サーチコンソールのリダイレクトエラーの原因を解説!【解決できます】 | AKINOTE

ブログ実践者であればサーチコンソール導入していると思いますが問題が発生するとかなり焦りますよね。 この記事ではサーチコンソールでの【リダイレクトエラー】の解決方法を解説していきます。 かなり単純なこと

そこで、ふと「ブログ記事のHTMLファイル名に問題があるのではないか」と考えた。

Bloggerでは「パーマリンク」という項目でURLの一部をユーザカスタムができ、私はなるべく記事のタイトルに即したものにする運用をしていた。

説明画像4

具体的には、タイトルを英訳し、単語をハイフン区切りにする。

そこでURLに含まれる記号(とりわけハイフン)について言及している記事をいくつか読んでみたが、ハイフンがいかんというようなモノは見つからなかった。

discovered url in search console with hyphen character | WordPress.org

My site urls have not been recognized by google even though I’m using XML Sitemaps plugin. According

blog card

SEO best practice: Underscores or Hyphens in URLs?

Google sees hyphens as word separators in URLs but does not view underscores in URLs the same.

blog card

しかし、試しにURLからハイフンを削除してみたところうまく行ってしまった。

結果的に、URLのHTMLファイル名に含まれるハイフンが原因となってしまった。

Search ConsoleやBloggerのドキュメントにその記載は見当たらない。

何より、ハイフンを含めて作成していた過去記事については問題なくインデックス登録され続けている。

非常に腑に落ちないが、現時点での結果。後日わかったことがあれば追記します。

対処方法

原因に書いた通り、Bloggerのパーマリンクでハイフンを削除し、Search Console でインデックス登録をリクエストした。

そうしたら半日かからずに問題なくインデックス登録された。

説明画像5

おわりに

6月に発覚してから解決まで長く時間がかかった割にはすっきりせず。

要因は、ハッキリした原因が分かっていないためだ。

6月ごろに仕様が変わったのか。そのようなアナウンスがあったのかな?

どなたかご存じの方がいましたらコメントやTwitter等で教えていただけたら嬉しい限りです。

【解決】リダイレクトエラーでGoogleインデックスに記事が登録されないトラブル【Blogger】

目次 [隠す]

xamarin logo

本記事の概要

『Xamarin.Formsで開発したAndroidアプリのパッケージサイズを圧縮しようと「Linker」「d8/r8」コンパイラを駆使したが、敗北する』、です。

アプリのパッケージサイズが気になる

先日、初めて個人開発したスマホアプリ(Android版のみ)をリリースしました。

アラフォー初心者だけどスマホアプリを開発~リリースまでがんばってみた【Android・Xamarin.Forms】 | neputa note

この度、素人ながらスマホアプリ開発に挑戦してみました。 今回の記事では概要と経緯について書き綴ってみたいと思います。 実際に行った作業の詳細は、今後それぞれ記事を書き、こちらにリンクを追記します。作っ

blog card

こちらでインストールできます
※アンドロイド版のみです。iPhoneユーザの方すみません。
Google Play で手に入れよう

色々と不具合問題で話題となっている「COCOA - 新型コロナウイルス接触確認アプリ」の影響もあり、すっかり悪いイメージがついた「Xamarin.Forms」で開発しました!!

Xamarin.Forms は直接Android、iOSのAPIを叩いて実行するアプリを作れるので、ネイティブ開発と比べて特別に劣るということも無いとは思うのです。

思うのですが、monoランタイムを抱えていることもあり、パッケージサイズが大きくなりがちです。

Xamarinの基盤「Mono」のmonoランタイムとクラスライブラリ - Build Insider検索

インサイドXamarin(3)。Xamarinにおけるソフトウェアの基盤であるMonoを深く理解すれば、Xamarin製品の理解はもっと深まる。今回はmonoランタイムと、Monoのクラスライブラリに

blog card

現在リリースしているバージョン1.0.4の時点で、ダウンロードサイズは34MB、インストールしたアプリサイズは49.45MBと、アプリの内容を考えると「で、でかいぞ……」と感じるわけです。

これをどうにかできないかと悪戦苦闘し、敗れる(つまり未可決)という、残念な内容な記事となります。

情報価値はゼロと思いますが、もしよろしければ暇つぶしにどうぞお付き合いください。

Xamarin.Forms だってダイエットしたい

参考にしたサイトはこちらになります。
Xamarin.Forms - Android App Performance and Package Size Reduction
Reducing iOS and Android App Size in Xamarin

サイズを小さくする方法はいくつかあります。

1.R8 Shrinker を使用する

Android's D8 dexer and R8 shrinker | Xamarin Blog

Learn more about Xamarin.Android’s D8 and R8 integration and deep dive on how R8 is being developed

blog card

2.Linker を使用する
Android でのリンク - Microsoft Docs

3.AOT&LLVM コンパイラを使用する
アプリケーションを保護する - Microsoft Docs

この中で、3番目のAOT&LLVMは、Visual StudioのEnterpriseエディションライセンスが必要なので、わたしは残念ながら利用できません。

では、最初の2つを使用すればいいじゃないかとなりますが、そうは簡単にはいかないのですね。

まずは、「R8 Shrinker」と「Linker」について、調べてみたことを簡単にまとめたいと思います。

R8 Shrinker

これは、Javaバイトコードを対象に未使用コードを削除してくれる機能です。
(ネイティブ開発と異なり、Xamarin.Forms では難読化の恩恵は得ることができません)

r8 shrinker

※ちなみにこれを書いている2021/3/12時点では、「R8」の他に「ProGuardを有効にする」という選択肢があります。 R8はProGuardを置き換える目的で開発されたもので、ProGuardを選択するとビルドで「R8」を使えと怒られます。

軽量化に役立つなら使えばいいじゃない、そう思うことでしょう。

なんの備えもなくこいつを選ぶとあら不思議、わたしのアプリは見事クラッシュします。

いろいろと対処をいないと使えないことがわかったので、必要事項を後述します。

Linker

これは、静的解析により不要と判断したコードをばっさり切り捨てることで軽量化を図る機能です。

オプションとしては、「一切使用しない(なし)」「SDKのみ対象とする(SDKアセンブリのみ)」「すべて対象(SDKおよびユーザアセンブリ)」の3つがあります。

linker

現在は、SDKのみを対象としており、わたしが書いたコードおよび追加したNuget Packageについては対象外となっています。

で、SDKとユーザアセンブリすべてを安易に選ぶとあら不思議、わたしのアプリは見事クラッシュします。

R8 Shrinker、Linkerどちらも何もせずに使えるわけではなく、導入するにはそれなりの準備が必要となります。

R8 Shrinker を使うために行った作業

まずは、Visual Studioのツール→Android→Android Device Monitorで、クラッシュ原因を見てみましょう。

crash

「FATAL」があるあたりを見てみると、こんなメッセージがあります。
java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.ads.MobileAdsInitProvider"

わたしのアプリには「Google AdMob」という広告表示用のプラグインがあるのですが、起動時にそんなもん見つかんねーよと言われておるのですね。

つまり、「R8 Shrinker」さん、「軽量化するため余計なコードぶった切ったけど、お前が追加したパッケージとかも切り捨ててやったよー」ということでしょうか。

R8 Shrinkerを使用していると、Androidプロジェクトフォルダ配下の「obj\Release\XXX\proguard」に「.cfg」拡張子のファイルがあります。(XXXは、お使いのエミュレータのバージョンが入ります)

これらのファイルを見てみると、「-keep class XXXX」という記述がずらりと並んでいます。

これは、コンパイル時に切り捨てずにキープ対象となるライブラリ名がずらりと書かれているのですね。

obj配下にあるファイルは自動生成されたものです。

これとは別に自分が追加したパッケージ等をkeepするために設定ファイルを用意する必要があります。

例えば「my_proguard_xamarin.cfg」というファイルをAndroidプロジェクトに追加し、「ビルドアクション」を「ProguardConfiguration」にしておきます。

こうすることで、ビルド時にこの設定ファイルを読んでくれるようになります。

ProGuard - Xamarin | Microsoft Docs

Xamarin.Android ProGuard は、Java クラス ファイルのシュリンカー、オプティマイザー、および事前検証機能です。 これは、未使用のコードを検出して削除し、バイトコードの分析と

blog card

ちなみに、自動生成された.cfgファイルをコピーして設定ファイルを作る場合、ファイル内のBOMがビルドエラーの原因となるので対応するエディタ等でBOMを削除する必要があります。

あとはひたすら、トライ&エラーです。

エラー原因となったライブラリを設定ファイルに追記し、Android Device Monitorで確認、また別のエラーが出たらそれを追記、そしてまた……。

わたしの場合、最初のAdMobに続いて、AdMobに関連する「com.google.unity.ads.UnityAdListener」、そして「androidx.work」、が原因ではじかれ、そのつど、ファイルにKeepを追加しました。

一番厄介だったのが、Splash screenのファイルに問題があるとエラーが出て、いろいろ調べた結果「Calligraphy」をアップデートしろという情報を見つけ対応したことです。

R8を使用していなければ特に問題は起きていなかったので、R8に関連してCalligraphyのバージョンが問題となるのかいまいち原因ははっきりせず。

Crash on Android 10 - stack overflow Calligraphy.Xamarin

結果として以下のような.cfgファイルを作成し、何とかアプリが起動するところまでたどり着きました。

-keep class com.google.unity.** {
  *;
}

-keep public class com.google.android.gms.ads.**{
public *;
}

-keep public class com.google.ads.**{
public *;
}

-keep class androidx.work.** { *; }

-keepattributes Annotation

R8については以上となります。

Linkerでユーザアセンブリも対象にする

続いて、Linker。

もっともパッケージ圧縮の恩恵が大きいのは「SDKおよびユーザアセンブリ」を選択すること。

しかしこちらもR8 Shrinker同様、必要な設定を施さないと、わたしの場合はアプリが見事にクラッシュしました。

行う作業も同様で、Linkerで切り捨ててほしくないライブラリ等を設定ファイルに追加していきます。

カスタム リンカーの構成 - Xamarin | Microsoft Docs

このドキュメントでは、必要なコードがリンクされているアプリケーションから削除されないことを明示的に確認し、リンカーを構成するために使用できる XML ファイルについて説明します。

blog card

Linkerの設定はXMLファイルに記述します。

とりあえず「LinkerSettings.xml」という名前のファイルをAndroidプロジェクトに追加し、ファイルプロパティのビルドアクションを「LinkDescription」にしておきます。

わたしの場合はこんな感じになりました。

使用しているNuget Packageと、作成したプロジェクトアセンブリが対象となっています。

<?xml version="1.0" encoding="utf-8" ?>
<linker>
  <!--
      For more information see the docs on creating custom Linker Settings
      https://docs.microsoft.com/en-us/xamarin/cross-platform/deploy-test/linker
  -->
  <assembly fullname="Essential.Interfaces">
    <type fullname="Xamarin.Essentials.Implementation.AppInfoImplementation">
      <method name=".ctor" />
    </type>
  </assembly>

  <assembly fullname="Prism.Forms">
    <type fullname="Prism.Common.ApplicationProvider" preserve="all" />
    <type fullname="Prism.Services.PageDialogService" preserve="all" />
    <type fullname="Prism.Services.DeviceService" preserve="all" />
    <type fullname="Prism.Ioc*" preserve="all" />
    <type fullname="Prism.Modularity*" preserve="all" />
    <type fullname="Prism.Navigation*" preserve="all" />
    <type fullname="Prism.Behaviors.PageBehaviorFactory" preserve="all">
      <method name=".ctor" />
    </type>
    <type fullname="Prism.Services.DependencyService" preserve="all">
      <method name=".ctor" />
    </type>
  </assembly>

  <assembly fullname="Prism">
    <type fullname="Prism.Navigation*" preserve="all" />
    <type fullname="Prism.Logging.EmptyLogger" preserve="all">
      <method name=".ctor" />
    </type>
  </assembly>

  <assembly fullname="Unity.Abstractions">
    <type fullname="*" />
  </assembly>

  <assembly fullname="Unity.Container">
    <type fullname="*" />
  </assembly>

  <assembly fullname="Prism.Unity.Forms">
    <type fullname="*" />
  </assembly>

  <assembly fullname="System">
    <type fullname="*" />
  </assembly>

  <assembly fullname="mscorlib">
    <type fullname="*" />
  </assembly>

  <assembly fullname="OneThird.Core">
    <type fullname="*" />
  </assembly>

  <assembly fullname="OneThird.Application">
    <type fullname="*" />
  </assembly>

  <assembly fullname="OneThird.Domain">
    <type fullname="*" />
  </assembly>

  <assembly fullname="OneThird.Infrastructure">
    <type fullname="*" />
  </assembly>

  <assembly fullname="Microsoft.Identity.Client">
    <type fullname="*" />
  </assembly>

  <assembly fullname="Realm">
    <type fullname="*" />
  </assembly>

  <assembly fullname="System.IdentityModel.Tokens.Jwt">
    <type fullname="*" />
  </assembly>

  <assembly fullname="Xamarin.CommunityToolkit">
    <type fullname="*" />
  </assembly>

  <assembly fullname="Xamarin.GooglePlayServices.Ads" >
    <type fullname="*" />
  </assembly>

</linker>

よし、これでしまいかと思いきや……。

見事にクラッシュします。

で、色々と調べているとLinkerの対象から外すために「Preserve属性を追加せよ」という情報を目にします。
Using The Linker In Xamarin Projects

たいへん面倒ではありますが、以下のように属性を付けて回ることにします。

Androidプロジェクトのすべてのクラス
[Android.Runtime.Preserve(AllMembers = true)]

共通プロジェクトのすべてのクラス
[Xamarin.Forms.Internals.Preserve(AllMembers = true)]

ここまでやって、ようやく、ようやくアプリが起動しました。

だが、これでは終わらない……

無事起動しました。

しかし物語は常にハッピーエンドとは限りませんね。

動作確認をすると、CosmosDBの接続でエラーが出る、広告が表示されない、などいくつかの不具合が見つかります。

「ンあーーーーーーっ」と叫びたい気持ちを抑え、またひとつひとつ潰していくかと思いました。

冷静にこの時点でどれほどパッケージサイズは小さくなっているのだろうと確認すると、わずか「3MB」……。

これだけやって、こんな程度かとまず脱力します。

そして、「エラーを潰す = 削除されたコードを残すようにする」わけです。

ここから更にパッケージサイズは大きくなります。

また将来的なことも考えてみます。

この先、きっと機能追加等でコードやNuGetを追加したりするでしょう。

そのたびに今回の作業を忘れずに行う必要があります。

アプリサイズが少しでも小さいほうが、ユーザにとって良いことです。

ですが、コストやリスクに対しメリット少なすぎやしませんか。

涙の結論

ということで、「R8 Shrinker」および「フルLinker」は、たいっへん残念ではありますが、めっちゃ頑張りましたが、すんごく悔しいですが(しつこい)、あきらめることとしました。

ダウンロードしてくれるユーザの皆さまのギガを奪ってすいません。

wi-fiがある場所でダウンロードしたりアップデートしてくれることを祈っています。

技術の話なのに最後はお祈りですよ。

Visual Studioのエンタープライズエディションゲットして「AOT&LLVM」使えば楽にちっさくなったりするんですかね。
でも$250/月とか無理っすよ……。

それとも何かいい方法があるのでしょうか。

もしご存じな親切な方いらっしゃいましたらコメントやTwitterなどで教えていただけますと、朝晩そちらに向かって毎日かかさず感謝の祈りを捧げたりします。

以上、プログラミングは祈りだ、の巻きでした。

AndroidアプリのAPKサイズを圧縮しようと試みて敗れる話【Xamarin.Forms / Linker / R8 Shrinker】

目次 [隠す]

OneThird ストア画像

記事の概要

こちらの一覧の7つ目、「保守フェーズ(公開から現在まで)」の記事となります。

はじめてスマホアプリを作ってみた 記事一覧

  1. 検討フェーズ(どんなアプリを作るか)
  2. 要件フェーズ(どんな要件のアプリにするか)
  3. 調査フェーズ(どんな技術を使うか)
  4. 設計フェーズ(どうやって作るか)
  5. 開発フェーズ(実際に作りはじめる)
  6. 公開フェーズ(アプリを公開する)
  7. 保守フェーズ(公開から現在まで)

こちらでインストールできます
※アンドロイド版のみです。iPhoneユーザの方すみません。
Google Play で手に入れよう

全7回に分割して書いていますが長いので、ダイジェストで読みたい方はこちらの記事をご覧ください。

アラフォー初心者だけどスマホアプリを開発~リリースまでがんばってみた【Android・Xamarin.Forms】 | neputa note

この度、素人ながらスマホアプリ開発に挑戦してみました。 今回の記事では概要と経緯について書き綴ってみたいと思います。 実際に行った作業の詳細は、今後それぞれ記事を書き、こちらにリンクを追記します。作っ

blog card

はじめてのスマホアプリ開発 保守フェーズ

前回は、アプリをGooglePlayでリリースする工程で行ったことをまとめました。

今回は、リリース後に見つけたバグや追加したい機能などをどのように管理し、実装しているのかについて書いてみたいと思います。

個人開発なので、自分が把握できる方法であれば何でもよいとは思います。

こういうやり方してる人もいるんだ、という感じに温かい目で読んでもらえるとありがたいです。

作業で使用しているツール

an image of tools
Photo by:Todd Quackenbush in Unsplash

まずは、どのようなツールを使用して作業を行っているかについてです。
現在の作業環境を図に書き出してみました。

work environment
作業環境図

図中の各ツールをどのような目的で使用しているのか説明したいと思います。

Visual Studio と Git

開発ツールは「Visual Studio Community」を使用しています。

Visual Studio Community 2019 - Free IDE and Developer Tools

Try our free, fully-featured, and extensible IDE for creating modern developer apps for Windows, And

blog card

ソース管理ツールの「Git」を操作する機能が統合されているので、作業時に起動するのはVisual Studioと次に説明する各Webツールのためにブラウザぐらいでしょうか。

Azure DevOps

わたしの場合は記憶力に自信がないので、ひとつひとつの作業を経緯を含めて記録しておかないと、後から見た際に「なんのこっちゃ」となることが多いです。

この作業を記録するために、Azure DevOpsが大いに役立っています。

Azure DevOps Services | Microsoft Azure

Azure DevOps Services (以前の Visual Studio Team Services) を利用して、よりスマートに計画を立て、より効率的に共同作業を行い、より迅速に公開しましょ

blog card

最初の5ユーザまでなら無料で利用できます。

.NETに限らず、Node.js、Python、Java、PHP、Ruby、C/C++など多くの言語に対応しています。

Azure DevOpsで主に使用している機能は以下となります。

Boards
「Basic」「Agile」「Scrum」の3種類から管理方法を選択し、プロジェクト管理を行うことができる機能です。
個人開発ではありますが、検索して分かりやすい情報が多かった「Scrum」を選択して使っています。

Repos
これはリモートリポジトリです。
Visual Studioからpushしたコミットをここで管理しています。
主にmainブランチに開発ブランチをマージする作業をここでしています。

Wiki
アプリの仕様をここに書いておくようにしています。
「仕様書」というほど厳密なものではなく、変更頻度が低いアプリの仕様上のルールなどを書くようにしています。

この他、「Pipeline」というビルドやデプロイを自動化する機能がありますが、この部分は別途「App Center」というツールで行っているので使っていません。

「Test」という機能は有償プランでフルに利用できるようになります。わたしは限定的にしか使用できないので、UIテストのチェックリストを「Test Case」として作成する機能などを使っています。

チーム開発であれば、Reposでテスト用のブランチを切って、Pipelineでビルド&検証環境へリリース、Testでテスターが作業みたいな流れが実現できるのだと思います。

App Center

Azure DevOpsで管理しているリポジトリを参照し、ビルド&リリースを自動化できるブラウザで使用するツールです。

Visual Studio App Center | Microsoft Azure

Visual Studio App Center でアプリケーション ライフサイクルを自動化することで、iOS、Android、Windows、macOS 向けの高品質のアプリをより迅速に作成できます

blog card

毎月のビルド数などに制限がありますが無償で使用できます。

接続IDなどシークレット情報を管理して、ビルド時に差し込んでくれる機能などがあります。

わたしはAzure DevOpsのReposでmainブランチのコミットを行い、App Centerが更新を検知して自動でビルド、Google Play Consoleへリリースしてくれるように設定しています。

Google Play Console

Google Playの公開情報をここで管理します。

アップデートをApp Centerでリリースしたら、審査中の間にここで多言語用のリリースノートを書いたりしています。

ダウンロード状況などを分析してくれる機能もありますが、まだユーザも多くないのでそれほど役立てることはできていません。

Google Cloud Platform

これは、App CenterからGoogle Play ConsoleへリリースできるようにするためのAPI Serviceを提供してくれるプラットフォームとして利用しています。

Azure

ユーザ認証の機能を提供してくれる「Azure AD B2C」と、サーバDBとして利用しているドキュメントDB「CosmosDB」を使用しています。

Azure Cosmos DB を試す| Microsoft Azure

Azure Cosmos DB を使用して、任意のプラットフォームやデバイス用に、Web およびモバイル アプリを迅速かつ簡単に構築してください。サブスクリプションは不要で、課金や契約もありません。

blog card

Azure Active Directory B2C とは | Microsoft Docs

Azure Active Directory B2C を使用して、Facebook、Google、その他の ID プロバイダーでのソーシャル ログインなど、外部 ID をアプリケーションでサポートする

blog card

サインイン画面のカスタムテンプレートを使用するために「Azure Blob」も併せて利用しています。

AWSなどの方が情報も多くユーザも多いとは思いますが、.NET開発者向けの情報やライブラリが充実しているので、いまのところ不自由なく利用することができています。

この他、Google Admobや、Admob用にadd-aps.txtをホストするためにFirebaseを利用しています。

作業の流れ

an image of a work flow
Photo by:Campaign Creators in Unsplash

続いて、ここまで書いたツールをどのような手順で使用しているか書いてみたいと思います。

  1. (Azure DevOps)Boardsに、Bug・Product Backlog Item を登録する。(随時)
  2. 優先度を整理し、次回リリース対象をBoardsのSprintsに登録する。
  3. Visual Studioで開発を行う。
  4. 作業内容をBoardsに記録する。
  5. 開発完了後、ローカルGitから、Azure DevOps ReposにPushする。
  6. Reposでmainブランチに開発ブランチをマージする。
  7. mainブランチの更新をApp Centerが検知し、Build → Distributeが行われる。(自動)
  8. App Centerから配布されたaabをGoogle Play Consoleが受け取りリリースが行われる(自動)
  9. BoardsにCommit IDを記録しStatusをDoneにする。
  10. 一連の作業が完了。
work flow
作業フロー図

現在は、こんな感じで作業を繰り返しアプリのアップデートを行っています。

初回リリースをするまでは、開発とこれらの環境構築を併せて行っていたのでかなり大変でしたが、おかげで今はコーディングに最も時間を費やすことができる環境となっています。

まとめ

ざっとではありますが、わたしの作業環境についてまとめてみました。

各ツールの使い方や設定方法などは、個別に別途記事を書きたいと思います。

すべて我流なので、使い方がおかしかったりするものもあると思います。
わからない部分や、もっといい使い方がある、いいツールがあるよーなど指摘いただけますととっても嬉しいです。

10年以上前、かつて知っていた開発環境とは大きく変わり、今では便利なツールがたくさんあることに驚くとともに、ツールを作ってくれた方々に感謝しながら使わせていただいています。
いずれ費用を捻出できるぐらいになったら、有償のさまざまな機能も使ってみたいなーなどと夢見ています。

ここまで、初心者がはじめてスマホアプリを開発し、リリースするまでを7回に分けで書いてきました。

独学で実践してきた偏ったものかもしれませんが、どなたかのお役に少しでもなれれば幸いです。

プログラミングはほんっとうに楽しいですね。

どうぞよき開発ライフを!

長文にお付合いいただき、ほんとうにありがとうございました!

はじめてスマホアプリを作ってみた 記事一覧

  1. 検討フェーズ(どんなアプリを作るか)
  2. 要件フェーズ(どんな要件のアプリにするか)
  3. 調査フェーズ(どんな技術を使うか)
  4. 設計フェーズ(どうやって作るか)
  5. 開発フェーズ(実際に作りはじめる)
  6. 公開フェーズ(アプリを公開する)
  7. 保守フェーズ(公開から現在まで)

07.はじめてスマホアプリを作ってみた(保守フェーズ)【 Android / Xamarin.Forms 】

目次 [隠す]

OneThird ストア画像

記事の概要

こちらの一覧の6つ目、「公開フェーズ(アプリを公開する)」の記事となります。

はじめてスマホアプリを作ってみた 記事一覧
  1. 検討フェーズ(どんなアプリを作るか)
  2. 要件フェーズ(どんな要件のアプリにするか)
  3. 調査フェーズ(どんな技術を使うか)
  4. 設計フェーズ(どうやって作るか)
  5. 開発フェーズ(実際に作りはじめる)
  6. 公開フェーズ(アプリを公開する)
  7. 保守フェーズ(公開から現在まで)

こちらでインストールできます
※アンドロイド版のみです。iPhoneユーザの方すみません。
Google Play で手に入れよう

全7回に分割して書いていますが長いので、ダイジェストで読みたい方はこちらの記事をご覧ください。

アラフォー初心者だけどスマホアプリを開発~リリースまでがんばってみた【Android・Xamarin.Forms】 | neputa note

この度、素人ながらスマホアプリ開発に挑戦してみました。 今回の記事では概要と経緯について書き綴ってみたいと思います。 実際に行った作業の詳細は、今後それぞれ記事を書き、こちらにリンクを追記します。作っ

blog card

はじめてのスマホアプリ開発 公開フェーズ

前回は、実装作業の工程で行ったことについて書きました。

今回はいよいよ作ったアプリをGoogle Playでリリースするまでに行ったことをまとめてみたいと思います。

リリースで行った作業メニューです。

  • アップデートを見据えたリリース環境の設計
  • リリースに向けたアプリの準備
  • Google Play デベロッパー アカウントへの登録
  • Googl Play Store API の準備
  • Google Play Console にアプリを登録
  • Visual Studio App Center の準備

ようやく開発を終え、一息付けたと思ったらリリース作業は思った以上に大変でした。

この記事では、大まかにどのような作業が発生するのかを記していきたいと思います。
それぞれの項目の細かい手順などは、後日、別途記事を書きたいと思います。

アップデートを見据えたリリース環境の設計

単純に作成したアプリをGoogle Playに公開するだけであればローカルでビルド・アーカイブを行い、Google Playに手動でアップロードすれば済みます。

しかし、リリース後にバグを発見したり、機能を追加するたびに慎重な作業を強いられるのは何かと面倒です。

ということで、リモートリポジトリから自動でビルド&リリースができる環境を構築しながら初めてのリリースを目指したいと考えました。

イメージとしてはこんな感じです。

a release diagram

では順を追って書いていきたいと思います。

Google Play デベロッパーアカウントへの登録

an image of design

AndroidアプリをGoogle Playで公開するには、「Google Play デベロッパーアカウント」に登録する必要があります。

Play Console の使用方法 - Play Console ヘルプ

Google Play デベロッパー アカウントへの登録Google Play で Android アプリを公開するには、Google Play デベロッパー アカウントを作成する必要があります

登録は、上記リンクの「ステップ1」にある「デベロッパー アカウントに登録」のリンクから行うことができます。

この作業自体は簡単です。
注意としては、$25の登録料がかかることぐらいでしょうか。
これは一度支払えばよい初期費用のようなものです。

ちなみにiPhoneアプリの場合は年間サブスクリプションで11,800円かかるそうです。
(2021/3/5 時点 Apple Developer Program)

リリースに向けたアプリの準備

an image of design

Xamarin.Formsでの開発用には一応、このような公式ドキュメントがありますので、ひと通り試してみました。
リリースに向けてアプリケーションを準備する

アプリケーション アイコンを指定する
わたしは「Prism」というXamarin.FormsをMVVMで実装するためのパッケージを使用したので、アイコンはデフォルトを置き換えるだけで済みましたが、イチから作った場合やAndroid Studioで開発した場合には設定が必要かと思います。

アプリケーションのバージョン
Android Manifest にバージョンを管理する項目があります。
ここのバージョン番号は、Google Playのリリースノートに表示されます。
デフォルトでは「1.0」となっていますが、とりあえず「1.0.0」と番号を区切ることにしました。
定義としては、大幅なリニューアルはメジャーバージョン番号、機能追加などマイナーアップデートは真ん中のマイナーバージョン番号、バグ修正などは一番右の番号をインクリメントすることとしました。

APK を圧縮する
これはですね、非常にやっかいです。
Android Studioでネイティブ開発をした方は、快適にリンカーや難読化を利用できるのでしょうか。

わたしの環境は、「Visual Studio Community 2019」です。

パッケージサイズを小さくできるならと、なんの準備もせずにリンカーを「[SDK およびユーザー アセンブリ」に設定すると、見事にリリースしたアプリは起動しませんでした。

このリンカーは、未使用と判断したコードを削除することで軽量化を行ってくれるツールのようですが、削除対象から外す設定をしっかりしておかないと、必要なコードまで削ってしまいます。

最初は「SDK アセンブリのみ」を選択しておくのがよいと思います。

これでも、リンカーをオフにするよりパッケージサイズはかなり小さくなります。

もうひとつ、Java バイトコード レベルで最適化をしてくれる「ProGuard」の説明がありますが、ドキュメント通りに設定するとビルドが通りません。

ProGuardは非推奨で「R8」を使えとなります。

で、R8を選択してリリースビルドするとあら不思議、またもやアプリは起動しません。

これも、必要なライブラリや自分のコードを設定ファイルで「keep」しておく作業が必要です。

これも、とりあえずは未選択としておきました。

※追記:2021/03/13
後日談として、APK圧縮にチャレンジし敗れ去る話をまとめています。

AndroidアプリのAPKサイズを圧縮しようと試みて敗れる話【Xamarin.Forms / Linker / R8 Shrinker】 | neputa note

『Xamarin.Formsで開発したAndroidアプリのパッケージサイズを圧縮しようと「Linker」「d8/r8」コンパイラを駆使したが、敗北する』、です。現在リリースしているバージョン1.0.

blog card

アプリケーションを保護する
仮にR8を使用したとしても、Xamarin.Forms の場合はコードの難読化はされません。
必要があれば「Dotfuscator」なるものを使えとあります。

Integrating Dotfuscator's Protection into Your Xamarin Apps in Visual Studio

こちらも試してみましたが、ビルドが通るようにするまでにかなり苦労しました。

しかし、コードの難読化はなされず……。

Root Checkは入れておきたいと思っているので、いずれまた挑戦するとして、今回は諦めることにしました。

AODコンパイルやLLVMコンパイラは、Visual Studioのエンタープライズエディションが必要なのでパスです。

パッケージング プロパティを設定する

わたしのAndroid.csprojのリリース用PropertyGroupはこんな感じになりました。

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
  <DebugType>pdbonly</DebugType>
  <Optimize>true</Optimize>
  <OutputPath>bin\Release</OutputPath>
  <DefineConstants>TRACE</DefineConstants>
  <ErrorReport>prompt</ErrorReport>
  <WarningLevel>4</WarningLevel>
  <AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
  <AndroidLinkMode>SdkOnly</AndroidLinkMode>
  <AotAssemblies>false</AotAssemblies>
  <EnableLLVM>false</EnableLLVM>
  <BundleAssemblies>false</BundleAssemblies>
  <AndroidDexTool>d8</AndroidDexTool>
  <AndroidPackageFormat>aab</AndroidPackageFormat>
  <MandroidI18n />
  <AndroidSupportedAbis>armeabi-v7a;arm64-v8a</AndroidSupportedAbis>
  <AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
  <AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
</PropertyGroup>

ターゲットアーキテクチャはインテル系はいまやモバイルではほぼ無いということで対象外としました。

ABIごとにパッケージを分けるは、APKではなくバンドルを選択したので選択の必要はありません。

Multi-Dexは64Kを超えるメソッド制限の対象となるコードがないのでチェックしていません。

App Bundleは、次期必須となることをGoogleがアナウンスしているのでapkではなくバンドルを選択しています。
Android App Bundle について

Compile

発行のためのアーカイブ
ビルドとアーカイブはApp Centerで行うのでスキップします。

Googl Play Store API の準備

とりあえず、Visual Studioで行う準備作業は完了しました。

続いて、App CenterからGoogle Playに直接リリースする導線を貼る作業です。

詳しい手順はこちらのサイトを参考にさせていただきました。

App Centerを通じてXamarin.Formsで作ったAndroidアプリをストアに公開する - shuhelohelo’s blog

docs.microsoft.com Googleデベロッパー登録する 外部ツールからのAPIアクセスを許可する App CenterからGoogle Play Storeにアプリを公開するために,G

blog card

App CenterからGoogl Play StoreのAPIを通じてアプリをリリースするには、「Google Cloud Platform」を使用します。

そして、上記ブログにある通り、初回のリリースはGoogle Play Consoleに直接アップロードしておく必要があります。

Google Play Consoleで一通りアプリの登録・公開が完了することで、App CenterからGoogle Play Consoleのアプリを検索し設定を行うことができるようになります。

Google Play Console にアプリを登録

これがハイライトと言えるボリュームのある作業となりました。
色々と準備するものが出てきます。

この作業も、先ほどと同じブログの別の記事を参考にさせていただきました。

Google Play StoreにAndroidアプリを公開する メモ - shuhelohelo’s blog

このへんはこちらの記事がとても参考になりました. kuneoresearch.com 「Google PlayにAndroidアプリを公開」を押します. 「アプリの作成」というダイアログが表示されるの

blog card

意外と面倒だったのは、アプリのスクリーンショットや1024×500指定のフィーチャーグラフィックという宣材画像を用意することですね。

高度な画像レタッチアプリは持っていないので、すべてWindows純正アプリを駆使して用意しました。

また、埋めていかなければいけない項目は、Google Play Consoleのサイドメニューにわかりやすく表示されるので、がんばってオールグリーンを目指しましょう。

Visual Studio App Center の準備

App Centerはとても簡単に利用できるWebツールです。

Visual Studio App Centerの始め方

potatotips #51 (iOS/Android開発Tips共有会)で発表した資料です。 https://potatotips.connpass.com/event/85025/

blog card

強いて言うならば、Environment variables を使った部分がやや面倒でした。
DBの接続キーなどシークレット情報をApp Centerのビルド時に差し込むように設定しました。

これも別途記事を書こうと思いますが、基本的にシークレット対象の情報は、デバッグはMobile.BuildToolsというNuGetパッケージを使用し、リリースは上述したようにApp CenterのEnvironment Variablesを使っています。

Getting Started - Mobile.BuildTools

Project docs for the Mobile.BuildTools

Environment Variablesは、値を差し込むスクリプトを「appcenter-post-clone.sh」というファイル名でAndroidプロジェクトに用意しておく必要があります。

appcenter-post-clone.sh
#!/usr/bin/env bash

echo "Environment Variables data replace"

##################################################
# variables

# (1) The target file
DirName=$BUILD_REPOSITORY_LOCALPATH
FilenameVariables="$DirName/OneThird.Core/Constants/Variables.cs"
FilenameCosmosdb="$DirName/OneThird.Infrastructure/CosmosDb/CosmosDBConstants.cs"

##################################################

echo ""
echo "######################################################################"
echo " Variables.cs"
echo "######################################################################"
echo " Working directory:" $DirName
echo "       Target file:" $FilenameVariables
echo "######################################################################"

# APP_ID_ANDROID
echo ""
echo "APP_ID_ANDROID - " $APP_ID_ANDROID
sed -i -e "s/\[APP_ID_ANDROID\]/$APP_ID_ANDROID/" $FilenameVariables

# TENANT_ID
echo ""
echo "TENANT_ID - " $TENANT_ID
sed -i -e "s/\[TENANT_ID\]/$TENANT_ID/" $FilenameVariables

# CLIENT_ID
echo ""
echo "CLIENT_ID - " $CLIENT_ID
sed -i -e "s/\[CLIENT_ID\]/$CLIENT_ID/" $FilenameVariables

# SIGN_IN_POLICY
echo ""
echo "SIGN_IN_POLICY - " $SIGN_IN_POLICY
sed -i -e "s/\[SIGN_IN_POLICY\]/$SIGN_IN_POLICY/" $FilenameVariables

# PASSWORD_RESET_POLICY
echo ""
echo "PASSWORD_RESET_POLICY - " $PASSWORD_RESET_POLICY
sed -i -e "s/\[PASSWORD_RESET_POLICY\]/$PASSWORD_RESET_POLICY/" $FilenameVariables

# AD_UNIT_ID_BANNER
echo ""
echo "AD_UNIT_ID_BANNER - " $AD_UNIT_ID_BANNER
sed -i -e "s|\[AD_UNIT_ID_BANNER\]|$AD_UNIT_ID_BANNER|" $FilenameVariables

# AD_UNIT_ID_INTERSTITIAL
echo ""
echo "AD_UNIT_ID_INTERSTITIAL - " $AD_UNIT_ID_INTERSTITIAL
sed -i -e "s|\[AD_UNIT_ID_INTERSTITIAL\]|$AD_UNIT_ID_INTERSTITIAL|" $FilenameVariables

# print out for reference
echo ""
echo "######################################################################"
echo "show result"
cat $FilenameVariables

echo ""
echo "######################################################################"
echo " CosmosDBConstants.cs"
echo "######################################################################"
echo " Working directory:" $DirName
echo "       Target file:" $FilenameCosmosdb
echo "######################################################################"

# COSMOSDB_ACCOUNT_URL
echo ""
echo "COSMOSDB_ACCOUNT_URL - " $COSMOSDB_ACCOUNT_URL
sed -i -e "s|\[COSMOSDB_ACCOUNT_URL\]|$COSMOSDB_ACCOUNT_URL|" $FilenameCosmosdb

# COSMOSDB_ACCOUNT_KEY
echo ""
echo "COSMOSDB_ACCOUNT_KEY - " $COSMOSDB_ACCOUNT_KEY
sed -i -e "s|\[COSMOSDB_ACCOUNT_KEY\]|$COSMOSDB_ACCOUNT_KEY|" $FilenameCosmosdb

# print out for reference
echo ""
echo "######################################################################"
echo "show result"
cat $FilenameCosmosdb

あとは、mainブランチを自動でビルド、リリースするように設定しておきます。
こうすると、Visual Studioで作業ブランチをmainブランチにマージしてリモートpushすると、自動でAzure DevOpsのリポジトリを経由してリリースまで行ってくれます。

まとめ

an image of a conclusion
Photo by:Ann H in Pexels

駆け足ではありましたが、リリースにおいて行った作業全体を書き出してみました。

個々の作業詳細は、それぞれ別途記事で分かりづらかったポイントなどを書きたいと思います。

1日当たりの作業時間が少ないのもありますが、なんだかんだで着手してからリリースまで半年以上の時間を要してしまいました。

ただかかった時間を将来にわたって回収できるような準備をそれなりに出来たと思います。

それは、ドメイン駆動設計、テスト駆動開発、Azure DevOps、App Centerといった素晴らしい手法やツールのおかげです。

バージョン1.0.0で2月13日にリリースをしてからこれを書いている3月4日現在では1.0.4なので、4回バグ修正や細かい追加などでアップデートを配布しています。

まだまだ改善の余地はあると思いますが、それなりの準備のおかげで修正や機能追加もコーディングに集中できるような環境となっています。

それにしてもリリースできたときは本当にうれしかった。
またGoogle Play Consoleから「公開されました」の通知が来たときは一人飛び上がって喜んでしまった。

これからアプリ開発を行う方にとって、少しでも役立つ情報がありましたら幸いです。

次回は最終回、これまで構築した環境を利用して運用保守をどんな感じで行っているかをまとめてみたいと思います。

長文にお付合いいただきありがとうございます。

はじめてスマホアプリを作ってみた 記事一覧
  1. 検討フェーズ(どんなアプリを作るか)
  2. 要件フェーズ(どんな要件のアプリにするか)
  3. 調査フェーズ(どんな技術を使うか)
  4. 設計フェーズ(どうやって作るか)
  5. 開発フェーズ(実際に作りはじめる)
  6. 公開フェーズ(アプリを公開する)
  7. 保守フェーズ(公開から現在まで)

06.はじめてスマホアプリを作ってみた(公開フェーズ)【 Android / Xamarin.Forms 】