From e41ba7d731965fbd82a42ca0e99d47f95a9e7958 Mon Sep 17 00:00:00 2001
From: shixiaochen <515584404@qq.com>
Date: Wed, 14 Dec 2022 16:15:34 +0800
Subject: [PATCH] =?UTF-8?q?1=E3=80=81Android=E5=AF=BC=E8=88=AA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 android/build.gradle                          |   1 +
 .../ClxMapNavigationPlugin.kt                 |  77 ++--
 .../clx_map_navigation/Constants.kt           |   7 +
 .../clx_map_navigation/LifecycleProvider.kt   |  13 +
 .../NavigationPlatformView.kt                 | 408 ++++++++++++++++++
 .../NavigationPlatformViewFactory.kt          |  34 ++
 6 files changed, 516 insertions(+), 24 deletions(-)
 create mode 100644 android/src/main/kotlin/com/clx/navigation/clx_map_navigation/Constants.kt
 create mode 100644 android/src/main/kotlin/com/clx/navigation/clx_map_navigation/LifecycleProvider.kt
 create mode 100644 android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformView.kt
 create mode 100644 android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformViewFactory.kt

diff --git a/android/build.gradle b/android/build.gradle
index b1f11c8..da7c2a2 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -47,4 +47,5 @@ android {
 
 dependencies {
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+    compileOnly  'com.amap.api:navi-3dmap:9.5.0_3dmap9.5.0'
 }
diff --git a/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/ClxMapNavigationPlugin.kt b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/ClxMapNavigationPlugin.kt
index 5ec77a6..3925618 100644
--- a/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/ClxMapNavigationPlugin.kt
+++ b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/ClxMapNavigationPlugin.kt
@@ -1,35 +1,64 @@
 package com.clx.navigation.clx_map_navigation
 
+import android.util.Log
 import androidx.annotation.NonNull
-
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import com.amap.api.navi.NaviSetting
 import io.flutter.embedding.engine.plugins.FlutterPlugin
+import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding
+import io.flutter.embedding.engine.plugins.activity.ActivityAware
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
+import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference
 import io.flutter.plugin.common.MethodCall
 import io.flutter.plugin.common.MethodChannel
-import io.flutter.plugin.common.MethodChannel.MethodCallHandler
-import io.flutter.plugin.common.MethodChannel.Result
+import io.flutter.plugin.common.PluginRegistry
+
 
 /** ClxMapNavigationPlugin */
-class ClxMapNavigationPlugin: FlutterPlugin, MethodCallHandler {
-  /// The MethodChannel that will the communication between Flutter and native Android
-  ///
-  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
-  /// when the Flutter Engine is detached from the Activity
-  private lateinit var channel : MethodChannel
-
-  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
-    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "clx_map_navigation")
-    channel.setMethodCallHandler(this)
-  }
-
-  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
-    if (call.method == "getPlatformVersion") {
-      result.success("Android ${android.os.Build.VERSION.RELEASE}")
-    } else {
-      result.notImplemented()
+class ClxMapNavigationPlugin : FlutterPlugin, ActivityAware {
+
+    private var mLifecycle: Lifecycle? = null
+
+    override fun onAttachedToEngine(@NonNull binding: FlutterPluginBinding) {
+        Log.d(Constants.TAG, "onAttachedToEngine: ")
+
+        binding.platformViewRegistry
+            .registerViewFactory(
+                Constants.VIEW_TYPE,
+                NavigationPlatformViewFactory(
+                    binding.binaryMessenger,
+                    object : LifecycleProvider {
+                        override val lifecycle: Lifecycle?
+                            get() = mLifecycle
+                    }
+                )
+            )
+    }
+
+    override fun onDetachedFromEngine(@NonNull binding: FlutterPluginBinding) {
+        Log.d(Constants.TAG, "onDetachedFromEngine: ")
+    }
+
+    /**=============================ActivityAware===============================*/
+    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
+        Log.d(Constants.TAG, "onAttachedToActivity: ")
+        mLifecycle = (binding.lifecycle as HiddenLifecycleReference).lifecycle
+    }
+
+    override fun onDetachedFromActivity() {
+        Log.d(Constants.TAG, "onDetachedFromActivity: ")
+        mLifecycle = null
+    }
+
+    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
+        Log.d(Constants.TAG, "onReattachedToActivityForConfigChanges: ")
+        onAttachedToActivity(binding)
+    }
+
+    override fun onDetachedFromActivityForConfigChanges() {
+        Log.d(Constants.TAG, "onDetachedFromActivityForConfigChanges: ")
+        onDetachedFromActivity()
     }
