MapFragmentを使ってみた
タイトル通り。今更ながらMapFragmentを使ってGoogle MapsをAndroidアプリ上に表示させてみた
インストール
Google Play Serviceが必要になる。Android Package Manager?で入れておく。で自分の場合はAndroid SDKが/opt/androidにあるので/opt/android/extras/google/google_play_services/libproject/google-play-services_libをEclipseのライブラリプロジェクトとしてインポートする
これがどうも「ファイル」->「インポート」で出来なかったので、「ファイル」->「新規」から「Android Project from Existing Code」からインポート処理をする。でどうやらこれが必要な理由としてcom.google.android.gcm.Rっていうクラスが必要なのだけど、これがこのプロジェクトしか入ってないので必要っぽい
Google Maps APIのAPI Keyを取得する
https://code.google.com/apis/console から
- Servicesで「Google Maps Android API v2」をonにする
- API Accessにて「Create new Android Key」でAPI Keyを取得する
1は問題無いけど2ではキーストアのフィンガープリントが必要なので
keytool -list -v -keystore debug.keystore
で出力されたSHA1なフィンガープリントをコピーして「フィンガープリント内容;パッケージ名」
でAPI Access時に指定して取得。ちなみにデバッグ用(Eclipseでやる場合)のキーストアは$HOME/.android/debug.keystoreっぽい。Windowsは知らん
これで準備完了、あとはコードを書くだけ
AndroidManifest.xml
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="sample.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
<permission android:name="sample.test.permission.MAPS_RECEIVE" android:protectionLevel="signature" />
<uses-permission android:name="sample.test.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="Google Maps APIのAPI Key" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
com.google.android.maps.v2.API_KEYが必要なくらいであとはパーミッションとかちょこちょこな事が必要なくらい
res/layout/main.xml
<?xml version="1.0" ?>
<fragment
class="com.google.android.gms.maps.SupportMapFragment"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
古い端末で実検証したのでcom.google.android.gms.maps.SupportMapFragmentを使ってますが、新しめな場合はcom.google.android.gms.maps.MapFragmentでいいのかも
MainActivity.java
package sample.test;
import java.util.ArrayList;
import java.util.List;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.android.gms.maps.model.PolylineOptions;
import android.app.AlertDialog;
import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
private static final String TAG = "MainActivity";
private GoogleMap map;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main);
map = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
map.setMyLocationEnabled(true);
map.setTrafficEnabled(true);
map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder
.setMessage(marker.getTitle())
.create()
.show();
}
});
map.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
@Override
public void onMyLocationChange(Location loc) {
LatLng pos1 = new LatLng(loc.getLatitude(), loc.getLongitude());
// 東京スカイツリー
LatLng pos2 = new LatLng(35.7105827, 139.81148759999996);
MarkerOptions marker1 = new MarkerOptions();
marker1
.position(pos2)
.title("タイトル")
.snippet("スニペット");
map.addMarker(marker1);
PolylineOptions marker2 = new PolylineOptions();
marker2
.add(pos1, pos2)
.color(Color.argb(80, 255, 0, 0))
.geodesic(true);
map.addPolyline(marker2);
int blueColor = Color.argb(80, 0, 0, 255);
CircleOptions marker3 = new CircleOptions();
marker3
.fillColor(blueColor)
.strokeWidth(0)
.center(pos2)
.radius(100);
// 以下のmarker4と位置がかぶる。一応見え無くもないけど
map.addCircle(marker3);
// GeoHashを使って近傍エリアを取得するだけ (APIはAndroidパッケージには含まれてない)
String geoCode = GeoHash.encode(pos2.latitude, pos2.longitude, 5);
List<String> geoCodes = GeoHash.neighbor(geoCode);
List<LatLng> positions = new ArrayList<LatLng>(geoCodes.size());
for (String code : geoCodes) {
double[] latlng = GeoHash.decode(code);
positions.add(new LatLng(latlng[0], latlng[1]));
}
PolygonOptions marker4 = new PolygonOptions();
marker4
.addAll(positions)
.strokeWidth(0)
.fillColor(blueColor);
map.addPolygon(marker4);
map.moveCamera(
CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(pos2)
.zoom(10f)
.build()
)
);
map.setOnMyLocationChangeListener(null);
}
});
}
}
でおおまかな動作概要
ソースに書いてる通り現在地と東京スカイツリーをPolylineで線を繋ぐ。で東京スカイツリーにマーカーを設置している
でちょいとズームしてマーカーをタップする
で出た吹き出しもタップすると
これがGoogleMap.OnInfoWindowClickListenerな模様。まぁ上で出てるけど、円なマーカーも付けてる。で最後にPolygonなマーカー
な感じでマーカーをつけれたりする
んまぁあとは以下に記載している参考サイトを見る+公式ドキュメントに書いているのでそれ読めば良いかと
参考: http://dev.classmethod.jp/smartphone/android/android-tips-25-google-maps-android-api-v2