今月のみてみて(2022年2月)

Firebase連携アプリ、みてみてエストーク伊勢125社巡り

このうち、みてみてにフォーカスを当て、Firebaseの動きやアプリの改善を考察する開発記事です。

Realtime Database+Storage構成の投稿アプリ

2022年2月1日~2月14日の変動

アプリのユーザー数の変動とともにFirebaseの動きを確認します。

(ユーザー数の変動)

微小ながらインストール数は伸びていますが、次に繋がる動きにはなっていません。

インストール、アンインストールの波を見るに小さなコミュニティで話題になったものの興味を引くことはできなかったということでしょうか。

(インストールの上位国)

インストールの上位国を見ると実際に投稿を頂けている国が上位になっています。

ただ、今のところ、ロシア、フランスからの投稿はありません。

アプリが日本語、英語のみに対応している影響かもしれないと思うと多言語化するか悩みどころです。

(Firebaseの変動)

100人を超えない程度のユーザー数なのでRealtime DatabaseはKB単位での変動となっています。

また、Storageにおいても投稿数が伸びないこともあり、10MBに届かない範囲での変更です。

まだまだ無料プランで維持できる状況となっています。

(今週の投稿ピックアップ)

フィリピンから空港の模様を投稿してもらえました。人がいないのはコロナの影響でしょうか?
投稿ありがとうございます。

(今後の改善案)

ユーザー数の減少を回避するための改善として以下の2点を強化予定。

・最近追加したコメント機能の強化。

・ユーザー間のコミュニケーション機能の追加。

まずは上記2点の改善を追加し、動きを見たいと思います。

,

的山登頂

執筆:2022年2月5日

昨年の年末、自宅にて階段を踏み外した際に右足の筋を伸ばしたようで歩くと痺れがでるように。
それがようやく治ってきたのでリハビリをかねて今年初の伊勢神宮参拝に行ってまいりました。
今年初めて参拝する伊勢神宮は鴨神社です。
前回の参拝時は的山山頂にある的山公園を訪れ、山頂からの展望を見ることができず心残りでした。
そこで今年の初参拝とし、鴨神社参拝と的山公園訪問を目指すことにしたのです。
コンクリートの坂道を登り、まずは鴨神社を参拝。
参拝を終え、少し道を引き返し、分岐路を的山公園に。
これが思った以上に山頂は遠く、少し後悔しましたがなんとか登頂。
山頂からの見晴らしはとても素敵でした。

日付のソートが失敗していた話

概要

型変換の認識不足により日付のソートに失敗しておりました。

Long型とInt型、型変換する際は気を付けねば、という話です。

2022年の投稿がソートで正しく表示されないバグ

投稿アプリ「みてみて」には全ての投稿をリスト表示する画面があります。

このリストでは新着順、いいね順、距離順の3パターンでソートできるようにしているのですが。。。

2022年の最新の投稿を新着順でソートした際に先頭に表示されないバグが発覚。

ロジックを見直しても一見、おかしなところも見当たらず。

そこでソートロジックを切り取り、テストアプリを作成してログを確認。

ようやく理由が判明した、というわけです。

日付をソートするテストアプリで動作確認

まずは適当に日付をセットしたリストを用意し、表示するだけのアプリを作成。

これにソート用のボタンを追加し、ボタンをタップするとソートしてリスト表示を反映させるロジックを追加。

        val btnUp = findViewById<Button>(R.id.btnUp)
        btnUp.setOnClickListener {
            Collections.sort(list, object : Comparator<List>{
                override fun compare(p0: List?, p1: List?): Int {
                    val tmpdiff = p1!!.timestamp - p0!!.timestamp
                    return tmpdiff.toInt()
                }
            })
            adapter.setList(list)
            adapter.notifyDataSetChanged()
        }

上記はアプリに組み込んだロジックを切り取ったものですが間違いに気づきましたでしょうか?

日付はLong型(1970年1月1日00:00を起点とした経過時間)で扱っています。

ソートはCollections.sortのcompareメソッドを使用。

