Smart Communication Design Company
ホーム > ナレッジ > Blog > Apps Blog > 2016年7月 > Yahoo!ローカルサーチAPIを利用してPokémon GOのポケストップっぽい場所にピンを刺す

Apps Blog

スマートフォンアプリに限らず、アプリに関するナレッジを幅広く紹介していきます。

Yahoo!ローカルサーチAPIを利用してPokémon GOのポケストップっぽい場所にピンを刺す

インタラクションエンジニア 白石

位置情報を使用したスマホゲーム「Pokémon GO」が世界中で大流行しています。

Pokémon GOの特徴にはモンスターを捕まえるほかに、ポケストップと呼ばれるアイテムが補給できるポイントに実際に足を運び、アイテムを取得するというものがあります。

Pokémon GOのように位置情報と連動したゲームやアプリを作成する場合、実際の地図上に存在する「ポケストップ的」な場所情報が必要不可欠になると思いますが、今現在、Pokémon GOで表示されるポケストップの情報を一般の開発者が利用することはできませんし、自前でポケストップのような場所情報データを作ることは個人では難しいです。

しかし、「Yahoo!ローカルサーチAPI」を使えば、ポケストップになっていそうな場所(公園、お寺、神社、駅、マクドナルドなどのチェーン店)を位置情報から取得できます。

Yahoo!ローカルサーチAPIとは

Yahoo! JAPANが提供しているAPIで、位置情報を引数にして、その周辺にある施設やお店の情報を返してくれるものです。

Yahoo!ローカルサーチAPIの主な機能は以下です。

Yahoo!ローカルサーチAPIを使用するためにはアプリケーションIDを取得する必要があります。 24時間中1アプリケーションIDにつき50000件のリクエストが上限となっています。

詳しくはYahoo!ローカルサーチAPIを確認してください。

サンプルコード

マップと位置情報を取得するための準備

iOSアプリにマップを表示させるには「MKMapView」を使用します。 位置情報を取得するには「CLLocationManager」を使用します。

// MapViewの生成
self.mapView = MKMapView()

// LocationManagerの生成
self.lm = CLLocationManager()
// 取得精度の設定
self.lm.desiredAccuracy = kCLLocationAccuracyBest
// 位置情報取得間隔(m)ここで指定した間隔移動したら「locationManager」の位置情報更新処理が呼ばれます
self.lm.distanceFilter = 40
// 精度.
self.lm.desiredAccuracy = kCLLocationAccuracyHundredMeters
// Delegateの設定.
self.lm.delegate = self

// セキュリティ認証のステータスを取得
let status = CLLocationManager.authorizationStatus()
// 認証が得られていない場合は、認証ダイアログを表示
if(status == CLAuthorizationStatus.NotDetermined) {
    // 承認が得られていない場合は、認証ダイアログを表示
    self.lm.requestWhenInUseAuthorization();
}

// 位置情報の更新を開始.
self.lm.startUpdatingLocation()

// 位置情報のトラッキングをする
self.mapView.setUserTrackingMode(MKUserTrackingMode.Follow, animated: true)
self.mapView.delegate = self
Yahoo!ローカルサーチAPIで現在地周辺の施設情報取得

事前にYahoo!のサイトでアプリケーションIDを取得してください。 SwiftでJSONを扱いやすくするためにSwiftyJSONライブラリを使っています。 APIを叩きやすくするためにAlamofireライブラリを使っています。

func setMapPin() {
    // 現在地から緯度経度取得
    let latitude = String(format: "%.06f", self.nowLocation.coordinate.latitude)
    let longitude = String(format: "%.06f", self.nowLocation.coordinate.longitude)
    let parameters = [
        "appid": "Yahooで取得したアプリケーションID",
        "lat": latitude,     // 緯度
        "lon": longitude,    // 経度
        "dist": 2,           // 現在位置を中心とした検索距離(km)
        "sort": "dist",      // 直線距離順にソート
        "results": 100,      // 取得件数(最大100)
        "output": "json",    // JSON形式で返してもらいます
        "gc": "0424,0305007",// 取得する業種コード(ここでは「神社・寺」「公園」を指定しています)
        "group": "gid"       // 名寄せされた同一店舗をまとめて表示
    ]

    // API呼び出し
    Alamofire.request(.GET,
        "http://search.olp.yahooapis.jp/OpenLocalPlatform/V1/localSearch?",
        parameters: parameters as? [String : AnyObject])
        .validate(contentType: ["application/json"])
        .responseJSON
        { request, response, result in

            switch result {
            // 成功の場合
            case .Success(let data):
                if JSON(data)["Feature"] != nil {
                    for count in 0 ..< JSON(data)["Feature"].count {
                        print(String(JSON(data)["Feature"][count]["Name"]))
                        print(String(JSON(data)["Feature"][count]["Geometry"]["Coordinates"]))

                        let coord = String(JSON(data)["Feature"][count]["Geometry"]["Coordinates"]).componentsSeparatedByString(",")
                        let mapPoint : CLLocationCoordinate2D = CLLocationCoordinate2DMake(
                            double_t(coord[1])!,
                            double_t(coord[0])!
                        )
                        let annotation = MKPointAnnotation()
                        annotation.coordinate = mapPoint
                        annotation.title = String(JSON(data)["Feature"][count]["Name"])
                        // ピンを地図上に追加
                        self.mapView.addAnnotation(annotation)
                    }
                }
                else {
                    // エラー
                }
            // 失敗の場合
            case .Failure(_, _):
                // エラー
            }
    }
}
Yahoo!ローカルサーチAPIの結果をマップ上に示す
// アノテーション表示の管理
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation.isKindOfClass(MKUserLocation) {
        // 現在地を示すアノテーションの場合はデフォルトのまま
        return nil
    }
    else {
        // 再利用可能オブジェクト取得
        var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier("pin") as! MKPinAnnotationView!

        // 再利用可能オブジェクト有無判定
        if annotationView == nil {
            annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
            annotationView.animatesDrop = true
            annotationView.canShowCallout = true
            annotationView.draggable = true

            // ピンの色変える
            annotationView.pinTintColor = UIColor.redColor()
            // ピンのボタン設定
            let pinButton = UIButton(type: UIButtonType.Custom) as UIButton
            pinButton.frame.size.width = 50
            pinButton.frame.size.height = 51
            pinButton.backgroundColor = UIColor.greenColor()
            pinButton.setImage(UIImage(named: "money"), forState: .Normal)
            annotationView.leftCalloutAccessoryView = pinButton
        }
        return annotationView
    }
}
実行結果

Yahoo!ローカルサーチAPIの結果(施設名と緯度経度)

結果コンソール結果コンソール

西新宿駅半径1キロの「神社・お寺」「公園」の位置を表示

結果画面1結果画面1
結果画面2結果画面2

まとめ

Yahoo!ローカルサーチAPIのアプリケーションIDをアプリ内のコードに記述するのには抵抗があると思いますので、実際に使う際にはYahoo!ローカルサーチAPIの呼び出しはサーバ側で行った方が良いと思います。

位置情報が更新されるたびにマップに刺したピンとの距離を計算して、ある程度近づいたらアイテムが取得できるというような機能をつくればポケストップと同じようなことができます。Yahoo!ローカルサーチAPIを利用すれば、Pokémon GOのように実際の施設と位置情報を連動したゲームなどが作れそうですね。