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