compareは大小比較さえできればよいだろうということでLong型の差分をリターンすればよいと判断。

ただし、それだとInt型で受けれないのでLong型からInt型に型変換を追加。

そして、このロジックでソートした結果が以下となります。

ソートされていません。

ここでログを仕込み、引数1、引数2、引数2と引数1の差分(Long型)、差分の型変換(Int型)の順で出力してみると。

Long型では負なのに、Int型では正になっていることが発覚。

Long型は8バイト、Int型は4バイト。

上記で1例を見るとLong型の値、-2678400000は16進数で0xFFFF FFFF 605A DC00。

これをInt型に変換すると先頭4バイトが落ち、16進数で0x605A DC00。

つまり、1616567296。正の値になりました。

Int型への型変換で4バイトの情報だけを参照した結果、正の領域が負の領域に切り替わってしまったというわけです。

正しいロジックとは

修正するとすれば2パターンでしょうか。

パターン1)Date型に変換し比較する。

        val btnUp = findViewById<Button>(R.id.btnUp)
        btnUp.setOnClickListener {
            Collections.sort(list, object : Comparator<List>{
                override fun compare(p0: List?, p1: List?): Int {
                    val datea = Date(p0!!.timestamp)
                    val dateb = Date(p1!!.timestamp)
                    return dateb.compareTo(datea)
                }
            })
            adapter.setDateList(list)
            adapter.notifyDataSetChanged()
        }

パターン2)Long型の差分結果をもとにInt型で正負に置き換える

        val btnUp = findViewById<Button>(R.id.btnUp)
        btnUp.setOnClickListener {
            Collections.sort(list, object : Comparator<List>{
                override fun compare(p0: List?, p1: List?): Int {
                    val tmpdiff = p1!!.timestamp - p0!!.timestamp
                    var rtnval = 0
                    if (tmpdiff < 0L) {
                        rtnval = -1
                    } else if (tmpdiff == 0L){
                        rtnval = 0
                    } else {
                        rtnval = 1
                    }
                    return rtnval
                }
            })
            adapter.setDateList(list)
            adapter.notifyDataSetChanged()
        }

どちらのロジックにしろ、正しくソートされました。

早速、修正したいと思います。

APIキー定義をプロジェクト外部で管理する

概要

少し前にandroidアプリをリリースしようとしたところ、

Google Play Consoleで警告を出されたので記事にしておきます。

APIキーの定義は慎重に

アプリに外部サービス(YouTubeやGoogle Mapなど)を組み込む場合、必ずAPIキーが必要になると思います。

APIキー(文字列)をどのように管理しますか?

私はstring.xmlに定義していました。

この管理方法に対し警告が出されたわけです。

外部サービスは基本的に従量課金制です。

一定量まで無料、それ以上はサービス使用量に応じて課金されます。

外部サービスにアクセスする際に使用されるAPIキーは言わばユーザーアカウント。

APIキーに紐づくユーザーにサービス使用量が加算されるわけです。

そのAPIキーをstring.xmlに定義するとどうなるか?

簡単なアプリ解析でバレてしまうようです。。。

APIキーが漏洩してしまうとそれを悪用してサービスのタダ乗りをされてしまうよ!

ということで警告を出されたのでした。

うかつでした。。。

APIキーを隠匿する2つの方法

APIキーをどのように管理すればいいのか。

APIキーをプロジェクト外部に定義し、プロジェクト起動時にメモリ(変数)に保持させるのがいいようです。

そして、その方法は2つ。

環境変数に定義する方法と外部ファイルに定義方法です。

外部管理方法その1.環境変数に定義する

(1)まずは環境変数にAPIキーをセットします。

コマンドライン操作を使った環境変数の設定方法はこちらを参照してください。

