はじめに
アンドロイドスマホアプリI'm a bikerについての開発ドキュメントを公開します。
I'm a bikerとは
I'm a biker(これ以降本アプリ)は、Stravaに記録されている自分が乗っているロードバイクの走行データを使って簡易的なサービスを提供するためのアンドロイドスマホアプリです。
Stravaは世界有数のフィットネスプラットフォームで、30種類以上のスポーツタイプを記録でき、新しいトレーニング場所の発見や、コミュニティとの繋がり、進捗管理をサポートするウェッブサービスです。
本アプリは、Stravaの数あるスポーツタイプの中でロードバイクにのみに特化し、記録されているアクティビティのデータをダウンロードし、以下の簡易的なサービスを提供します。
- ユーザーが使用したロードバイクの情報を保存し管理します。
- Strava APIを使用してアクティビティのデータを取得し管理します。
- 取得したアクティビティデータは、スマホのデータベースとして保存し、スクロールビュー上に表示します。
- アクティビティデータ内のマップのポリラインデータからGoogle Map上に走行ルートを描画し、そのスクリーンショットを画像としてスマホに保存し、データベースとリンクすることでスクロールビュー上に表示します。
- ロードバイクのメンテナンス情報を保存し管理します。
- Strava API
-
Stravaが提供するAPI(Application Programming Interface)で、アプリケーションの開発者が様々なStravaデータセットに対するアクセスを可能にするインターフェースが公開されています。
-
- ポリラインデータ
-
Strava APIで取得することが出来るデータセットには、アスリートがロードバイクで走行したルートに関するマップ情報があります。 このうち走行ルートのポリラインデータを使うことで、Google Map上に走行ルートの軌跡を描画することが出来ます。 本アプリケーションは、このポリラインデータを使ったGoogle Map上の走行ルートをスクリーンショットで画像として保存し、データベースのスクロールビュー上に表示することで、どの辺を走行したのかを一目で分かるようにしています。
-
- メンテナンス情報
-
ユーザーは、使用するロードーバイクを登録することが出来ます。登録したロードバイク情報には、タイヤやチェーンなどの消耗品に対する交換時期を設定することが出来ます。 本アプリケーションは、走行距離に基づいて消耗品の交換時期をチェックし、ユーザーに通知することでロードバイクのメンテナンス時期を知らせることが出来ます。
Android Studio
本アプリは、Android用のスマホアプリです。その開発には、Android Studioを使用しました。 Android Studioは Androidアプリ開発用の公式の統合開発環境(IDE)です。 詳細は、Android Studioを参照してください。
開発環境は、Windows 11のパソコンです。この時アカウントに日本語を使っていると、Android Studio実行時に正しく機能しないことがあるため、英語名でのアカウントを作成する必要があります。 日本語のアカウントでAndroid Studioをインストールすると、この最初の段階で相当トラブルことになります。
また、Android Studioには、Android Emulatorが附属しています。これを使うと、様々なAndroidスマホやタブレットのデバイスを画面上で仮想的に実現し、アプリを評価することが出来ます。 ただし、これらをエミュレートするには、デバイス一つに対して相当ディスク容量を使います。簡単に10GBを超えてしまい、初期設定はCドライブであるため、あっという間にディスクフルになってしまいます。
Android Studioには、実機(スマホ)でアプリを実行することも出来ます。私の場合、普段使いのスマホ以外にSIMなしの古いスマホがあったので、それを評価用に使っています。 Emulatorを使うより、起動も速いし問題なく評価が出来ます。
実機でアプリを動かす
次の手順で行います。
Android Studioでアプリを実行すると、プログラムがスマホにアップロードされて、スマホ上でアプリが実行され、デバッグも行うことが出来ます。 また、Android Studio上での実行を停止した後であっても、スマホ単体でアプリを実行することも出来ます。
- スマホで設定のデバイス情報を開きます。
- ビルド番号を7回タップします。
- 設定に戻って、システムを開きます。
- 開発者向けオプションが追加されているので、これを開きます。
- ワイヤレスデバッグを開いて、ワイヤレスデバッグの使用をオンにします。
- パソコンでAndroid Studioを起動し、Device ManagerもPair Devices Using Wi-Fiをクリックすると、QRコード画面が表示されます。
- スマホに戻って、ワイヤレスデバッグのQRコードによるデバイスのペア設定をクリックして、下記のQRコードを読み込みます。
- 接続に成功すると、Android StudioのDevice Managerにスマホ名が追加されます。
認証コードを取得する
Stravaから認証コードを取得するには、Strava APIを利用してStravaのホームページから情報を取得する必要があります。 ここでは、その技術的方法を説明します。 Strava APIに関しては、Getting Startedのドキュメントを参照ください。
それでは、Stravaから認証コードを取得する方法を説明します。
- Getting StartedのD. How to AuthenticateからURLは次に定義されている。
URL:http://www.strava.com/oauth/authorize?client_id=[REPLACE_WITH_YOUR_CLIENT_ID]&response_type=code&redirect_uri=http://localhost/exchange_token&approval_prompt=force&scope=read>
実際のアドレスは、https://www.strava.com/oauth/mobile/authorizeに置き換えます。 - パラメータの詳細は、Details About Requesting Accessを参照ください。
- [REPLACE_WITH_YOUR_CLIENT_ID]は、本アプリの使い方のはじめにで取得したクライアントIDを設定します。
- response_typeは、"code"を設定することで、認証コードを要求します。
- redirect_uriは、認証コードを返送先を指定するもので、"http://localhost"を設定します。
- approval_promptは、"force"か"auto"ですが、"auto"を設定します。
- scopeは、"activity:read_all"を設定して問題ありません。
このURLを元に、startActivityを起動します。
val intentUri = "https://www.strava.com/oauth/mobile/authorize".toUri()
.buildUpon()
.appendQueryParameter("client_id", gbv_clientId)
.appendQueryParameter("redirect_uri", REDIRECT_URI)
.appendQueryParameter("response_type", RESPONSE_TYPE)
.appendQueryParameter("approval_prompt", APPROVAL_PROMPT)
.appendQueryParameter("scope", SCOPE)
.build()
val intent = Intent(Intent.ACTION_VIEW, intentUri)
startActivity(intent)
Webブラウザで次の画面が表示されます。
このStravaの画面に従って、認証コードを取得します。 詳しくは、本アプリの使い方の認証コードの取得を参照してください。
次にStravaからアクセストークンを取得する方法を説明します。
アクセストークンを取得する
Stravaからアクティビティのデータを取得するには、Strava APIを利用してStravaのホームページから情報を取得する必要があります。
本アプリでは、Retrofitを使ったHTTP通信を行い、そのレスポンスでデータを取得しています。 Retrofitは、HTTPクライアント通信ができるライブラリで、使用できるHTTPメソッドには、GET、POST、PUT、PATCH、DELETE、OPTIONS、HEADがあります。 Retrofitでは、使用するAPIをインターフェースとアノテーションにて定義します。 Retrofitの実態は、OkHttpのラッパーであり、OkHttpClientを使用して機能を拡張することができます。
- アプリをインターネットに接続する許可を与えるため、AndroidManifest.xmlに以下のタグを追加します。
<uses-permission android:name="android.permission.INTERNET"/>
- build.gradle.ktdにOkHttpモジュールへの参照を追記します。
implementation(libs.okhttp)
- Tokenの取得には、非同期通信(enqueue)を使います。
val client = OkHttpClient() val request = Request.Builder() .url("https://www.strava.com/api/v3/oauth/token") .post(formBody) .header("Content-Type", "application/x-www-form-urlencoded") .build() try { val call = client.newCall(request) call.enqueue(object : Callback { override fun onFailure(call: Call, ex: IOException) {} @RequiresApi(Build.VERSION_CODES.O) override fun onResponse(call: Call, response: Response) { val jsonData = response.body!!.string() if (!response.isSuccessful) { // 受信エラー処理 return } // JSONによるデータ抽出処理 } }) } catch (ex: Exception) { // 例外処理 } - 取得したデータは、JSONによって処理し抽出します。
例えば、Tokenを処理する場合は、次のようにプロファイルを定義します。data class TokenProfile( @SerializedName("token_type") var tokenType: String, @SerializedName("expires_at") var expiresAt: Int, @SerializedName("expires_in") var expiresIn: Int, @SerializedName("refresh_token") var refreshToken: String, @SerializedName("access_token") var accessToken: String, @SerializedName("athlete") var athlete: TokenAthlete? )これを使って、次のコードでデータを抽出します。var profile = Gson().fromJson(jsonData, TokenProfile::class.java)
例えば、アクセストークンは、profile.accessTokenを使ってデータを取得できます。
アクティビティデータを取得する
- 走行データ等のアクティビティのデータの取得には、同期通信(execute)を使います。
これは、これは大量のデータを分割受信し、データを加工する処理を繰り返し行うようにするためです。
例えば、Strava APIのList Athlete Activitiesを使ってデータを取得する場合はval stravaUri = "https://www.strava.com/api/v3/athlete/activities".toUri() .buildUpon() .appendQueryParameter("page", pageNo) .appendQueryParameter("per_page", noOfPage) .build() val request = Request.Builder() .url(stravaUri.toString()) .header("Authorization", "Bearer $gbv_accessToken") .build() responseData = "" try { runBlocking { val response = httpGET(request).await() if (response!!.isSuccessful) { responseData = response.body!!.string() } else { // 受信エラー処理 } } } catch (ex: Exception) { // 例外処理 } - responseDataにpageNoに該当するページのnoOfPageに相当するデータが格納されます。
これを全ページ分繰り返して、全データを取得します。取得したデータは、JSONを使ってデータを抽出します。





