読者です 読者をやめる 読者になる 読者になる

GoogleMap系の周辺技術の整理メモ

随時追記予定


staticMap

Googleで地名検索をした場合に、表示される簡易mapの画像表示で使われている技術

画像がそのまま返却されるので、そのままPicasso等で表示するとかにも使えますね。

一応keyが必要ということになっているけど、

request数の大幅な制限があることを除けば指定なしても表示は実は可能

制限的な箇所は

  • 複数のマーカを指定した場合

    • zoom値を指定すると、距離がある場合に画面内に表示されない
    • scale=2 とか指定してしまうと、劇的に生成時間が増える
      • 2秒 =>4秒程度
    • 二点間の距離が1kmを超えると劇的に生成時間が増える
      • 2秒 =>4秒程度
  • play-ground

streetviewのサムネイルが欲しい時

Street View Image API を使う

https://maps.googleapis.com/maps/api/streetview?<パラメーター>

属性 説明
location 緯度経度(緯度,経度)
size 表示する画像のサイズ(縦x横)
heading カメラの方位(0 〜 360) 0=北
pitch カメラのアングル(90 〜 -90) 90=上 -90=下
fov カメラの水平視野(0 〜 120) 0=狭い 120=広い
zoom カメラのズーム(0〜5) 0=遠い 5=近い
https://maps.googleapis.com/maps/api/streetview?size=400x400&location=40.720032,-73.988354
&fov=90&heading=235&pitch=10

intentによるMapアプリの呼び出し

指定位置の表示

geo:35.684331,139.735232

geo:35.684331,139.735232?z=19 //(z:ズーム値)

指定をしたときに、左下に近場のstreetview サムネイル*1が表示されるようになってる

geo:35.684331,139.735232?q=35.684331,139.735232

と指定した場合は、

geo:目的地座標?q=目的地座標

みたいな感じで、目的地に マーカーピン を立てる

geo:目的地座標?q=<<検索ワード(要URLエンコード)>>

だと、Mapアプリの上の方に検索された状態で表示される

最新版のGoogleMapアプリで拡張されている処(2016年版)

geo:目的地座標?q=目的地座標

で マーカーピンを表示た場合「名前のない場所」

geo:目的地座標?q=目的地座標(ラベル<<要URLエンコード>>)

と設定すると

URLエンコードされたラベルが

「名前のない場所」=>「指定ラベル」

となります。

GoogleMapアプリが片手落ちな処

これ ユーザーのアカウントに紐付いて

  • GoogleMapにカスタムプレイスを保存する機能

の利用を促進するためのやつなんですが、

  • この設定したラベルが保存するときに引き継がれない
    • 一から新規で入れる・・しかも別画面・・・見ながらも入力不可・・・
  • コピー機能はなぜか住所をコピーする*2

経路情報

経路情報に関しては、APIとしては未だ提供されていないのが現状だったり。。

特に公式ドキュメントに記載はないが

http://maps.google.co.jp/maps?saddr=現在地&daddr=目的地&dirflg=w //d:車/t:電車(デフォルト)/w:徒歩

を setPackage でcom.google.android.apps.mapsを指定すれば

mapアプリ内で表示はされる

Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setClassName("com.google.android.apps.maps","com.google.android.maps.MapsActivity");
        intent.setData(Uri.parse("http://maps.google.com/maps?saddr=35.684331,139.735232&daddr=35.684331,139.735232"));
        startActivity(intent);

みたいな感じ。

自前で遣る場合は、Google Directions API を使いましょうって話で

Google Maps Android V2 でルート検索

が出てくるくらいかと。

後はラップしたライブラリを作っている方もいますね

github.com

google.navigation:q=35.684331,139.735232

google.navigation:q=35.684331,139.735232&mode=w //(d:車/w:歩き/b:自転車)

な指定の感じだけど、こっちだとなんか感じが違う感じがする

streetviewのintentに関して

google.streetview:cbll=35.684331,139.735232

で呼び出し

  • 現在はstreetviewアプリをinstallしていても呼び出されず、現在はGoogleMapアプリが呼び出される
    • Intent経由の表示で 近くの表示できる位置まで移動して表示 という対処が入っていたはず
    • 2016/10末のアップデートでこれが動かなくなってる*3
    • 位置指定したときに、付近直近のpanoIdの箇所は 左下に表示しているので、表示されるはずなんですが・・・*4

