自分だけのスペイン語検索ログを作る スマホ編
構想編の続きです。
androidアプリでやりたいことを整理すると以下の3つです。
1.文字選択メニューに自作アプリを出す
2.サーバーに選択文字列を送る
3.サーバーから受け取った結果をアプリに反映させる
開発環境はAndroid Studio bumblebee(2021)で作ることを想定しています。
やっていることが分かりやすい様にプロジェクトテンプレートのEmpty Activityをベースに作成します。
テンプレートのうち修正したファイルだけgitへ上げておきます。(https://github.com/samsumario/blog_public/tree/main/blog_3110)
コードはkotlinで、プロジェクトの対象OSはAndroid10.0(Q)以上としていますが多分殆どのバージョンで動くと思います。
1.文字選択メニューに自作アプリを出す
少し専門的に言うとIntentでアプリを起動するというみたいで、マニフェストに書きます。(全文 : AndroidManifest.xml)
intent起動用の専用クラスを作っているサンプルもありましたが、今回は最小実装をしたいのでMainActivity内のintent-filterに追加してMainActivityクラスで処理します。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/mysample/android"
package="com.example.mysample">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.mysample">
<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>
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
</application>
</manifest>
23~28行目が追加したintent処理部分です。
アプリ内でネット接続をするために5,6行目にpermissionも追加しています。
そのほかの部分はテンプレートのままです。
2.サーバーに選択文字列を送る
送ると言ってもURLを開く様な感じです。詳しく言うとHTTP通信のGETメソッドで行います。
1から作るのは大変そうなので今回はokhttp3というライブラリを使いました。
build.gradle(Moduleの方)のdependenciesにokhttp3をバージョンべた書きで追記します。早さ優先です。
下記のなんちゃってdependenciesの3行目がテンプレートからの追加部分で今回使ったバージョンは4.9.0です。
編集後にsyncさせて完了です。(build.gradel全文はこちら)
dependencies {
・・・(元からあるimplementation)
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
ManifestとGradleの下準備が終わったので次はMainActivityのコーディングをします。
コーディング内容は下記3点。
1.選択文字列を取得する
2.GETのURLを指定する
3.okhttpのクライアントとリクエストのインスタンスを作る
既にテンプレートで用意されているsetContentViewの下に続けて書きます。(コード全文はこちら)
val intentText = intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT)?.toString()
val baseURL = "https://my-api/?word="
if (intentText != null) {
if(intentText.isNotEmpty()) {
val client = OkHttpClient.Builder().build()
val request = Request.Builder()
.url("$baseURL${intentText.lowercase()}")
.build()
・・・(続く)・・・
3行目と4行目で一応選択文字のnull除けをしています。
2行目のbaseURLはあくまでサンプルですが今回はwordという変数に選択文字を入れてサーバーに送ることを想定しています。
7行目は取得した選択文字を小文字化してbaseURLとくつっけてurlを生成しています。(ただの文字列です)
まだサーバーへ送信していませんがひとまずここまで。
3.サーバーから受け取った結果を反映させる
サーバーとの通信はandroidのお約束でUIスレッド(メインスレッド)で出来ません。
大きな理由は通信中にアプリが固まるからでスレッドやらコルーチンやらを使ったサンプルが大量に出て来ます。。。が、今回はあくまでサクッと作りたいのでその辺の事情はokhttpライブラリにお任せすることにします。
enqueueメソッドが一番やり易そうだったので、さっき書いたMainActivity.ktファイルに続けて下記の用に実装しました。(コード全文はこちら)
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
runOnUiThread {
val tv = findViewById<TextView>(R.id.hellowworld)
tv.text = "error: $e"
}
}
@SuppressLint("SetTextI18n")
override fun onResponse(call: Call, response: Response) {
runOnUiThread {
val jsonText = response.body!!.string()
val tv = findViewById<TextView>(R.id.hellowworld)
tv.text = jsonText
}
}
})
Callbackの中でonFailure(通信エラー時処理)とonResponse(データ受信時処理)をオーバーライドしているだけの簡単なものを用意しました。
onFailureの中身はempry activityに唯一あるtext viewにエラーメッセージを張り付けるだけです。
textviewのidだけ付け加えています。(レイアウト全文はこちら)
onResponseの中身は受け取ったデータをやっぱりtext viewに貼り付けるだけで今回は済ませます。
12行目の処理は作っていくうちに色々なデータをやり取りしたくなる気がするので敢えてjson形式でのレスポンスを想定した実装にしました。
以上でandroidアプリ側は完了です。