Help us understand the problem. What is going on with this article?

【iOS】Google People APIでユーザーの情報を取得する

はじめに

前の記事(【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では、profileemailがあります。なんでこれだけ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します。

Podfile
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)

    }

実行すると、ちゃんと取れてることがわかると思います!

ryokkkke
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした