MapboxのAndroid SDKを少しだけ触ってみました\(^o^)/
実装方法や使い方を触った範囲で書こうと思います。
Mapboxって何?
Mapboxは、簡単に言うとGoogle mapみたいなやつです(笑)
アプリやWebに簡単に地図を実装できます。
あと、地図上にマーカー置いたり線も引けたりできます。
今のところWeb, iOS, Androidなど一通りのプラットフォームで動くみたいです。
ちなみに、お値段は、こんな感じです。
https://www.mapbox.com/pricing/
アカウント登録
Mapboxを使うには、はじめにアカウント登録する必要があります。
登録完了するとアクセストークンがもらえます。
トップページの右上らへんにログインする所あるので、ここからアカウント登録。
登録が完了すると、こんな管理画面みたいなものが表示されると思うので、**「Access token」**の所にトークンがあると思うので、コピーします。
AndroidでMapboxを使う
実際にAndroidアプリでMapBoxを使ってみます。(ライブラリは4.1.0を使用しています)
Gradle
GradleでMapboxのライブラリをいれます。
repositories {
mavenCentral()
}
dependencies {
compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:4.0.0@aar'){
transitive=true
}
}
AndroidManifest
AndroidManifest.xmlに以下のpermissionと...
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
このserviceを入れます。
<service android:name="com.mapbox.mapboxsdk.telemetry.TelemetryService" />
全体は、こんな感じ。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="パッケージ名">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<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>
<service android:name="com.mapbox.mapboxsdk.telemetry.TelemetryService" />
</application>
</manifest>
activity_main.xml
MainActivity.javaとactivity_main.xmlの2つ用意してください。
activityのxmlにcom.mapbox.mapboxsdk.maps.MapViewを追加します。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:access_token="アクセストークン"
mapbox:style_url="@string/style_mapbox_streets"
mapbox:center_latitude="33.590098"
mapbox:center_longitude="130.419484"
mapbox:zoom="15"/>
</RelativeLayout>
MainActivity.java
MainActivity.javaの方は、こんな感じです。
public class MainActivity extends AppCompatActivity {
private MapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
//地図読込完了...
}
});
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
これで、完了です。
実行すると、こんな感じに地図が表示されるはずです。
ちなみに、この辺のxmlの設定は、
mapbox:access_token="アクセストークン"
mapbox:style_url="@string/style_mapbox_streets"
mapbox:center_latitude="33.590098"
mapbox:center_longitude="130.419484"
mapbox:zoom="15"
こんな感じにJavaでも可能です。
MapView mapView = (MapView) findViewById(R.id.map_view);
mapView.setAccessToken("アクセストークン");
mapView.setStyle(Style.MAPBOX_STREETS);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(33.583549, 130.393819))
.zoom(14)
.bearing(0)
.tilt(0)
.build()));
}
});
Mapboxの機能
マーカー
こんなやつを表示させる方法です。
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
mapboxMap.addMarker(new MarkerOptions()
.position(new LatLng(33.583549, 130.393819))
.title("たいとる だよ")
.snippet("すにぺっと"));
}
});
マーカーの画像を変更する場合は、このようにします。
IconFactory iconFactory = IconFactory.getInstance(MainActivity.this);
Drawable iconDrawable = ContextCompat.getDrawable(MainActivity.this, R.drawable.icon);
Icon icon = iconFactory.fromDrawable(iconDrawable);
mapboxMap.addMarker(new MarkerOptions()
.position(new LatLng(33.583549, 130.393819))
.title("たいとる だよ")
.snippet("すにぺっと")
.icon(icon));
マーカーをタップしたかの判定は、こんな感じみたいです。
mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(@NonNull Marker marker) {
Toast.makeText(getApplicationContext(), "マーカークリック: " + marker.getTitle(), Toast.LENGTH_LONG).show();
return false;
}
});
線
地図上に線をひく方法は、これらしい。
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
List<LatLng> line = new ArrayList<>();
line.add(new LatLng(33.586319, 130.421886));
line.add(new LatLng(33.590018, 130.374715));
mapboxMap.addPolyline(new PolylineOptions().addAll(line));
}
});
色や太さも変更できるみたいです。
mapboxMap.addPolyline(new PolylineOptions().addAll(line).width(1).color(Color.BLUE));
オフライン使用
事前に地図をダウンロードしておくことで、オフラインになった時でも利用できるみたいです。
public class MainActivity extends AppCompatActivity {
private MapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.map_view);
mapView.setAccessToken("アクセストークン");
mapView.setStyle(Style.MAPBOX_STREETS);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(33.583549, 130.393819))
.zoom(14)
.bearing(0)
.tilt(0)
.build()));
}
});
OfflineManager mOfflineManager = OfflineManager.getInstance(this);
mOfflineManager.setAccessToken("アクセストークン");
LatLngBounds latLngBounds = new LatLngBounds.Builder()
.include(new LatLng(33.597793, 130.431185))
.include(new LatLng(33.576200, 130.406466))
.build();
OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(
mapView.getStyleUrl(), latLngBounds, 10, 20, this.getResources().getDisplayMetrics().density);
byte[] metadata;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("FIELD_REGION_NAME", "Fukuoka");
String json = jsonObject.toString();
metadata = json.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
metadata = null;
}
mOfflineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() {
@Override
public void onCreate(OfflineRegion offlineRegion) {
offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);
offlineRegion.setObserver(new OfflineRegion.OfflineRegionObserver() {
@Override
public void onStatusChanged(OfflineRegionStatus status) {
//進捗
double percentage = status.getRequiredResourceCount() >= 0 ?
(100.0 * status.getCompletedResourceCount() / status.getRequiredResourceCount()) :
0.0;
if (status.isComplete()) {
//ダウンロード完了
return;
}
}
@Override
public void onError(OfflineRegionError error) {
//エラー
}
@Override
public void mapboxTileCountLimitExceeded(long limit) {
}
});
}
@Override
public void onError(String error) {
//エラー
}
});
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
オフラインになったら自動で切り替わるみたいです。
ちなみにこのデータはmbgl-offline.dbに保存されてるみたいです。
あ!
こちらのmetadataを使うと、ダウンロードした地図と一緒に別の値を保存することができます。
byte[] metadata;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("FIELD_REGION_NAME", "Fukuoka");
String json = jsonObject.toString();
metadata = json.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
metadata = null;
}
ここでは、jsonの形で「Fukuoka」という値をいれています。(別にjsonでする必要はないです)
地図の名前やIDなど、そういったものに使うと良いと思います。
で、指定したmetadataは、**offlineRegion.getMetadata()**で取得できます。
mOfflineManager.listOfflineRegions(new OfflineManager.ListOfflineRegionsCallback() {
@Override
public void onList(OfflineRegion[] offlineRegions) {
if (offlineRegions == null || offlineRegions.length == 0) {
return;
}
for (OfflineRegion offlineRegion : offlineRegions) {
//metadata取得
offlineRegion.getMetadata();
}
}
@Override
public void onError(String error) {
//エラー
}
});
まとめ
ただ地図を表示するくらいなら、Mapboxでも良いかも。
個人的にはMapboxの地図のデザインはGoogle mapより好き(笑)
ライブラリが頻繁に更新されているみたいで、仕様変更がよくあるらしい。。。
ちなみに、Mapboxのサンプル集は、こちらです。
https://github.com/mapbox/mapbox-gl-native/tree/11f7db293e5488690b87ee0260f910e49e5e0275/platform/android/MapboxGLAndroidSDKTestApp