(2)次にbuild.gradle(app)に環境変数の参照処理を定義します。

    defaultConfig {
        minSdk 24
        targetSdk 31
        versionCode 1
        versionName "1.0"

        manifestPlaceholders = [KEY_VALUE: System.getenv("api_key")]
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

上記は環境変数”api_key”の値を変数”KEY_VALUE”に格納しています。

(3)次にAndroidManifest.xmlの定義です。

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"

        <meta-data
            android:name="API_KEY"
            android:value="${KEY_VALUE}" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

プロジェクト内で参照できるようメタデータに格納します。

(4)あとは参照するだけです。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val appInfo = getPackageManager().getApplicationInfo(packageName, PackageManager.GET_META_DATA)
        val apiKey = appInfo.metaData.getString("API_KEY")

        val txtSet = findViewById<TextView>(R.id.txtSet)
        txtSet.setText(apiKey)
    }
}

上記では取得した環境変数をテキストに表示させています。

外部管理方法その2.外部ファイルに定義する

(1)まずは定義ファイルを作成します。

ファイル名に任意ですがファイルの格納場所は以下です。

debugとreleaseの2か所に格納します。ファイルは全く同じもので問題ありません。

赤枠の場所にファイルを格納します。

ファイルの格納パス

C:\~\AndroidStudioProjects\プロジェクト名\app\src\release\res\values\

C:\ ~ \AndroidStudioProjects\ プロジェクト名 \app\src\debug\res\values\

定義ファイル

<resources>
    <string name="api_key" templateMergeStrategy="preserve" translatable="false">APIキー</string>
</resources>

上記の”APIキー”の箇所に実際のAPIキーを定義します。

(2) 次にAndroidManifest.xmlの定義です。

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"

        <meta-data
            android:name="API_KEY"
            android:value="@string/api_key" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

プロジェクト内で参照できるようメタデータに格納します。

(3)あとは参照するだけです。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val appInfo = getPackageManager().getApplicationInfo(packageName, PackageManager.GET_META_DATA)
        val apiKey = appInfo.metaData.getString("API_KEY")

        val txtSet = findViewById<TextView>(R.id.txtSet)
        txtSet.setText(apiKey)
    }
}

以上がAPIキーの外部管理方法です。

APIキーのstring.xml定義はくれぐれもご注意ください。

,

バッチファイルを使う

概要

バッチファイルの役割からWindows環境でのバッチファイルの使い方までをまとめました。

コマンドライン操作

基本的にWindowsで何か作業をする場合、

例えばフォルダを作る、ファイルをコピーする、環境変数を設定する、など。

マウスを使い、アイコンをクリック、メニューを表示して、とGUI操作で作業すると思います。

しかし、パソコンを操作する手段はもう1つ用意されています。

それがコマンドライン操作です。

ますはコマンドプロンプトを起動。
(Winキー+Rで「ファイル名を指定して実行」を表示、”cmd” と入力で起動します。)

コマンドプロンプトにコマンドを入力するとGUI操作と同様のことが行えます。

例えばフォルダを作る。

コマンドプロンプトに”mkdir work”と入力します。

そうすると”work”という名前のフォルダが作成されます。

以下は一般的なコマンド一覧です。

Noコマンド処理内容
dirフォルダに格納されたファイルリスト表示
mkdirフォルダ作成
cd フォルダ移動
renファイル名変更
delファイル削除
copyファイルコピー
7typeファイルのテキスト表示
8set環境変数設定
9d:Dドライブに移動
10exitコマンドプロンプト終了

バッチファイルの役割

コマンド入力で操作をしていると繰り返し同じコマンドの流れを入力するときがあると思います。

そのようなときに活躍するのがバッチファイルです。

実行したいコマンドの流れをテキストファイルに書き出して拡張子を.batとして保存。

コマンドラインに保存したバッチファイルのファイル名を入力。

するとテキストファイルに書き出したコマンドが順次実行されます。

バッチファイルの実行はファイルのアイコンをダブルクリックするだけでもOKです。

それならコマンドを知らない人でも容易にコマンドライン操作が実行できるわけです。

バッチファイルを作成することはコマンド入力の簡素化や誰でもコマンドライン操作ができるようになるというメリットがあります。

例えばプログラムの開発環境を作成するために環境変数を設定する。

