Android
mapbox

MapboxのAndroid SDKを少しだけ触ってみた

More than 1 year has passed since last update.

MapboxのAndroid SDKを少しだけ触ってみました\(^o^)/

実装方法や使い方を触った範囲で書こうと思います。


Mapboxって何?

Mapboxは、簡単に言うとGoogle mapみたいなやつです(笑)

アプリやWebに簡単に地図を実装できます。

あと、地図上にマーカー置いたり線も引けたりできます。

今のところWeb, iOS, Androidなど一通りのプラットフォームで動くみたいです。

ちなみに、お値段は、こんな感じです。

https://www.mapbox.com/pricing/

スクリーンショット 2016-04-05 15.40.35.png


アカウント登録

Mapboxを使うには、はじめにアカウント登録する必要があります。

登録完了するとアクセストークンがもらえます。

トップページの右上らへんにログインする所あるので、ここからアカウント登録。

スクリーンショット 2016-04-05 15.44.12.png

登録が完了すると、こんな管理画面みたいなものが表示されると思うので、「Access token」の所にトークンがあると思うので、コピーします。

スクリーンショット 2016-04-05 15.44.53.png


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" />

全体は、こんな感じ。


AndroidManifest.xml


<?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を追加します。


activity_main.xml


<?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の方は、こんな感じです。


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);
}

}


これで、完了です。

実行すると、こんな感じに地図が表示されるはずです。

Screenshot_.png

ちなみに、この辺の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の機能


マーカー

こんなやつを表示させる方法です。

スクリーンショット 2016-04-06 11.25.24.png


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));

スクリーンショット 2016-04-06 11.27.33.png

マーカーをタップしたかの判定は、こんな感じみたいです。


mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(@NonNull Marker marker) {
Toast.makeText(getApplicationContext(), "マーカークリック: " + marker.getTitle(), Toast.LENGTH_LONG).show();
return false;
}
});

スクリーンショット 2016-04-06 11.28.47.png


地図上に線をひく方法は、これらしい。


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));

}
});

スクリーンショット 2016-04-06 11.30.45.png

色や太さも変更できるみたいです。

  mapboxMap.addPolyline(new PolylineOptions().addAll(line).width(1).color(Color.BLUE));

スクリーンショット 2016-04-06 11.31.00.png


オフライン使用

事前に地図をダウンロードしておくことで、オフラインになった時でも利用できるみたいです。

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