試しにやってみたので導入までの流れを解説します。
前提
- エミュレータでは動かないので実機が必要です。
- GoogleのDevloper登録は不要
- GoogleのAPI登録は必要
- Android Studio2.0 β6使用・インストール済み
- Android SDKインストール済み
上記の前提で解説していきます。
Android Studioのバージョンは2以降であればおそらく問題ないと思います。
Google Play Servicesのインストール
GoogleMapを使用するにはGoogle Play Servicesのプロジェクトへの導入が必須です。
なので、まず事前にこれをインストールしておきます。
※Google Play ServicesとGoogle Repositoryがすでにインストールされている場合はこの工程は不要です。
SDK Managerの起動
Android Studioを立ち上げてTools → Android → SDK Managerを選択します。
SDK Managerを起動したら、ここからGoogle Play Serviceをインストールします。
SDK Toolsタブを選択すると、各ツール類のインストール有無がリストされます。
Google Play servicesとGoogle Repositoryの2つにチェックをつけてApplyを押します。
ラインセンスの確認が表示されますので、確認してAcceptにチェックをしてNextを押します。あとは勝手にダウンロードされてインストールされます。
プロジェクトを作る
開発用のプロジェクトを作ります。これは特別な手順は無く、通常通りで大丈夫です。
サンプルではActivityにはEmpty Activityを選択している前提です。
署名を設定する
GoogleのAPIを利用するためには署名が必須です。なのでこれも事前に用意します。
※署名はデバッグ用とリリース用の2種類用意するのをオススメします。
既に署名があるならこの手順は飛ばして大丈夫です。
署名ファイルを作る
Build → Generate Signed APKを選択します。
ダイアログが出ますのでCreate newを選択します。
必要な情報を埋めます。
Aliasは何でも構いません。
Certificateは少なくともFirst and Last Nameを埋める必要があるようです。
また、このファイルは絶対に無くさないようにし、パスワードも絶対に忘れないようにしてください。
アプリのリリース時にも必ず必要になるファイルですが、これを無くすとアプリの更新がまったく出来なくなります。
署名をプロジェクトに関連付ける
File → Build Structuerを選択します。
Modulesを選択し、Signingタブを選択します。
Nameにはdebug、Key Alias・Key Password、Store Passwordには先ほど作った署名のものをそのまま設定してください。
※先ほどのダイアログではStoreのパスワードが上側にAliasのパスワードが下側にあったので間違えないよう気を付けてください。
Google Play Servicesをプロジェクトに設定する
次に前述したとおりGoogle Play Serviceをプロジェクトに設定します。
こちらもFile → Build Structuerから設定します。
Dependenciesタブを選択し、右側の+を押して、Library dependencyを選択します。
ライブラリの選択からplay-servicesを探してOKします。
ビルドエラーが出る場合
Google Play Servicesを設定したらエラーが出るようになる場合があります。
設定されているGoogle Play ServicesがインストールされているSDKに対応していない可能性があります。SDKとGoogle Play Services両方を最新に更新してみてください。
それでも解決しない場合はbuild.gradleを少し編集する必要があります。
appのbuild.gradeの一番下のdependenciesを変更します。
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.google.android.gms:play-services:7.8.0'
}
play-services:の後に3つの数字があります。これがGoogle Play Servicesのバージョンを表しています。これを少し古いものにする事で解決する可能性があります。
古いバージョンに何があるかはSDKのインストールフォルダの「extras\google\m2repository\com\google\android\gms\play-services」のフォルダ名を見ることでわかります。
APIの登録を行う
プロジェクトの作成が終わったのでGoogleのAPI登録を行います。
GoogleのAPIライブラリのページへアクセスします。(※リンク先は変わっている可能性があります…)
右上にプロジェクトの作成があるのでそこから新規作成します。
プロジェクトが完成したら、Google Maps Android APIを選択し有効化します。
左側の認証情報を選択し、APIキー → Androidキーを選択します。
名前を適当に設定し、パッケージ名とフィンガープリントの追加を押してそれぞれ追加します。
あとは作成で登録完了です。表示されるAPIキーをメモしておきましょう。
パッケージ名
パッケージ名はAndroidManifestの2行目付近「manifest package=”ココ”」に記載されています。
フィンガープリント
フィンガープリントはkeytoolというjavaのツールで確認できます。
コマンドプロンプトを開き、「”jdkをインストールしたフォルダ\bin\keytool” -list -v -keystore 署名ファイル」を実行します。
パスワードの入力を求められますので、入力します。
SHA1の項目をコピーしてフィンガープリントの項に貼り付けます。
※右クリック → 範囲指定 → ドラッグで選択 → 右クリックの手順でコピーできます。
プロジェクトにGoogle Mapの設定を行う
マップの設定を終わらせます。
パーミッション
まず、パーミッションを設定します。
AndroidManifestを開き</manifest>の前に以下を記述します。
<!-- permissions -->
<!-- Internet(これはGoogle Play Servicesを入れたら勝手に設定されるので無くても良い) -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD Card (Mapのバージョン8.3以降は不要) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- GPS -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Google MapではSDカードとGPSのパーミッションが必要です。(※インターネット関連も必要ですが、これは自動で設定されるようです。)
SDカードは新しいMap(8.3以降)では不要なようです。
OpenGL
次にGoogle MapではOpenGLを使って描画されているため、マニフェストに要件として記述します。
<!-- OpenGL -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
これは上記のパーミッションの直後に記述します。
Map用定数
次にGoogle Mapに必要な定数を設定します。
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<meta-data android:name="com.google.android.geo.API_KEY" android:value="APIキー" />
これは</application>の直前に入れます。
APIキーにはAPIの登録完了時に表示されたキーを入力してください。
APIキーは「AIzaSyBdVl-cTICSwYKrZ95SuvNw7dbMuDt1KG0」こんな感じの見た感じランダムな文字列です。
AndroidManifestのサンプル
<?xml version="1.0" encoding="utf-8"?>
<manifest package="jp.ne.sakura.cfm_art.maptest"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<meta-data android:name="com.google.android.geo.API_KEY" android:value="APIキー" />
</application>
<!-- permissions -->
<!-- Internet(これはGoogle Play Servicesを入れたら勝手に設定されるので無くても良い) -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD Card (Mapのバージョン8.3以降は不要) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- GPS -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- OpenGL -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
</manifest>
レイアウトにMapを入れる
レイアウトにマップを入れます。
レイアウトファイルを開いたら、Custom → Fragmentを選択します。
選択するとダイアログが開きますので、ここからMapFragmentを探します。
OKを押すとレイアウトに追加されます。
LinearLayoutなんかの適当なLayoutの子供にwrap_contentで設定するのが使いやすいのかなとは思いますが、そこはお好みで。
注意点として、デザイナーでは必ずRender Problemsが発生します。実機で実行するとちゃんと表示されますので、確認は実機で行ってください。
プログラムで制御する例
Mapをプログラムで制御するサンプルを記載します。このあたりは公式にちゃんと書かれてますのでそちらを参照したほうがいいかもしれません。
※以下のサンプルではpackageとimportを省略しています。
マップのオブジェクトを取得する
マップのオブジェクトの取得にはコールバックの登録が必要です。コールバックを登録したら、マップの初期化が終わった時点でメソッドが自動で呼び出されます。
コールバックを受け取るにはOnMapReadyCallbackをimplementsします。
public class SampleCallback
implements OnMapReadyCallback
{
@Override
public void onMapReady( GoogleMap googleMap )
{
// 初期化完了
}
}
このような形式です。引数のGoogleMapにマップのオブジェクトが入っていますので、それを介してさまざまな処理を行います。
コールバックの登録にはMapFragmentのgetMapAsyncメソッドを利用します。
面倒なのでActivityにOnMapReadyCallbackを実装した例が以下です。
public class MainActivity
extends AppCompatActivity
implements OnMapReadyCallback
{
private GoogleMap map_ = null;
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
// マップを取得して初期化の検知を登録
MapFragment map = (MapFragment) getFragmentManager().findFragmentById( R.id.map_fragment );
map.getMapAsync( this );
}
@Override
public void onMapReady( GoogleMap googleMap )
{
map_ = googleMap;
}
}
デザイナーで設定されているMapFragmentを取得し、getMapAsyncメソッドに自身(OnMapReadyCallback)を設定しています。
マップの初期化が完了したらonMapReadyメソッドが呼び出されます。
長押しされたらそこにピンを立てる例
ピンを立てるには
ピンを立てるのは簡単です。GoogleMapのaddMarkerメソッドを呼び出します。
LatLng latLng = new LatLng( 0, 0 );
map_.addMarker( new MarkerOptions()
.title( "ピンのタイトル" )
.position( latLng ) );
titleにはピンを押したときに出る題を、positionにはピンを立てる座標(緯度・経度)を設定します。
長押しの検知には
長押しはGoogleMapのsetOnMapLongClickListenerにコールバックを登録する事で検知できます。
setOnMapLongClickListenerに登録できるのはGoogleMap.OnMapLongClickListenerをimplementsしたクラスのインスタンスです。
このコールバックでは長押ししたタイミングで押している座標(緯度・経度)を検知できます。
public class MainActivity
extends AppCompatActivity
implements OnMapReadyCallback
,GoogleMap.OnMapLongClickListener
{
private GoogleMap map_ = null;
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
MapFragment map = (MapFragment) getFragmentManager().findFragmentById( R.id.map_fragment );
map.getMapAsync( this );
}
/** 初期化検知 */
@Override
public void onMapReady( GoogleMap googleMap )
{
map_ = googleMap;
// 各種コールバック
googleMap.setOnMapLongClickListener( this );
}
/** 長押し検知 */
@Override
public void onMapLongClick( LatLng latLng )
{
Log.i( "MapTest", "LongClick:" + latLng.latitude + "," + latLng.longitude );
}
}
長押しされた場所にピンを立てる
上記2つを合わせてこんな感じです。
public class MainActivity
extends AppCompatActivity
implements OnMapReadyCallback
,GoogleMap.OnMapLongClickListener
{
private GoogleMap map_ = null;
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
MapFragment map = (MapFragment) getFragmentManager().findFragmentById( R.id.map_fragment );
map.getMapAsync( this );
}
@Override
public void onMapReady( GoogleMap googleMap )
{
map_ = googleMap;
// 各種コールバック
googleMap.setOnMapLongClickListener( this );
}
@Override
public void onMapLongClick( LatLng latLng )
{
// ピン立てる
map_.addMarker( new MarkerOptions()
.title( "LongClick!" )
.position( latLng )
.draggable( false ) );
}
}
その他マップの上に矩形を書いたりと言ったこともできるようです。細かい内容は公式のドキュメントを是非確認してください。