Dimによる変数宣言と、値の設定は一行で書ける。
Dim numberValue As Integer: numberValue = 30000
Dim text As String: text = "sample text"
Dimによる変数宣言と、値の設定は一行で書ける。
Dim numberValue As Integer: numberValue = 30000
Dim text As String: text = "sample text"
どうも。どっことです。今回は複数のキーをPRIMARY KEYに設定するSQLを紹介します。
まず、前提として主キーが1つだけの場合です。
テーブルを生成する際、1つのキーだけを主キーに設定する場合は以下のようになります。
create table user(id int primary key, name text);
しかし複数のキーを主キーに設定する場合、上記と同じような形にするとエラーが発生します。
複数のキーを設定する場合は、最後の方にPRIMARY KEY
節を追加します。例えばid
,subId
を主キーに設定する場合は以下となります。
create table user(id int, subId int, value text, ..., PRIMARY KEY(id, subId));
今回は簡単ですが以上です。
どうも。どっことです。今回はiOSでのキーボードを閉じる実装について解説します。
iOSではアプリからキーボードを閉じるのは非常に簡単で、UITextField#endEditing(true)
を呼び出すだけでOKです。
@IBOutlet weak var textField: UITextField!
func closeKeyboard() {
// キーボードを閉じる
textField.endEditing(true)
}
AndroidではInputManager
にアクセスしたり必要な情報を渡したりで面倒臭いのに、iOSはとにかくシンプルで羨ましいですね。
どうも。どっことです。今回はKoinの使い方について解説します。
Koinってなんだよ、というあなたはこちらを見てくださると大変嬉しいです。ちなみに、Daggerというライブラリを使ってDIを実現するパターンもありましたが、実装難易度の観点から今回はKoinを使う方針としました。
それでは実装方法について解説します。
まずはライブラリを組み込む必要があるのでapp/build.gradle.kt
のdependencies
に以下を記述します。
dependencies {
// 他にもあるけど説明のためこれだけ。
implementation("io.insert-koin:koin-android:3.4.2")
}
続いて、Application
クラスに必要な処理を追加していきます。Application
ってどうすんだっけ、というあなたはこちらを見てくださると大変嬉しいです。
module
インスタンスを作ってstartKoin
を実行します。module
インスタンスには
DIするインターフェースとそれの実装クラスを登録します。以下はSampleRepositoryImpl(dao: Dao)
をDIするサンプルです。
private val appModule = module {
single<SampleRepository> { SampleRepositoryImpl(get()) }
}
protected open val dao = module {
single {
Room.databaseBuilder(
applicationContext,
Database::class.java,
DATABASE_NAME
).build().dao()
}
}
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@SampleApplication)
modules(appModule, dao)
}
}
メモ:single
で登録しておくと、シングルトンパターンでオブジェクトを管理してくれる。
あとはDIしたい箇所で、by inject()
を使ってインジェクトすると、簡単にアクセスすることができます。
private val repository : SampleRepository by inject()
今回はDIをシンプルにアプリに導入できるライブラリであるKoinの使い方を解説しました。昨今のプログラムのレガシー化やCI/CDに向けたモジュールの疎結合を意識する上でDIは必要不可欠な機能の一つです。DIを実現するものは今回のKoin以外にもさまざまなものがありますので、比較・検討した上で導入しましょう。
前回の続きです。今回はリリースファイルを作るための各種設定を備忘録として記載したいと思います。
とはいえ、基本は以下の手順通りに設定すれば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に用意されているテキスト生成のステップを利用する。ざっくり書くと、以下。
GOOGLE_SERVICES_JSON
とか。
google-services.json
ファイルとして生成する。
「テキストファイルを生成する」ステップが用意されているのが、直感的で非常にわかりやすい。
おそらくAndroidアプリ開発者ならほとんどの人がハマるポイント。build.gradle
でBuildConfigField
を定義する際、ダブルクォーテーションを定義に含めないと、生成される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(定義したキー)}"
この前の続き。CI/CD環境の構築に向けて、良さそうなサービスを探す。
CI/CDと聞いて真っ先に思いつくのはJenkinsだが、オンデマンドに構築できるほど私のプライベート環境は充実していないので却下。外部サービスで検討する。
調査・知っている範囲で、以下のサービスをピックアップした。
で、結論としてBitriseで進めることにした。
理由としては
Bitrise以外のサービスについては
ただし注意事項として、Bitriseは1アカウントにつき処理できるジョブやタスクの回数?リソースの使用量?に制限がある。無料アカウントでは、毎月「300クレジット」という単位でサービスを利用できるが、これを越えると次のクレジット支給まで使えなくなる様子。
正直どんなもん?というところだが、(構築後日談として)1回のワークフロー(ビルドをするためのセットアップからビルド完了までの一連の流れ)を処理するのに大体10クレジット程度を消費しているため、30日間ではおよそ30回しか利用できない、ということになる。
とはいえ「プライベートで回している開発フローで、複数のプロジェクトを加味する必要があるとはいえ1ヶ月に30回もリリースビルド→デプロイすることあるか…?」と考えると、これが制限となってしまうことは稀になりそうだ。
というわけで今回はCI/CD環境を構築するためのサービスの選定とその理由について投稿した。次回はBitriseを利用したAndroidアプリのデプロイ環境の構築について投稿予定だ。
Logcatとかコンソールでログとか漁ってるときに、「必要なところを探して、必要な所だけくり抜くのマジだるい…」ってなる。
正規表現を使えば簡単なんだけど、「必要な所だけくり抜く」表現がわからなかったので放置してた。でもいい加減(ちゃんと書ければ秒で済む話を何時間もかけて作業してるの、マジ無能…と思い)なんとかしたかったので、調べて備忘録として残す。
知ってしまえば本当に簡単なんだわ。
(検索したいけど置換したくない文字)なにかしら置換したい文字(検索したいけど置換したくない文字)
$1置換後の文字$2
ポイントは
検索での表現
<(/*)div>
div
を指定する。/
があるかないかは、置換後のテキストにも影響するので、()
で書く。
*
は0文字以上の意味。置換での表現
<$1p>
p
タグを指定する。()
で書いた箇所が$1
として置換後のテキストに反映される。/
があった場合に限り置換後に/
が入るようにする。
どうも。どっことです。今回は環境変数や定数を
build.gradle
で管理する実装を解説します。
Gradleが自動生成してくれるBuildConfig
を使うことで、buildTypes
やproductFlavor
ごとに初期値や定数値を持たせることができます。よくあるのはAPIのドメインや、広告IDの切り分けなどですね。開発版(buildType
:debug
)とリリース版(buildType
:release
)で開発用と本番用で切り替えるなどに利用できます。今回はBuildConfig
にアプリ内で参照できるパラメータを乗せる実装を解説します。
buildTypes
(debug
/release
)ごとに定義する場合は以下でOKです。
defaultConfig
に初期値を設定する。buildTypes
ごとに定数の値を上書き設定する。android {
// ...
defaultConfig {
// buildTypesで上書きがなかった場合に設定される値
buildConfigField "String", "AD_UNIT_ID", "\"とりあえずな広告ID\""
}
// ...
buildTypes {
release {
// 本物の広告IDを上書きして定義
buildConfigField("String", "AD_UNIT_ID", "\"本物の広告ID\"")
...
}
// とりあえずな広告IDをdefaultConfigに書いていますが、
// debugブロックに書いて、defaultConfigは空文字などを指定しても問題ありません。
}
}
あとは上記の定数を使いたいところで、以下ように参照すれば値を取得することができます。
const val AD_UNIT_ID_SIDE_BAR = BuildConfig.AD_UNIT_ID
今回は、BuildConfig
に定数を持たせる実装について解説しました。同じアプリでも開発環境やクライアントに見せる版、一般公開版など種別がさまざまになることが多いと思います。このような機能を利用して、ソースコード上に煩わしい実装が増やさないように心がけましょう。
どうも。どっことです。今回はキーイベントを発行する実装方法を解説します。
例えば方向キーのキーイベントを発行する場合、以下をつかいます。
KeyEvent
を生成して、dispatchKeyEvent
で投げるだけ。これだけです。
dispatchKeyEvent(KeyEvent(ACTION_KEY_DOWN, KEYCODE_DPAD_UP))
気をつけないといけないのは、KeyEvent
コンストラクタに渡している第一引数には
ACTION_KEY_DOWN
を指定することです。
そもそもACTION_KEY_DOWN
はキー開始(画面やキーが押され始めた)、ACTION_KEY_UP
はタッチ終了(画面やキーから離れた)を表すイベントですが、第一引数にACTION_KEY_UP
を指定しても、OS側で制御してくれません。というのもOSからしてみれば
「押されてないのに離れたとか何事!?怖いから無視しとこ…」
という形に整理されていそうだからです。そのため、どうしてもACTION_KEY_UP
でやりたかったら、ACTION_KEY_DOWN
によりキーが押され始めたイベントも一緒に発行する必要があります。(どれだけ頑張る必要があるかは知らない…)ACTION_KEY_UP
に思い入れしなければ、非常に簡単ですね。
今回はキーイベントを発行する実装方法を解説しました。カスタムキーボードなどに役立てていただければと思います。
Intent.FLAG_ACTIVITY_CLEAR_TOP
を Intent#setFlag(int)
でセットするだけ。
fun showTop(View view) {
let intent = Intent(getApplication(), MainActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent);
}
どうも。どっことです。 タイトルの通りですが、諸事情により GitHubPage に移行予定です。 https://mkt120.github.io/ この備忘録に記載の内容を転記しつつ、今後はこちらのページを更新していく予定です。