そのようなときはバッチファイルを作成し、、グループで共有すれば共通の環境を作成することができます。

バッチファイルの中身

環境変数を設定する場合、バッチファイルの記載内容は以下です。

set WORK=testvalue

上記では変数名”WORK”に”testvalue”を設定しています。

また、Windows10の場合はsetxコマンドを使います。

setx WORK testvalue

環境変数にはユーザー環境変数とシステム環境変数がありますが上記はユーザー環境変数に設定するコマンドです。

また、コマンド実行後はパソコンを再起動しないと反映されません。

,

今週のFirebase

2022年1月11日~1月17日のFirebase使用状況

さて、今週のFirebaseの使用状況はどうだったでしょうか?

アプリのユーザー数の変動とともに確認します。

みてみて

Realtime Database+Storage構成の投稿アプリ

(ユーザー数の変動)

興味本位でインストールして頂けているようですが定着せず。

まずはUIの改善を早めにいれたいところです。

(Firebaseの変動)

インストールに伴うユニークID登録の影響でRealtime Databaseが微増。

投稿に伴うStorageの変動は確認できず。

エストーク

Realtime Database単体構成のチャットアプリ

(ユーザー数の変動)

こちらもみてみて同様、インストールされているものの定着せず。

(Firebaseの変動)

インストールに伴うユニークID登録の影響でストレージが微増。

オンラインチャットが使われだすとDLサイズももっと伸びてくると思うのですが

まだその影響を見ることはなさそうです。

,

androidアプリを初めて作るなら【書籍紹介】

初めてのandroidアプリ開発

androidアプリを開発するには何が必要でしょうか?

アプリ開発用のパソコン、ネット環境、スマートフォン(android)。

以上です。

あとは統合開発環境 android studio をインストールしてアプリを制作。

スマートフォンで動作確認。

最後にGoogle PlayにリリースでOK!

1度でもアプリ開発を経験するとそんなものだと分かるんですが3年前の私は違いました。

アプリ開発用のPCを買った。ネットは使える。

あとandroidアプリを作るには何が必要なんだろうか。。。

そんなときに買った本がこちらです。

統合開発環境 android studio のインストール方法から 基本的な使い方、そして、簡単なアプリ制作の例までし っかりガイドしてくれています。

「1日で基本が身に付く!」 のうたい文句通り、ざっくり理解するのであれば 1日で充分なわかりやすさでした。

androidアプリを開発するには何をすべきか悩んだ人におすすめの1冊です。

改訂版もリリースされているようです。

アプリ制作で使っているおすすめソフトウェア

より快適にアプリ開発をするためのソフトウェア

プログラミングをするなら、それぞれの言語に合わせて統合開発環境が用意されていると思います。

例えば、android開発ならandroid studioです。

統合開発環境を使ってプログラミングをするとリリースまでの作業は大抵できてしまいます。

それでも、統合開発環境だけでは賄えきれないものもあるのではないでしょうか?

今回は私がアプリ開発時に実際に使っているソフトウェアを紹介したいと思います。

ソースコードの編集をもっと自由に。

プログラミングする。と言えば、ソースコードを書き連ねる作業になると思います。

そうなるとやはり大事になってくるのが文字列編集。

変数名やメソッドの変更、移植など文字列を扱う作業も多いと思います。

そのようなときには私はテキストエディタ―を使って作業しています。

無料ソフトだと サクラエディタ

有料ソフトだと 秀丸 がおすすめです。

プログラム前後の差分を抽出する。

プログラミングをするうえで気を付けたいのがデグレード。

前にできていたことが知らない間にできなくなっている。

考えただけで怖いですよね。

それを防ぐ手立てとしてはプログラム修正前後のソースファイルの差分をチェックしています。

差分をチェックすることで想定外や間違った修正に気付くことができます。

そのためのソフトウェアが差分ソフトです。

無料ソフトだと DF や WinMerge

有料ソフトだと Araxix merge がおすすめです。

ソフトウェアを自由自在に呼び出す。

使用するソフトウェアが多くなってくるとソフトウェアを立ち上げるのにも一苦労です。

