このページを正しく表示するにはJavascriptを有効にしてください。
AndroidでfoursquareとAuth連携する
Foursquare(4sq)のAPIを使ったAndroidアプリを作ってみようと思い、
とりあえずAuth連携の部分だけ実装してみました。
Auth連携することでユーザーのチェックイン操作などが出来たり、
APIの使用制限もアプリ全体の制限からユーザーベースの回数制限に
移行することができるので何かと便利です。
[https://github.com/foursquare/foursquare-android-oauth](https://github.com/foursquare/foursquare-android-oauth)
サードパーティでもAndoid用4sqライブラリがありますが、
WebView使っていたりとセキュリティ面に不安があったので
公式のライブラリを利用することにしました。
公式のライブラリですとAuth認証の部分しか面倒見てくれませんが、
Tokenさえ取ってしまえばそんなにAPI利用するの難しくなさそうです。
## 組み込み
AndroidStudioを使って組み込んでみます。
### アプリクライアント登録
[https://foursquare.com/developers/apps](https://foursquare.com/developers/apps)
まずはこちらからアプリクライアント登録をします。
重要なのはアプリのkeystoreのフィンガープリントが必要な点です。
AndroidのアプリをGooglePlayで配布するにはkeystoreを
作成して埋め込む必要がありますが、その署名の情報を
4sq側にも登録してあげる必要があるみたいです。
これによって第三者によるTokenの不正利用を防ぐのでしょう。
ただAndroidのデバッグ(開発)時にはデバッグ専用の署名が
自動で使われてしまう為、本番用の署名との切り替えが面倒です。
そこで4sqに本番用アプリとデバッグ用の2種類アプリクライアントを登録して、
AndroidStudioの機能で署名とクライアントIDの切り替えを自動制御するようにします。
#### Build Variants
AndroidStudioにはBuild Variantsという便利な機能があります。
[Android Studio で Build Variants](http://qiita.com/kojionilk/items/0b34ad03497dae1093ff)
リンク先が詳しいので是非見て欲しいのですが、
要するにデバッグビルド時とリリースビルド時で利用する
リソースや署名などの設定を自動で切り分けられる機能です。
これを利用することで4sqの連携もスムーズに行えます。
#### keystore作成
まずは本番用とDebug用のキーを用意します。
デバッグ用は
[debug用keystoreについて調べてみた](http://qiita.com/taka0125/items/c408df4061a0af49c9b3)
みたいな感じですでに生成されていると思うのでこれをコピーして利用します。
本番用はとりあえず初期化したプロジェクトを公開用にビルドして
keystoreを生成しておきます。(もちろんコマンドからでも可)
それぞれのキーをプロジェクト内に置いておきます。
(今回はプロジェクトのルートに/etc/keystore/みたいな階層を作って置いておきました。)
#### ハッシュ生成
それぞれの証明書からフィンガープリントを計算します。
```keytool -list -v -keystore (keystoreファイル名)```
Javaのパスが通った状態で上記コマンドを叩きます。
キーストアに設定したPasswordを入れてあげると
証明書のフィンガープリントが算出されます。
sha1のフィンガープリントを先ほどの4sqクライアント登録画面で
それぞれ設定してあげればOKです。
登録完了するとアプリ用のClientIDとClientKeyが
発行されるので控えておきます。
### Gradle設定
クライアント情報が取得できたのでアプリ側の開発に進んでいきます。
まずはGradleの設定を行い、ライブラリの導入と
署名・フィンガープリントの切り分けを行います。
まずはプロジェクト直下のbuild.gradleを開き
```
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
maven {
// 4sq auth library
url 'http://fredericosilva.github.io/foursquare-android-oauth-aar'
}
}
}
```
のようにレポジトリのURLを追加してあげます。
そして今度はapp直下のbuild.gradleを
```
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "20.0.0"
defaultConfig {
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
// 証明書の設定
signingConfigs {
debug {
keyAlias 'androiddebugkey'
keyPassword 'android'
storeFile file('../etc/keystore/debug.keystore')
storePassword 'android'
}
release {
keyAlias 'xxxxxxx'
keyPassword 'xxxxxxxxxxxxx'
storeFile file('../etc/keystore/release.keystore')
storePassword 'xxxxxxxxxxxxxx'
}
}
// buildの切り分け
buildTypes {
debug{
applicationIdSuffix = '.degug'
versionNameSuffix = 'd'
signingConfig signingConfigs.debug
}
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// 4sq auth
compile 'com.foursquare:foursquare-android-nativeoauth-lib:1.0.0@aar'
}
```
のような形で設定してあげます。
keystoreのパスワード等は合わせて書き換えてください。
こうすることで4sqのライブラリを使えるようになります。
gradleだと自分でソースをダウンロードしたりしなくていいのは便利ですね。
またBuildConfigを切り替えるだけで証明書も適したものを利用する事ができます。
### Client情報切り替え
証明書だけでなく、ClientKeyなどの情報もデバッグと本番では異なるので
切り替えの設定を行ってあげる必要があります。
この切替を行うにはリソースを利用するのが簡単です。
```app/src/```の中に```main```というフォルダがあると思いますが、
ここと同じ階層に```debug```と```release```というフォルダを作ってあげます。
このような構成にするとmainの中身をdebug, releaseの中身で
上書き(衝突しなければ追記)することができるようになります。
なので、
* ```app/src/debug/res/value/string.xml```
* ```app/src/release/res/value/string.xml```
2つのファイルを作ってあげ、
それぞれのクライアント情報を暗号化して格納してあげます。
ここで一旦gradle syncをしてエラーがないかチェックしてみます。
エラーが無ければBuild Variantsの切り分けが上手く行っているはずです。
あとManifestにインターネット権限をつけるのを忘れずに。
## トークン取得処理
最後にプログラムで実際のTokenを取得してあげます。
### 流れ
Authは認証のフローがちょっと複雑で、
1.リクエストコード発行リクエスト(ClientId利用)
1.4sqアプリが起動し連携許可の確認
1.RequestCode取得
1.Token発行リクエスト(ClientId, ClientKey, RequestCode利用)
1.Token取得
みたいな流れを踏む必要があります。
### リクエストコード発行
```
Intent intent = FoursquareOAuth.getConnectIntent(context, CLIENT_ID);
startActivityForResult(intent, REQUEST_CODE_FSQ_CONNECT);
```
この2行をActivityの好きなところで呼び出してあげれば
requestCodeというものの取得を行ってくれます。
CLIENT_IDは先ほど登録画面で取得したものです。
(リソースから復号して渡します。)
REQUEST_CODE_FSQ_CONNECTはリクエストを受け取る時の識別番号なので、
適当な数字をクラス内で定数として定義してあげて利用します。
この状態でビルドしてみると、
リクエストコード発行処理が動いた時点で、端末内の4sqアプリが起動し、
ユーザーにAuth連携を許可するか聞いてきます。
端末に4sqが入っていない場合はGooglePlayに飛ぶみたいです。
ここで取得したRequestCodeを受け取るには
Activityの```onActivityResult```を実装します。
```
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_FSQ_CONNECT:
AuthCodeResponse codeResponse = FoursquareOAuth.getAuthCodeFromResult(resultCode, data);
log.d("4sq auth", "RequestCode:" + codeResponse.getCode());
break;
}
}
```
エラー処理とかを一切無視した場合こんな感じでRequestCodeが取得できます。
実際には認証許可しなかった場合などのエラー処理を適切にして上げる必要があります。
### Token取得
最後に受け取ったRequestCodeを使ってTokenの取得を行います。
アプリのみでToken取得しようとすると、ClientSecretをリソースに
含めなくてはならないのでセキュリティ的には推奨されていませんが、
以下のような形でTokenを取得する事が可能です。
```
android:name="com.foursquare.android.nativeoauth.TokenExchangeActivity"
android:theme="@android:style/Theme.Dialog" />
```
AndroidManifestにこのActivityを追記
```
Intent intent = FSOauth.getTokenExchangeIntent(context, CLIENT_ID, CLIENT_SECRET, requestCode);
startActivityForResult(intent, REQUEST_CODE_FSQ_TOKEN_EXCHANGE);
```
RequestCodeを受け取り後、この2行を追記。
これにより端末のみでToken取得リクエストを投げれます。
受け取りは先程の```onActivityResult```にCase文を追加し、
```
case REQUEST_CODE_FSQ_TOKEN_EXCHANGE:
Log.d("4sq auth", "Token:" + tokenResponse.getAccessToken());
```
みたいな形で取得します。
こちらも適切な例外処理を行いましょう。
無事Tokenが取得できたので、あとはこれを付与してAPIを叩くだけです。
# セキュリティ対策
先ほども書いたとおり、この方法だとSecretをアプリ内に含める
必要があるのでセキュリティ上好ましく無いです。
より適切に実装するのであれば
アプリにはClientIDのみを持たせて、
RequestCode取得後は自前で用意したサーバーでToken発行処理を行い、
結果のTokenだけをアプリに返すという実装にしてあげる必要があります。
[https://developer.foursquare.com/overview/auth#code](https://developer.foursquare.com/overview/auth#code)
詳しくはこちらの公式ドキュメントで