Initialize and DisplayMap

地図描画用レイアウトの準備

プロジェクト生成時に用意された activity_main.xml を編集し、地図描画用のエリアを確保します。
具体的には、FrameLayout を追加し、リソース ID を map に設定してください。
なお、不要な TextView(Hello world!) は削除してください。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

初期化の流れ

地図を表示するために、以下の手順で初期化を行います。

  1. Activityの初期化
  2. SDKの初期化
  3. 地図の初期化

1. Activityの初期化

コンポーネントのインポート

必要なコンポーネントを MainActivity.kt に import します。

import android.content.Context
import android.provider.Settings;
import android.provider.Settings.Secure.ANDROID_ID
import com.pioneer.android.mpa.ApiKeyInfo
import com.pioneer.android.mpa.CalcRouteListener
import com.pioneer.android.mpa.Common
import com.pioneer.android.mpa.DemoRunSetting
import com.pioneer.android.mpa.GeoCoordinate
import com.pioneer.android.mpa.Map
import com.pioneer.android.mpa.MapSetting
import com.pioneer.android.mpa.Navi
import com.pioneer.android.mpa.NaviInitInfo
import com.pioneer.android.mpa.NaviInitListener
import com.pioneer.android.mpa.OnMapEventListener
import com.pioneer.android.mpa.RouteOptions
import com.pioneer.android.mpa.RoutePlan
import com.pioneer.android.mpa.SupportMapFragment
import com.pioneer.android.mpa.GuidePointResult
import com.pioneer.android.mpa.ProbeDataSettingInfo
import com.pioneer.android.mpa.ProbeDataSettingInfo.DataType
import com.pioneer.android.mpa.RunInfoListener
import com.pioneer.android.mpa.ServerSettingInfo
import com.pioneer.android.mpa.SetupInfo
import com.pioneer.android.mpa.StartGuidanceListener
import com.pioneer.android.mpa.UserSettingResultListener

ViewBindingの設定

MainActivity クラスのメンバに ActivityMainBinding を追加します。

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    ...

onCreate 内でbindingを設定します。
元々記述されている setContentView 以下の処理は削除してください。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }
Note:

ActivityMainBinding を使用するには、以下のようにパッケージをimportしてください。

例:

import com.example.myfirstnavigation.databinding.ActivityMainBinding

※アプリのパッケージ名に合わせて修正してください。

2. SDKの初期化

SDK初期化手順の詳細は、「Initialize」 を参照してください。
ここでは、地図表示に必要な最小限のコードを説明します。

onCreate 内で、initializeNaviinitializeMap を呼び出します。

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        initializeNavi(applicationContext)
        initializeMap()
    }

MainActivityinitializeNavi 関数を追加し、初期化処理を実装します。

    private fun initializeNavi(context: Context) {
        val initInfo = NaviInitInfo(context)
        val apiKeyInfo = ApiKeyInfo();
        apiKeyInfo.setApiKey(API_KEY); // 具体的なキー(文字列)については営業窓口までお問い合わせください。
        apiKeyInfo.setTrafficProviderKey(PROVIDER_KEY); // 具体的なキー(文字列)については営業窓口までお問い合わせください。
        apiKeyInfo.setTrafficProviderUserID(USER_ID); // 具体的なID(文字列)については営業窓口までお問い合わせください。
        initInfo.setServerSettingInfo(ServerSettingInfo(apiKeyInfo));

        // UserID(このIDを元にクラウドの設定やルート保存が行われるためユニークなIDを推奨)
        val userID = "MyAppName" + Settings.Secure.getString(context.contentResolver, ANDROID_ID)
        initInfo.setUserID(userID);

        Navi.getInstance().initialize(initInfo) { errorCode, naviInitResult ->
            if (errorCode == NaviInitListener.ErrorCode.NONE) {
                Navi.getInstance().mobileAppLifecycle = lifecycle
            }
        }
    }
Note:

