はじめに
前の記事(【iOS】Gmail APIを使って、ユーザーの複数のGmailアカウントからメールを取得する。)の半分続きで、iOSアプリからGoogle のPeople APIを使ってみようと思います。
これもまた謎に迷うトラップがいくつかあるので...
今回はユーザーの名前と、メアドを取得したいと思います。
Google People API
リファレンスはこちら:Introduction | People API | Google Developers
2016年の2月に発表されているのでわりかし最近、って書こうとしたけど2016年2月はもはや最近ではなかった😇
Google Developers Japan: People API を公開しました
Plus APIは?
同じようなこと(ユーザーの情報を取得する)をするAPIに、Google Plus APIが存在します。
このPlus APIなんですが、iOSのGoogle+ Sign-Inは2017年6月現在Deprecatedになっています。
ただ、RESTのPlus API(Plus API for web)は特にそういうことはありません。
ちょっとこの辺の関係性がよく分かりませんが...People APIを新しく開発してるということはPlusの方じゃなくてPeople使ってよということなのかな。
People APIの仕様変更
最近(2017年6月)People APIに突然の仕様変更があったらしく、使っていた人たちに少し影響があったようです。
Google People API “Request mask cannot be empty” - Stack Ovewflow
ようですっていうか僕もそれで戸惑ったうちの一人なのだけども...後述します。
ここでは「People API使えなくなったけど、Plus APIで同じことができるからPlusに変えたよ」というような話が上がってますが...それで大丈夫なのかな
ライブラリ
最初勝手にライブラリないだろと思って、PlusのAPIをURLSession
を使って直にリクエスト送ってたんですが、よく探したらPlusもPeopleもライブラリがありました。
せっかくなので実装ではURLSession
を使ったやり方も載せておきます。
共通の準備
※細かいAPI使用前の準備(Google DevelopersでのApp作成、認証情報作成など)は前の記事(【iOS】Gmail APIを使って、ユーザーの複数のGmailアカウントからメールを取得する。)に書いているので割愛します。
APIの有効化
まず、Google APIsの方で、People APIを有効化します。
スコープ
それから、スコープを付け足します。
private let scopes = [
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email"
]
でこのscopeの文字列も、どれが正しいのか微妙に不明なのですが...
People APIのAuthorize Requests | People API | Google Developersでは、profile
とemail
があります。なんでこれだけURLじゃないんだろう。
OAuth 2.0 Scopes for Google APIs | Google Identity Platform | Google Developersでは、People APIのprofileとemailのスコープはそれぞれ
email : "https://www.googleapis.com/auth/userinfo.email"
profile : "https://www.googleapis.com/auth/userinfo.profile"
になっています。
後述するライブラリのスコープの定数はこのページの値(URLになっている方)と同じでした。
なので、URLになっている方にするべき...というかライブラリの定数を使いましょう()
ちなみにURLでない"profile"と"email"だけでもPlus APIは実行できました。
実装
URLSession
URLSessionを直に使ってAPIを叩く場合は以下の感じになります。
let session = URLSession(configuration: URLSessionConfiguration.default)
var request = URLRequest(url: URL(string: "https://www.googleapis.com/plus/v1/people/me")!)
// Authorizationヘッダにて認証情報を指定
request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let task = session.dataTask(with: request) { (data, response, error) in
if ((error) == nil) {
print(NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!)
do{
// レスポンスをJSONパース
let responseJson = ( try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! NSDictionary)
let email = ((responseJson["emails"] as! NSArray)[0] as! NSDictionary)["value"] as! String
let displayName = responseJson["displayName"] as! String
print(email)
print(displayName)
}catch{
print("JSONパースに失敗しました。")
}
} else {
print("Google People APIへのリクエストに失敗しました。")
}
};
task.resume()
気をつけるところと言えばアクセストークンをヘッダに付与する部分でしょうか↓
// Authorizationヘッダにて認証情報を指定
request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
参考:トークンを利用した認証・認可 API を実装するとき Authorization: Bearer ヘッダを使っていいのか調べた
アクセストークンは、
// authorization: GTMAppAuthFetcherAuthorization
authorization.authState.lastTokenResponse?.accessToken
とかで取得できます。
GTMAppAuthFetcherAuthorization
に関しては前の記事を参照ください。
この方法ならPeople APIに限らずどれでも実行できますが、まあライブラリ使いましょう...
ライブラリ
Podfileを以下のようにして、pod install
します。
platform :ios, '8.0'
use_frameworks!
target 'TestApp' do
pod 'GoogleAPIClientForREST/PeopleService', '~> 1.3.0'
pod 'GTMAppAuth'
end
GoogleAPIClientForREST/People
ではなくGoogleAPIClientForREST/PeopleService
であるところに気をつけてください。
google-api-objectivec-client-for-rest/GoogleAPIClientForREST.podspecを見ると分かりやすいです。
なんでPeopleだけは"Service"ってついてるんだろう。
以下コードです。
let query = GTLRPeopleServiceQuery_PeopleGet.query(withResourceName: "people/me")
let service = GTLRPeopleServiceService()
service.authorizer = self.authorization
query.requestMaskIncludeField = "person.names,person.email_addresses"
service.executeQuery( query,
delegate: self,
didFinish: #selector(callback) )
他はmeだけがパラメータなのに、PeopleAPIのgetってなんでpeople/
までパラメータになってるんですかね...
meだけだとだめなので、気をつけてください。
requestMaskIncludeField
で、先ほど上で書いた仕様変更というのはこのrequestMaskIncludeField
というパラメータについての話です。
このパラメータ、ちょっと前までは任意だったのですが、現在は必須項目になっています。
これが、リファレンスも一部しか更新されておらず、中身の仕様だけ変わるという鬼の所業...
もちろんライブラリもまだ更新されていません。
RequestMask | People API | Google Developersを見ると確かにRequiredとなっているのですが、Method: people.get | People API | Google Developersでは必須ではないことになっています。
まあともかく、2017年6月現在はrequestMaskIncludeField
パラメータは必須です。
つけないと、Request mask can not be empty.
というエラーが返ってくるので注意してください。
コードにおいては、クエリオブジェクトのイニシャライザで指定する方法がないので、
query.requestMaskIncludeField = "person.names,person.email_addresses"
このようにオブジェクト生成後にプロパティに代入します。
ちなみに使える値は2017年6月現在、
person.addresses
person.age_ranges
person.biographies
person.birthdays
person.bragging_rights
person.cover_photos
person.email_addresses
person.events
person.genders
person.im_clients
person.interests
person.locales
person.memberships
person.metadata
person.names
person.nicknames
person.occupations
person.organizations
person.phone_numbers
person.photos
person.relations
person.relationship_interests
person.relationship_statuses
person.residences
person.skills
person.taglines
person.urls
の27種類です。
その他は他のAPIと特に変わったところはないです!
コールバック
func callback( ticket : GTLRServiceTicket,
finishedWithObject response : GTLRPeopleService_Person,
error : NSError? ){
if let error = error {
print("プロフィールの取得に失敗しました。")
print(error)
return
}
print("プロフィールの取得に成功しました。")
print(response.names)
print(response.emailAddresses)
}
実行すると、ちゃんと取れてることがわかると思います!