streetviewを確実に表示するには

SupportStreetViewPanoramaFragment 等で自前で出しましょうという話

下記は 東京タワーを表示する記述例

StreetViewPanoramaView を使う場合

public class StreetViewActivity extends Activity {
    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        StreetViewPanoramaView sv;
        final StreetViewPanoramaOptions options = new StreetViewPanoramaOptions();
        latitude = 35.657797;
        longitude = 139.745625;
        final LatLng TOKYO_TOWER = new LatLng(latitude, longitude);
        options.position(TOKYO_TOWER); // 場所の指定
        sv = new StreetViewPanoramaView(this, options);

        addContentView(sv, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        sv.onCreate(savedInstanceState);
    }
}

SupportStreetViewPanoramaFragment を使う場合

StreetViewPanoramaCamera で更に下記の指定も指定することが可能

項目 設定内容
zoom ズーム倍率  
tilt カメラの水平角度を指定
bearing 真北を0とした方角を指定
<fragment
android:name="com.google.android.gms.maps.SupportStreetViewPanoramaFragment"
    android:id="@+id/streetviewpanorama"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
setContentView(R.layout.activity_streetview);
final SupportStreetViewPanoramaFragment fm = (SupportStreetViewPanoramaFragment) getSupportFragmentManager().findFragmentById(R.id.map_streetview);


fm.getStreetViewPanoramaAsync(new OnStreetViewPanoramaReadyCallback(){
    @Override
    public void onStreetViewPanoramaReady(StreetViewPanorama map) {
          // 座標の設定(★)
          Double latitude = 35.657797; // 緯度
          Double longitude = 139.745625; // 経度
          LatLng TOKYO_TOWER = new LatLng(latitude, longitude);
          map.setPosition(TOKYO_TOWER);

          //セットしたポジションからpanolamaIdを取得する◎
          StreetViewPanoramaLocation location = map.getLocation();
          if (location != null && location.links != null) {
               map.setPosition(location.links[0].panoId);
          }

          // カメラコントロールの設定
          float zoom = 0.0f; // ズーム倍率
          float tilt = 37.462147f; // カメラの水平角度
          float bearing = 347.0586f; // 真北を0とした方角
          final StreetViewPanoramaCamera camera = new StreetViewPanoramaCamera(zoom, tilt, bearing);

          // カメラをその位置へ3秒かけて移動する
          map.animateTo(camera, 3000);
     }
});

ちなみに◎は必須。

  • 理由は
    • ビルの中等の座標を指定した場合、
    • 勿論G様でもPanorama撮影していないから、
    • 近辺(近くの道路画像とか)のPanoramaIdを検索する必要があるらしい

使い勝手を考えるなら、★はIntent等で渡す作りにしたほうが良いかもしれませんね


住所から位置情報を取得する(Geocoder)

seesaawiki.jp

基本上記のコードでよくて、 v1/v2の違いで

  • 1E6をかけてint型に変換する必要がない(double型でそのまま扱えばOK)

ぐらいの差分でしょうか。。ググると未だ古い記述のものが多くて混乱しますね(汗

今風で使うとすると

AppCompat + SearchView 辺りでの利用でしょうか。。

因みに、

<item android:id="@+id/action_search"
    android:title="@string/action_search"
    android:icon="@drawable/ic_action_search"
    app:showAsAction="always|collapseActionView"
    android:actionViewClass="android.support.v7.widget.SearchView" />
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));//★    searchView.setOnQueryTextListener(this);
    return super.onCreateOptionsMenu(menu);
}

な記述をかくと思いますが、

support-library-24.2.X になるまで、Android 5.0以上で

MenuItemCompat.getActionView でnullを返すというバグが有りました・・。

*1:クリックするとstreetviewモードへ

*2:Geo情報から逆引きされた・・・

*3:画面が真っ黒のままになる。以前もよくこの不具合あったらしい

*4:G様特有のデグレ?。更新する前はちゃんと表示できていたので・・