それを解決するのがランチャーソフトです。

私は CLaunch 一択です。

アプリ開発時に使用しているソフトウェアを3つ紹介してみました。

よかったらお試しください。

スマートフォンアプリを作るときに決めるべき大事なこと

概要

統合開発環境(SDK)を用意し、スマートフォンアプリを作る。

そのアプリ、世の中全てのスマートフォンで使えるとは限りません。

なぜならスマートフォンのなかで動くOSによってアプリ開発に必要となる統合開発環境が異なるからです。

まずはアプリのターゲットユーザーを絞り、それに適した統合開発環境を用意する必要があります。

スマートフォンOSの2大勢力、androidとiOS。

スマートフォンOSの2大勢力をご存じでしょうか?

そうです、Googleが開発したandroidとAppleが開発したiOSです。

それぞれのOSでアプリを動かすには、OSに合わせてアプリを作る必要があります。

androidの場合、開発言語は、java、または、kotlin。

作成したアプリは、 Google Play にリリースします。

iOSの場合、開発言語は、Objective-C、または、Swift。

作成したアプリは、 App Store にリリースします。

いずれにしろ、オブジェクト指向言語で開発することになります。

ですが、開発言語それぞれでプログラム構文が異なり、必要な開発環境も異なってきます。

つまり、アプリを作るなら、どちらのOSにアプリをリリースするのか。

ターゲットを絞ってアプリを作る必要があるわけです。

(どちらにもリリースできるよう言語変換できる有料の開発環境サービスもあります。)

(また1つのプログラムからandroid向けとiOS向け、それぞれのアプリを作ることができる無料の統合開発環境FlutterがGoogleによってリリースされています。)

androidとiOSの違いを理解し、どちらでアプリをリリースするか悩む必要があります。

アプリをリリースするのに必要な費用

androidでアプリをリリースするにはGoogle Playに開発者情報を登録する必要があります。

登録手数料は25$です。

1度登録すると以後、数に限りなくアプリをリリースすることができます。

それに対し、iOSでアプリをリリースするにはApp Storeに開発者情報を登録する必要があります。

登録手数料は年会費99$です。

つまり、iOSでアプリを継続してリリースするには固定費が必要ということになります。

その点でiOS向けにアプリを作る場合、開発者の負担が大きいといえます。

androidとiOSのシェア争い

次に考えるべきはユーザー数でしょう。

せっかくアプリをリリースするならできるだけ多くのユーザーに使って欲しいもの。

androidとiOS、どちらのユーザー数が多いでしょうか?

2021年の調査によると日本においては約50%どうしでシェアを分け合っているようです。

また、世界に目を向けた場合は、androidが約70%となり、android優勢となっているようです。

スマートフォンアプリを作るときはまず統合開発環境を選定すべき

開発言語、開発費用、ユーザー数を考慮した上でandroid、iOSどちらに向けたアプリを作るか決めるのがいいのではないでしょうか?

android向け統合開発環境 android studio のインストール

iOS向け統合開発環境 Xcode のインストール

ちなみに私の場合は海外にもリリースすることを前提にユーザー数がより多いandroidで開発することにしました。

開発アプリはこちら

また、iOSユーザーに対するフォローとし、現時点ではwebでサービスを提供しようと考えています。

年末外宮参拝

執筆:2021年12月28日

本日を含め2021年も残すところあと4日となりました。
みなさま、いかがお過ごしでしょうか?
なにかと忙しい時期ではありますが豊受大神宮(外宮)を参拝してまいりました。
今年は伊勢神宮125社を巡り、伊勢神宮をより身近に感じた年となりました。
参拝の道中、外宮参道を通りましたがにぎわいを感じられ、コロナ禍の落ち着きを感じた次第です。
来年はコロナ禍が収まり、外出を楽しめる年になって欲しいと思います。
来年もYouTubeに、四季だよりにとアプリを更新していきたいと思いますので今後ともよろしくお願い致します。
それでは、みなさま、よいお年をお迎えください。