From 60622a3197fad890856997e7411e8ee526dc3da8 Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Mon, 24 Apr 2023 10:52:14 +0800 Subject: [PATCH 1/2] =?UTF-8?q?1.=20=E5=A2=9E=E5=8A=A0OMDB=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=9B=BE=E5=B1=82=202.=20=E4=BF=AE=E6=94=B9Realm?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=96=87=E4=BB=B6=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/navinfo/omqs/OMQSApplication.kt | 17 -- .../omqs/ui/activity/PermissionsActivity.kt | 26 +-- .../omqs/ui/activity/login/LoginViewModel.kt | 26 ++- .../personalcenter/PersonalCenterFragment.kt | 6 + .../personalcenter/PersonalCenterViewModel.kt | 1 + .../library/data/entity/RenderEntity.kt | 9 +- .../map/handler/LayerManagerHandler.kt | 36 +++- .../library/map/source/OMDBDataDecoder.java | 190 ++++++++++++++++++ .../map/source/OMDBTileDataSource.java | 74 +++++++ .../library/map/source/OMDBTileSource.java | 25 +++ .../collect/library/system/Constant.java | 1 + 11 files changed, 370 insertions(+), 41 deletions(-) create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileDataSource.java create mode 100644 collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileSource.java diff --git a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt index bd145e45..c1d6b8e3 100644 --- a/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt +++ b/app/src/main/java/com/navinfo/omqs/OMQSApplication.kt @@ -20,20 +20,6 @@ class OMQSApplication : Application() { Util.getInstance().init(applicationContext) NetUtils.getInstance().init(this) TakePhotoManager.getInstance().init(this, 1) - FileManager.initRootDir(this) - Realm.init(this) - val password = "encryp".encodeToByteArray().copyInto(ByteArray(64)) - // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - Log.d("OMQSApplication", "密码是: ${byteArrayToHexString(password)}") - // 1110000011000010111001101110011011101110110111101110010011001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - val config = RealmConfiguration.Builder() - .directory(File(Constant.DATA_PATH)) - .name("OMQS.realm") - .encryptionKey(password) -// .modules(Realm.getDefaultModule(), MyRealmModule()) - .schemaVersion(1) - .build() - Realm.setDefaultConfiguration(config) } private fun getKey(inputString: String): String { @@ -42,7 +28,4 @@ class OMQSApplication : Application() { return hashBytes.joinToString("") { "%02x".format(it) }; } - fun byteArrayToHexString(byteArray: ByteArray): String { - return byteArray.joinToString("") { "%02x".format(it) } - } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt index 89b88868..d5319a75 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/PermissionsActivity.kt @@ -10,7 +10,7 @@ import com.hjq.permissions.XXPermissions /** * 权限申请Activity */ -open class PermissionsActivity : BaseActivity() { +open abstract class PermissionsActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val permissionList = mutableListOf() @@ -29,11 +29,11 @@ open class PermissionsActivity : BaseActivity() { //定位权限 permissionList.add(Permission.ACCESS_FINE_LOCATION) permissionList.add(Permission.ACCESS_COARSE_LOCATION) - //android10 - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) { - permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION) - } -/* XXPermissions.with(this) +// //android10 +// if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) { +// permissionList.add(Permission.ACCESS_BACKGROUND_LOCATION) +// } + XXPermissions.with(this) // 申请单个权限 .permission(permissionList) // 设置权限请求拦截器(局部设置) @@ -50,10 +50,10 @@ open class PermissionsActivity : BaseActivity() { Toast.LENGTH_SHORT ) .show() - onPermissionsGranted() + onPermissionsDenied() return } else { - onPermissionsDenied() + onPermissionsGranted() } // 在SD卡创建项目目录 } @@ -73,20 +73,16 @@ open class PermissionsActivity : BaseActivity() { onPermissionsDenied() } } - })*/ + }) } /** * 权限全部同意 */ - open fun onPermissionsGranted() { - - } + open abstract fun onPermissionsGranted() /** * 权限 */ - open fun onPermissionsDenied() { - - } + open abstract fun onPermissionsDenied() } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt index d0bc2101..da6ccc0e 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt @@ -7,14 +7,18 @@ import android.widget.Toast import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.navinfo.omqs.Constant import com.navinfo.omqs.bean.LoginUserBean import com.navinfo.omqs.db.RoomAppDatabase import com.navinfo.omqs.http.NetResult import com.navinfo.omqs.http.NetworkService import com.navinfo.omqs.tools.FileManager import dagger.hilt.android.lifecycle.HiltViewModel +import io.realm.Realm +import io.realm.RealmConfiguration import kotlinx.coroutines.* import okio.IOException +import java.io.File import javax.inject.Inject enum class LoginStatus { @@ -110,8 +114,7 @@ class LoginViewModel @Inject constructor( //文件夹初始化 try { loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_INIT) - createUserFolder(context) - // 初始化Realm + createUserFolder(context, "1") } catch (e: IOException) { loginStatus.postValue(LoginStatus.LOGIN_STATUS_FOLDER_FAILURE) } @@ -151,8 +154,21 @@ class LoginViewModel @Inject constructor( * 创建用户目录 */ @Throws(IOException::class) - private fun createUserFolder(context: Context) { + private fun createUserFolder(context: Context, userId: String) { // 在SD卡创建用户目录,解压资源等 + // 初始化Realm + Realm.init(context.applicationContext) + val password = "encryp".encodeToByteArray().copyInto(ByteArray(64)) + // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + Log.d("OMQSApplication", "密码是: ${byteArrayToHexString(password)}") + val config = RealmConfiguration.Builder() + .directory(File("${Constant.DATA_PATH}/${userId}")) + .name("OMQS.realm") + .encryptionKey(password) +// .modules(Realm.getDefaultModule(), MyRealmModule()) + .schemaVersion(1) + .build() + Realm.setDefaultConfiguration(config) } /** @@ -169,4 +185,8 @@ class LoginViewModel @Inject constructor( super.onCleared() cancelLogin() } + + private fun byteArrayToHexString(byteArray: ByteArray): String { + return byteArray.joinToString("") { "%02x".format(it) } + } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt index b4d7f882..bfdaf91a 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt @@ -17,6 +17,7 @@ import com.github.k1rakishou.fsaf.callback.FSAFActivityCallbacks import com.github.k1rakishou.fsaf.callback.FileChooserCallback import com.navinfo.collect.library.data.RealmUtils import com.navinfo.collect.library.data.entity.OMDBEntity +import com.navinfo.collect.library.map.NIMapController import com.navinfo.omqs.R import com.navinfo.omqs.databinding.FragmentPersonalCenterBinding import com.navinfo.omqs.db.ImportOMDBHelper @@ -30,6 +31,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.oscim.core.GeoPoint import java.io.File import java.util.UUID import javax.inject.Inject @@ -46,6 +48,8 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { private val viewModel by lazy { viewModels().value } @Inject lateinit var importOMDBHiltFactory: ImportOMDBHiltFactory + @Inject + lateinit var niMapController: NIMapController override fun onCreateView( @@ -107,6 +111,8 @@ class PersonalCenterFragment : Fragment(), FSAFActivityCallbacks { } R.id.personal_center_menu_test -> { viewModel.readRealmData() + // 定位到指定位置 + niMapController.mMapView.vtmMap.animator().animateTo(GeoPoint(28.608398, 115.67901)) } } true diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt index cfad6b4f..fec2265e 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt @@ -10,6 +10,7 @@ import com.blankj.utilcode.util.UriUtils import com.blankj.utilcode.util.ZipUtils import com.google.gson.Gson import com.navinfo.collect.library.data.entity.* +import com.navinfo.collect.library.map.NIMapController import com.navinfo.collect.library.utils.GeometryTools import com.navinfo.omqs.bean.ScProblemTypeBean import com.navinfo.omqs.bean.ScRootCauseAnalysisBean diff --git a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt index b4842cb2..3f7f0df0 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/data/entity/RenderEntity.kt @@ -23,7 +23,10 @@ open class RenderEntity(): RealmObject() { lateinit var table: String //要素表名 var code: Int = 0 // 要素编码 var geometry: String = "" - get() = field + get() { + wkt = GeometryTools.createGeometry(field) + return field + } set(value) { field = value // 根据geometry自动计算当前要素的x-tile和y-tile @@ -39,8 +42,8 @@ open class RenderEntity(): RealmObject() { @Ignore var wkt: Geometry? = null var properties: RealmDictionary = RealmDictionary() - val tileX: RealmSet = RealmSet() // x方向的tile编码 - val tileY: RealmSet = RealmSet() // y方向的tile编码 + var tileX: RealmSet = RealmSet() // x方向的tile编码 + var tileY: RealmSet = RealmSet() // y方向的tile编码 constructor(name: String, properties: RealmDictionary): this() { this.name = name diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt index 0bd7b965..746d6e1b 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/handler/LayerManagerHandler.kt @@ -15,6 +15,7 @@ import com.navinfo.collect.library.map.cluster.ClusterMarkerRenderer import com.navinfo.collect.library.map.layers.MyItemizedLayer import com.navinfo.collect.library.map.source.MapLifeNiLocationTileSource import com.navinfo.collect.library.map.source.NavinfoMultiMapFileTileSource +import com.navinfo.collect.library.map.source.OMDBTileSource import com.navinfo.collect.library.system.Constant import com.navinfo.collect.library.utils.GeometryTools import io.realm.Realm @@ -30,12 +31,17 @@ import org.oscim.backend.CanvasAdapter import org.oscim.backend.canvas.Bitmap import org.oscim.backend.canvas.Paint import org.oscim.core.GeoPoint +import org.oscim.event.EventListener import org.oscim.layers.GroupLayer -import org.oscim.layers.marker.* +import org.oscim.layers.marker.MarkerInterface +import org.oscim.layers.marker.MarkerItem +import org.oscim.layers.marker.MarkerRendererFactory +import org.oscim.layers.marker.MarkerSymbol 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.layers.tile.vector.labeling.LabelTileLoaderHook +import org.oscim.map.Map import org.oscim.tiling.source.OkHttpEngine.OkHttpFactory import org.oscim.tiling.source.mapfile.MapFileTileSource import java.io.File @@ -79,7 +85,11 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr * 增加作业渲染 */ private lateinit var labelNiLocationLayer: LabelLayer - + /** + * 显示待测评OMDB数据的图层 + * */ + private lateinit var omdbVectorTileLayer: VectorTileLayer + private lateinit var omdbLabelLayer: LabelLayer /** * 文字大小 */ @@ -87,6 +97,14 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr init { initMap() + mMapView.vtmMap.events.bind(Map.UpdateListener { e, mapPosition -> + val isOmdbZoom = mapPosition.zoomLevel>=Constant.OMDB_MIN_ZOOM + baseGroupLayer?.layers?.forEach { + it.isEnabled = !isOmdbZoom + } + omdbVectorTileLayer.isEnabled = isOmdbZoom + omdbLabelLayer.isEnabled = isOmdbZoom + }) } /** @@ -96,6 +114,8 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr loadBaseMap() + initOMDBVectorTileLayer() + mapLifeNiLocationTileSource = MapLifeNiLocationTileSource(mContext, mTracePath) vectorNiLocationTileLayer = VectorTileLayer(mMapView.vtmMap, mapLifeNiLocationTileSource) @@ -119,9 +139,19 @@ open class LayerManagerHandler(context: AppCompatActivity, mapView: NIMapView,tr mMapView.vtmMap.updateMap() - } + private fun initOMDBVectorTileLayer() { + val omdbTileSource: OMDBTileSource = OMDBTileSource() + omdbVectorTileLayer = VectorTileLayer(mMapView.vtmMap, omdbTileSource) + omdbLabelLayer = LabelLayer(mMapView.vtmMap, omdbVectorTileLayer, LabelTileLoaderHook(), Constant.OMDB_MIN_ZOOM) + if(omdbVectorTileLayer!=null){ + addLayer(omdbVectorTileLayer,NIMapView.LAYER_GROUPS.VECTOR_TILE) + } + if(omdbLabelLayer!=null){ + addLayer(omdbLabelLayer, NIMapView.LAYER_GROUPS.VECTOR_TILE) + } + } /** * 切换基础底图样式 diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java new file mode 100644 index 00000000..17111dc6 --- /dev/null +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBDataDecoder.java @@ -0,0 +1,190 @@ +package com.navinfo.collect.library.map.source; + +import static org.oscim.core.MercatorProjection.latitudeToY; +import static org.oscim.core.MercatorProjection.longitudeToX; + +import android.os.Build; +import android.util.Log; + +import androidx.annotation.RequiresApi; + +import com.navinfo.collect.library.data.entity.GeometryFeatureEntity; +import com.navinfo.collect.library.data.entity.RenderEntity; + +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.LineString; +import org.locationtech.jts.geom.MultiLineString; +import org.locationtech.jts.geom.MultiPoint; +import org.locationtech.jts.geom.MultiPolygon; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.Polygon; +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKBReader; +import org.oscim.core.MapElement; +import org.oscim.core.Tag; +import org.oscim.core.Tile; +import org.oscim.tiling.ITileDataSink; +import org.oscim.tiling.source.mvt.TileDecoder; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +public class OMDBDataDecoder extends TileDecoder { + private final String mLocale; + + private static final float REF_TILE_SIZE = 4096.0f; + + private final GeometryFactory mGeomFactory; + private final MapElement mMapElement; + private ITileDataSink mTileDataSink; + private double mTileY, mTileX, mTileScale; + + public OMDBDataDecoder() { + super(); + mLocale = ""; + mGeomFactory = new GeometryFactory(); + mMapElement = new MapElement(); + mMapElement.layer = 5; + } + + @Override + public boolean decode(Tile tile, ITileDataSink sink, InputStream is) throws IOException { + mTileDataSink = sink; + mTileScale = 1 << tile.zoomLevel; + mTileX = tile.tileX / mTileScale; + mTileY = tile.tileY / mTileScale; + mTileScale *= Tile.SIZE; + return true; + } + + @RequiresApi(api = Build.VERSION_CODES.N) + public boolean decode(Tile tile, ITileDataSink sink, List listResult) { + mTileDataSink = sink; + mTileScale = 1 << tile.zoomLevel; + mTileX = tile.tileX / mTileScale; + mTileY = tile.tileY / mTileScale; + mTileScale *= Tile.SIZE; + + listResult.stream().iterator().forEachRemaining(new Consumer() { + @Override + public void accept(RenderEntity renderEntity) { + Log.d("RealmDBTileDataSource", renderEntity.getGeometry()); + Map properties= new HashMap<>(renderEntity.getProperties().size()); + properties.putAll(renderEntity.getProperties()); + parseGeometry(renderEntity.getTable(), renderEntity.getWkt(), properties); + } + }); + return true; + } + + public void parseGeometry(String layerName, Geometry geometry, Map tags) { + mMapElement.clear(); + mMapElement.tags.clear(); + + parseTags(tags, layerName); + if (mMapElement.tags.size() == 0) { + return; + } + + boolean err = false; + if (geometry instanceof Point) { + mMapElement.startPoints(); + processCoordinateArray(geometry.getCoordinates(), false); + } else if (geometry instanceof MultiPoint) { + MultiPoint multiPoint = (MultiPoint) geometry; + for (int i = 0; i < multiPoint.getNumGeometries(); i++) { + mMapElement.startPoints(); + processCoordinateArray(multiPoint.getGeometryN(i).getCoordinates(), false); + } + } else if (geometry instanceof LineString) { + processLineString((LineString) geometry); + } else if (geometry instanceof MultiLineString) { + MultiLineString multiLineString = (MultiLineString) geometry; + for (int i = 0; i < multiLineString.getNumGeometries(); i++) { + processLineString((LineString) multiLineString.getGeometryN(i)); + } + } else if (geometry instanceof Polygon) { + Polygon polygon = (Polygon) geometry; + processPolygon(polygon); + } else if (geometry instanceof MultiPolygon) { + MultiPolygon multiPolygon = (MultiPolygon) geometry; + for (int i = 0; i < multiPolygon.getNumGeometries(); i++) { + processPolygon((Polygon) multiPolygon.getGeometryN(i)); + } + } else { + err = true; + } + + if (!err) { + mTileDataSink.process(mMapElement); + } + } + + private void processLineString(LineString lineString) { + mMapElement.startLine(); + processCoordinateArray(lineString.getCoordinates(), false); + } + + private void processPolygon(Polygon polygon) { + mMapElement.startPolygon(); + processCoordinateArray(polygon.getExteriorRing().getCoordinates(), true); + for (int i = 0; i < polygon.getNumInteriorRing(); i++) { + mMapElement.startHole(); + processCoordinateArray(polygon.getInteriorRingN(i).getCoordinates(), true); + } + } + + private void processCoordinateArray(Coordinate[] coordinates, boolean removeLast) { + int length = removeLast ? coordinates.length - 1 : coordinates.length; + for (int i = 0; i < length; i++) { + mMapElement.addPoint((float) ((longitudeToX(coordinates[i].x) - mTileX) * mTileScale), + (float) ((latitudeToY(coordinates[i].y) - mTileY) * mTileScale)); + } + +// int length = removeLast ? coordinates.length - 1 : coordinates.length; +// // 初始化3D数据类型 +// float[] point3D = new float[coordinates.length*3]; +// for (int i = 0; i < length; i++) { +// point3D[i*3] = (float) coordinates[i].x; +// point3D[(i*3)+1] = (float) coordinates[i].y; +// point3D[(i*3)+2] = (float) coordinates[i].z; +// } +// mMapElement.points = point3D; +// mMapElement.pointNextPos = mMapElement.points.length; +// mMapElement.type = GeometryBuffer.GeometryType.TRIS; + } + + private void parseTags(Map map, String layerName) { + mMapElement.tags.add(new Tag("layer", layerName)); + boolean hasName = false; + String fallbackName = null; + for (Map.Entry entry : map.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 (mLocale.equals(key.substring(5))) { + hasName = true; + mMapElement.tags.add(new Tag(Tag.KEY_NAME, val, false)); + } + } else { + mMapElement.tags.add(new Tag(key, val)); + } + } + if (!hasName && fallbackName != null) + mMapElement.tags.add(new Tag(Tag.KEY_NAME, fallbackName, false)); + } +} diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileDataSource.java b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileDataSource.java new file mode 100644 index 00000000..31f2291a --- /dev/null +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileDataSource.java @@ -0,0 +1,74 @@ +package com.navinfo.collect.library.map.source; + +import android.os.Build; +import android.util.Log; + +import androidx.annotation.RequiresApi; + +import com.navinfo.collect.library.data.RealmUtils; +import com.navinfo.collect.library.data.entity.GeometryFeatureEntity; +import com.navinfo.collect.library.data.entity.RenderEntity; +import com.navinfo.collect.library.system.Constant; + +import org.oscim.layers.tile.MapTile; +import org.oscim.tiling.ITileDataSink; +import org.oscim.tiling.ITileDataSource; +import org.oscim.tiling.QueryResult; + +import java.util.List; + +import io.realm.Realm; +import io.realm.RealmQuery; + +public class OMDBTileDataSource implements ITileDataSource { + private final ThreadLocal mThreadLocalDecoders = new ThreadLocal() { + @Override + protected OMDBDataDecoder initialValue() { + return new OMDBDataDecoder(); + } + }; + + @RequiresApi(api = Build.VERSION_CODES.N) + @Override + public void query(MapTile tile, ITileDataSink mapDataSink) { + // 获取tile对应的坐标范围 + if (tile.zoomLevel>=Constant.OMDB_MIN_ZOOM&&tile.zoomLevel<=Constant.OVER_ZOOM) { + int m = Constant.OVER_ZOOM-tile.zoomLevel; + int xStart = (int)tile.tileX< realmQuery = Realm.getDefaultInstance().where(RenderEntity.class) + .rawPredicate("tileX>="+xStart+" and tileX<="+xEnd+" and tileY>="+yStart+" and tileY<="+yEnd); +// // 筛选不显示的数据 +// if (Constant.HAD_LAYER_INVISIABLE_ARRAY!=null&&Constant.HAD_LAYER_INVISIABLE_ARRAY.length>0) { +// realmQuery.beginGroup(); +// for (String type: Constant.HAD_LAYER_INVISIABLE_ARRAY) { +// realmQuery.notEqualTo("name", type); +// } +// realmQuery.endGroup(); +// } + List listResult = realmQuery/*.distinct("id")*/.findAll(); + if (!listResult.isEmpty()) { + mThreadLocalDecoders.get().decode(tile, mapDataSink, listResult); + } + mapDataSink.completed(QueryResult.SUCCESS); + Log.d("RealmDBTileDataSource", "tile:"+tile.getBoundingBox().toString()); + } else { + mapDataSink.completed(QueryResult.SUCCESS); + } + } + + @Override + public void dispose() { + + } + + @Override + public void cancel() { + if (Realm.getDefaultInstance().isInTransaction()) { + Realm.getDefaultInstance().cancelTransaction(); + } + } +} diff --git a/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileSource.java b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileSource.java new file mode 100644 index 00000000..2ac45ac9 --- /dev/null +++ b/collect-library/src/main/java/com/navinfo/collect/library/map/source/OMDBTileSource.java @@ -0,0 +1,25 @@ +package com.navinfo.collect.library.map.source; + +import com.navinfo.collect.library.system.Constant; + +import org.oscim.tiling.ITileDataSource; +import org.oscim.tiling.OverzoomTileDataSource; +import org.oscim.tiling.TileSource; + +public class OMDBTileSource extends TileSource { + + @Override + public ITileDataSource getDataSource() { + return new OverzoomTileDataSource(new OMDBTileDataSource(), Constant.OVER_ZOOM); + } + + @Override + public OpenResult open() { + return OpenResult.SUCCESS; + } + + @Override + public void close() { + + } +} diff --git a/collect-library/src/main/java/com/navinfo/collect/library/system/Constant.java b/collect-library/src/main/java/com/navinfo/collect/library/system/Constant.java index ab5e683d..104b9932 100644 --- a/collect-library/src/main/java/com/navinfo/collect/library/system/Constant.java +++ b/collect-library/src/main/java/com/navinfo/collect/library/system/Constant.java @@ -31,5 +31,6 @@ public class Constant { public static String[] HAD_LAYER_INVISIABLE_ARRAY; public static final int OVER_ZOOM = 21; public static final int MAX_ZOOM = 25; + public static final int OMDB_MIN_ZOOM = 18; } From 8e9bd3bc5d4a35281f58d7d5a0a0ea5ba5f6ef38 Mon Sep 17 00:00:00 2001 From: xiaoyan Date: Mon, 24 Apr 2023 15:02:48 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/omdb.config | 35 +++++++++++ .../main/java/com/navinfo/omqs/Constant.kt | 7 ++- .../com/navinfo/omqs/db/ImportOMDBHelper.kt | 61 +++++++++++++------ .../omqs/hilt/ImportOMDBHiltFactory.kt | 2 +- .../omqs/ui/activity/login/LoginViewModel.kt | 10 ++- .../personalcenter/PersonalCenterFragment.kt | 29 +++++---- .../personalcenter/PersonalCenterViewModel.kt | 36 ++--------- 7 files changed, 112 insertions(+), 68 deletions(-) create mode 100644 app/src/main/assets/omdb.config diff --git a/app/src/main/assets/omdb.config b/app/src/main/assets/omdb.config new file mode 100644 index 00000000..a6737381 --- /dev/null +++ b/app/src/main/assets/omdb.config @@ -0,0 +1,35 @@ +{ + "tables" : [ + { + "table": "OMDB_RD_LINK", + "code": 2001, + "name": "道路线" + }, + { + "table": "OMDB_RD_LINK_KIND", + "code": 2008, + "name": "道路种别" + }, + { + "table": "OMDB_RD_LINK_DIRECT", + "code": 2001, + "name": "道路方向" + }, + { + "table": "OMDB_SPEEDLIMIT_COND", + "code": 2001, + "name": "条件点限速" + }, + { + "table": "OMDB_SPEEDLIMIT_VAR", + "code": 2001, + "name": "可变点限速" + }, + { + "table": "OMDB_SPEEDLIMIT", + "code": 2001, + "name": "常规点限速" + } + + ] +} \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/Constant.kt b/app/src/main/java/com/navinfo/omqs/Constant.kt index 6612fdc2..bed0d809 100644 --- a/app/src/main/java/com/navinfo/omqs/Constant.kt +++ b/app/src/main/java/com/navinfo/omqs/Constant.kt @@ -19,6 +19,11 @@ class Constant { */ lateinit var DATA_PATH: String + /** + * 当前用户ID + */ + lateinit var CURRENT_USER_ID: String + /** * 离线地图目录 */ @@ -36,7 +41,7 @@ class Constant { const val message_version_right_off = "1" //立即发送 const val MESSAGE_PAGE_SIZE = 30 //消息列表一页最多数量 - lateinit var realm: Realm + const val OMDB_CONFIG = "omdb.config" } } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt b/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt index adef0eaa..666679c0 100644 --- a/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt +++ b/app/src/main/java/com/navinfo/omqs/db/ImportOMDBHelper.kt @@ -11,11 +11,13 @@ import com.blankj.utilcode.util.ZipUtils import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.navinfo.collect.library.data.entity.RenderEntity +import com.navinfo.omqs.Constant import com.navinfo.omqs.bean.ImportConfig import com.navinfo.omqs.hilt.ImportOMDBHiltFactory import com.navinfo.omqs.hilt.OMDBDataBaseHiltFactory import dagger.assisted.Assisted import dagger.assisted.AssistedInject +import io.realm.Realm import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow @@ -28,13 +30,13 @@ import kotlin.streams.toList /** * 导入omdb数据的帮助类 * */ -class ImportOMDBHelper @AssistedInject constructor(@Assisted("context") val context: Context,@Assisted("omdbFile") val omdbFile: File,@Assisted("configFile") val configFile: File) { +class ImportOMDBHelper @AssistedInject constructor(@Assisted("context") val context: Context,@Assisted("omdbFile") val omdbFile: File) { @Inject lateinit var omdbHiltFactory: OMDBDataBaseHiltFactory @Inject lateinit var gson: Gson private val database by lazy { omdbHiltFactory.obtainOmdbDataBaseHelper(context, omdbFile.absolutePath, 1).writableDatabase } - + private val configFile: File = File("${Constant.DATA_PATH}/${Constant.CURRENT_USER_ID}", Constant.OMDB_CONFIG) /** * 读取config的配置文件 @@ -99,10 +101,10 @@ class ImportOMDBHelper @AssistedInject constructor(@Assisted("context") val cont * @param omdbZipFile omdb数据抽取生成的Zip文件 * @param configFile 对应的配置文件 * */ - suspend fun importOmdbZipFile(omdbZipFile: File): Flow>> = withContext(Dispatchers.IO) { + suspend fun importOmdbZipFile(omdbZipFile: File): Flow = withContext(Dispatchers.IO) { val importConfig = openConfigFile() val unZipFolder = File(omdbZipFile.parentFile, "result") - flow>> { + flow { if (unZipFolder.exists()) { unZipFolder.deleteRecursively() } @@ -110,26 +112,45 @@ class ImportOMDBHelper @AssistedInject constructor(@Assisted("context") val cont // 开始解压zip文件 val unZipFiles = ZipUtils.unzipFile(omdbZipFile, unZipFolder) // 遍历解压后的文件,读取该数据返回 - for (txtFile in unZipFiles) { - val listResult: MutableList> = mutableListOf() - // 根据文件名称获取对应的配置 - val currentConfig=importConfig.tables.find { - txtFile.name.substring(0, txtFile.name.lastIndexOf("."))==it.table + for ((index, currentConfig) in importConfig.tables.withIndex()) { + val txtFile = unZipFiles.find { + it.name == currentConfig.table } - val list = FileIOUtils.readFile2List(txtFile, "UTF-8") - // 将list数据转换为map - for (line in list) { - val map = gson.fromJson>(line, object : TypeToken>() {}.type) - .toMutableMap() - currentConfig?.let { - map["QItable"] = currentConfig.table - map["QIname"] = currentConfig.name - map["QIcode"] = currentConfig.code - listResult.add(map) + + val listResult: MutableList> = mutableListOf() + currentConfig?.let { + val list = FileIOUtils.readFile2List(txtFile, "UTF-8") + if (list!=null) { + // 将list数据转换为map + for (line in list) { + val map = gson.fromJson>(line, object : TypeToken>() {}.type) + .toMutableMap() + map["QItable"] = currentConfig.table + map["QIname"] = currentConfig.name + map["QIcode"] = currentConfig.code + listResult.add(map) + } } } + // 将listResult数据插入到Realm数据库中 + Realm.getDefaultInstance().beginTransaction() + for (map in listResult) { // 每一个map就是Realm的一条数据 + // 先查询这个mesh下有没有数据,如果有则跳过即可 +// val meshEntity = Realm.getDefaultInstance().where(RenderEntity::class.java).equalTo("properties['mesh']", map["mesh"].toString()).findFirst() + val renderEntity = RenderEntity() + renderEntity.code = map["QIcode"].toString().toInt() + renderEntity.name = map["QIname"].toString() + renderEntity.table = map["QItable"].toString() + // 其他数据插入到Properties中 + renderEntity.geometry = map["geometry"].toString() + for (entry in map) { + renderEntity.properties[entry.key] = entry.value.toString() + } + Realm.getDefaultInstance().insert(renderEntity) + } + Realm.getDefaultInstance().commitTransaction() // 1个文件发送一次flow流 - emit(listResult) + emit("${index+1}/${importConfig.tables.size}") } } } diff --git a/app/src/main/java/com/navinfo/omqs/hilt/ImportOMDBHiltFactory.kt b/app/src/main/java/com/navinfo/omqs/hilt/ImportOMDBHiltFactory.kt index 5f3ff4fd..a1036dc0 100644 --- a/app/src/main/java/com/navinfo/omqs/hilt/ImportOMDBHiltFactory.kt +++ b/app/src/main/java/com/navinfo/omqs/hilt/ImportOMDBHiltFactory.kt @@ -8,5 +8,5 @@ import java.io.File @AssistedFactory interface ImportOMDBHiltFactory { - fun obtainImportOMDBHelper(@Assisted("context")context: Context, @Assisted("omdbFile") omdbFile: File, @Assisted("configFile") dbVersion: File): ImportOMDBHelper + fun obtainImportOMDBHelper(@Assisted("context")context: Context, @Assisted("omdbFile") omdbFile: File): ImportOMDBHelper } \ No newline at end of file diff --git a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt index da6ccc0e..20bb6afb 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/activity/login/LoginViewModel.kt @@ -7,6 +7,7 @@ import android.widget.Toast import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.blankj.utilcode.util.ResourceUtils import com.navinfo.omqs.Constant import com.navinfo.omqs.bean.LoginUserBean import com.navinfo.omqs.db.RoomAppDatabase @@ -156,19 +157,26 @@ class LoginViewModel @Inject constructor( @Throws(IOException::class) private fun createUserFolder(context: Context, userId: String) { // 在SD卡创建用户目录,解压资源等 + val userFolder = File("${Constant.DATA_PATH}/${userId}") + Constant.CURRENT_USER_ID = userId // 初始化Realm Realm.init(context.applicationContext) val password = "encryp".encodeToByteArray().copyInto(ByteArray(64)) // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Log.d("OMQSApplication", "密码是: ${byteArrayToHexString(password)}") val config = RealmConfiguration.Builder() - .directory(File("${Constant.DATA_PATH}/${userId}")) + .directory(userFolder) .name("OMQS.realm") .encryptionKey(password) // .modules(Realm.getDefaultModule(), MyRealmModule()) .schemaVersion(1) .build() Realm.setDefaultConfiguration(config) + // 拷贝配置文件到用户目录下 + val omdbConfigFile = File(userFolder.absolutePath, Constant.OMDB_CONFIG); + if (!omdbConfigFile.exists()) { + ResourceUtils.copyFileFromAssets(Constant.OMDB_CONFIG, omdbConfigFile.absolutePath) + } } /** diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt index e6c34221..b39d5cc0 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterFragment.kt @@ -77,15 +77,14 @@ class PersonalCenterFragment : BaseFragment(), FSAFActivityCallbacks { val file = UriUtils.uri2File(uri) // 开始导入数据 // 656e6372797000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - val job = CoroutineUtils.launchWithLoading( + CoroutineUtils.launchWithLoading( requireContext(), loadingMessage = "生成数据..." ) { val importOMDBHelper: ImportOMDBHelper = importOMDBHiltFactory.obtainImportOMDBHelper( requireContext(), - file, - File(file.parentFile, "config.json") + file ) viewModel.obtainOMDBZipData(importOMDBHelper) } @@ -99,19 +98,19 @@ class PersonalCenterFragment : BaseFragment(), FSAFActivityCallbacks { override fun onResult(uri: Uri) { val file = UriUtils.uri2File(uri) - // 开始导入数据 - CoroutineUtils.launchWithLoading( - requireContext(), - loadingMessage = "导入数据..." - ) { - val importOMDBHelper: ImportOMDBHelper = - importOMDBHiltFactory.obtainImportOMDBHelper( - requireContext(), - file, - File(file.parentFile, "config.json") - ) + val importOMDBHelper: ImportOMDBHelper = + importOMDBHiltFactory.obtainImportOMDBHelper( + requireContext(), + file + ) viewModel.importOMDBData(importOMDBHelper) - } +// // 开始导入数据 +// CoroutineUtils.launchWithLoading( +// requireContext(), +// loadingMessage = "导入数据..." +// ) { +// +// } } }) } diff --git a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt index 3f1cd13c..19106b80 100644 --- a/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt +++ b/app/src/main/java/com/navinfo/omqs/ui/fragment/personalcenter/PersonalCenterViewModel.kt @@ -136,39 +136,15 @@ class PersonalCenterViewModel @Inject constructor( /** * 导入OMDB数据 * */ - suspend fun importOMDBData(importOMDBHelper: ImportOMDBHelper) { - Log.d("OMQSApplication", "开始导入数据") -// Realm.getDefaultInstance().beginTransaction() - importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile).collect { - Realm.getDefaultInstance().beginTransaction() - for (map in it) { // 每一个map就是Realm的一条数据 - val renderEntity = RenderEntity() - renderEntity.code = map["QIcode"].toString().toInt() - renderEntity.name = map["QIname"].toString() - renderEntity.table = map["QItable"].toString() - // 其他数据插入到Properties中 - renderEntity.geometry = map["GEOMETRY"].toString() - for (entry in map) { - renderEntity.properties[entry.key] = entry.value.toString() - } - Realm.getDefaultInstance().insert(renderEntity) + fun importOMDBData(importOMDBHelper: ImportOMDBHelper) { + viewModelScope.launch(Dispatchers.IO) { + Log.d("OMQSApplication", "开始导入数据") + importOMDBHelper.importOmdbZipFile(importOMDBHelper.omdbFile).collect { + Log.d("importOMDBData", it) } - Realm.getDefaultInstance().commitTransaction() + Log.d("OMQSApplication", "导入数据完成") } -// Realm.getDefaultInstance().commitTransaction() -// val gson = Gson() -// // 数据导入结束后,开始生成渲染表所需的json文件,并生成压缩包 -// for (table in importOMDBHelper.openConfigFile().tables/*listOf("HAD_LINK")*/) { -// val omdbList = Realm.getDefaultInstance().where(OMDBEntity::class.java).equalTo("table", table.table).findAll() -// val outputFile = File(importOMDBHelper.omdbFile, "${table.table}.txt") -// // 将读取到的数据转换为json数据文件 -// for (omdb in omdbList) { -// FileIOUtils.writeFileFromString(outputFile, gson.toJson(omdb)) -// } -// } - - Log.d("OMQSApplication", "导入数据完成") } fun importScProblemData(uri: Uri) {