Conflicts:
	app/build.gradle
	app/src/main/java/com/navinfo/omqs/OMQSApplication.kt
	app/src/main/java/com/navinfo/omqs/ui/MainActivity.kt
	app/src/main/java/com/navinfo/omqs/ui/activity/map/MainActivity.kt
	app/src/main/res/layout/fragment_offline_map_state_list.xml
	app/src/main/res/layout/map_view.xml
	collect-library/build.gradle
This commit is contained in:
qiji4215
2023-04-19 15:52:28 +08:00
90 changed files with 2972 additions and 812 deletions

View File

@@ -1,6 +1,10 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
id 'kotlin-parcelize' // 序列化
id 'kotlin-android'
id 'kotlin-kapt'
id 'realm-android'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
@@ -34,14 +38,24 @@ dependencies {
api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation "androidx.appcompat:appcompat:$appcompatVersion"
implementation "com.google.android.material:material:$materialVersion"
api files('libs/BaiduLBS_Android.jar')
//
api 'androidx.core:core-ktx:1.9.0'
api 'androidx.appcompat:appcompat:1.6.1'
api 'com.google.android.material:material:1.8.0'
api 'androidx.constraintlayout:constraintlayout:2.1.4'
api 'androidx.navigation:navigation-fragment-ktx:2.5.3'
api 'androidx.navigation:navigation-ui-ktx:2.5.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.yanzhenjie:kalle:0.1.7'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// implementation 'com.yanzhenjie:kalle:0.1.7'
// VTM依赖
implementation "net.sf.kxml:kxml2:2.3.0"
implementation "org.slf4j:slf4j-api:1.7.28"
implementation 'org.slf4j:slf4j-api:2.0.7'
implementation "org.mapsforge:vtm:$vtmVersion"
implementation "org.mapsforge:vtm-themes:$vtmVersion"
implementation "org.mapsforge:vtm-android:$vtmVersion"
@@ -69,30 +83,37 @@ dependencies {
implementation "com.badlogicgames.gdx:gdx-backend-android:1.11.0"
implementation "com.caverock:androidsvg:1.4"
implementation "org.mapsforge:vtm-jts:$vtmVersion"
implementation "org.locationtech.jts:jts-core:1.18.2"
implementation "com.squareup.okhttp3:okhttp:3.12.13"
implementation "com.squareup.okio:okio:1.15.0"
implementation 'org.locationtech.jts:jts-core:1.19.0'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.11'
implementation 'com.squareup.okio:okio:3.3.0'
implementation "com.fasterxml.jackson.core:jackson-annotations:2.9.9"
implementation "com.fasterxml.jackson.core:jackson-core:2.9.9"
implementation "com.fasterxml.jackson.core:jackson-databind:2.9.9"
implementation 'com.tencent.wcdb:room:1.0.8' // 代替 room-runtime同时也不需要再引用 wcdb-android
implementation "androidx.sqlite:sqlite:2.0.1"
implementation "androidx.room:room-runtime:2.1.0"
annotationProcessor "androidx.room:room-compiler:2.1.0"
kapt "androidx.room:room-compiler:2.1.0"
androidTestImplementation 'androidx.room:room-testing:2.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
kapt 'androidx.lifecycle:lifecycle-compiler:2.0.0'
implementation 'com.tencent.wcdb:wcdb-android:1.0.0'
implementation "androidx.core:core-ktx:1.8.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// 协程核心库
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
// 协程Android支持库
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
// 协程Java8支持库
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4'
//room 数据库相关
api 'com.tencent.wcdb:room:1.1-19' // 代替 room-runtime同时也不需要再引用 wcdb-android
api 'androidx.sqlite:sqlite-ktx:2.3.1'
api "androidx.room:room-runtime:2.5.1"
api "androidx.room:room-ktx:2.5.1"
annotationProcessor "androidx.room:room-compiler:2.5.1"
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的
kapt "androidx.room:room-compiler:2.5.1"
kapt "androidx.room:room-ktx:2.5.1"
// //分页加载
// api "androidx.room:room-paging:$roomversion"
// api "androidx.paging:paging-runtime-ktx:3.1.1"
androidTestImplementation "android.arch.persistence.room:testing:1.1.1"
api 'com.tencent.wcdb:wcdb-android:1.1-19'
// // 协程核心库
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
// // 协程Android支持库
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
// // 协程Java8支持库
// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4'
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,57 +1,57 @@
package com.navinfo.collect.library.data.entity
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
//enum class StatusEnum(val status: Int) {
// NONE(0), WAITING(1), LOADING(2), PAUSE(3),
// ERROR(4), DONE(5), UPDATE(6)
//}
open class OfflineMapCityBean @JvmOverloads constructor(
@PrimaryKey var id: String = "",
var fileName: String = "",
var name: String = "",
var url: String = "",
var version: Long = 0L,
var fileSize: Long = 0L,
var currentSize: Long = 0L,
var status: Int = NONE
) : RealmObject() {
companion object Status{
const val NONE = 0 //无状态
const val WAITING = 1 //等待中
const val LOADING = 2 //下载中
const val PAUSE = 3 //暂停
const val ERROR = 4 //错误
const val DONE = 5 //完成
const val UPDATE = 6 //有新版本要更新
}
// // status的转换对象
// var statusEnum: StatusEnum
// get() {
// return try {
// StatusEnum.values().find { it.status == status }!!
// } catch (e: IllegalArgumentException) {
// StatusEnum.NONE
// }
// }
// set(value) {
// status = value.status
// }
fun getFileSizeText(): String {
return if (fileSize < 1024.0)
"$fileSize B"
else if (fileSize < 1048576.0)
"%.2f K".format(fileSize / 1024.0)
else if (fileSize < 1073741824.0)
"%.2f M".format(fileSize / 1048576.0)
else
"%.2f M".format(fileSize / 1073741824.0)
}
}
//package com.navinfo.collect.library.data.entity
//
//import io.realm.RealmObject
//import io.realm.annotations.PrimaryKey
//
////enum class StatusEnum(val status: Int) {
//// NONE(0), WAITING(1), LOADING(2), PAUSE(3),
//// ERROR(4), DONE(5), UPDATE(6)
////}
//
//open class OfflineMapCityBean @JvmOverloads constructor(
// @PrimaryKey var id: String = "",
// var fileName: String = "",
// var name: String = "",
// var url: String = "",
// var version: Long = 0L,
// var fileSize: Long = 0L,
// var currentSize: Long = 0L,
// var status: Int = NONE
//) : RealmObject() {
//
// companion object Status{
// const val NONE = 0 //无状态
// const val WAITING = 1 //等待中
// const val LOADING = 2 //下载中
// const val PAUSE = 3 //暂停
// const val ERROR = 4 //错误
// const val DONE = 5 //完成
// const val UPDATE = 6 //有新版本要更新
// }
//
//// // status的转换对象
//// var statusEnum: StatusEnum
//// get() {
//// return try {
//// StatusEnum.values().find { it.status == status }!!
//// } catch (e: IllegalArgumentException) {
//// StatusEnum.NONE
//// }
//// }
//// set(value) {
//// status = value.status
//// }
//
// fun getFileSizeText(): String {
// return if (fileSize < 1024.0)
// "$fileSize B"
// else if (fileSize < 1048576.0)
// "%.2f K".format(fileSize / 1024.0)
// else if (fileSize < 1073741824.0)
// "%.2f M".format(fileSize / 1048576.0)
// else
// "%.2f M".format(fileSize / 1073741824.0)
// }
//
//
//}

View File

@@ -1,43 +1,43 @@
package com.navinfo.collect.library.data.entity
import io.realm.RealmModel
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.annotations.RealmClass
@RealmClass
open class OfflineMapCityRealmObject: RealmModel {
@PrimaryKey
var id: String = ""
var fileName: String=""
var name: String = ""
var url: String = ""
var version: Long = 0
var fileSize: Long = 0
var currentSize:Long = 0
var status:Int = 0
constructor(){
}
constructor(
id: String,
fileName: String,
name: String,
url: String,
version: Long,
fileSize: Long,
currentSize: Long,
status: Int
) {
this.id = id
this.fileName = fileName
this.name = name
this.url = url
this.version = version
this.fileSize = fileSize
this.currentSize = currentSize
this.status = status
}
}
//package com.navinfo.collect.library.data.entity
//
//import io.realm.RealmModel
//import io.realm.RealmObject
//import io.realm.annotations.PrimaryKey
//import io.realm.annotations.RealmClass
//
//@RealmClass
//open class OfflineMapCityRealmObject: RealmModel {
// @PrimaryKey
// var id: String = ""
// var fileName: String=""
// var name: String = ""
// var url: String = ""
// var version: Long = 0
// var fileSize: Long = 0
// var currentSize:Long = 0
// var status:Int = 0
//
// constructor(){
//
// }
//
// constructor(
// id: String,
// fileName: String,
// name: String,
// url: String,
// version: Long,
// fileSize: Long,
// currentSize: Long,
// status: Int
// ) {
// this.id = id
// this.fileName = fileName
// this.name = name
// this.url = url
// this.version = version
// this.fileSize = fileSize
// this.currentSize = currentSize
// this.status = status
// }
//}

View File

@@ -0,0 +1,102 @@
package com.navinfo.collect.library.data.entity
import com.navinfo.collect.library.utils.GeometryToolsKt
import io.realm.RealmObject
import io.realm.RealmSet
import io.realm.annotations.PrimaryKey
import io.realm.annotations.RealmClass
/**
* @author zhjch
* @version V1.0
* @ClassName: Rd_qcRecord
* @Date 2016/1/12
* @Description: ${TODO}(质检对象)
*/
@RealmClass
open class QsRecordBean @JvmOverloads constructor(
/**
* id 主键
*
*/
@PrimaryKey
var id: String = "",
/**
* 关联要素id
*/
var elementId: String = "",
/**
* linkPid 绑定的道路ID
*/
var linkId: String = "",
/**
*问题分类
*/
var classType: String = "",
/**
* 问题类型
*/
var type: String = "",
/**
* 问题现象
*/
var phenomenon: String = "",
/**
* 描述信息
*/
var description: String = "",
/**
* 问题环节
*/
var problemLink: String = "",
/**
* 问题原因
* 根本原因RCA
*/
var cause: String = "",
/**
* 质检员ID
*/
var checkUserId: String = "",
/**
* 质检日期
*/
var checkTime: String = "",
/**
* 确认人
*/
var confirmUserId: String = "",
/**
* 状态 0 无; 1 删除2 更新3 新增;
*/
var t_lifecycle: Int = 3,
/**
* 问题记录提交状态 0 未提交1 已提交;
*/
var t_status: Int = 0,
/**
* 显示坐标
*/
// var geometry: String = "",
/**
* 显示坐标
*/
var guideGeometry: String = "",
) : RealmObject() {
private val tileX = RealmSet<Int>() // x方向的tile编码
private val tileY = RealmSet<Int>() // y方向的tile编码
var geometry: String = ""
set(value) {
field = value
// 根据geometry自动计算当前要素的x-tile和y-tile
GeometryToolsKt.getTileXByGeometry(value, tileX)
GeometryToolsKt.getTileYByGeometry(value, tileY)
}
}

View File

@@ -0,0 +1,14 @@
package com.navinfo.collect.library.map
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class GeoPoint(
var latitude: Double = 0.0,
var longitude: Double = 0.0
) : Parcelable {
fun toGeometry(): String {
return "POINT($longitude $latitude)"
}
}

View File

@@ -2,6 +2,7 @@ package com.navinfo.collect.library.map
import android.content.Context
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.navinfo.collect.library.map.handler.*
import com.navinfo.collect.library.map.maphandler.MeasureLayerHandler
import com.navinfo.collect.library.map.handler.ViewportHandler
@@ -23,7 +24,7 @@ class NIMapController {
lateinit var measureLayerHandler: MeasureLayerHandler
fun init(context: Context, mapView: NIMapView, options: NIMapOptions? = null, mapPath: String) {
fun init(context: AppCompatActivity, mapView: NIMapView, options: NIMapOptions? = null, mapPath: String) {
Constant.MAP_PATH = mapPath
layerManagerHandler = LayerManagerHandler(context, mapView)
locationLayerHandler = LocationLayerHandler(context, mapView)
@@ -37,5 +38,6 @@ class NIMapController {
mapView.setOptions(options)
}
}

View File

@@ -3,7 +3,6 @@ package com.navinfo.collect.library.map;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -15,37 +14,21 @@ import androidx.annotation.Nullable;
import com.navinfo.collect.library.R;
import com.navinfo.collect.library.map.layers.NaviMapScaleBar;
import com.navinfo.collect.library.map.source.MapLifeDBTileSource;
import com.navinfo.collect.library.map.source.MapLifeNiLocationTileDataSource;
import com.navinfo.collect.library.map.source.MapLifeNiLocationTileSource;
import com.navinfo.collect.library.system.Constant;
import org.oscim.android.MapPreferences;
import org.oscim.android.MapView;
import org.oscim.core.GeoPoint;
import org.oscim.android.theme.AssetsRenderTheme;
import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.event.Event;
import org.oscim.event.Gesture;
import org.oscim.event.GestureListener;
import org.oscim.layers.GroupLayer;
import org.oscim.layers.Layer;
import org.oscim.layers.TileGridLayer;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.OsmTileLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook;
import org.oscim.map.Map;
import org.oscim.renderer.GLViewport;
import org.oscim.theme.IRenderTheme;
import org.oscim.theme.ThemeLoader;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.source.mapfile.MapFileTileSource;
import org.oscim.tiling.source.mapfile.MultiMapFileTileSource;
import java.io.File;
/**
@@ -125,14 +108,14 @@ public final class NIMapView extends RelativeLayout {
*
* @param point
*/
void onMapClick(GeoPoint point);
void onMapClick(com.navinfo.collect.library.map.GeoPoint point);
/**
* 地图内 Poi 单击事件回调函数
*
* @param poi
*/
void onMapPoiClick(GeoPoint poi);
// void onMapPoiClick(GeoPoint poi);
}
/**
@@ -218,10 +201,8 @@ public final class NIMapView extends RelativeLayout {
this.mContext = context;
mapView = rootView.findViewById(R.id.base_map_view);
// map = new NIMap(this);
compassImage = rootView.findViewById(R.id.navinfo_map_compass);
initMapGroup(); // 初始化图层组
// mLayerManager = new NILayerManager(context, getVtmMap());
logoImage = rootView.findViewById(R.id.navinfo_map_logo);
mRotateAnimation = new NIRotateAnimation(compassImage);
@@ -251,6 +232,7 @@ public final class NIMapView extends RelativeLayout {
}
});
// 增加比例尺图层
NaviMapScaleBar naviMapScaleBar = new NaviMapScaleBar(getVtmMap());
naviMapScaleBar.initScaleBarLayer(GLViewport.Position.BOTTOM_LEFT, 25, 60);
@@ -302,6 +284,9 @@ public final class NIMapView extends RelativeLayout {
zoomLayout = rootView.findViewById(R.id.navinfo_map_zoom_layer);
switchTileVectorLayerTheme(MAP_THEME.DEFAULT);
MapEventsReceiver mapEventReceiver = new MapEventsReceiver(mapView.map());
getVtmMap().layers().add(mapEventReceiver);
}
@@ -923,7 +908,7 @@ public final class NIMapView extends RelativeLayout {
GeoPoint geoPoint = mMap.viewport().fromScreenPoint(e.getX(), e.getY());
if (g instanceof Gesture.Tap) { // 单击事件
if (mapClickListener != null) {
mapClickListener.onMapClick(geoPoint);
mapClickListener.onMapClick(new com.navinfo.collect.library.map.GeoPoint(geoPoint.getLatitude(), geoPoint.getLongitude()));
}
} else if (g instanceof Gesture.DoubleTap) { // 双击
if (mapDoubleClickListener != null) {
@@ -934,17 +919,6 @@ public final class NIMapView extends RelativeLayout {
mapLongClickListener.onMapLongClick(geoPoint);
}
}
setOnMapClickListener(new OnMapClickListener() {
@Override
public void onMapClick(GeoPoint point) {
}
@Override
public void onMapPoiClick(GeoPoint poi) {
}
});
return false;
}
}
@@ -952,7 +926,7 @@ public final class NIMapView extends RelativeLayout {
/**
* 设置地图的点击事件
*/
public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
public void setOnMapClickListener(OnMapClickListener listener) {
this.mapClickListener = listener;
}

View File

@@ -1,11 +1,12 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import com.navinfo.collect.library.map.NIMapView
import org.oscim.layers.Layer
abstract class BaseHandler(context: Context, mapView: NIMapView) {
protected val mContext: Context = context
abstract class BaseHandler(context: AppCompatActivity, mapView: NIMapView) {
protected val mContext: AppCompatActivity = context
protected val mMapView: NIMapView = mapView
fun addLayer(layer: Layer, groupType: NIMapView.LAYER_GROUPS) {
@@ -19,4 +20,11 @@ abstract class BaseHandler(context: Context, mapView: NIMapView) {
mMapView.vtmMap.layers().remove(layer)
}
fun setOnMapClickListener(listener: NIMapView.OnMapClickListener) {
mMapView.setOnMapClickListener(listener)
}
fun removeOnMapClickListener() {
mMapView.setOnMapClickListener(null)
}
}

View File

@@ -1,25 +1,46 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import android.os.Environment
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.navinfo.collect.library.data.entity.QsRecordBean
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.map.NIMapView.LAYER_GROUPS
import com.navinfo.collect.library.map.source.NavinfoMapRastorTileSource
import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource
import com.navinfo.collect.library.system.Constant
import io.realm.Realm
import io.realm.kotlin.where
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Cache
import okhttp3.OkHttpClient
import org.oscim.layers.Layer
import org.oscim.layers.LocationLayer
import org.oscim.layers.tile.bitmap.BitmapTileLayer
import org.oscim.backend.CanvasAdapter
import org.oscim.backend.canvas.Paint
import org.oscim.layers.GroupLayer
import org.oscim.layers.tile.buildings.BuildingLayer
import org.oscim.layers.tile.vector.VectorTileLayer
import org.oscim.layers.tile.vector.labeling.LabelLayer
import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory
import org.oscim.tiling.source.mapfile.MapFileTileSource
import java.io.File
/**
* Layer 操作
*/
class LayerManagerHandler(context: Context, mapView: NIMapView) :
class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView) :
BaseHandler(context, mapView) {
private var baseRasterLayer: Layer? = null
private var baseGroupLayer // 用于盛放所有基础底图的图层组,便于统一管理
: GroupLayer? = null
/**
* 默认文字颜色
*/
private val mDefaultTextColor = "#4E55AF"
/**
* 文字画笔
*/
private lateinit var paint: Paint
init {
initMap()
@@ -29,9 +50,12 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
* 初始化地图
*/
private fun initMap() {
switchBaseMapType(BASE_MAP_TYPE.CYCLE_MAP)
// initVectorTileLayer()
loadBaseMap()
mMapView.switchTileVectorLayerTheme(NIMapView.MAP_THEME.DEFAULT)
//初始化之间数据图层
initQsRecordDataLayer()
mMapView.vtmMap.updateMap()
// initMapLifeSource()
}
@@ -39,40 +63,104 @@ class LayerManagerHandler(context: Context, mapView: NIMapView) :
/**
* 切换基础底图样式
*/
fun switchBaseMapType(type: BASE_MAP_TYPE) {
if (baseRasterLayer != null) {
mMapView.vtmMap.layers().remove(baseRasterLayer)
baseRasterLayer = null
mMapView.vtmMap.updateMap()
fun loadBaseMap() {
//给地图layer分组
if (baseGroupLayer == null) {
baseGroupLayer = GroupLayer(mMapView.vtmMap)
addLayer(baseGroupLayer!!, NIMapView.LAYER_GROUPS.BASE)
}
baseRasterLayer = getRasterTileLayer(type.url, type.tilePath, true)
addLayer(baseRasterLayer!!, LAYER_GROUPS.BASE)
mMapView.updateMap()
}
baseGroupLayer?.let {
for (layer in it.layers) {
removeLayer(layer)
}
it.layers.clear()
val builder = OkHttpClient.Builder()
val urlTileSource: NavinfoMultiMapFileTileSource =
NavinfoMultiMapFileTileSource.builder()
.httpFactory(OkHttpFactory(builder)) //.locale("en")
.build()
private fun getRasterTileLayer(
url: String?,
tilePath: String?,
useCache: Boolean
): Layer {
val builder = OkHttpClient.Builder()
val mTileSource =
NavinfoMapRastorTileSource.builder(url).tilePath(tilePath)
.httpFactory(OkHttpFactory(builder)).build()
// 如果使用缓存
if (useCache) {
val cacheDirectory: File =
File(Constant.MAP_PATH, "tiles-raster")
val cacheSize = 300 * 1024 * 1024 // 300 MB
// Cache the tiles into file system
val cacheDirectory = File(Constant.MAP_PATH, "cache")
val cacheSize = 200 * 1024 * 1024 // 10 MB
val cache = Cache(cacheDirectory, cacheSize.toLong())
builder.cache(cache)
}
// mTileSource.setHttpEngine(new OkHttpEngine.OkHttpFactory(builder));
// mTileSource.setHttpRequestHeaders(Collections.singletonMap("User-Agent", "vtm-android-example"));
// mTileSource.setCache(new TileCache(mContext, defaultDir, url.substring(url.indexOf(":")+1)));
return BitmapTileLayer(mMapView.vtmMap, mTileSource)
// val headerMap = HashMap<String, String>()
// headerMap["token"] = ""//Constant.TOKEN
// urlTileSource.setHttpRequestHeaders(headerMap)
val baseLayer = VectorTileLayer(mMapView.vtmMap, urlTileSource)
val baseMapFolder = File("${Constant.MAP_PATH}offline")
if (baseMapFolder.exists()) {
val dirFileList = baseMapFolder.listFiles()
if (dirFileList != null && dirFileList.isNotEmpty()) {
for (mapFile in dirFileList) {
if (!mapFile.isFile || !mapFile.name.endsWith(".map")) {
continue
}
val mTileSource = MapFileTileSource()
mTileSource.setPreferredLanguage("zh")
if (mTileSource.setMapFile(mapFile.absolutePath)) {
urlTileSource.add(mTileSource)
}
}
}
baseLayer.tileSource = urlTileSource
//增加基础路网图层
it.layers.add(baseLayer)
//增加建筑图层
it.layers.add(BuildingLayer(mMapView.vtmMap, baseLayer))
//增加文字图层
it.layers.add(LabelLayer(mMapView.vtmMap, baseLayer))
for (layer in it.layers) {
addLayer(layer, NIMapView.LAYER_GROUPS.BASE)
}
mMapView.updateMap()
}
}
}
private fun initQsRecordDataLayer() {
paint = CanvasAdapter.newPaint()
paint.setTypeface(Paint.FontFamily.DEFAULT, Paint.FontStyle.NORMAL)
paint.setTextSize(13 * CanvasAdapter.getScale())
paint.strokeWidth = 2 * CanvasAdapter.getScale()
paint.color = Color.parseColor(mDefaultTextColor)
mContext.lifecycleScope.launch(Dispatchers.IO) {
val realm = Realm.getDefaultInstance()
realm.executeTransaction {
val list = realm.where<QsRecordBean>().findAll()
paint.setColor(Color.parseColor(mDefaultTextColor))
}
realm.close()
}
}
// private fun getRasterTileLayer(
// url: String?,
// tilePath: String?,
// useCache: Boolean
// ): Layer {
// val builder = OkHttpClient.Builder()
// val mTileSource =
// NavinfoMapRastorTileSource.builder(url).tilePath(tilePath)
// .httpFactory(OkHttpFactory(builder)).build()
// // 如果使用缓存
// if (useCache) {
// val cacheDirectory =
// File(Constant.MAP_PATH, "cache")
// val cacheSize = 300 * 1024 * 1024 // 300 MB
// val cache = Cache(cacheDirectory, cacheSize.toLong())
// builder.cache(cache)
// }
//
// return BitmapTileLayer(mMapView.vtmMap, mTileSource)
// }
}
/**

View File

@@ -8,12 +8,12 @@ import com.baidu.location.BDLocation
import com.baidu.location.LocationClient
import com.baidu.location.LocationClientOption
import com.baidu.location.LocationClientOption.LocationMode
import com.navinfo.collect.library.map.GeoPoint
import com.navinfo.collect.library.map.NIMapView
import org.oscim.layers.LocationLayer
class LocationLayerHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView) {
class LocationLayerHandler(context: Context, mapView: NIMapView) : BaseHandler(context, mapView) {
private var mCurrentLocation: BDLocation? = null
private var bFirst = true
@@ -55,13 +55,11 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
val errorCode = it.locType
mCurrentLocation = it
mLocationLayer.setPosition(
it.latitude,
it.longitude,
it.radius
it.latitude, it.longitude, it.radius
)
//第一次定位成功显示当前位置
if (this.bFirst) {
animateToCurrentPosition()
animateToCurrentPosition(16.0)
}
}
@@ -97,9 +95,7 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
// locationOption.setOpenAutoNotifyMode()
//设置打开自动回调位置模式该开关打开后期间只要定位SDK检测到位置变化就会主动回调给开发者
locationOption.setOpenAutoNotifyMode(
1000,
1,
LocationClientOption.LOC_SENSITIVITY_HIGHT
1000, 1, LocationClientOption.LOC_SENSITIVITY_HIGHT
)
//需将配置好的LocationClientOption对象通过setLocOption方法传递给LocationClient对象使用
locationClient.locOption = locationOption
@@ -130,21 +126,36 @@ class LocationLayerHandler(context: Context, mapView: NIMapView) :
/**
* 回到当前位置
*/
fun animateToCurrentPosition()
{
fun animateToCurrentPosition(zoom: Double) {
mCurrentLocation?.run {
val mapPosition = mMapView.vtmMap.mapPosition;
mapPosition.setPosition(this.latitude, this.longitude);
mMapView.vtmMap.animator().animateTo(300, mapPosition);
val mapPosition = mMapView.vtmMap.mapPosition
mapPosition.zoom = zoom
mapPosition.setPosition(this.latitude, this.longitude)
mMapView.vtmMap.animator().animateTo(300, mapPosition)
}
}
fun animateToCurrentPosition() {
mCurrentLocation?.run {
val mapPosition = mMapView.vtmMap.mapPosition
mapPosition.setPosition(this.latitude, this.longitude)
mMapView.vtmMap.animator().animateTo(300, mapPosition)
}
}
fun getCurrentGeoPoint(): GeoPoint? {
mCurrentLocation?.let {
return GeoPoint(it.latitude, it.longitude)
}
return null
}
}
/**
* 实现定位回调
*/
private class MyLocationListener(callback: (BDLocation) -> Unit) :
BDAbstractLocationListener() {
private class MyLocationListener(callback: (BDLocation) -> Unit) : BDAbstractLocationListener() {
val call = callback;
override fun onReceiveLocation(location: BDLocation) {
call(location)

View File

@@ -1,75 +1,101 @@
package com.navinfo.collect.library.map.handler
import android.content.Context
import android.graphics.BitmapFactory
import com.navinfo.collect.library.R
import com.navinfo.collect.library.map.GeoPoint
import com.navinfo.collect.library.map.NIMapView
import com.navinfo.collect.library.utils.StringUtil
import org.oscim.core.GeoPoint
import org.oscim.android.canvas.AndroidBitmap
import org.oscim.layers.marker.ItemizedLayer
import org.oscim.layers.marker.ItemizedLayer.OnItemGestureListener
import org.oscim.layers.marker.MarkerInterface
import org.oscim.layers.marker.MarkerItem
import org.oscim.layers.marker.MarkerSymbol
/**
* marker 操作
*/
open class MarkHandler(context: Context, mapView:NIMapView) :
BaseHandler(context, mapView), OnItemGestureListener<MarkerInterface> {
class MarkHandler(context: Context, mapView: NIMapView) :
BaseHandler(context, mapView) {
// //增加marker
// fun addMarker(
// geoPoint: GeoPoint,
// title: String?,
// description: String? = ""
// ): MarkerItem {
// var marker: MarkerItem? = null
// for (e in mMapView.layerManager.defaultMarkerLayer.itemList) {
// if (e is MarkerItem && e.title == title) {
// marker = e;
// break;
// }
// }
// if (marker == null) {
// var tempTitle = title;
// if (tempTitle.isNullOrBlank()) {
// tempTitle = StringUtil.createUUID();
// }
// val marker = MarkerItem(
// tempTitle,
// description,
// geoPoint
// )
// mMapView.layerManager.defaultMarkerLayer.addItem(marker);
// mMapView.vtmMap.updateMap(true)
// return marker
// } else {
// marker.description = description
// marker.geoPoint = geoPoint
// mMapView.layerManager.defaultMarkerLayer.removeItem(marker)
// mMapView.layerManager.defaultMarkerLayer.addItem(marker)
// mMapView.vtmMap.updateMap(true)
// return marker
// }
// }
//
// fun removeMarker(title: String) {
// var marker: MarkerItem? = null
// for (e in mMapView.layerManager.defaultMarkerLayer.itemList) {
// if (e is MarkerItem && e.title == title) {
// marker = e;
// break;
// }
// }
// if (marker != null) {
// mMapView.layerManager.defaultMarkerLayer.removeItem(marker)
// mMapView.vtmMap.updateMap(true)
// }
// }
//
override fun onItemSingleTapUp(index: Int, item: MarkerInterface): Boolean {
return false
// //默认marker图层
private var mDefaultMarkerLayer: ItemizedLayer
init {
//新增marker图标样式
val mDefaultBitmap =
AndroidBitmap(BitmapFactory.decodeResource(context.resources, R.mipmap.marker));
val markerSymbol = MarkerSymbol(
mDefaultBitmap,
MarkerSymbol.HotspotPlace.BOTTOM_CENTER
);
//新增marker图层
mDefaultMarkerLayer = ItemizedLayer(
mapView.vtmMap,
ArrayList<MarkerInterface>(),
markerSymbol,
object : OnItemGestureListener<MarkerInterface> {
override fun onItemSingleTapUp(index: Int, item: MarkerInterface?): Boolean {
return false
}
override fun onItemLongPress(index: Int, item: MarkerInterface?): Boolean {
return false
}
}
)
addLayer(mDefaultMarkerLayer, NIMapView.LAYER_GROUPS.OPERATE);
}
override fun onItemLongPress(index: Int, item: MarkerInterface): Boolean {
return false
//增加marker
fun addMarker(
geoPoint: GeoPoint,
title: String?,
description: String? = ""
) {
var marker: MarkerItem? = null
for (e in mDefaultMarkerLayer.itemList) {
if (e is MarkerItem && e.title == title) {
marker = e
break
}
}
if (marker == null) {
var tempTitle = title;
if (tempTitle.isNullOrBlank()) {
tempTitle = StringUtil.createUUID();
}
val marker = MarkerItem(
tempTitle,
description,
org.oscim.core.GeoPoint(geoPoint.latitude, geoPoint.longitude)
)
mDefaultMarkerLayer.addItem(marker);
mMapView.vtmMap.updateMap(true)
} else {
marker.description = description
marker.geoPoint = org.oscim.core.GeoPoint(geoPoint.latitude, geoPoint.longitude)
mDefaultMarkerLayer.removeItem(marker)
mDefaultMarkerLayer.addItem(marker)
mMapView.vtmMap.updateMap(true)
}
}
fun removeMarker(title: String) {
var marker: MarkerItem? = null
for (e in mDefaultMarkerLayer.itemList) {
if (e is MarkerItem && e.title == title) {
marker = e
break
}
}
if (marker != null) {
mDefaultMarkerLayer.removeItem(marker)
mMapView.vtmMap.updateMap(true)
}
}
}

View File

@@ -7,7 +7,6 @@ import org.oscim.core.GeoPoint
import org.oscim.core.Point
open class ViewportHandler(context: Context, mapView: NIMapView) : BaseHandler(context, mapView) {
/**
* Set pivot horizontal / vertical relative to view center in [-1, 1].
* e.g. pivotY 0.5 is usually preferred for navigation, moving center to 25% of view height.
@@ -73,7 +72,7 @@ open class ViewportHandler(context: Context, mapView: NIMapView) : BaseHandler(c
px: Float, py: Float
): Map<String, Any> {
val geo = mMapView.vtmMap.viewport().fromScreenPoint(px,py)
val geo = mMapView.vtmMap.viewport().fromScreenPoint(px, py)
return mapOf(
"latitude" to geo.latitude,

View File

@@ -1,39 +1,38 @@
package com.navinfo.collect.library.map.source;
import android.util.Log;
import com.navinfo.collect.library.system.Constant;
import org.oscim.core.BoundingBox;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import org.oscim.core.Tile;
import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.OverzoomTileDataSource;
import org.oscim.tiling.source.UrlTileSource;
import org.oscim.tiling.source.geojson.GeojsonTileSource;
import org.oscim.tiling.source.mapfile.IMapFileTileSource;
import org.oscim.tiling.source.mapfile.MapDatabase;
import org.oscim.tiling.source.mapfile.MapFileTileSource;
import org.oscim.utils.FastMath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/*
*com.navinfo.map.source
*com.nmp.map.source
*zhjch
*2021/9/17
*9:46
*说明()
*/
public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements IMapFileTileSource {
public class NavinfoMultiMapFileTileSource extends UrlTileSource implements IMapFileTileSource {
// private static final String DEFAULT_URL = "http://cmp-gateway-sp9-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/maponline/map/online";
private static final String DEFAULT_URL = "http://epohvqjxts85k6u-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/map/online/geoJson";
private static final String DEFAULT_PATH = "x={X}&y={Y}&z={Z}";
private static final String DEFAULT_URL = "http://c.tile.opencyclemap.org/cycle";
private static final String DEFAULT_PATH = "/{Z}}/{X}/{Y}.png";
private static final TileUrlFormatter mTileUrlFormatter = URL_FORMATTER;
@@ -67,7 +66,6 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
public String getTileUrl(Tile tile) {
StringBuilder sb = new StringBuilder();
sb.append(DEFAULT_URL).append("?").append(mTileUrlFormatter.formatTilePath(this, tile));
System.out.println(sb.toString());
return sb.toString();
}
@@ -125,66 +123,13 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
mapDatabase.restrictToZoomRange(zoomLevels[0], zoomLevels[1]);
multiMapDatabase.add(mapDatabase);
} catch (IOException e) {
Log.e("jingo", e.getMessage());
log.debug(e.getMessage());
}
}
// return new NavinfoMultiMapDatabase(this, new NavinfoVectorTileDecoder(locale), getHttpEngine());
return new OverzoomTileDataSource(multiMapDatabase, mOverZoom);
}
private static Map<String, Tag> mappings = new LinkedHashMap<>();
private static Tag addMapping(String key, String val) {
Tag tag = new Tag(key, val);
mappings.put(key + "=" + val, tag);
return tag;
}
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
boolean hasName = false;
String fallbackName = null;
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
String val = (value instanceof String) ? (String) value : String.valueOf(value);
if (key.startsWith(Tag.KEY_NAME)) {
int len = key.length();
if (len == 4) {
fallbackName = val;
continue;
}
if (len < 7)
continue;
if (locale.equals(key.substring(5))) {
hasName = true;
mapElement.tags.add(new Tag(Tag.KEY_NAME, val, false));
}
continue;
}
Tag tag = mappings.get(key + "=" + val);
if (tag == null)
tag = addMapping(key, val);
mapElement.tags.add(tag);
}
if (!hasName && fallbackName != null)
mapElement.tags.add(new Tag(Tag.KEY_NAME, fallbackName, false));
// Calculate height of building parts
if (!properties.containsKey(Tag.KEY_HEIGHT)) {
if (properties.containsKey(Tag.KEY_VOLUME) && properties.containsKey(Tag.KEY_AREA)) {
Object volume = properties.get(Tag.KEY_VOLUME);
String volumeStr = (volume instanceof String) ? (String) volume : String.valueOf(volume);
Object area = properties.get(Tag.KEY_AREA);
String areaStr = (area instanceof String) ? (String) area : String.valueOf(area);
float height = Float.parseFloat(volumeStr) / Float.parseFloat(areaStr);
String heightStr = String.valueOf(FastMath.round2(height));
mapElement.tags.add(new Tag(Tag.KEY_HEIGHT, heightStr, false));
}
}
}
@Override
public OpenResult open() {
@@ -194,8 +139,10 @@ public class NavinfoMultiMapFileTileSource extends GeojsonTileSource implements
if (result != OpenResult.SUCCESS)
openResult = result;
}
if(openResult != OpenResult.SUCCESS)
return super.open();
if(openResult != OpenResult.SUCCESS) {
return super.open();
}
return openResult;
}

View File

@@ -11,6 +11,9 @@ import java.util.Map;
public class Constant {
//服务地址
public static String URL_BASE = "http://cmp-gateway-sp9-port.ayiqdpfs.cloud.app.ncloud.navinfo.com/";
public static String MAP_PATH = Environment.getExternalStorageDirectory() + "/map/";
public static void setVisibleTypeMap(Map<String, Boolean> visibleTypeMap) {

View File

@@ -10,7 +10,7 @@ class GeometryToolsKt {
/**
* 根据给定的geometry计算其横跨的20级瓦片Y值
*/
fun getTileYByGeometry(wkt: String, tileYSet: MutableSet<Int?>): Set<Int?>? {
fun getTileYByGeometry(wkt: String, tileYSet: MutableSet<Int?>){
val reader = WKTReader()
val geometry = reader.read(wkt);
@@ -20,6 +20,7 @@ class GeometryToolsKt {
if (tileYSet == null) {
tileYSet = RealmSet()
}
tileYSet.clear()
val envelope = geometry.envelope
if (envelope != null) {
val coordinates = envelope.coordinates
@@ -48,13 +49,12 @@ class GeometryToolsKt {
}
}
println("YGeometry-time:" + (System.currentTimeMillis() - startTime))
return tileYSet
}
/**
* 根据给定的geometry计算其横跨的20级瓦片X值
*/
fun getTileXByGeometry(wkt: String, tileXSet: MutableSet<Int?>): Set<Int?>? {
fun getTileXByGeometry(wkt: String, tileXSet: MutableSet<Int?>) {
val reader = WKTReader()
val geometry = reader.read(wkt);
@@ -63,6 +63,7 @@ class GeometryToolsKt {
if (tileXSet == null) {
tileXSet = RealmSet()
}
tileXSet.clear()
if (geometry != null) {
val envelope = geometry.envelope
if (envelope != null) {
@@ -92,7 +93,6 @@ class GeometryToolsKt {
}
}
println("XGeometry-time:" + (System.currentTimeMillis() - startTime))
return tileXSet
}
fun getMasterPoint(wkt: String): String {