-  }
 
-  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
-    channel.setMethodCallHandler(null)
-  }
 }
diff --git a/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/Constants.kt b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/Constants.kt
new file mode 100644
index 0000000..dbb4abd
--- /dev/null
+++ b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/Constants.kt
@@ -0,0 +1,7 @@
+package com.clx.navigation.clx_map_navigation
+
+object Constants {
+
+    const val TAG = "ClxMapNavigationPlugin"
+    const val VIEW_TYPE = "clx_map_navigation"
+}
\ No newline at end of file
diff --git a/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/LifecycleProvider.kt b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/LifecycleProvider.kt
new file mode 100644
index 0000000..59beeb4
--- /dev/null
+++ b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/LifecycleProvider.kt
@@ -0,0 +1,13 @@
+package com.clx.navigation.clx_map_navigation
+
+import androidx.lifecycle.Lifecycle
+
+/**
+ * @author whm
+ * @date 2020/11/8 6:17 PM
+ * @mail hongming.whm@alibaba-inc.com
+ * @since
+ */
+interface LifecycleProvider {
+    val lifecycle: Lifecycle?
+}
\ No newline at end of file
diff --git a/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformView.kt b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformView.kt
new file mode 100644
index 0000000..3e8c5f7
--- /dev/null
+++ b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformView.kt
@@ -0,0 +1,408 @@
+package com.clx.navigation.clx_map_navigation
+
+import android.content.Context
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import com.amap.api.navi.*
+import com.amap.api.navi.enums.NaviType
+import com.amap.api.navi.enums.PathPlanningStrategy
+import com.amap.api.navi.model.*
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding.OnSaveInstanceStateListener
+import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.MethodCall
+import io.flutter.plugin.common.MethodChannel
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler
+import io.flutter.plugin.platform.PlatformView
+
+/**
+ * @author whm
+ * @date 2020/10/27 5:49 PM
+ * @mail hongming.whm@alibaba-inc.com
+ * @since
+ */
+class NavigationPlatformView internal constructor(
+    private val context: Context,
+    messenger: BinaryMessenger,
+    viewId: Int,
+    args: Any?,
+    lifecycleProvider: LifecycleProvider?,
+) : DefaultLifecycleObserver,
+    OnSaveInstanceStateListener, MethodCallHandler, PlatformView, AMapNaviListener,
+    AMapNaviViewListener {
+
+    private var mAMapNaviView: AMapNaviView? = null
+    private var disposed = false
+    private var methodChannel: MethodChannel
+
+    init {
+        Log.d(Constants.TAG, "init: viewId = $viewId args = $args")
+        val map = args as Map<*, *>
+        val startPoint = map["startPoint"] as Map<*, *>
+        val endPoint = map["endPoint"] as Map<*, *>
+        val startLat = (startPoint["latitude"] ?: 0.0) as Double
+        val startLng = (startPoint["longitude"] ?: 0.0) as Double
+        val endLat = (endPoint["latitude"] ?: 0.0) as Double
+        val endLng = (endPoint["longitude"] ?: 0.0) as Double
+        Log.d(
+            Constants.TAG, "init: startLat = $startLat startLng = $startLng" +
+                    " endLat = $endLat endLng = $endLng"
+        )
+        // 鍚屾剰闅愮鏉冮檺
+        NaviSetting.updatePrivacyShow(context.applicationContext, true, true)
+        NaviSetting.updatePrivacyAgree(context.applicationContext, true)
+        // 鏂规硶閫氶亾
+        methodChannel = MethodChannel(messenger, Constants.VIEW_TYPE)
+        methodChannel.setMethodCallHandler(this)
+        // 瀵艰埅view
+        try {
+            mAMapNaviView = AMapNaviView(context)
+            mAMapNaviView?.setAMapNaviViewListener(this)
+            lifecycleProvider?.lifecycle?.addObserver(this)
+            // 鑾峰彇瀵艰埅Manager
+            val aMapNavi = AMapNavi.getInstance(context)
+            aMapNavi.addAMapNaviListener(this)
+            // 璁剧疆璇煶鎾姤
+            aMapNavi.setUseInnerVoice(true, false)
+            aMapNavi.startSpeak()
+            // 璧风偣淇℃伅
+            val startList: MutableList<NaviLatLng> = ArrayList()
+            startList.add(NaviLatLng(startLat, startLng))
+            // 缁堢偣淇℃伅
+            val endList: MutableList<NaviLatLng> = ArrayList()
+            endList.add(NaviLatLng(endLat, endLng))
+            // 缁忕含搴︾畻璺�
+            aMapNavi.calculateDriveRoute(
+                startList,
+                endList,
+                null,
+                PathPlanningStrategy.DRIVING_MULTIPLE_ROUTES_DEFAULT
+            )
+
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "<init>", e)
+        }
+    }
+
+    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
+        Log.d(Constants.TAG, "onMethodCall: ")
+        result.notImplemented()
+    }
+
+    override fun onCreate(owner: LifecycleOwner) {
+        Log.d(Constants.TAG, "onCreate==>")
+        try {
+            if (disposed) {
+                return
+            }
+            if (null != mAMapNaviView) {
+                mAMapNaviView?.onCreate(null)
+            }
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "onCreate", e)
+        }
+    }
+
+    override fun onStart(owner: LifecycleOwner) {
+        Log.d(Constants.TAG, "onStart==>")
+    }
+
+    override fun onResume(owner: LifecycleOwner) {
+        Log.d(Constants.TAG, "onResume==>")
+        try {
+            if (disposed) {
+                return
+            }
+            if (null != mAMapNaviView) {
+                mAMapNaviView?.onResume()
+            }
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "onResume", e)
+        }
+    }
+
+    override fun onPause(owner: LifecycleOwner) {
+        Log.d(Constants.TAG, "onPause==>")
+        try {
+            if (disposed) {
+                return
+            }
+            mAMapNaviView?.onPause()
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "onPause", e)
+        }
+    }
+
+    override fun onStop(owner: LifecycleOwner) {
+        Log.d(Constants.TAG, "onStop==>")
+    }
+
+    override fun onDestroy(owner: LifecycleOwner) {
+        Log.d(Constants.TAG, "onDestroy==>")
+        try {
+            if (disposed) {
+                return
+            }
+            destroyMapViewIfNecessary()
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "onDestroy", e)
+        }
+    }
+
+    override fun onSaveInstanceState(bundle: Bundle) {
+        Log.d(Constants.TAG, "onDestroy==>")
+        try {
+            if (disposed) {
+                return
+            }
+            mAMapNaviView?.onSaveInstanceState(bundle)
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "onSaveInstanceState", e)
+        }
+    }
+
+    override fun onRestoreInstanceState(bundle: Bundle?) {
+        Log.d(Constants.TAG, "onDestroy==>")
+        try {
+            if (disposed) {
+                return
+            }
+            mAMapNaviView?.onCreate(bundle)
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "onRestoreInstanceState", e)
+        }
+    }
+
+    override fun getView(): View? {
+        Log.d(Constants.TAG, "getView: ")
+        return mAMapNaviView
+    }
+
+    override fun dispose() {
+        Log.d(Constants.TAG, "dispose==>")
+        try {
+            if (disposed) {
+                return
+            }
+            methodChannel.setMethodCallHandler(null)
+            destroyMapViewIfNecessary()
+            disposed = true
+        } catch (e: Throwable) {
+            Log.d(Constants.TAG, "dispose", e)
+        }
+    }
+
+    private fun destroyMapViewIfNecessary() {
+        if (mAMapNaviView == null) {
+            return
+        }
+        // 鍋滄鎾姤璇煶
+        AMapNavi.getInstance(context).stopSpeak()
+        mAMapNaviView?.onDestroy()
+    }
+
+    /**===========================AMapNaviListener================================*/
+
+    override fun onCalculateRouteSuccess(p0: AMapCalcRouteResult?) {
+        Log.d(Constants.TAG, "onCalculateRouteSuccess: ")
+        // 寮€鍚鑸�
+        AMapNavi.getInstance(context).startNavi(NaviType.GPS)
+    }
+
+    override fun onInitNaviFailure() {
+        Log.d(Constants.TAG, "onInitNaviFailure: ")
+    }
+
+    override fun onInitNaviSuccess() {
+        Log.d(Constants.TAG, "onInitNaviSuccess: ")
+    }
+
+    override fun onStartNavi(p0: Int) {
+        Log.d(Constants.TAG, "onStartNavi: ")
+    }
+
+    override fun onTrafficStatusUpdate() {
+        Log.d(Constants.TAG, "onTrafficStatusUpdate: ")
+    }
+
+    override fun onLocationChange(p0: AMapNaviLocation?) {
+        Log.d(Constants.TAG, "onLocationChange: ")
+    }
+
+    override fun onGetNavigationText(p0: Int, p1: String?) {
+        Log.d(Constants.TAG, "onGetNavigationText: ")
+    }
+
+    override fun onGetNavigationText(p0: String?) {
+        Log.d(Constants.TAG, "onGetNavigationText: ")
+    }
+
+    override fun onEndEmulatorNavi() {
+        Log.d(Constants.TAG, "onEndEmulatorNavi: ")
+    }
+
+    override fun onArriveDestination() {
+        Log.d(Constants.TAG, "onArriveDestination: ")
+    }
+
+    override fun onCalculateRouteFailure(p0: Int) {
+        Log.d(Constants.TAG, "onCalculateRouteFailure: ")
+    }
+
+    override fun onCalculateRouteFailure(p0: AMapCalcRouteResult?) {
+        Log.d(Constants.TAG, "onCalculateRouteFailure: ")
+    }
+
+    override fun onReCalculateRouteForYaw() {
+        Log.d(Constants.TAG, "onReCalculateRouteForYaw: ")
+    }
+
+    override fun onReCalculateRouteForTrafficJam() {
+        Log.d(Constants.TAG, "onReCalculateRouteForTrafficJam: ")
+    }
+
+    override fun onArrivedWayPoint(p0: Int) {
+        Log.d(Constants.TAG, "onArrivedWayPoint: ")
+    }
+
+    override fun onGpsOpenStatus(p0: Boolean) {
+        Log.d(Constants.TAG, "onGpsOpenStatus: ")
+    }
+
+    override fun onNaviInfoUpdate(p0: NaviInfo?) {
+        Log.d(Constants.TAG, "onNaviInfoUpdate: ")
+    }
+
+    override fun updateCameraInfo(p0: Array<out AMapNaviCameraInfo>?) {
+        Log.d(Constants.TAG, "updateCameraInfo: ")
+    }
+
+    override fun updateIntervalCameraInfo(
+        p0: AMapNaviCameraInfo?,
+        p1: AMapNaviCameraInfo?,
+        p2: Int
+    ) {
+        Log.d(Constants.TAG, "updateIntervalCameraInfo: ")
+    }
+
+    override fun onServiceAreaUpdate(p0: Array<out AMapServiceAreaInfo>?) {
+        Log.d(Constants.TAG, "onServiceAreaUpdate: ")
+    }
+
+    override fun showCross(p0: AMapNaviCross?) {
+        Log.d(Constants.TAG, "showCross: ")
+    }
+
+    override fun hideCross() {
+        Log.d(Constants.TAG, "hideCross: ")
+    }
+
+    override fun showModeCross(p0: AMapModelCross?) {
+        Log.d(Constants.TAG, "showModeCross: ")
+    }
+
+    override fun hideModeCross() {
+        Log.d(Constants.TAG, "hideModeCross: ")
+    }
+
+    override fun showLaneInfo(p0: Array<out AMapLaneInfo>?, p1: ByteArray?, p2: ByteArray?) {
+        Log.d(Constants.TAG, "showLaneInfo: ")
+    }
+
+    override fun showLaneInfo(p0: AMapLaneInfo?) {
+        Log.d(Constants.TAG, "showLaneInfo: ")
+    }
+
+    override fun hideLaneInfo() {
+        Log.d(Constants.TAG, "hideLaneInfo: ")
+    }
+
+    override fun onCalculateRouteSuccess(p0: IntArray?) {
+        Log.d(Constants.TAG, "onCalculateRouteSuccess: ")
+    }
+
+    override fun notifyParallelRoad(p0: Int) {
+        Log.d(Constants.TAG, "notifyParallelRoad: ")
+    }
+
+    override fun OnUpdateTrafficFacility(p0: Array<out AMapNaviTrafficFacilityInfo>?) {
+        Log.d(Constants.TAG, "OnUpdateTrafficFacility: ")
+    }
+
+    override fun OnUpdateTrafficFacility(p0: AMapNaviTrafficFacilityInfo?) {
+        Log.d(Constants.TAG, "OnUpdateTrafficFacility: ")
+    }
+
+    override fun updateAimlessModeStatistics(p0: AimLessModeStat?) {
+        Log.d(Constants.TAG, "updateAimlessModeStatistics: ")
+    }
+
+    override fun updateAimlessModeCongestionInfo(p0: AimLessModeCongestionInfo?) {
+        Log.d(Constants.TAG, "updateAimlessModeCongestionInfo: ")
+    }
+
+    override fun onPlayRing(p0: Int) {
+        Log.d(Constants.TAG, "onPlayRing: ")
+    }
+
+    override fun onNaviRouteNotify(p0: AMapNaviRouteNotifyData?) {
+        Log.d(Constants.TAG, "onNaviRouteNotify: ")
+    }
+
+    override fun onGpsSignalWeak(p0: Boolean) {
+        Log.d(Constants.TAG, "onGpsSignalWeak: ")
+    }
+
+    /**=======================AMapNaviViewListener=======================*/
+
+    override fun onNaviCancel() {
+        Log.d(Constants.TAG, "onNaviCancel: ")
+        // 閫€鍑哄鑸�
+        methodChannel.invokeMethod("navigationClosed", "")
+    }
+
+    override fun onNaviBackClick(): Boolean {
+        Log.d(Constants.TAG, "onNaviBackClick: ")
+        return false
+    }
+
+    override fun onNaviSetting() {
+        Log.d(Constants.TAG, "onNaviSetting: ")
+    }
+
+    override fun onNaviMapMode(p0: Int) {
+        Log.d(Constants.TAG, "onNaviMapMode: ")
+    }
+
+    override fun onNaviTurnClick() {
+        Log.d(Constants.TAG, "onNaviTurnClick: ")
+    }
+
+    override fun onNextRoadClick() {
+        Log.d(Constants.TAG, "onNextRoadClick: ")
+    }
+
+    override fun onScanViewButtonClick() {
+        Log.d(Constants.TAG, "onScanViewButtonClick: ")
+    }
+
+    override fun onLockMap(p0: Boolean) {
+        Log.d(Constants.TAG, "onLockMap: ")
+    }
+
+    override fun onNaviViewLoaded() {
+        Log.d(Constants.TAG, "onNaviViewLoaded: ")
+    }
+
+    override fun onMapTypeChanged(p0: Int) {
+        Log.d(Constants.TAG, "onMapTypeChanged: ")
+    }
+
+    override fun onNaviViewShowMode(p0: Int) {
+        Log.d(Constants.TAG, "onNaviViewShowMode: ")
+    }
+
+
+}
\ No newline at end of file
diff --git a/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformViewFactory.kt b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformViewFactory.kt
new file mode 100644
index 0000000..3d0b598
--- /dev/null
+++ b/android/src/main/kotlin/com/clx/navigation/clx_map_navigation/NavigationPlatformViewFactory.kt
@@ -0,0 +1,34 @@
+package com.clx.navigation.clx_map_navigation
+
+import android.content.Context
+import android.util.Log
+import io.flutter.plugin.common.BinaryMessenger
+import com.clx.navigation.clx_map_navigation.LifecycleProvider
+import io.flutter.plugin.platform.PlatformViewFactory
+import io.flutter.plugin.common.StandardMessageCodec
+import io.flutter.plugin.platform.PlatformView
+import com.clx.navigation.clx_map_navigation.NavigationPlatformViewFactory
+import com.clx.navigation.clx_map_navigation.NavigationPlatformView
+
+/**
+ * @author whm
+ * @date 2020/10/27 4:08 PM
+ * @mail hongming.whm@alibaba-inc.com
+ * @since
+ */
+internal class NavigationPlatformViewFactory(
+    private val messenger: BinaryMessenger,
+    private val lifecycleProvider: LifecycleProvider
+) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
+    override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
+        Log.d(Constants.TAG, "create: ")
+        return NavigationPlatformView(
+            context,
+            messenger,
+            viewId,
+            args,
+            lifecycleProvider
+        )
+    }
+
+}
\ No newline at end of file
-- 
2.17.1