NaviInitInfo.userID は、アプリ内でユニークな値を設定してください。 弊社クラウド内でこの userID を元に状態管理が行われるため、単純な test 等のIDにしてしまうと、他のユーザーと重複し、正常動作しない可能性があります。

3. 地図の初期化

地図操作用の map オブジェクトを MainActivity に追加します。

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var map: Map
    ...

地図の描画領域はSupportFragmentを使用し、既存のFragmentと置き換えることでSDKが自動的に地図更新できるようになります。
ここでは先述のFrameLayoutをgetSupportFragmentManager を利用して置き換えてみます。

MainActivityinitializeMappostOnInitializeMap の2つの関数を追加します。

    // 地図の初期化
    private fun initializeMap() {
        val mapSetting = MapSetting()
        mapSetting.setMapStyle(Map.MapStyle.DEFAULT)

        // Create fragment
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.map, SupportMapFragment.newInstance(), "supportMapFragment")
        transaction.commitNow()
        val supportMapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?

        supportMapFragment?.initialize(mapSetting, object : OnMapEventListener {
            override fun onInitializationCompleted(errorCode: OnMapEventListener.ErrorCode) {
                postOnInitializeMap(errorCode, supportMapFragment)
            }

            override fun onMapModeChanged(mapMode: Map.MapMode) {}
        })
    }

    // 地図初期化完了後の処理
    private fun postOnInitializeMap(errorCode: OnMapEventListener.ErrorCode, supportMapFragment: SupportMapFragment) {
        if (errorCode != OnMapEventListener.ErrorCode.NONE) {
            return
        }

        map = supportMapFragment.map!!
        Navi.getInstance().attach(map)
    }

アプリを実行すると、東京都庁を中心に地図が表示されます。
現在位置と違う地図を出している状態ですが、この時点では正常です。

地図のみ描画

Note:

Androidのシステムが地図表示用のActivityを再作成すると地図が再初期化されるため、再作成されないようにすることを推奨します。
例えば、AndroidManifest.xmlで対象のActivityにandroid:configChange属性を設定することで、端末回転時の再生成を防げます。

    <activity 
        android:name="com.example.myfirstnavigation.MyActivity"
+       android:configChanges="screenSize|orientation"
        ...

端末回転以外の値についてはこちらをご確認ください。

自車位置を特定する

アプリ実行中に権限を変更したい場合、Google Developersのこちらの記事を参考にしてください。

ここでは手動で権限を変更する方法を採用します。
アプリを終了し、アプリの設定から位置情報権限を許可してください。

SDK初期化完了後に Navi.startPositioning() を呼び出すと、デバイスの位置が地図に反映されます。

    private fun initializeNavi(context: Context) {
        val initInfo = NaviInitInfo(context)
        ...

        Navi.getInstance().initialize(initInfo) { errorCode, naviInitResult ->
            if (errorCode == NaviInitListener.ErrorCode.NONE) {
                Navi.getInstance().mobileAppLifecycle = lifecycle
+               Navi.getInstance().startPositioning()
            }
        }
    }

起動後に地図を自車位置中心に移動する

自車位置を中心に地図を描画し続けるには、Map.setMapMode() による描画指定が必要です。

postOnInitializeMap 内で、以下のように設定してください。

    private fun postOnInitializeMap(errorCode: ErrorCode, supportMapFragment: SupportMapFragment) {
        if (errorCode != ErrorCode.NONE) {
            return
        }

        map = supportMapFragment.map
        Navi.getInstance().attach(map)
+       map.mapMode = Map.MapMode.NORTH_UP // 北を画面上部にします
    }

これで起動完了とともに自車位置を中心に地図が描画されるようになります。

自車位置中心

地図の制御方法の詳細は「Camera Control」を参照してください。

Note:

もし地図が東京都庁付近のままであれば、アプリの位置情報権限が付与されていない可能性があります。

以上でSDKの初期化と地図表示は完了です。
続いて、ルート探索と誘導開始を説明します。