|
ニュース検索
ピックアップ
今週のIT求人情報
|
2008年8月22日 10:00
AndroidでのGoogle APIを使った地図表示はじめに地図表示機能は、今日のモバイル端末にとって必須の機能となりました。新技術の発展により、モバイル端末(とりわけ携帯電話)の能力は、複雑な数値計算処理を単体で行ったり、サーバーとの大容量通信を行ったりするのに十分なレベルに達しています。地図表示機能と言えばかつてはGPS機器が主役でしたが、今ではほぼ完全なGPS機能を提供するモバイル端末が非常に増えてきています。GoogleのAndroidでは、Googleのよく知られた地図表示ツールに直接アクセスできます。本稿では、この地図機能を利用するための主なプログラミングAPIを見ていきます。 地図表示用の各種Google APIまず、必要な開発ツール、プラグイン、サンプルコードはすべてGoogle AndroidのWebサイトにあります。このWebサイトには、利用にあたってのわかりやすい説明も掲載されています。まだご覧になっていなければ、ご一読されることをお勧めします。地図表示APIの大半は、com.google.android.mapsパッケージ内にあります。ソフトウェアに地図ツールを組み込むには、MapActivityとMapViewの最低限2つのAPIが必要です。MapActivityは、MapViewの背後でアクティビティのライフサイクルとサービスを管理します。MapViewは、Androidで地図を表示するビューです。これらのAPIのほかに、地図の移動と拡大縮小を行うMapControllerもあります。MyLocationOverlayとOverlayは、地図上にユーザーの設定した情報やオブジェクトを描画するのに使用します。 地図表示を語るうえで、GPSの存在を忘れるわけにはいきません。GPSは今やモバイル端末に欠かせない機能の1つとなっているからです。そこでGPSサポート用には、android.locationパッケージが用意されています。LocationManagerは最も重要なAPIであり、システムロケーションサービスへのアクセスを行います。地図表示とGPSのAPIは、位置情報サービス(LBS)を行うためには欠かせないものです。以降で紹介するサンプルでは、こうしたAPIをできるだけ多く取り上げます。 MapActivityでMapViewを生成するMapViewを生成できるのはMapActivityだけです。なぜなら、MapViewはネットワークとファイルシステムにアクセスするバックグラウンドスレッドに依存しており、このバックグラウンドスレッドはMapActivityによって管理されているからです。そのため、まず次のようにMapActivityを継承するクラスを作成する必要があります。public class TutorialOnMaps extends MapActivity { private static MapView mMapView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); // Get the map view from resource file mMapView = (MapView)findViewById(R.id.mv); } } <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <view id="@+id/mv" class="com.google.android.maps.MapView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#550000ff" android:padding="2px" > <Button id="@+id/sat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="40px" android:text="Satellite" /> (...snipped) </LinearLayout> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="fill_parent" android:background="#550000ff" android:padding="2px" > <Button id="@+id/zin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30px" android:text="+" /> (...snipped) </LinearLayout> </FrameLayout> 図1 指定位置を中心とした初期マップ ![]() 地図の移動、拡大縮小、モードの切り替え先ほど述べたとおり、MapControllerは地図の移動と拡大縮小に使用します。各ボタンをクリックリスナーに関連付ける必要があります。以下はその一例です。// Set up the button for "Pan East" mPanE = (Button)findViewById(R.id.pane); mPanE.setOnClickListener(new OnClickListener(){ // @Override public void onClick(View arg0) { panEast(); } }); panEast()関数は、画面サイズの4分の1の幅で地図を動かします。その他の移動も同様に行われます。実際には、タッチスクリーンLCDが搭載されている機器の場合は、この地図だけでドラッグ可能です。タッチスクリーンが搭載されていない機器では、画面上のボタンかパッドの矢印キーを使って地図を動かします。panEast()関数のコードは次のとおりです。public void panEast() { Point pt = new Point( mMapView.getMapCenter().getLatitudeE6(), mMapView.getMapCenter().getLongitudeE6() + mMapView.getLongitudeSpan() / 4); mMapView.getController().centerMapTo(pt, true); } public void zoomIn() { mMapView.getController().zoomTo(mMapView.getZoomLevel() + 1); } public void toggleSatellite() { mMapView.toggleSatellite(); } public void toggleTraffic() { mMapView.toggleTraffic(); } 図2 衛星画像 ![]() 図3 衛星画像上での渋滞状況表示 ![]() 現在のMapViewの情報を取得するMapViewが正しく作成されれば、表示中の画面に関するさまざまな情報を取得できるようになります。表示中の地図のステータスを把握するのに役立つ主な関数を次に示します。
利用者が設定した情報をMapView上に表示する基本クラスのOverlayは、地図上に重ねるオーバーレイを表します。オーバーレイは、地図上にカスタムグラフィックオブジェクトを描画して表示するために使用します。実際のコードでは、基本的にdraw()メソッドをオーバーライドして、デフォルト位置に円を描き、キャプションを透明な角丸長方形のボックスで囲むようにします。オーバーライドした draw()メソッドのコードを次に示します。このコードでは、位置から画面座標への変換(PixelCalculatorを使用)、フォントメトリクスの計算(PaintのmeasureText()を使用)、アンチエイリアス処理したテキストの描画(PaintのsetAntiAlias()を使用)といった処理を行っています。// This is used draw an overlay on the map protected class MyOverlay extends Overlay { @Override public void draw(Canvas canvas, PixelCalculator pc, boolean shadow) { super.draw(canvas, pc, shadow); if (mDefCaption.length() == 0) { return; } Paint p = new Paint(); int[] scoords = new int[2]; int sz = 5; // Convert to screen coords pc.getPointXY(mDefPoint, scoords); // Draw point caption and its bounding rectangle p.setTextSize(14); p.setAntiAlias(true); int sw = (int)(p.measureText(mDefCaption) + 0.5f); int sh = 25; int sx = scoords[0] - sw / 2 - 5; int sy = scoords[1] - sh - sz - 2; RectF rec = new RectF(sx, sy, sx + sw + 10, sy + sh); p.setStyle(Style.FILL); p.setARGB(128, 255, 0, 0); canvas.drawRoundRect(rec, 5, 5, p); p.setStyle(Style.STROKE); p.setARGB(255, 255, 255, 255); canvas.drawRoundRect(rec, 5, 5, p); canvas.drawText(mDefCaption, sx + 5, sy + sh - 8, p); // Draw point body and outer ring p.setStyle(Style.FILL); p.setARGB(88, 255, 0, 0); p.setStrokeWidth(1); RectF spot = new RectF(scoords[0] - sz, scoords[1] + sz, scoords[0] + sz, scoords[1] - sz); canvas.drawOval(spot, p); p.setARGB(255, 255, 0, 0); p.setStyle(Style.STROKE); canvas.drawCircle(scoords[0], scoords[1], sz, p); } } // Set up the overlay controller mOverlayController = mMapView.createOverlayController(); MyOverlay mo = new MyOverlay(); mOverlayController.add(mo, true); 図4 オーバーレイで地図上にラベルを表示 ![]() 現在のGPS位置情報と統合するandroid.locationは、ロケーションプロバイダの一覧を検索して、現在位置の定期的な更新を行うための登録ができるAPIを含んだパッケージです。各ロケーションプロバイダは、/data/misc/location/<provider_name>ディレクトリ配下のファイルを随時更新します。したがって、デフォルトのダミーGPSプロバイダ「gps」の情報は、エミュレータ上では/data/misc/location/gps/に置かれます。GPSファイルの形式はプロバイダごとに異なる可能性があります。詳細な情報については、Androidのサイトを参照してください。LocationManagerを初めてアクティブにするときは、初期化を行うために多少時間がかかりますので注意してください。その後に続く呼び出しは、すぐに応答があります。次のコードは、プロバイダからのGPS位置情報を取得して、MapViewのコントローラに送る方法を示しています。 private void centerOnGPSPosition() { String provider = "gps"; LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); // NOTE: When LocationManager is called the first time, // lat / lon is initialized to 0. // Subsequent calls are fine and fast. Location loc = lm.getCurrentLocation(provider); mDefPoint = new Point((int)(loc.getLatitude() * 1000000), (int)(loc.getLongitude() * 1000000)); mDefCaption = "GPS location"; mMapView.getController().animateTo(mDefPoint); mMapView.getController().centerMapTo(mDefPoint, true); } 図5 オーバーレイで地図上にGPS情報を表示 ![]() まとめここまでの解説を読んで、この地図表示ソフトを試してみたい、独自の機能を追加してみたいと思った読者は多いのではないでしょうか。このソフトウェアパッケージは、本稿のダウンロードサンプルに収録されています。サンプルプロジェクトをEclipseにインポートするだけで使えます。Androidの地図表示APIは、既に普及しているGoogleのツールに直接アクセスできるため、簡単に使えてしかも強力です。Androidとより高度なAPIが発展していくにつれて、より多くの地図表示機能がAndroidプラットフォームに移植されることになるでしょう。私が思いつくだけでも、次のようなアイデアがあります。皆さんもぜひ挑戦してみてください。
参考資料著者紹介Chunyen Liu(Chunyen Liu)
世界トップのGPS企業のエンジニアリング部門に在籍。SUN、ACM、IBMの主催するプログラミングコンテストで複数の入賞経験がある。コンピュータサイエンスの上級学位を保有し、The J Makerという個人サイトを運営。このほか、卓球の腕前は競技者レベルであり、アメリカ卓球協会認定の審判員、指導員という一面も持つ。メールの宛先はこちら。
![]()
新着ニュース・コラム ホワイトペーパー
|
注目のトピックス 話題の記事
Android スマートフォンを Ubuntu デスクトップに― 「Ubuntu for Android」
ソフトバンク、下り最大 110Mbps の「SoftBank 4G」を2月24日開始
iPhone で SD カードの写真/動画が見られる Wi-Fi SD カードリーダー「AirStash(エアスタッシュ)」
新潟では54cm、東京では7cm の積雪で生活に影響―ウェザーニューズ「積雪×生活調査」を発表
USB ハブ「どっちもハブ」、挿す向きを気にせずイライラ解消
⇒一覧を見る
アクセスランキング
最新コラム一覧
|
||||||||||||||||||||||||