2023年10月4日水曜日

Android gradleのキャッシュを削除するコマンドを紹介

どうも。どっことです。今回は、毎回忘れるGradleのキャッシュ削除のコマンドを備忘録として紹介します。

gradleのキャッシュを削除するコマンド

早速ですが、コマンドを載せます。

rm -rf ~/.gradle/cashes

~/となっていることを見ても分かる通り、削除するディレクトリはアプリプロジェクトにあるディレクトリではなくユーザディレクトリにあるキャッシュのディレクトリになります。これを実行すると、次回ビルドは非常に時間がかかるのが見込まれますので、「PCやプロジェクトがおかしいな?」と思った時にやるのがちょうどいいと思います。

ちなみに .gradle フォルダを削除しても、Gradle がビルドする時に再構築してくれるらしいので気にすることは全くありません。

独り言

ただ、最近AndroidStudioのビルドが全く通らない。

C:\Users\XXXXX\Documents\project\sampleProject\app\build\intermediates\incremental\packageDebug\tmp\debug\zip-cache\androidResources (アクセスが拒否されました。)

いったいなんだってばよ。

追記。なんか解決した。新規に記事にした。

2023年9月1日金曜日

Python HTTP通信で情報取得

どうも。どっことです。通信取得する処理について紹介します。今回はPythonでサーバ通信・情報取得する処理です。

説明

さっそくサンプルを載せます。pythonをインストールできていれば、以下でOKです。

import sys
import json 
import urllib.request

# 取得したい情報のURL
url = "取得したい情報のURL"
header = {
  # 例えば header に仕込む key-value
  'key': 'value', 
  # 例えば header に仕込む 認証情報
  'Authorization': 'Bearer <YOUR TOKEN>'
}
req = urllib.request.Request(url, headers = header)

with urllib.request.urlopen(req) as res:
    body = json.load(res)
    print(body)

Android/iOSといったネイティブアプリのように、非同期処理などのことを考えなくていいので、とても簡単ですね(逆に不安になる)。巷ではrequestsといった、通信処理を簡単に実装できるようなライブラリはごまんとあるようですが、今回は「可能な限り簡単に使えるスクリプト」を意識したいので、標準のurllibを使いました。

参考

2023年8月10日木曜日

Android 通知チャンネルの設定画面を表示する実装方法について解説

どうも。どっことです。今回は、通知チャンネルの設定画面を表示するための実装方法について解説します。

通知チャンネルの設定画面を表示する

Android O から追加された通知チャンネルですが、アプリからは追加・削除以外は通知チャンネルの設定値を修正・変更することができません。その代わりに端末の設定画面に遷移させるための導線を具備することで、ユーザに通知チャンネルまで簡単にアクセスできるようにしてあげましょう。

実装方法

アプリが追加したチャンネルの設定画面に遷移する方法は以下となります。

val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
intent.putExtra(Settings.EXTRA_CHANNEL_ID, channelId)
startActivity(intent)

通常のstartActivityと同様に、必要なActionやパラメーターを設定することで通知チャンネルの設定画面に遷移することができます。

まとめ

今回は、通知チャンネルの設定画面を表示するための実装方法について解説しました。このブログでは、アプリで通知を表示するために必要な実装として他にも投稿しているので、もしよろしければそちらも参考にしていただけると幸いです。

参考

2023年8月9日水曜日

Android AndroidPでhttp通信に失敗する問題

targetSDKVersionをAndroidP以上に設定すると、セキュリティの問題でアプリでのhttp通信が失敗する。AndroidManifest.xml のapplicationタグに以下の属性を追加する。

<application
    ....
    android:usesCleartextTraffic="true">
</application>

開発段階ではローカル環境にサーバ立ててそこにスタブデータを置いて動作確認することが多いが、本番環境では回避すべき設定なので、debug/releaseでAndroidManifest.xmlを分けるなど、きちんと切り分けること。

2023年8月8日火曜日

HTML/CSS マウスオーバーしたときの表示をカスタマイズする

マウスオーバーしたときに表示を切り替えたいときは、CSSに疑似クラスを指定する。

a:hover {
  マウスオーバー中に表示したい内容
}

この指定を複数の要素に指定することで、例えばテキストやイメージの表示切替などもできる。

a:hover {
  マウスオーバー中に表示したい内容
}
.a-covered:hover {
  マウスオーバー中に表示したい内容
}

マウスオーバー以外にも疑似クラスの指定により表示を変えられるものは以下。

  • link:御訪問リンク
  • visited:訪問済みリンク
  • hover : マウスオーバー
  • active : リンククリック中

参考

2023年8月7日月曜日

Android Parcelableを実装する方法を解説

どうも。どっことです。今回はParcelableの実装方法について解説します。

Parcelableを実装する

ActivityFragmentなどの画面間におけるデータ受け渡しはアプリ全体の動きを考える上でなくてはならない処理ですが、自前で用意したデータクラスはそのままだとBundleに乗せることができません。

