Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 1 prohibition of copy or reproduction
4. 演習プログラム2の作成
4-1. 演習プログラム2の概要 GoogleMapアプリケーション
GoogleMapを表示させ、現在地について GPS情報を中心とした地図を表示。
機能
• ToggleButtonのチェック状態による、中心点制御
• TextEditからの地図検索
• Overlayを使用した、自宅から目的地までの直線描画
画面
• GoogleMap画面
• 設定画面
4-2. プロジェクトの準備 4-2-1. 作成 メニューバーより選択、新規作成⇒Android Project
↓のウィンドウが表示される。
図 1 プロジェクト作成
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 2 prohibition of copy or reproduction
• プロジェクト名:MapSample
• ビルド・ターゲット:Google APIs プラットフォーム 2.1チェック
• アプリケーション名:MapSample
• パッケージ名:jp.co.deltawing.mapsample
• Create Activity にチェック MapSampleと入力
• Min SDK Version:4
4-2-2. API Keyの取得 コマンドプロンプトを起動し、インストールした JavaJDKの keytool.exeと
AndroidSDK内の、debugkeystoreを起動させる。
コマンドラインは、-list -keystore を指定する。
尚、AndroidSDK内の debugkeystoreの位置は、Eclipse内に記載。
ウィンドウ⇒設定⇒Android⇒Default debug keystoreに表記。
図 2 Default debug keystore
"C:¥Program Files¥Java¥jre¥bin¥keytool.exe" -list -keystore
Vista または 7 :"C:¥Users¥%USERNAME%¥.android¥debug.keystore"
XP:”C:¥Documents and Settings¥%USERNAME%¥.android¥debug.keystore”
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 3 prohibition of copy or reproduction
図 3 フィンガープリントの取得
証明書のフィンガープリントを下記URLに記載する。
http://code.google.com/android/maps-api-signup.html
I have read and agree with the terms and conditions (printable version)
同意の為、チェックボックスをチェック。
My certificate's MD5 fingerprint:欄へ、先ほどのフィンガープリントを入力する。
Generate API Keyをクリック。
• Googleへ未ログイン状態では、ログイン画面に移動し、ログインすれば取得できます。
図 4 Android Maps APIキーの取得
APIキーは、設定にて使用しますので、残しておく事。
• 文字化けする可能性がありますが、キー取得に関しては問題ありません。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 4 prohibition of copy or reproduction
4-3. AndroidManifestの作成 4-3-1. GoogleAPIの使用について
GoogleMapを使用するための API。
Googleから提供されている APIではありますが、標準で Androidの中に組み込まれている APIではなく外部 APIになります。
現在の GoogleMapの使用制限で、日本は地図・ジオコーディング・ストリートビューなどに対応されてますが、ルート検索機能の範囲には含まれていません。
ここで使用するMapsパッケージは ViewGroupeのサブクラスです。
また、組み合わせることで様々なカスタマイズを行えます。
GoogleAPIを使用するために
• MapSample直下にある、AndroidManifestをダブルクリックし開く。
• GoogleAPIを使用する為に、AndroidManifestにて、使用する宣言をします。
• アプリケーションのタブを選択。
• 追加ボタンを押すと、ウィンドウが表示。
• Uses Libraryを選択。
• Name欄の、プルダウンから、「com.google.android.maps」を選択。
図 5 GoogleAPIの使用
4-3-2. AndroidManifestへ、Permissionの記載 Permissionについて
Androidでは、基本的にデバイスに関わっている機器を利用する場合は Permissionが必要となります。
アクション Intentを利用する上では、Activityと連携をさせる為の利用許可を記載する。
Permissionを追加するには、許可のタブを選択すると下の画面になります。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 5 prohibition of copy or reproduction
図 6 Android Manifestへ Permissionの記載
追加ボタンを押すと、種類を聞かれるので、Uses Permissionを選択。
ここでは、4つの Permissionを追加します。
それぞれの意味は、以下の通りです。
<!-- インターネットアクセスに必要なManifest宣言 -->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<!-- GPS情報取得に必要なManifest宣言 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!—取得した GPS情報をエミュレータで使用する為のManifest宣言 -->
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"></uses-permission>
<!-- コースロケーションサービスへのManifest宣言 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
4-4. リソースファイルの定義 4-4-1. valuesを設定する
Res.value.stringsの設定を行います。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 6 prohibition of copy or reproduction
このファイルは、Activity内で使用する文字列を定義しておくことができます。
4-4-2. res.values.strings.xml 初期に作成されているファイルで、ボタン名称など固定の文字を定義します。
図 7 res.values.strings.xmlの設定
strings.xmlを開くと、ソースを表示。
〔strings.xml〕
ソース 4-4-2-1_values.txt
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="hello">Hello World, MapSample!</string>
<string name="app_name">MapSample</string>
<string name="api_key">【①プロジェクトの作成で取得した APIキー】</string>
<string name="button01_name">Now Location</string>
<string name="button02_name">Destination</string>
<string name="button03_name">Home</string>
<string name="select02_title">Please Select Location</string>
<string name="select02_hint">Please Input Location</string>
<string name="setting_title">Settings</string>
<string name="setting_home_title">Home Address</string>
<string name="setting_home_summary">Enter Home Address</string>
<string name="menu_settings">Settings</string>
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 7 prohibition of copy or reproduction
4-4-3. res.values-ja.strings.xml 日本語として、表示される設定。
resを右クリック。
新規⇒フォルダ⇒フォルダ名:values-ja
values-jaを右クリック。
新規⇒Android XML File⇒ファイル名:strings.xml
作成した strings.xmlをダブルクリック。
図 8 res.values-ja.strings.xml
strings.xmlを開くと、ソースとして表示されます。
〔strings.xml〕
<resources>
<string name="hello">Hello World, MapSample!</string>
<string name="app_name">MapSample</string>
<string name="api_key">【①プロジェクトの作成で取得した APIキー】</string>
<string name="button01_name">現在位置</string>
<string name="button02_name">目的地</string>
<string name="button03_name">自宅</string>
<string name="select02_title">目的地を選択してください</string>
</resources>
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 8 prohibition of copy or reproduction
<string name="select02_hint">目的地を入力</string>
<string name="setting_title">設定</string>
<string name="setting_home_title">自宅住所</string>
<string name="setting_home_summary">自宅住所を入力</string>
<string name="menu_settings">設定</string>
</resources>
ソース 4-4-3-1_values-ja.txt 4-4-4. menuを設定する。
Menuボタンを押した際のメニュー項目を設定。
今回は一項目を設定をします。
以下、設定ファイルを準備します。
res.menu.menu.xml
resを右クリック
新規⇒フォルダ⇒フォルダ名を menuとし、作成。
menuフォルダを右クリック
新規⇒Android XML File⇒ファイル名:menu、作成。
作成した、menu.xmlをダブルクリック。
menu.xmlに以下を記載。
図 9 res.menu.menu.xml
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 9 prohibition of copy or reproduction
stringsと同様に、menu.xmlを開き、ソースを表示。
〔menu.xml〕
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_settings" android:title="@string/menu_settings"></item>
</menu>
ソース 4-4-4-1_menu.txt 4-4-5. 画像を用意する 以下、使用する画像を読み込ませます。
下記URLに用意してある画像をドロップアンドドラッグします。
画像ダウンロードサイト:http://delta-t20-2/e-text/MapSample/drawable/
resを右クリック。
フォルダを作成、フォルダ名:drawable
drawableフォルダに先ほど、ダウンロードした画像を追加します。
Mapstart9.png mapgoal9.png mappoint.9.png
図 10 drawable 4-5. 画面作成 4-5-1. 画面作成
Androidの画面は、res/layoutに格納してある xmlファイルを編集します。
このファイルは画面定義の為のファイルになります。
MapSample.res.layout.main.xmlをダブルクリックし、表示。
レイアウトのタブを選択することによって、視覚的に編集することが可能です。
今回は、3つのレイアウトに分けて構成します。
上部に情報の表示、中段に移動項目、下段に実際の GoogleMapを表示させます。
各部分に配置するイベントは以下の通りです。
画面の構成
レイアウト:全画面のレイアウト(LinearLayout)
1段目:Map中心点のレイアウト(LinearLayout)
1-1段目:Map中心点のボタン(ToggleButton)
1-2段目:現在地の住所表示(TextView)
2段目:目的地検索のレイアウト(LinearLayout)
2-1段目:目的地の検索文字列(EditText)
2-2段目:EditTextの検索ボタン(Button)
2-3段目:自宅呼び出しボタン(Button)
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 10 prohibition of copy or reproduction
3段目:GoogleMapを表示する為のビュー(MapView)
図 11 mainレイアウト
main.xmlタグで、ソースを表示
〔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"
>
<LinearLayout
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ToggleButton
android:text="@string/button01_name"
android:layout_width="fill_parent"
android:layout_weight="3"
android:id="@+id/Button01"
android:textOff="@string/button01_name"
android:textOn="@string/button01_name"
android:layout_height="wrap_content"
>
</ToggleButton>
<TextView
android:layout_width="fill_parent"
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 11 prohibition of copy or reproduction
android:text="@string/hello"
android:id="@+id/TextView01"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:id="@+id/LinearLayout02"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/EditText02"
android:layout_width="fill_parent"
android:layout_weight="2"
android:layout_height="wrap_content"
android:hint="@string/select02_hint"
android:inputType="textPostalAddress">
</EditText>
<Button
android:id="@+id/Button02"
android:text="@string/button02_name"
android:layout_width="fill_parent"
android:layout_weight="3"
android:layout_height="wrap_content">
</Button>
<Button
android:id="@+id/Button03"
android:text="@string/button03_name"
android:layout_width="fill_parent"
android:layout_weight="3"
android:layout_height="wrap_content">
</Button>
</LinearLayout>
<com.google.android.maps.MapView
android:id="@+id/MapView01"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:enabled="true"
android:clickable="true"
android:apiKey="@string/api_key"
android:layout_weight="1"/>
</LinearLayout>
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 12 prohibition of copy or reproduction
ソース 4-5-1-1_main.txt 4-6. MapActivity 4-6-1. インポート宣言 今回使用する APIをインポートします。
〔MapSample.java〕
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
ソース 4-6-1-1_Import.txt 4-6-2. GoogleMapの使用準備
GoogleMapを表示させるために、ViewクラスのサブクラスとしてあるMapViewクラスを使用します。
通常は、Activityクラスを使いますが、MapViewを使いたい場合はMapActivityを使用します。
MapActivityは Activityクラスのサブクラスであり、Activityと同じサイクルを持ちます。 extends Activity を MapActivityへ変更。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 13 prohibition of copy or reproduction
〔MapSample.java〕
public class MapSample extends MapActivity{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MapView mapview = (MapView) findViewById(R.id.MapView01);
mapview.setEnabled(true);
mapview.setClickable(true);
mapview.setBuiltInZoomControls(true);
MapController mapctrl = mapview.getController();
mapctrl.setZoom(18);
}
}
ソース 4-6-2-1_MapActivity.txt 解説:
mapview.setEnabled(true)
• 表示させるかどうかを設定。
mapview.setClickable(true)
• スクリーンタッチに反応するかを設定。
mapview.setBuiltInZoomcontrols(true)
• ズームコントローラを設定。
mapctrl.setZoom(18);
• ズーム倍率を設定。
未実装メソッドがあるため、isRouteDisplayerメソッドが追加されます。
〔MapSample.java〕
protected boolean isRouteDisplayed() {
return false;
}
ソース 4-6-2-2_isRouteDisplayed.txt 4-7. GPS情報に関して
GPS(Global Positioning System)を組み合わせる事で、現在位置に応じたアプリケーションを作ることができます。
Androidでは、携帯電話の現在位置を取得するサービスを、位置情報サービス(LBS:Location-Based Services)と呼んでます。
精度としては、室内や都心などでは誤差が大きくなってしまいますが、Wi-Fiを使用するなど、精度を高める事もできます。
4-7-1. GeoPointについて GeoPointとは、地図上の位置を表す点情報を保持するクラス。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 14 prohibition of copy or reproduction
緯度・経度を Int型で保持し、Map上の座標の指定や取得に使用します。
GeoPointを使用する事で、ジオコーディングなどの処理を行う。具体的な方法は後述。
GeoPointは GPS情報を整数で設定されるが、LocationManagerクラスの GPS情報は少数第 6位までの数字の為、用途によって変換の必要がある。
GeoPointと LocationManagerを、クラス変数として、宣言します。
〔MapSample.java〕
4-7-2. Button01のイベントを設定 Button01をMapSample内へ定義します。
このボタンにはトグルボタンを割り当て。トグルボタンのチェック状態により、マップの移動を制御。ToggleButtonがチェック状態になった時、animateToメソッドにて、地図を中心に表示させます。
onCreateメソッドへボタンイベントを設定。
〔MapSample.java〕
m_LocationManager = (LocationManager)getSystemService( LOCATION_SERVICE );
final ToggleButton button01 = (ToggleButton) findViewById(R.id.Button01);
button01.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if( button01.isChecked() ) {
if( m_SrcPoint != null ) {
mapview.getController().animateTo(m_SrcPoint);
}
}
}
});
button01.setChecked(true);
ソース 4-7-2-1_button01.txt 解説:
mapview.getController().animateTo( GeoPoint point );
• pointを中心とした地図へ移動
mapview.invalidate()
• 前回描画したものを消す
private LocationManager m_LocationManager;
private String m_Provider = LocationManager.GPS_PROVIDER;
private GeoPoint m_SrcPoint;
private GeoPoint m_DstPoint;
ソース 4-7-1-1_Location.txt
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 15 prohibition of copy or reproduction
4-7-3. LocationListenerの実装 GPSの位置情報取得の際、呼び出されるメソッドを実装します。
匿名クラスで作成する事も可能です。
ただしエミュレータ上では、任意で GPS情報を送信してやらなければ、Nullが入ります。
今回はMapSampleに implementsします。
実装すると 4つのメソッドのオーバーライドを要求されます。
〔MapSample.java〕
public class MapSample extends MapActivity implements LocationListener{
private long m_MinTime = 10000;
private float m_MinDistance = 5;
public void onLocationChanged(Location location) {
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
ソース 4-7-3-1_LocationListener.txt 4-7-4. onLocationChanged(Location location)メソッドの設定 ロケーション情報が変更された際に、呼び出されるメソッドです。
ToggleButtonでロケーションが変更された時の処理を判定。
ToggleButtonがチェック状態であれば、ロケーションを中心に地図が表示されます。
ロケーションが変更された事を、Toastにて表示するので、onLocationChangerdメソッドに設定します。
〔MapSample.java〕
public void onLocationChanged(Location location) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
m_SrcPoint = new GeoPoint( (int)(latitude * 1E6),(int)(longitude * 1E6));
MapView mapview = (MapView) findViewById(R.id.MapView01);
ToggleButton button01 = (ToggleButton) findViewById(R.id.Button01);
if( button01.isChecked() ) {
if( m_SrcPoint != null ) {
mapview.getController().animateTo( m_SrcPoint );
}
}
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 16 prohibition of copy or reproduction
//
// m_routeoverlay.setRoutePoint( m_SrcPoint, m_DstPoint );
mapview.invalidate();
String message = "onLocationChanged:"
+ m_SrcPoint.getLatitudeE6()
+ "," + m_SrcPoint.getLongitudeE6();
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
ソース 4-7-4-1_onLocationChanged.txt 解説:
m_SrcPoint = new GeoPoint( (int)(latitude * 1E6),(int)(longitude * 1E6));
整数にする為、1E6を掛けます。
4-7-5. onProviderDisabled(String provider)の設定 プロバイダが使用不可の際に、呼び出される。
ロケーションの更新処理を制御する為、クラス変数として宣言。
プロバイダーが GPSプロバイダーかを判定し、GPSプロバイダーが使用できない場合、ネットワークプロバイダーを設定します。
〔MapSample.java〕
public void onProviderDisabled(String provider) {
String message = "LocationListener#onProviderDisabled : provider=" + provider;
String oldProvider = m_Provider;
if( provider.equals( m_Provider ) ) {
m_LocationManager.removeUpdates( this );
m_Provider = null;
if( oldProvider.equals( LocationManager.GPS_PROVIDER ) ) {
if(m_LocationManager.isProviderEnabled
(LocationManager.NETWORK_PROVIDER ) ) {
m_Provider=LocationManager.NETWORK_PROVIDER;
}
}
if( m_Provider != null ) {
m_LocationManager.requestLocationUpdates
(m_Provider,m_MinTime,m_MinDistance, this);
message = message + ", change to NETWORK_PROVIDER";
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
}
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 17 prohibition of copy or reproduction
ソース 4-7-5-1_onProviderDisabled.txt 解説:
m_LocationManager.requestLocationUpdates
(m_Provider,m_MinTime,m_MinDistance, this);
• minTime・minDistanceによって設定した間隔で更新をする。
m_LocationManager.removeUpdates( this );
• requestLocationUpdatesの更新を中止する。
4-7-6. onProviderEnabled(String provider)の設定 プロバイダを使用可能な状態になった際に、呼び出される。
GPS_PROVIDERを優先的に使用し、使用できなかった場合、NETWORK_PROVIDERを使用する設定をしています。
〔MapSample.java〕
public void onProviderEnabled(String provider) {
String message = "LocationListener#onProviderEnabled : provider=" + provider;
if(m_Provider==null){
if( m_LocationManager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
m_Provider = LocationManager.GPS_PROVIDER;
message = message + ", enable to GPS_PROVIDER";
}else if(m_LocationManager.isProviderEnabled
(LocationManager.NETWORK_PROVIDER ) ) {
m_Provider = LocationManager.NETWORK_PROVIDER;
message = message + ", enable to NETWORK_PROVIDER";
}
if( m_Provider != null ) {
m_LocationManager.requestLocationUpdates
(m_Provider , m_MinTime , m_MinDistance, this);
Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}
}else if(provider.equals(LocationManager.GPS_PROVIDER)&&
m_Provider.equals( LocationManager.NETWORK_PROVIDER ) ) {
m_LocationManager.removeUpdates( this );
m_Provider = null;
if(m_LocationManager.isProviderEnabled
(LocationManager.GPS_PROVIDER) ) {
m_Provider = LocationManager.GPS_PROVIDER;
}
if( m_Provider != null ) {
m_LocationManager.requestLocationUpdates
(m_Provider , m_MinTime , m_MinDistance, this);
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 18 prohibition of copy or reproduction
message = message + ", change to GPS_PROVIDER";
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
}
ソース 4-7-6-1_onProviderEnabled.txt 4-7-7. onStatusChanged(String provider, int status, Bundle extras)の設定 プロバイダ状態が変更された際に、呼び出される。
Toastにて選択されているプロバイダを表示。
〔MapSample.java〕
public void onStatusChanged(String provider, int status, Bundle extras) {
String message="LocationListener#onStatusChanged : provider=" + provider;
switch (status) {
case LocationProvider.AVAILABLE:
message = message + ", status=AVAILABLE";
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
break;
case LocationProvider.OUT_OF_SERVICE:
message = message + ", status=OUT_OF_SERVICE";
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
message = message + ", status=TEMPORARILY_UNAVAILABLE";
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
break;
}
}
ソース 4-7-7-1_onStatusChanged.txt 4-7-8. ベースクラスの設定
onResume:Activityがユーザ操作可能となった際に呼び出される。
操作が可能となった時、プロバイダーをセット。
プロバイダーのセットをした折、ロケーションの更新と取得を行う。
MapSample のクラスメソッドとして宣言。
〔MapSample.java〕
protected void onResume() {
if( m_LocationManager != null ) {
m_Provider = null;
if( m_LocationManager.isProviderEnabled
( LocationManager.GPS_PROVIDER ) ) {
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 19 prohibition of copy or reproduction
m_Provider = LocationManager.GPS_PROVIDER;
}else if(m_LocationManager.isProviderEnabled
(LocationManager.NETWORK_PROVIDER ) ) {
m_Provider = LocationManager.NETWORK_PROVIDER;
}
if( m_Provider != null ){
m_LocationManager.requestLocationUpdates
(m_Provider,m_MinTime,m_MinDistance,this);
Location location = m_LocationManager.getLastKnownLocation( m_Provider );
if(location != null) {
onLocationChanged(location);
}
}
MapView mapview = (MapView) findViewById(R.id.MapView01);
// m_routeoverlay.setRoutePoint( m_SrcPoint, m_DstPoint );
mapview.invalidate();
}
super.onResume();
}
ソース 4-7-8-1_onResume.txt 解説:
Location location = m_LocationManager.getLastKnownLocation( m_Provider );
• 一番最後に取得した GPS情報を取得する。
onPause:Activityがユーザ操作不可能となった際に呼び出される。
ユーザが操作不可能な時は、更新処理を止めます。
MapSample のクラスメソッドとして宣言。
〔MapSample.java〕
protected void onPause() {
if( m_LocationManager != null ) {
m_LocationManager.removeUpdates( this );
}
super.onPause();
}
ソース 4-7-8-2_onPause.txt onDestroy:Activityが破棄される直前のタイミングで呼び出される。
MapSample のクラスメソッドとして宣言。
〔MapSample.java〕
protected void onDestroy() {
MapView mapview = (MapView) findViewById(R.id.MapView01);
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 20 prohibition of copy or reproduction
// mapview.getOverlays().remove( m_routeoverlay );
super.onDestroy();
}
ソース 4-7-8-3_onDestroy.txt 本体の向きを変更する場合、保持している値が破棄されてしまうのを防ぐ処置を設定します。
onSaveInstanceState:Activityのインスタンス情報を保存させるためのメソッド。
MapSample のクラスメソッドとして宣言。
〔MapSample.java〕
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
int latitude;
int longitude;
if( m_SrcPoint != null ) {
latitude = m_SrcPoint.getLatitudeE6();
longitude = m_SrcPoint.getLongitudeE6();
outState.putInt("m_SrcPoint_latitude", latitude);
outState.putInt("m_SrcPoint_longitude", longitude);
}
if( m_DstPoint != null ) {
latitude = m_DstPoint.getLatitudeE6();
longitude = m_DstPoint.getLongitudeE6();
outState.putInt("m_DstPoint_latitude", latitude);
outState.putInt("m_DstPoint_longitude", longitude);
}
}
ソース 4-7-8-4_onSaveInstanceState.txt onRestoreInstanceState:Activityの再初期化直前に、呼び出される。
MapSample のクラスメソッドとして宣言。
〔MapSample.java〕
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int latitude;
int longitude;
latitude = savedInstanceState.getInt("m_SrcPoint_latitude",-1);
longitude = savedInstanceState.getInt("m_SrcPoint_longitude",-1);
if(latitude >= 0 && longitude >= 0 ) {
m_SrcPoint = new GeoPoint( latitude,longitude );
}
latitude = savedInstanceState.getInt("m_DstPoint_latitude",-1);
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 21 prohibition of copy or reproduction
longitude = savedInstanceState.getInt("m_DstPoint_longitude",-1);
if(latitude >= 0 && longitude >= 0 ) {
m_DstPoint = new GeoPoint(latitude,longitude);
}
}
ソース 4-7-8-5_onRestoreInstanceState.txt 4-8. GPS情報の住所変換 4-8-1. GPS情報の変換
GPSの情報を変換するには、Geocoderクラスを使用。
Geocoderの getFromLocationメソッドを使用することで、ジオコーディングします。
今回は、onLocationChanged・Button02・Button03 へのリスナーとして使用します。
4-8-2. onLocationChangedへの設定 onLocationChangedへ追加し、TextViewへ住所を表示させます。
〔MapSample.java〕
Geocoder geocoder = new Geocoder(getBaseContext(), Locale.getDefault());
TextView textview = (TextView) findViewById(R.id.TextView01);
int cnt = 0;
try {
List<Address> addressList = geocoder.getFromLocation(latitude, longitude, 10);
if (addressList != null && !addressList.isEmpty()) {
cnt = addressList.size();
String value = "";
for( Address address: addressList) {
String str = address.getAddressLine(address.getMaxAddressLineIndex());
if( str.length() > value.length() ) {
value = str;
}
}
textview.setText( value );
}
} catch (IOException e) {
e.printStackTrace();
}
ソース 4-8-2-1_onLocationChanged.txt 解説:
List<Address> addressList = geocoder.getFromLocation(latitude, longitude, 10);
• latitude,longitudeで、緯度・経度の住所情報を取得し、検索候補を 10個取得
String str = address.getAddressLine(address.getMaxAddressLineIndex());
• 10個の内、一番詳細な住所情報を取得
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 22 prohibition of copy or reproduction
4-8-3. Button02へのリスナー設定 Button01と同様に、EditTextで検索した住所を、地図の中心に表示させます。
onCreateメソッドへ設定します。
〔MapSample.java〕
final Geocoder geocoder = new Geocoder(getBaseContext(), Locale.getDefault());
final Button button02 = (Button) findViewById(R.id.Button02);
final EditText edittext02 = (EditText) findViewById(R.id.EditText02);
button02.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodManager inputMethodManager
= (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
String value = edittext02.getText().toString();
if( value.length() > 0 ) {
try {
final List<Address> addressList = geocoder.getFromLocationName(value, 10);
if (addressList != null && !addressList.isEmpty()) {
final String[] strItems = new String[ addressList.size() ];
for( int i=0; i<addressList.size(); i++ ) {
Address address = addressList.get(i);
strItems[i]=address.getAddressLine
(address.getMaxAddressLineIndex());
}
new AlertDialog.Builder(MapSample.this)
.setTitle(R.string.select02_title)
.setItems(strItems, new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
Address address = addressList.get(which);
double latitude = address.getLatitude();
double longitude = address.getLongitude();
m_DstPoint=
new GeoPoint( (int)(latitude * 1E6),(int)(longitude * 1E6));
edittext02.setText( strItems[which] );
button01.setChecked(false);
mapview.getController().animateTo( m_DstPoint );
// m_routeoverlay.setRoutePoint( m_SrcPoint, m_DstPoint );
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 23 prohibition of copy or reproduction
解説:
InputMethodManager inputMethodManager
= (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
• ソフトウェアキーボードを隠す
AlertDialog.Builderについて
• 一つ一つの値を分ける事なく、1ラインとして設定
4-8-4. Menuボタンの登録 menuボタンの登録は、新たに Activityを作成し、Intentを発生させます。
二つのメソッドをクラスメソッドとして、実装。
〔MapSample.java〕
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_settings:
Intent intent_Settings = new Intent(this, Settings.class);
startActivity(intent_Settings);
return true;
default:
break;
}
mapview.invalidate();
}
})
.show();
}
} catch (IOException e) {
e.printStackTrace();
}
}
else {
m_DstPoint = null;
}
// m_routeoverlay.setRoutePoint( m_SrcPoint, m_DstPoint );
mapview.invalidate();
}
});
ソース 4-8-3-1_button02.txt
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 24 prohibition of copy or reproduction
return super.onOptionsItemSelected(item);
}
ソース 4-8-4-1_onCreateOptionsMenu.txt 解説:
onCreateOptionsMenu(Menu menu)
• メニューバーへの編集
ここでは、menu.xmlにて設定した項目を表示
onOptionsItemSelected(MenuItem item)
• onCreateOptionsMenuにて編集したメニューのイベント設定。
getMenuInflater().inflate(R.menu.menu, menu)
取得したメニューボタンに対して、イベントを設定。
Settings.javaを別クラスとして作成します。
/jp.co.deltawing.mapsampleを右クリック→新規→クラスを選択
• パッケージ:/jp.co.deltawing.mapsample
• 名前 Settings⇒完了。
• スーパークラス:android.preference.PreferenceActivity
「完了」ボタンでファイルを生成
Setting.javaに、メニューから呼び出される項目を登録します。
Settingsクラスを以下に設定。
〔Settings.java〕
public class Settings extends PreferenceActivity {
private static String OPT_HOME = "home";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
public static String getHome(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getString(OPT_HOME,"");
}
}
ソース 4-8-4-2_Settings.txt 解説:
addPreferencesFromResource(R.xml.settings);
• 表示させる項目を xmlファイルより読み込みます。
R.xml.settingsを作ります。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 25 prohibition of copy or reproduction
• resを右クリック
• 新規⇒フォルダ⇒フォルダ名:xml⇒完了
• xmlを右クリック
新規⇒Android XML File⇒ファイル名:settings.xml⇒完了
xmlファイルにて、設定項目を表記し、EditTextの文字列を保持します。
作成した xmlファイルに以下を設定。
〔settings.xml〕
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/setting_title">
<EditTextPreference android:title="@string/setting_home_title"
android:dialogTitle="@string/setting_home_summary"
android:summary="@string/setting_home_summary"
android:key="home">
</EditTextPreference>
</PreferenceCategory>
</PreferenceScreen>
ソース 4-8-4-3_settings.txt 解説:
android:key="home"
• Settings.javaの getHomeメソッドより呼び出され、homeをキーとして保持した文字列を取り出します。
AndroidManifestに Settingsの Activityの登録をする。
Applicationのタグ内に、以下を記載。
アプリケーションタグの Application Nodesにて、追加を押し、Activitiの追加を行い、Nameに Settingsを追加します。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 26 prohibition of copy or reproduction
図 12 AndroidManifest
AndroidManifestには、Applicationタグの中に、以下が追加されてます。
<activity android:name="Settings"></activity>
以上で、Menuボタンの登録を完了しました。
4-8-5. ボタン 03のイベントを設定 MapSampleへ戻ります。
onCreateメソッドに、button03のイベントを設定。
〔MapSample.java〕
final Button button03 = (Button) findViewById(R.id.Button03);
button03.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String value = Settings.getHome(getBaseContext());
if( value.length() > 0 ) {
try {
final List<Address> addressList = geocoder.getFromLocationName(value, 10);
if (addressList != null && !addressList.isEmpty()) {
final String[] strItems = new String[ addressList.size() ];
for( int i=0; i<addressList.size(); i++ ) {
Address address = addressList.get(i);
strItems[i]=
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 27 prohibition of copy or reproduction
address.getAddressLine(address.getMaxAddressLineIndex());
}
new AlertDialog.Builder(MapSample.this)
.setTitle(R.string.select02_title)
.setItems(strItems,new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
Address address = addressList.get(which);
double latitude = address.getLatitude();
double longitude = address.getLongitude();
m_DstPoint =
new GeoPoint( (int)(latitude * 1E6),(int)(longitude * 1E6));
edittext02.setText( strItems[which] );
button01.setChecked(false);
mapview.getController().animateTo( m_DstPoint );
// m_routeoverlay.setRoutePoint( m_SrcPoint, m_DstPoint );
mapview.invalidate();
}
})
.show();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
ソース 4-8-5-1_button03.txt 解説:
String value = Settings.getHome(getBaseContext());
• 登録した menuの値を、取得します。
4-9. Orverlayクラスを使った地図への描画
Overlayとは、GoogleMap上に、様々なオブジェクトを描画する為に用います。
ここでは、始点と終点に別々のアイコンを描き、2点間で直線を描画。
ReouteOverlayファイルを作成し描画をさせます。
4-9-1. ReouteOverlayファイルの作成 新規⇒クラス⇒ファイル名:ReouteOverlay⇒完了。
extends を ItemizedOverlay<OverlayItem> へ変更する。
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 28 prohibition of copy or reproduction
〔MapSample.java〕
private List<GeoPoint> m_routePoint;
private GeoPoint m_srcPoint;
private GeoPoint m_dstPoint;
private Drawable m_srcMarker;
private Drawable m_dstMarker;
public class ReouteOverlay extends ItemizedOverlay<OverlayItem>{
}
ソース 4-9-1-1_ReouteOverlay.txt コンストラクタの中身を設定。
〔MapSample.java〕
public ReouteOverlay(Drawable defaultMarker) {
super( boundCenterBottom(defaultMarker) );
m_routePoint = new ArrayList<GeoPoint>();
m_srcMarker = null;
m_dstMarker = null;
clearRoutePoint();
}
ソース 4-9-1-2_ReouteOverlay_constructor.txt 解説:
boundCenterBottom(Drawable balloon)
• Overlayクラスの位置を中央底辺へ設定します。
4-9-2. 処理メソッドの設定 calcRouteメソッドを呼び出し、始点 or終点を設定します。
Populateメソッドで、再描画させます。
引数を GeoPointに格納し、始点・終点の設定を行い、ポイントのセットと破棄を行います。
〔ReouteOverlay.java〕
public void setRoutePoint(GeoPoint mSrcPoint, GeoPoint mDstPoint) {
m_srcPoint = mSrcPoint;
m_dstPoint = mDstPoint;
populateRoute();
}
public void populateRoute() {
calcRoute();
populate();
}
private void calcRoute() {
m_routePoint.clear();
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 29 prohibition of copy or reproduction
if( m_srcPoint != null ) {
GeoPoint geoPoint;
geoPoint = new GeoPoint( m_srcPoint.getLatitudeE6(), m_srcPoint.getLongitudeE6() );
m_routePoint.add(geoPoint);
}
if( m_dstPoint != null ) {
GeoPoint geoPoint;
geoPoint = new GeoPoint( m_dstPoint.getLatitudeE6(), m_dstPoint.getLongitudeE6() );
m_routePoint.add(geoPoint);
}
}
public void clearRoutePoint() {
m_srcPoint = null;
m_dstPoint = null;
populateRoute();
}
public void setSrcMarker(Drawable mSrcMarker) {
m_srcMarker = mSrcMarker;
}
public void setDstMarker(Drawable mDstMarker) {
m_dstMarker = mDstMarker;
}
ソース 4-9-2-1_setRoutePoint.txt 解説:
public void populateRoute()
• 始点・終点を決めるメソッドを呼び出し、ポイントをセット。
populate();
• 再描画呼び出し。
public void clearRoutePoint()
• GeoPointを初期化。
4-9-3. createItemメソッド createItemメソッドは描画時に呼び出されます。
単純に描画するだけであれば、GeoPointをリターンさせれば良いです。
ここでは、始点と終点のアイコンを設定しています。
〔ReouteOverlay.java〕
protected OverlayItem createItem(int i) {
OverlayItem item = null;
if( m_routePoint.size() > i ) {
GeoPoint point = m_routePoint.get(i);
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 30 prohibition of copy or reproduction
if( i == 0 && m_srcMarker != null ) {
item = new OverlayItem(point, "Start", "");
item.setMarker( boundCenterBottom(m_srcMarker) );
}
else if( i == m_routePoint.size() - 1 && m_dstMarker != null ) {
item = new OverlayItem(point, "Goal", "");
item.setMarker( boundCenterBottom(m_dstMarker) );
}else {
item = new OverlayItem(point, "", "");
}
}
return item;
}
public int size() {
return m_routePoint.size();
}
ソース 4-9-3-1_OverlayItem.txt 解説:
public int size()
• アイコンを描画する数を設定。
drawメソッドを作成し、各種プロパティを設定。
始点から終点に掛けて、直線をひいてます。
〔ReouteOverlay.java〕
public void draw(Canvas canvas, MapView mapview, boolean shadow) {
Path path = new Path();
Point point = new Point();
float iShadow_x = 0;
float iShadow_y = 0;
int iColor = Color.YELLOW;
if( shadow ) {
iShadow_x = SHADOW_X_SKEW;
iShadow_y = SHADOW_Y_SCALE;
iColor = Color.DKGRAY;
}
if( m_srcPoint != null && m_dstPoint != null && m_routePoint.size() > 0 ) {
Projection projection = mapview.getProjection();
for( int i = 0; i < m_routePoint.size(); i++ ) {
point = new Point();
projection.toPixels( m_routePoint.get(i), point );
if( i == 0 ) {
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 31 prohibition of copy or reproduction
path.moveTo(((float)point.x) + iShadow_x, ((float)point.y) + iShadow_y);
}else {
path.lineTo(((float)point.x) + iShadow_x, ((float)point.y) + iShadow_y);
}
}
Paint paint = new Paint();
paint.setColor( iColor );
paint.setStrokeCap( Paint.Cap.ROUND );
paint.setStrokeJoin( Paint.Join.ROUND );
paint.setStyle( Paint.Style.STROKE );
paint.setStrokeWidth( 5 );
paint.setAlpha( 255 );
paint.setAntiAlias( true );
canvas.drawPath(path, paint);
}
super.draw(canvas, mapview, shadow);
}
ソース 4-9-3-2_draw.txt 4-9-4. MapSample描画処理 クラス変数として、ReouteOverlayを宣言。
〔MapSample.java〕
private ReouteOverlay m_routeoverlay;
ソース 4-9-4-1_m_routeoverlay.txt 描画するアイコンを読み込み、オーバーレイクラスへ渡します。
MapSampleの onCreateへ設定。
〔MapSample.java〕
Drawable srcMarker = getResources().getDrawable( R.drawable.mapstart );
Drawable posMarker = getResources().getDrawable( R.drawable.mappoint );
Drawable dstMarker = getResources().getDrawable( R.drawable.mapgoal );
m_routeoverlay = new ReouteOverlay( posMarker );
m_routeoverlay.setSrcMarker( srcMarker );
m_routeoverlay.setDstMarker( dstMarker );
mapview.getOverlays().add( m_routeoverlay );
ソース 4-9-4-2_getOverlays.txt ボタンイベントへ設定し、描画させます。
〔MapSample.java〕
m_routeoverlay.setRoutePoint( m_SrcPoint, m_DstPoint );
ソース 4-9-4-3_setRoutePoint.txt 今回の描画タイミングは、
① button02を押した時、地図がポイント中心に移動した後にアイコンを描画
総務省 ICTふるさと元気事業 スマートフォンプロジェクト 7/2010 IN OKAYAMA
PAGE 32 prohibition of copy or reproduction
mapview.getController().animateTo( m_DstPoint );の直後
② button02の EditTextが未入力状態で button02が押されても、アイコンを描画
if( value.length() > 0 ) { }の直後
③ button03のリスナー時、地図がポイント中心に移動した後にアイコンを描画
mapview.getController().animateTo( m_DstPoint );直後
④ onResumuメソッドが呼び出された際に描画。
MapView mapview = (MapView) findViewById(R.id.MapView01);直後
⑤ onLocationChangedメソッドに設定、button01のチェック後にアイコンを描画させます。
if( button01.isChecked() ) { }直後
オーバーレイを初期化させます。
onDestroyメソッドへ設定。Activityが終了した後は、終了させる為。
〔MapSample.java〕
mapview.getOverlays().remove( m_routeoverlay );
ソース 4-9-3-4_getOverlays.txt