[[ワーキンググループ/ハンズオンセッション]] * Google Mapを使ってみよう [#w60534b8] AndroidでGoogle Maps を使用したアプリケーションを作成してみましょう。 Androidには、MapView, MapActivityというGoogle Mapを簡単使用するクラスが用意されています。 ** 作成するアプリケーション [#q733d8f1] Android上に地図を表示して、タップした位置にアイコンを描画するアプリです。 以下のページを参考にしながら、作成することができます。 http://developer.android.com/guide/tutorials/views/hello-mapview.html ここでは、上記のページの一部を簡略化したサンプルを作成してみます。 Google Map APIのドキュメントは、以下のサイトで参照することができます。 http://code.google.com/intl/ja/android/add-ons/google-apis/ ** 作成手順の概略 [#h3cecb24] アプリケーションを作成する手順の概略です。 - Google MapsのAPIキーを取得します -- アプリに署名する証明書が必要です - 新規のプロジェクトを作成します -- Google APIを選択します - マニフェストファイルを設定します -- ライブラリやパーミッションの設定が必要です - MapViewで地図を表示します -- 取得したAPIキーを使用します - MapActivityで地図の表示を制御します -- ズームコントローラで地図の拡大縮小できます - タップされた位置にアイコンを描画します -- Overlayクラスで地図上に描画できます ** Google MapsのAPIキー取得 [#da7ada73] Google MapsはGoogleが提供するWeb上のサービスです。Androidでは、このサービスにアクセスするための専用のライブラリが提供されています。 このライブラリは、Googleが提供しているものであり、オープンソースのAndroidの一部ではありません。このため、このライブラリを使用するには、Googleに開発者としての登録を行う必要があります。登録を行うと、APIキーという文字列が発行されます。この文字列をアプリケーション内に組み込みむことで、サービスにアクセスすることが可能になります。 APIキーの取得には、アプリケーションの開発時に使用する証明書のハッシュが必要になります。証明書とは、開発者の名前や所属に、秘密鍵で署名したものです。 #ref(Ceart.png) Androidのアプリケーションのパッケージには、開発者自身の証明書による署名が必要になります。デバッグには、開発ツールが自動的に作成した証明書が使用されてるのであまり意識することがありませんが、エミュレータや携帯端末の実機に転送する前に常に署名がおこなわれています。 証明書のMD5のハッシュは、SunのJDKに含まれているkeytoolという証明書操作用のツールを使用します。まずは、keytoolがインストールされているか、以下のコマンドを実行して確認しましょう。 > keytool -help もし、コマンドが見つからない場合には、JDKをインストールしたディレクトリのbinディレクトリを確認してみましょう。以下の、%JAVA_HOME%をJDKをインストールしたディレクトリに置き換えて実行してみましょう。うまく実行できれば、PATH環境変数に、%JAVA_HOME%\binを追加しておきます。 > "%JAVA_HOME%\bin\keytool" -help ... つぎに、使用している証明書のMD5のハッシュを取ります。デバッグ時に使用される証明書は、使用しているOSに応じて、以下の場所に格納されています。 - OS X ~/.android/debug.keystore - Linux ~/.android/debug.keystore - SDK1.1 Windows -- Windows Vista C:\Users\%USERNAME%\AppData\Local\Android\debug.keystore -- Windows XP C:\Documents and Settings\%USERNAME%\Local Settings\Application Data\Android\debug.keystore - SDK1.5 Windows -- Windows Vista C:\Users\%USERNAME%\.android\debug.keystore -- Windows XP C:\Documents and Settings\%USERNAME%\.android\debug.keystore keytoolの-listコマンドで証明書の一覧を表示します。例えば、SDK1.5のVistaの場合には、以下のコマンドを実行します。パスワードは、入力しないで単純にリターンを押すだけで大丈夫です。(入れたい人は、"android"と入れてください) > keytool -list -keystore C:\Users\%USERNAME%\.android\debug.keystore キーストアのパスワードを入力してください: android キーストアのタイプ: JKS キーストアのプロバイダ: SUN キーストアには 1 エントリが含まれます。 androiddebugkey, 2008/10/14, PrivateKeyEntry, 証明書のフィンガープリント (MD5): 4B:28:72:FB:D3:2C:86:D5:A5:F8:B4:BA:09:C3:90:29 ここで表示されたフィンガープリントを、以下のページで入力します。 - http://code.google.com/intl/ja/android/maps-api-signup.html #ref(AndroidMapsAPI.jpg) 生成したフィンガープリントは、後で使用するので、控えておきます。 #ref(AndroidMapsAPIKey.jpg) アプリケーションの署名は、端末のインストール時と、マーケットへのアップロード時に確認されます。 #ref(Sign.png) * プロジェクトの作成 [#n00544cc] 必要に応じて、File > New > Android Projectで新規のプロジェクトを作成します。 ここでは、以下のようなプロジェクトを作成してみます。 #ref(Project.jpg) |Project Name|HelloMapProject| |Build Target|Google APIs| |Application Name|HelloMap| |Package Name|jp.hews.hellomap| |Create Activity|HelloMapActivity| |Min SDK Version|3(Build Targetを指定すると自動的に設定される)| * マニフェストファイルの設定 [#t8718dce] 地図を使用するには、マニフェストのapplication内にライブラリを使用するを宣言します。 EclipseのGUIでは、AndroidManifestのApplicationタブの下の「Application Nodes」で設定します。 - <uses-library android:name="com.google.android.maps" /> #ref(UsesLibrary.jpg) また、インターネットに接続するために、同じくマニフェスト内で以下のパーミッションの使用を宣言します。 EclipseのGUIでは、AndroidManifestのPermissionタブで設定します。 - <uses-permission android:name="android.permission.INTERNET" /> #ref(Permission.jpg) * レイアウトの作成 [#hbc54666] - レイアウトリソースファイル(res/layout/main.xml)を以下のように書き換えます。 - レイアウトリソースファイル(res/layout/main.xml)を以下のように書き換えます。 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <com.google.android.maps.MapView android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="取得したAPI Key" /> </LinearLayout> * MapViewクラスを作成する [#y1861223] - MapViewクラスを表示して、MapActivityを継承させます。これによって、MapViewの制御をこのクラスが行えるようになります。(Shift-Ctrl-Oでcom.google.android.maps.MapActivityをインポートします。) public class HelloMapView extends MapActivity - Add unimplement methodを使用して、isRouteDisplayedメソッドをオーバーライドします。 @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } ここで、アプリケーションを実行して、地図が表示されることを確認しましょう。もし、地図が表示されてない場合には、以下の項目を確認してみましょう。 - SDKにあらかじめインストールされているMapアプリケーションで地図が表示されるか確認する。 -- 表示されてなけば、ネットワークの設定などOSの設定を確認する。Proxyが設定されていると、表示できないので注意する。 - MapのAPIキーが正しく入力されているか確認する。APIキーの取得は何度でも行えるので、再度取得し直してみる。 - 使用している証明書が正しいか確認する。Windowsでは、SDK1.1からSDK1.5で証明書の位置が変更になっているので、注意する * ズームコントローラを配置する。 [#sace11bc] コンストラクタを以下のように変更します。 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); MapView mapView = (MapView) findViewById(R.id.mapview); mapView.setBuiltInZoomControls(true); } 実行して、地図を表示してみましょう。タップするとズームコントローラが表示されます。 * 初期値を設定する [#g221fed4] 以下のフィールドを定義します。 // ログ出力用のタグ static final String TAG = "HelloMapActivity"; // 地図の初期値 static final int INITIAL_ZOOM_LEVE = 16; static final int INITIAL_LATITUDE = 36564000; static final int INITIAL_LONGITUDE = 136661000; コンストラクタに最後に、以下の行を追加します。 // 位置とズームレベルの初期状態を設定する MapController controller = mapView.getController(); GeoPoint point = new GeoPoint(INITIAL_LATITUDE, INITIAL_LONGITUDE); controller.setCenter(point); controller.setZoom(INITIAL_ZOOM_LEVE); 実行してみましょう。 * タップされた位置にアイコンを描画する [#fd4b61bb] Overlayクラスを使用して、地図上に描画できます。 コンストラクタの最後に以下の呼び出しを追加します。 // イメージを地図上に表示する setOverlay(point); 以下のプライベートメソッドを定義します。 ここでは、アプリケーションのアイコンを地図上に描画するので、アプリケーションのアイコンを好きな柄に書き換えておきましょう。 private void setOverlay(GeoPoint point) { // Overlayクラスを生成する Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.icon); IconOverlay overlay = new IconOverlay(icon, point); // 生成したOverlayクラスを追加する MapView map_view = (MapView) findViewById(R.id.mapview); List<Overlay> overlays = map_view.getOverlays(); overlays.add(overlay); } // 地図上に表示されるオーバーレイ private class IconOverlay extends Overlay { // 描画するアイコン Bitmap mIcon; int mOffsetX; int mOffsetY; // アイコンを表示する位置 GeoPoint mPoint; IconOverlay(Bitmap icon, GeoPoint initial) { // アイコンと、アイコンの中心のオフセット mIcon = icon; mOffsetX = 0 - icon.getWidth() / 2; mOffsetY = 0 - icon.getHeight() / 2; mPoint = initial; } // 地図のタップ時に呼び出される @Override public boolean onTap(GeoPoint point, MapView mapView) { // タップされた位置を記録する mPoint = point; Log.i(TAG, "Point = " + point.getLatitudeE6() + " , " + point.getLongitudeE6()); return super.onTap(point, mapView); } // 地図の描画時に、shadow=true, shadow=falseと2回呼び出される @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { super.draw(canvas, mapView, shadow); if (!shadow) { // 地図上の場所と、描画用のCanvasの座標の変換 Projection projection = mapView.getProjection(); Point point = new Point(); projection.toPixels(mPoint, point); point.offset(mOffsetX, mOffsetY); // アイコンを描画 canvas.drawBitmap(mIcon, point.x, point.y, null); } } }; 実行してみましょう。 ---- [[ワーキンググループ/ハンズオンセッション]]