それではどうするかというと、そのデータクラスにParcelableSerializableを実装します。取り出すときにキャストが必要にはなるが、これでBundleに乗せることができるようになり画面間のデータ受け渡しができるようになります。

今回はその呪文の如きParcelableのインターフェース群の実装について、説明します。

実装

必要な実装ですが、データクラスに以下のクラス・メソッドを実装します。

  • Parcelableを実装する
  • describeContentsを実装する
  • 引数がParcelのコンストラクタを実装する
  • writeToParcel()を実装する
  • CREATOR : Parcelable.Creatorを実装する

サンプルとしてItemクラスにParcelableを実装する場合は以下となります。

data class Item(
    var title: String,
    var description: String,
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString()!!,
        parcel.readString()!!
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(title)
        parcel.writeString(description)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Item> {
        override fun createFromParcel(parcel: Parcel): Item {
            return Item(parcel)
        }

        override fun newArray(size: Int): Array<Item?> {
            return arrayOfNulls(size)
        }
    }
}

あとは実装したデータクラスのオブジェクトをBundle#putParcelable()Bundleに詰め

val bundle = Bundle().apply {
    putSerializable("適当なキー", item)
}

Bundle#getParcelable()Bundleから取り出すことで

val item = bundle.getParcelable("適当なキー", Item::class.java)

画面間でデータクラスをやり取りすることができます。

ここまで書いててですが…

Percelableをいい感じに実装してくれるアノテーションがあると公式サイトが謳っていました。

Parcelable 実装生成ツール

アノテーション付けるだけで上記の面倒臭い実装をしなくてよくなるなんて、なんて素晴らしいんだ!!ありがとうGoogle様!!!

まとめ

今回はParcelableの実装方法について解説しました。ボイラープレートなParcelableの実装ですが、すでに自動生成してくれるツールがあるので、そちらを使う方が無難でしょう。今回の紹介した内容がほぼ無用なものになってしまいますが、必要なものが簡単に実装できることの方が重要だと思うので、まあ仕方ないでしょう笑

2023年8月3日木曜日

iOS TextFieldのキーボードを閉じる実装方法を解説

どうも。どっことです。今回はiOSでのキーボードを閉じる実装について解説します。

解説

iOSではアプリからキーボードを閉じるのは非常に簡単で、UITextField#endEditing(true)を呼び出すだけでOKです。

@IBOutlet weak var textField: UITextField!

func closeKeyboard() {
    // キーボードを閉じる
    textField.endEditing(true)
}

AndroidではInputManagerにアクセスしたり必要な情報を渡したりで面倒臭いのに、iOSはとにかくシンプルで羨ましいですね。

参考

2023年8月1日火曜日

CI/CD Bitriseでaabを生成する

前回の続きです。今回はリリースファイルを作るための各種設定を備忘録として記載したいと思います。

リリースファイル(aab)を生成するための設定

とはいえ、基本は以下の手順通りに設定すればOK。日本語ページはなかなか残念なことになっているので、英語ページをベースに作業したほうが結果的にストレスが少なくて済む。

Generating and deploying Android app bundles

ただし、少しだけハマりポイントがあるので注意が必要。ハマったポイントは以下。

gradlewのパス

唯一納得いかなかったハマりポイント。gradlewのパスがデフォルトのままだとビルドが通らない。

上記ページの手順で追加した「Gradle Runner」のステップ内にあるInput variables>gradlew file pathの項目に以下を設定する。

./gradlew

最小構成のプロジェクトなら、これだけ手直しすればビルドが通ってaabができるはず。

(追記)最新の設定だと、「Gradle Runner」を追加せずともaabファイルを生成できる模様...何のために試行錯誤したのか。。。

google-services.jsonの準備

google-services.jsonはFirebaseの機能を使うためにアプリに組み込む設定ファイル。秘匿情報が含まれるため、原則Gitには登録しない。しかし、Gitに登録しないとBitriseでビルドする時にこの設定ファイルが無いせいでビルドに失敗する。

この矛盾を解消するために、Bitriseに用意されているテキスト生成のステップを利用する。ざっくり書くと、以下。

  1. ファイルの中身をまるっとコピーする。
  2. コピーしたテキストをBitriseの定数として保存。
    • 定数の名前は適当でOK。例えば直感的にGOOGLE_SERVICES_JSONとか。
  3. テキストファイル生成のステップ(Generate Text File)を追加。
    • 定数として定義したテキストを使って、google-services.jsonファイルとして生成する。

「テキストファイルを生成する」ステップが用意されているのが、直感的で非常にわかりやすい。

センシティブな情報の設定

おそらくAndroidアプリ開発者ならほとんどの人がハマるポイント。build.gradleBuildConfigFieldを定義する際、ダブルクォーテーションを定義に含めないと、生成されるBuildConfigでいい感じに定義できない問題。これがBitriseでも(というより環境変数として定義する場合でも)同様に発生する。

何も考えないならbuild.gradle内で

buildConfigField "String", "AD_UNIT_ID", "\"広告ID\""

って形で定義すれば問題ない。

しかし、これを(センシティブな情報だから、外部に設定+それを参照するような形とするために)環境変数などに設定しそれを参照する形で

buildConfigField "String", "AD_UNIT_ID", System.getEnv(定義したキー)

って書くと残念ながらビルドに失敗する。設定値側(環境変数)にダブルクォーテーションを含めて定義するか、参照時に文字テンプレートを使うことで解消できる。

AndroidManifest.xmlも参照する必要が出てくるはずなので、文字テンプレートを使った方が無難。つまり以下。

buildConfigField "String", "AD_UNIT_ID", "${System.getEnv(定義したキー)}"

参考

2023年7月31日月曜日

CI/CD 各種サービスを比較し使うものを選定する

この前の続き。CI/CD環境の構築に向けて、良さそうなサービスを探す。

CI/CDと聞いて真っ先に思いつくのはJenkinsだが、オンデマンドに構築できるほど私のプライベート環境は充実していないので却下。外部サービスで検討する。

調査・知っている範囲で、以下のサービスをピックアップした。

  • Github Action
  • Circle CI
  • TravisCI
  • Bitrise

で、結論としてBitriseで進めることにした。

理由としては

  • Bitriseはモバイルアプリ(特にAndroid)のインテグレーション(単体テストなど)、デプロイ(apkやaabの生成、GooglePlayStoreへのアップロード)が初期状態でほぼ構築済み。ユーザーは必要なパラメーターを入力するだけでほぼ実現できる。

Bitrise以外のサービスについては

  • GitHubActionはリポジトリをpublicにしたいという要件を満たせない。署名キーや広告IDは秘匿にできるにせよ、それにより生成されたバイナリが表に丸見えになりうる。やり方次第かもだが、バイナリを生成するワークフローを表に見せたくない…。
  • CircleCIはfastlaneの導入が必要になる。iOSアプリ開発者だと、コマンド一つでipaを生成するために導入したりなど比較的馴染みのあるツールだが、AndroidでCI/CDするためだけにわざわざ導入したいと思わない。
  • 残るTravisCIがBitriseの対抗馬となったが、導入の容易さから結果としてBitriseに軍配があがることとなった。

ただし注意事項として、Bitriseは1アカウントにつき処理できるジョブやタスクの回数?リソースの使用量?に制限がある。無料アカウントでは、毎月「300クレジット」という単位でサービスを利用できるが、これを越えると次のクレジット支給まで使えなくなる様子。
正直どんなもん?というところだが、(構築後日談として)1回のワークフロー(ビルドをするためのセットアップからビルド完了までの一連の流れ)を処理するのに大体10クレジット程度を消費しているため、30日間ではおよそ30回しか利用できない、ということになる。
とはいえ「プライベートで回している開発フローで、複数のプロジェクトを加味する必要があるとはいえ1ヶ月に30回もリリースビルド→デプロイすることあるか…?」と考えると、これが制限となってしまうことは稀になりそうだ。

というわけで今回はCI/CD環境を構築するためのサービスの選定とその理由について投稿した。次回はBitriseを利用したAndroidアプリのデプロイ環境の構築について投稿予定だ。

2023年7月30日日曜日

正規表現 文字列の一部だけを加工したい

Logcatとかコンソールでログとか漁ってるときに、「必要なところを探して、必要な所だけくり抜くのマジだるい…」ってなる。

正規表現を使えば簡単なんだけど、「必要な所だけくり抜く」表現がわからなかったので放置してた。でもいい加減(ちゃんと書ければ秒で済む話を何時間もかけて作業してるの、マジ無能…と思い)なんとかしたかったので、調べて備忘録として残す。

知ってしまえば本当に簡単なんだわ。

検索での表現

(検索したいけど置換したくない文字)なにかしら置換したい文字(検索したいけど置換したくない文字)

置換の表現

$1置換後の文字$2

ポイントは

  • 「くり抜くところ」を括弧書き()にすると、置換するときに$*(数字)て書けば検索したときに括弧書きに該当するところがそのまま残る。ちなみに、カッコはグループ化する表現らしい。
  • そのまま残したいところが複数ある場合でも、$に付ける数字を増やしていけばOK。

<div>タグを<p>タグに変えたい。"/"も気にせず置換したい。

検索での表現

<(/*)div>
  • 検索対象のdivを指定する。
  • /があるかないかは、置換後のテキストにも影響するので、()で書く。
  • *は0文字以上の意味。

置換での表現

<$1p>

  • 置換したい文字としてpタグを指定する。
  • ()で書いた箇所が$1として置換後のテキストに反映される。
  • 今回は、/があった場合に限り置換後に/が入るようにする。

参考

移行予定

どうも。どっことです。 タイトルの通りですが、諸事情により GitHubPage に移行予定です。 https://mkt120.github.io/ この備忘録に記載の内容を転記しつつ、今後はこちらのページを更新していく予定です。