Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
p x
MapMultiEngine
Commits
c6411612
Commit
c6411612
authored
Aug 19, 2025
by
p x
Browse files
在线小车
parent
b484b0d0
Changes
16
Hide whitespace changes
Inline
Side-by-side
app/src/main/AndroidManifest.xml
View file @
c6411612
...
@@ -12,6 +12,14 @@
...
@@ -12,6 +12,14 @@
android:supportsRtl=
"true"
android:supportsRtl=
"true"
android:theme=
"@style/Theme.MapMultiEngine"
android:theme=
"@style/Theme.MapMultiEngine"
tools:targetApi=
"31"
>
tools:targetApi=
"31"
>
<activity
android:name=
".ui.ShowCarOnlineActivity"
android:exported=
"false"
/>
<activity
android:name=
".ui.AMapWmsActivity"
android:exported=
"false"
/>
<activity
<activity
android:name=
".ui.CalculateDistanceActivity"
android:name=
".ui.CalculateDistanceActivity"
android:exported=
"false"
/>
android:exported=
"false"
/>
...
@@ -52,8 +60,6 @@
...
@@ -52,8 +60,6 @@
android:name=
".ui.ShowMyLocLandian"
android:name=
".ui.ShowMyLocLandian"
android:exported=
"false"
android:exported=
"false"
android:theme=
"@style/Theme.MapMultiEngine"
/>
android:theme=
"@style/Theme.MapMultiEngine"
/>
<activity
<activity
android:name=
".ui.TBaseActivity"
android:name=
".ui.TBaseActivity"
android:exported=
"false"
/>
android:exported=
"false"
/>
...
...
app/src/main/java/com/sd/mapmultiengine/LayerManage.java
0 → 100644
View file @
c6411612
package
com.sd.mapmultiengine
;
import
android.content.Context
;
import
com.amap.api.maps.AMap
;
import
com.amap.api.maps.CameraUpdateFactory
;
import
com.amap.api.maps.model.TileOverlay
;
import
com.amap.api.maps.model.TileOverlayOptions
;
import
com.amap.api.maps.model.TileProvider
;
import
com.amap.api.maps.model.UrlTileProvider
;
import
com.amap.api.maps.model.LatLng
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
/**
* 图层管理
*
* @author Hu
* @date 2024/5/23
*/
public
class
LayerManage
{
private
static
final
String
TAG
=
"LayerManage"
;
private
Context
mContext
;
private
AMap
aMap
;
private
int
titleSize
=
256
;
private
double
initialResolution
=
156543.03392804062
;
//2*Math.PI*6378137/titleSize;//
private
double
originShift
=
20037508.342789244
;
//2*Math.PI*6378137/2.0;//
private
TileOverlay
tileOverlay
;
/**
* 构造函数
*/
public
LayerManage
(
Context
context
,
AMap
aMap
)
{
mContext
=
context
.
getApplicationContext
();
this
.
aMap
=
aMap
;
}
/**
* 设置地图模式,aMap是地图控制器对象
*
* @param type 地图模式
* MAP_TYPE_NORMAL:普通地图,值为1;
* MAP_TYPE_SATELLITE:卫星地图,值为2;
* MAP_TYPE_NIGHT 黑夜地图,夜间模式,值为3;
* MAP_TYPE_NAVI 导航模式,值为4;
* MAP_TYPE_BUS 公交模式,值为5。
*/
public
void
setMapType
(
int
type
)
{
aMap
.
setMapType
(
type
);
}
/**
* 添加图层
*
* @param url 构建WMS图层URL
*/
public
TileOverlay
addTileOverlay
(
String
url
)
{
// 实例化自定义TileProvider
TileProvider
tileProvider
=
new
UrlTileProvider
(
256
,
256
)
{
@Override
public
URL
getTileUrl
(
int
x
,
int
y
,
int
zoom
)
{
// 构建WMS图层URL
try
{
System
.
out
.
println
(
x
+
"/"
+
y
+
"/"
+
zoom
+
"=====>"
+
url
+
TitleBounds
(
x
,
y
,
zoom
));
return
new
URL
(
url
+
TitleBounds
(
x
,
y
,
zoom
));
}
catch
(
MalformedURLException
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
};
TileOverlayOptions
tileOverlayOptions
=
new
TileOverlayOptions
().
tileProvider
(
tileProvider
);
// 添加TileOverlay
tileOverlay
=
aMap
.
addTileOverlay
(
tileOverlayOptions
);
LatLng
latLng
=
new
LatLng
(
39.80870258484975
,
116.5011886304098
);
aMap
.
moveCamera
(
CameraUpdateFactory
.
newLatLngZoom
(
latLng
,
18.0f
));
return
tileOverlay
;
}
/**
* 移除图层
*/
public
void
removeLayer
()
{
tileOverlay
.
remove
();
}
/**
* 设置图层可见性
*
* @param visibility - true: 表示显示,为默认值; false: 不显示
*/
public
void
setLayerVisibility
(
boolean
visibility
)
{
if
(
tileOverlay
!=
null
)
{
tileOverlay
.
setVisible
(
visibility
);
}
}
/**
* 根据像素、等级算出坐标
*
* @param p
* @param zoom
* @return
*/
private
double
Pixels2Meters
(
int
p
,
int
zoom
)
{
return
p
*
Resolution
(
zoom
)
-
originShift
;
}
/**
* 根据瓦片的x/y等级返回瓦片范围
*
* @param tx
* @param ty
* @param zoom
* @return
*/
private
String
TitleBounds
(
int
tx
,
int
ty
,
int
zoom
)
{
double
minX
=
Pixels2Meters
(
tx
*
titleSize
,
zoom
);
double
maxY
=
-
Pixels2Meters
(
ty
*
titleSize
,
zoom
);
double
maxX
=
Pixels2Meters
((
tx
+
1
)
*
titleSize
,
zoom
);
double
minY
=
-
Pixels2Meters
((
ty
+
1
)
*
titleSize
,
zoom
);
//转换成经纬度
// minX = Meters2Lon(minX);
// minY = Meters2Lat(minY);
// maxX = Meters2Lon(maxX);
// maxY = Meters2Lat(maxY);
//经纬度转换米
// minX = Lon2Meter(minX);
// minY = Lat2Meter(minY);
// maxX = Lon2Meter(maxX);
// maxY = Lat2Meter(maxY);
//坐标转换工具类构造方法 GPS( WGS-84) 转 为高德地图需要的坐标
// CoordinateConverter converter = new CoordinateConverter(context);
// converter.from(CoordinateConverter.CoordType.GPS);
// converter.coord(new LatLng(minY, minX));
// LatLng min = converter.convert();
// converter.coord(new LatLng(maxY, maxX));
// LatLng max = converter.convert();
// minX = Lon2Meter(-min.longitude + 2 * minX);
// minY = Lat2Meter(-min.latitude + 2 * minY);
// maxX = Lon2Meter(-max.longitude + 2 * maxX);
// maxY = Lat2Meter(-max.latitude + 2 * maxY);
return
minX
+
","
+
minY
+
","
+
maxX
+
","
+
maxY
+
"&WIDTH=256&HEIGHT=256"
;
}
/**
* 计算分辨率
*
* @param zoom
* @return
*/
private
double
Resolution
(
int
zoom
)
{
return
initialResolution
/
(
Math
.
pow
(
2
,
zoom
));
}
/**
* X米转经纬度
*/
private
double
Meters2Lon
(
double
mx
)
{
double
lon
=
(
mx
/
originShift
)
*
180.0
;
return
lon
;
}
/**
* Y米转经纬度
*/
private
double
Meters2Lat
(
double
my
)
{
double
lat
=
(
my
/
originShift
)
*
180.0
;
lat
=
180.0
/
Math
.
PI
*
(
2
*
Math
.
atan
(
Math
.
exp
(
lat
*
Math
.
PI
/
180.0
))
-
Math
.
PI
/
2.0
);
return
lat
;
}
/**
* X经纬度转米
*/
private
double
Lon2Meter
(
double
lon
)
{
double
mx
=
lon
*
originShift
/
180.0
;
return
mx
;
}
/**
* Y经纬度转米
*/
private
double
Lat2Meter
(
double
lat
)
{
double
my
=
Math
.
log
(
Math
.
tan
((
90
+
lat
)
*
Math
.
PI
/
360.0
))
/
(
Math
.
PI
/
180.0
);
my
=
my
*
originShift
/
180.0
;
return
my
;
}
}
app/src/main/java/com/sd/mapmultiengine/MainActivity.kt
View file @
c6411612
...
@@ -14,10 +14,12 @@ import com.sd.maplibrary.MSDKInitializer
...
@@ -14,10 +14,12 @@ import com.sd.maplibrary.MSDKInitializer
import
com.sd.maplibrary.OnSdkInitCb
import
com.sd.maplibrary.OnSdkInitCb
import
com.sd.mapmultiengine.adapter.DemoListAdapter
import
com.sd.mapmultiengine.adapter.DemoListAdapter
import
com.sd.mapmultiengine.databinding.ActivityMainBinding
import
com.sd.mapmultiengine.databinding.ActivityMainBinding
import
com.sd.mapmultiengine.ui.AMapWmsActivity
import
com.sd.mapmultiengine.ui.CalculateDistanceActivity
import
com.sd.mapmultiengine.ui.CalculateDistanceActivity
import
com.sd.mapmultiengine.ui.ChangeMapCenterAct
import
com.sd.mapmultiengine.ui.ChangeMapCenterAct
import
com.sd.mapmultiengine.ui.DisplayMapActivity
import
com.sd.mapmultiengine.ui.DisplayMapActivity
import
com.sd.mapmultiengine.ui.GestureDemo
import
com.sd.mapmultiengine.ui.GestureDemo
import
com.sd.mapmultiengine.ui.ShowCarOnlineActivity
import
com.sd.mapmultiengine.ui.ShowMyLocLandian
import
com.sd.mapmultiengine.ui.ShowMyLocLandian
import
com.sd.mapmultiengine.ui.TCircelActivity
import
com.sd.mapmultiengine.ui.TCircelActivity
import
com.sd.mapmultiengine.ui.TDriveRouteActivity
import
com.sd.mapmultiengine.ui.TDriveRouteActivity
...
@@ -57,8 +59,14 @@ class MainActivity : AppCompatActivity() {
...
@@ -57,8 +59,14 @@ class MainActivity : AppCompatActivity() {
DemoDetails
(
"两点间距离计算"
,
CalculateDistanceActivity
::
class
.
java
),
DemoDetails
(
"两点间距离计算"
,
CalculateDistanceActivity
::
class
.
java
),
DemoDetails
(
"定位,获取我的位置"
,
TGpsActivity
::
class
.
java
),
DemoDetails
(
"定位,获取我的位置"
,
TGpsActivity
::
class
.
java
),
DemoDetails
(
"在线地图显示小车"
,
ShowCarOnlineActivity
::
class
.
java
),
DemoDetails
(
"驾车路线规划"
,
TDriveRouteActivity
::
class
.
java
),
DemoDetails
(
"驾车路线规划"
,
TDriveRouteActivity
::
class
.
java
),
DemoDetails
(
"测试高德加载WMS"
,
AMapWmsActivity
::
class
.
java
),
)
)
...
@@ -108,7 +116,7 @@ class MainActivity : AppCompatActivity() {
...
@@ -108,7 +116,7 @@ class MainActivity : AppCompatActivity() {
}
}
fun
initMap
(
type
:
MAP_TYPE
=
MAP_TYPE
.
AMAP
)
{
fun
initMap
(
type
:
MAP_TYPE
=
MAP_TYPE
.
MINE
)
{
MSDKInitializer
.
initializeMap
(
this
,
type
,
object
:
OnSdkInitCb
{
MSDKInitializer
.
initializeMap
(
this
,
type
,
object
:
OnSdkInitCb
{
override
fun
onInitSuccess
()
{
override
fun
onInitSuccess
()
{
println
(
"--------onMapInitSuccess"
)
println
(
"--------onMapInitSuccess"
)
...
...
app/src/main/java/com/sd/mapmultiengine/ui/AMapWmsActivity.kt
0 → 100644
View file @
c6411612
package
com.sd.mapmultiengine.ui
import
android.os.Bundle
import
androidx.activity.enableEdgeToEdge
import
androidx.appcompat.app.AppCompatActivity
import
androidx.core.view.ViewCompat
import
androidx.core.view.WindowInsetsCompat
import
com.amap.api.maps.AMap
import
com.sd.mapmultiengine.LayerManage
import
com.sd.mapmultiengine.R
import
com.sd.mapmultiengine.databinding.ActivityAmapWmsBinding
class
AMapWmsActivity
:
AppCompatActivity
()
{
lateinit
var
binding
:
ActivityAmapWmsBinding
private
var
layerManage
:
LayerManage
?
=
null
private
var
aMap
:
AMap
?
=
null
// var url =
// "https://faw.cuscavp.cn:8443/geoserver/changchun/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=true"
var
url
:
String
=
"http://10.166.15.10:8080/geoserver/cusc/wms?LAYERS=cusc%3AHMI_GJDT&FORMAT=image%2Fpng&TRANSPARENT=TRUE&SERVICE="
+
"WMS&VERSION=1.1.0&REQUEST=GetMap&STYLES=&SRS=EPSG:3857&BBOX="
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
enableEdgeToEdge
()
binding
=
ActivityAmapWmsBinding
.
inflate
(
layoutInflater
)
setContentView
(
binding
.
root
)
binding
.
mapView
.
onCreate
(
savedInstanceState
)
ViewCompat
.
setOnApplyWindowInsetsListener
(
findViewById
(
R
.
id
.
main
))
{
v
,
insets
->
val
systemBars
=
insets
.
getInsets
(
WindowInsetsCompat
.
Type
.
systemBars
())
v
.
setPadding
(
systemBars
.
left
,
systemBars
.
top
,
systemBars
.
right
,
systemBars
.
bottom
)
insets
}
aMap
=
binding
.
mapView
.
map
layerManage
=
LayerManage
(
this
,
aMap
)
layerManage
?.
addTileOverlay
(
url
)
}
override
fun
onSaveInstanceState
(
outState
:
Bundle
)
{
super
.
onSaveInstanceState
(
outState
)
//在activity执行onSaveInstanceState时执行mapView.onSaveInstanceState (outState),保存地图当前的状态
binding
.
mapView
.
onSaveInstanceState
(
outState
)
}
override
fun
onResume
()
{
super
.
onResume
()
//在activity执行onResume时执行mapView.onResume (),重新绘制加载地图
binding
.
mapView
.
onResume
()
}
override
fun
onPause
()
{
super
.
onPause
()
//在activity执行onPause时执行mapView.onPause (),暂停地图的绘制
binding
.
mapView
.
onPause
()
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
//在activity执行onDestroy时执行mapView.onDestroy(),销毁地图
binding
.
mapView
.
onDestroy
()
}
}
\ No newline at end of file
app/src/main/java/com/sd/mapmultiengine/ui/ShowCarOnlineActivity.kt
0 → 100644
View file @
c6411612
package
com.sd.mapmultiengine.ui
import
android.os.Bundle
import
androidx.activity.enableEdgeToEdge
import
androidx.appcompat.app.AppCompatActivity
import
androidx.core.view.ViewCompat
import
androidx.core.view.WindowInsetsCompat
import
com.minedata.minenavi.mapdal.LatLng
import
com.minedata.minenavi.util.Tools
import
com.sd.maplibrary.bean.MSLatLng
import
com.sd.maplibrary.bean.MSLocBean
import
com.sd.maplibrary.core.MSGpsLocation
import
com.sd.maplibrary.core.MSMethodAdv
import
com.sd.maplibrary.core.MShowMainCarModel
import
com.sd.maplibrary.core.MapReadyView
import
com.sd.maplibrary.ui.MapMultiView.OnMapReadyLis
import
com.sd.mapmultiengine.R
import
com.sd.mapmultiengine.databinding.ActivityShowCarOnlineBinding
import
com.sd.mapmultiengine.databinding.ActivityTgpsBinding
import
com.sd.mapmultiengine.ui.TGpsActivity
/***在线地推显示小车***/
class
ShowCarOnlineActivity
:
AppCompatActivity
()
{
private
lateinit
var
binding
:
ActivityShowCarOnlineBinding
var
mapReadView
:
MapReadyView
?
=
null
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
enableEdgeToEdge
()
binding
=
ActivityShowCarOnlineBinding
.
inflate
(
layoutInflater
)
setContentView
(
binding
.
root
)
binding
.
mapMultiView
.
addMapRenderCallback
(
object
:
OnMapReadyLis
{
override
fun
onMapReady
(
mapReadyView
:
MapReadyView
)
{
this
@ShowCarOnlineActivity
.
mapReadView
=
mapReadyView
//添加小车
var
center
=
MSLatLng
(
39.787678
,
116.518766
)
MSMethodAdv
.
setMapCenter
(
mapReadView
,
center
.
lat
,
center
.
lng
)
MShowMainCarModel
.
addMyLocCarModel
(
mapReadView
,
this
@ShowCarOnlineActivity
,
center
.
lat
,
center
.
lng
,
0f
)
}
})
//显示小车
binding
.
bt1
.
setOnClickListener
{
}
//隐藏小车
binding
.
bt2
.
setOnClickListener
{
}
//初始化定位
MSGpsLocation
.
initLoc
(
this
)
//设置回调
MSGpsLocation
.
setOnMsGpsLoc
(
object
:
MSGpsLocation
.
OnMsGpsLoc
{
override
fun
onMsGpsLoc
(
mSLocBean
:
MSLocBean
)
{
}
})
//开启定位
MSGpsLocation
.
starLoc
()
}
}
\ No newline at end of file
app/src/main/java/com/sd/mapmultiengine/ui/TGpsActivity.kt
View file @
c6411612
...
@@ -39,7 +39,7 @@ class TGpsActivity : AppCompatActivity() {
...
@@ -39,7 +39,7 @@ class TGpsActivity : AppCompatActivity() {
}
}
})
})
//初始化
//初始化
定位
MSGpsLocation
.
initLoc
(
this
)
MSGpsLocation
.
initLoc
(
this
)
//设置回调
//设置回调
MSGpsLocation
.
setOnMsGpsLoc
(
object
:
MSGpsLocation
.
OnMsGpsLoc
{
MSGpsLocation
.
setOnMsGpsLoc
(
object
:
MSGpsLocation
.
OnMsGpsLoc
{
...
...
app/src/main/res/layout/activity_amap_wms.xml
0 → 100644
View file @
c6411612
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/main"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
tools:context=
".ui.AMapWmsActivity"
>
<com.amap.api.maps.MapView
android:id=
"@+id/mapView"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/activity_show_car_online.xml
0 → 100644
View file @
c6411612
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<Button
android:id=
"@+id/bt1"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"显示小车"
/>
<Button
android:id=
"@+id/bt2"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"删掉小车"
/>
<com.sd.maplibrary.ui.MapMultiView
android:id=
"@+id/mapMultiView"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</LinearLayout>
\ No newline at end of file
maplibrary/src/main/assets/models/car_model/Binary_0.jpeg
0 → 100644
View file @
c6411612
1.17 MB
maplibrary/src/main/assets/models/car_model/gszh_xyz.mtl
0 → 100644
View file @
c6411612
# exported by gszh.xyz
newmtl 99ce393e_fd5e_44cc_9c31_49c4bb9ceed6
Kd 1.0431372549019609 1.0431372549019609 1.0431372549019609
d 1
Ka 0 0 0
Ks 0 0 0
Ns 0
map_Kd Binary_0.jpeg
maplibrary/src/main/assets/models/car_model/gszh_xyz.obj
0 → 100644
View file @
c6411612
This source diff could not be displayed because it is too large. You can
view the blob
instead.
maplibrary/src/main/java/com/sd/maplibrary/core/MSMethodAdv.kt
View file @
c6411612
package
com.sd.maplibrary.core
package
com.sd.maplibrary.core
import
android.graphics.Rect
import
com.amap.api.maps.CameraUpdateFactory
import
com.amap.api.maps.CameraUpdateFactory
import
com.amap.api.maps.model.CameraPosition
import
com.amap.api.maps.model.CameraPosition
import
com.minedata.minenavi.mapdal.LatLng
import
com.minedata.minenavi.mapdal.LatLng
...
@@ -54,6 +53,20 @@ object MSMethodAdv {
...
@@ -54,6 +53,20 @@ object MSMethodAdv {
}
}
}
}
/***获取地图缩放级别**/
fun
getMapZoom
(
mapReadView
:
MapReadyView
?):
Float
{
when
(
MSDKInitializer
.
getMapType
())
{
MAP_TYPE
.
MINE
->
{
return
mapReadView
?.
mMineMap
?.
zoomLevel
?:
0f
}
MAP_TYPE
.
AMAP
->
{
return
mapReadView
?.
aMap
?.
cameraPosition
?.
zoom
?:
0f
}
}
}
/***设置地图显示区域**/
/***设置地图显示区域**/
// fun setMapBoundArea(mapReadView: MapReadyView?) {
// fun setMapBoundArea(mapReadView: MapReadyView?) {
...
...
maplibrary/src/main/java/com/sd/maplibrary/core/MSRoutePlans.kt
View file @
c6411612
...
@@ -101,7 +101,7 @@ object MSRoutePlans {
...
@@ -101,7 +101,7 @@ object MSRoutePlans {
}
}
}
}
/***驾车路径规划
/***驾车路径规划
,直接跳转到 导航页面
*@param starPoint 起点坐标
*@param starPoint 起点坐标
* @param endPoint 终点坐标
* @param endPoint 终点坐标
* @param endName 终点名称(高德可不传)
* @param endName 终点名称(高德可不传)
...
...
maplibrary/src/main/java/com/sd/maplibrary/core/MShowMainCarModel.kt
0 → 100644
View file @
c6411612
package
com.sd.maplibrary.core
import
android.content.Context
import
android.util.Log
import
androidx.lifecycle.viewModelScope
import
com.amap.api.maps.AMapUtils
import
com.amap.api.maps.model.LatLng
as
ALatLng
import
com.minedata.minenavi.map.Model
import
com.minedata.minenavi.map.ModelOptions
import
com.minedata.minenavi.map.Overlay
import
com.minedata.minenavi.mapdal.LatLng
import
com.sd.maplibrary.MAP_TYPE
import
com.sd.maplibrary.MSDKInitializer
import
com.sd.shupathwebview.utils.FileIoUtils
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
java.io.File
import
java.io.IOException
/***在线地图上绘制小车**/
object
MShowMainCarModel
{
//四维主车obj模型
private
var
objPath
=
""
//四维在线地图用户当前位置模型
private
var
mainCarMo
:
Model
?
=
null
/****加载主车特斯拉模型***/
private
suspend
fun
loadMainCar
(
context
:
Context
)
{
withContext
(
Dispatchers
.
IO
)
{
try
{
var
parentFileDir
=
File
(
context
.
filesDir
,
"models/car_model"
)
if
(!
parentFileDir
.
exists
())
parentFileDir
.
mkdirs
()
objPath
=
FileIoUtils
.
assetFilePath
(
context
,
"models/car_model/gszh_xyz.obj"
)
Log
.
d
(
"-----"
,
"✅ OBJ文件复制成功: "
+
objPath
)
var
path
=
FileIoUtils
.
assetFilePath
(
context
,
"models/car_model/Binary_0.jpeg"
)
Log
.
d
(
"-----"
,
"✅ 纹理文件复制成功: "
+
path
)
path
=
FileIoUtils
.
assetFilePath
(
context
,
"models/car_model/gszh_xyz.mtl"
)
Log
.
d
(
"-----"
,
"✅ 材质文件复制成功: "
+
path
)
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
}
}
}
/****添加我的定位小车模型
* 这小车模型航向角0是冲下的
* ***/
fun
addMyLocCarModel
(
mapReadView
:
MapReadyView
?,
context
:
Context
,
lat
:
Double
,
lng
:
Double
,
heading
:
Float
)
{
// mMineMap?.removeOverlay(mainCarMo)
// deleteMyLocMarker()
when
(
MSDKInitializer
.
getMapType
())
{
MAP_TYPE
.
MINE
->
{
CoroutineScope
(
Dispatchers
.
IO
).
launch
{
loadMainCar
(
context
)
if
(
objPath
.
isEmpty
()
||
lat
==
0.0
)
return
@launch
// 模型文件相对路径
var
modelOptions
=
ModelOptions
()
.
objFile
(
objPath
)
.
position
(
LatLng
(
lat
,
lng
))
.
layer
(
Overlay
.
Layer
.
aboveMarker
)
.
heading
(
heading
)
.
keepScaleSize
(
8f
)
// 保持尺寸的比例尺
.
scaleFactor
(
0.01f
)
// 缩放因子
.
visible
(
true
)
if
(
mainCarMo
!=
null
)
{
mapReadView
?.
mMineMap
?.
removeOverlay
(
mainCarMo
)
}
mainCarMo
=
mapReadView
?.
mMineMap
?.
addModel
(
modelOptions
)
}
}
MAP_TYPE
.
AMAP
->
{
}
}
}
/****更新模型**/
fun
upMyLocCarModel
(
lat
:
Double
,
lng
:
Double
,
heading
:
Float
)
{
when
(
MSDKInitializer
.
getMapType
())
{
MAP_TYPE
.
MINE
->
{
if
(
mainCarMo
==
null
)
return
var
temp
=
0f
-
180f
-
heading
mainCarMo
?.
setPosition
(
LatLng
(
lat
,
lng
))
mainCarMo
?.
setHeading
(
temp
)
}
MAP_TYPE
.
AMAP
->
{
}
}
}
/****更新模型**/
fun
upMyLocCarModelSmooth
(
lat
:
Double
,
lng
:
Double
,
heading
:
Float
)
{
when
(
MSDKInitializer
.
getMapType
())
{
MAP_TYPE
.
MINE
->
{
}
MAP_TYPE
.
AMAP
->
{
}
}
}
}
\ No newline at end of file
maplibrary/src/main/java/com/sd/maplibrary/utils/FileIoUtils.kt
0 → 100644
View file @
c6411612
package
com.sd.shupathwebview.utils
import
android.content.ContentValues
import
android.content.Context
import
android.graphics.Bitmap
import
android.net.Uri
import
android.os.Build
import
android.os.Environment
import
android.provider.MediaStore
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.coroutineScope
import
kotlinx.coroutines.runBlocking
import
kotlinx.coroutines.withContext
import
java.io.*
import
java.math.BigDecimal
object
FileIoUtils
{
/**
* 读取asset 文件
*/
fun
getAssetContent
(
context
:
Context
,
fileName
:
String
):
String
{
val
assetManager
=
context
.
assets
var
stringBuilder
=
StringBuilder
()
var
bf
:
BufferedReader
?
=
null
try
{
val
inputReader
=
InputStreamReader
(
assetManager
.
open
(
fileName
))
bf
=
BufferedReader
(
inputReader
)
var
line
=
""
while
(!
bf
.
run
{
line
=
readLine
()
return
@run
line
}.
isNullOrEmpty
())
{
stringBuilder
.
append
(
line
)
}
bf
?.
close
()
assetManager
.
close
()
return
stringBuilder
.
toString
()
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
return
""
}
finally
{
bf
?.
close
()
assetManager
.
close
()
}
}
/**
* 复制assets 到手机内存里
* @param prePath 为路径前缀
* @param assetName 为文件名
* **/
suspend
fun
assetFilePath
(
context
:
Context
,
assetName
:
String
):
String
{
return
withContext
(
Dispatchers
.
IO
)
{
val
file
=
File
(
context
.
filesDir
,
assetName
)
if
(
file
.
exists
()
&&
file
.
length
()
>
0
)
{
return
@withContext
file
.
absolutePath
}
try
{
var
inputs
=
context
.
assets
.
open
(
assetName
)
var
os
:
OutputStream
=
FileOutputStream
(
file
)
val
buffer
=
ByteArray
(
4
*
1024
)
var
read
:
Int
while
((
inputs
.
read
(
buffer
).
also
{
read
=
it
})
!=
-
1
)
{
os
.
write
(
buffer
,
0
,
read
)
}
os
.
flush
()
return
@withContext
file
.
absolutePath
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
return
@withContext
""
}
}
}
suspend
fun
getAssetMock
(
context
:
Context
,
fileName
:
String
,
dst
:
MutableList
<
String
>)
:
Int
{
val
assetManager
=
context
.
assets
var
bf
:
BufferedReader
?
=
null
try
{
val
inputReader
=
InputStreamReader
(
assetManager
.
open
(
fileName
))
bf
=
BufferedReader
(
inputReader
)
var
line
=
""
while
(!
bf
.
run
{
line
=
readLine
()
return
@run
line
}.
isNullOrEmpty
())
{
dst
.
add
(
line
)
}
bf
?.
close
()
return
1
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
}
finally
{
bf
?.
close
()
}
return
0
}
/**
* 读取asset 文件
*/
fun
getAsset
(
context
:
Context
,
fileName
:
String
):
String
{
val
assetManager
=
context
.
assets
var
inputStream
:
InputStream
?
=
null
var
str
=
""
try
{
inputStream
=
assetManager
.
open
(
fileName
)
val
size
=
inputStream
.
available
()
val
bytes
=
ByteArray
(
size
)
inputStream
.
read
(
bytes
)
str
=
String
(
bytes
)
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
}
finally
{
inputStream
?.
close
()
// assetManager.close()
}
return
str
}
//Uri获取真实路径转换成File的方法
fun
getAbsoluteImagePath
(
contentUri
:
Uri
,
context
:
Context
):
String
{
// can post image
var
res
=
""
val
proj
=
arrayOf
(
MediaStore
.
Images
.
Media
.
DATA
)
val
cursor
=
context
.
contentResolver
.
query
(
contentUri
,
proj
,
null
,
null
,
null
)
if
(
cursor
!!
.
moveToFirst
())
{
val
column_index
=
cursor
.
getColumnIndexOrThrow
(
MediaStore
.
Images
.
Media
.
DATA
)
res
=
cursor
.
getString
(
column_index
)
}
cursor
.
close
()
return
res
}
/**
* 把图片复制到应用缓存里
*/
fun
copyHeImgFileToPath
(
context
:
Context
,
fileName
:
String
,
source
:
File
,
isRemove
:
Boolean
=
true
):
File
?
{
try
{
var
dir
=
File
(
context
.
externalCacheDir
,
"xunhepic"
)
if
(!
dir
.
exists
())
{
dir
.
mkdirs
()
}
var
imgFile
=
File
(
dir
,
fileName
)
if
(!
dir
.
exists
())
{
imgFile
.
createNewFile
()
}
var
fosfrom
=
FileInputStream
(
source
)
var
fosto
=
FileOutputStream
(
imgFile
)
var
bt
=
ByteArray
(
1024
)
var
c
=
0
while
(
fosfrom
.
run
{
c
=
read
(
bt
)
return
@run
c
}
>
0
)
{
fosto
.
write
(
bt
,
0
,
c
)
//将内容写到新文件当
}
if
(
isRemove
)
{
// source.deleteOnExit()
}
fosfrom
.
close
()
fosto
.
close
()
return
imgFile
}
catch
(
e
:
IOException
)
{
return
null
}
}
//file文件读取成byte[]
fun
readFileToByte
(
file
:
File
?):
ByteArray
?
{
val
byte_size
=
1024
val
b
=
ByteArray
(
byte_size
)
try
{
val
fileInputStream
=
FileInputStream
(
file
)
val
outputStream
=
ByteArrayOutputStream
(
byte_size
)
var
length
:
Int
while
(
fileInputStream
.
read
(
b
).
also
{
length
=
it
}
!=
-
1
)
{
outputStream
.
write
(
b
,
0
,
length
)
}
fileInputStream
.
close
()
outputStream
.
close
()
return
outputStream
.
toByteArray
()
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
}
return
null
}
/**
* 获取总共的缓存
*/
fun
getTotalCacheSize
(
context
:
Context
):
Long
{
var
size
:
Long
=
0
return
try
{
size
=
getFolderSize
(
context
.
cacheDir
)
size
+=
getFolderSize
(
context
.
filesDir
)
// size += getFolderSize(context.externalCacheDir)
size
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
0
}
}
/**
* 获取文件夹大小
*/
private
fun
getFolderSize
(
file
:
File
?):
Long
{
if
(
file
==
null
)
{
return
0
}
var
size
:
Long
=
0
try
{
val
fileList
=
file
!!
.
listFiles
()
for
(
i
in
fileList
.
indices
)
{
// 如果下面还有文件
size
=
if
(
fileList
[
i
].
isDirectory
)
{
size
+
getFolderSize
(
fileList
[
i
])
}
else
{
size
+
fileList
[
i
].
length
()
}
}
}
catch
(
e
:
java
.
lang
.
Exception
)
{
e
.
printStackTrace
()
}
return
size
}
/**
* 删除总共的缓存
*/
fun
deleteTotalCacheSize
(
context
:
Context
)
{
runBlocking
{
coroutineScope
{
withContext
(
Dispatchers
.
IO
)
{
context
.
cacheDir
.
deleteRecursively
()
context
.
filesDir
.
deleteRecursively
()
// if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
// context.externalCacheDir?.deleteRecursively()
// }
}
}
}
}
/**
* 格式化单位
*/
fun
getFormatSize
(
size
:
Double
):
String
?
{
val
kiloByte
=
size
/
1024
if
(
kiloByte
<
1
)
{
return
size
.
toString
()
+
"Byte"
}
val
megaByte
=
kiloByte
/
1024
if
(
megaByte
<
1
)
{
val
result1
=
BigDecimal
(
kiloByte
.
toString
())
return
result1
.
setScale
(
2
,
BigDecimal
.
ROUND_HALF_UP
)
.
toPlainString
().
toString
()
+
"KB"
}
val
gigaByte
=
megaByte
/
1024
if
(
gigaByte
<
1
)
{
val
result2
=
BigDecimal
(
megaByte
.
toString
())
return
result2
.
setScale
(
1
,
BigDecimal
.
ROUND_HALF_UP
)
.
toPlainString
().
toString
()
+
"MB"
}
val
teraBytes
=
gigaByte
/
1024
if
(
teraBytes
<
1
)
{
val
result3
=
BigDecimal
(
gigaByte
.
toString
())
return
result3
.
setScale
(
2
,
BigDecimal
.
ROUND_HALF_UP
)
.
toPlainString
().
toString
()
+
"GB"
}
val
result4
=
BigDecimal
(
teraBytes
)
return
result4
.
setScale
(
2
,
BigDecimal
.
ROUND_HALF_UP
).
toPlainString
()
.
toString
()
+
"TB"
}
/**
* 保存图片到本地相册
*/
fun
saveBitmapToGalley
(
context
:
Context
,
bitmap
:
Bitmap
)
{
try
{
var
parentDir
:
File
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
Q
)
{
if
(
Environment
.
getExternalStorageState
().
equals
(
Environment
.
MEDIA_MOUNTED
))
{
parentDir
=
context
.
getExternalFilesDir
(
Environment
.
DIRECTORY_DCIM
)
!!
}
else
{
return
}
}
else
{
parentDir
=
Environment
.
getExternalStoragePublicDirectory
(
Environment
.
DIRECTORY_DCIM
)
}
var
fileName
=
"firend.jpg"
var
file
=
File
(
parentDir
,
fileName
)
val
contentValues
=
ContentValues
()
contentValues
.
put
(
MediaStore
.
Images
.
Media
.
DISPLAY_NAME
,
fileName
)
contentValues
.
put
(
MediaStore
.
Images
.
Media
.
MIME_TYPE
,
"image/JPEG"
)
//兼容Android Q和以下版本
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
Q
)
{
//android Q中不再使用DATA字段,而用RELATIVE_PATH代替
//RELATIVE_PATH是相对路径不是绝对路径
//DCIM是系统文件夹,关于系统文件夹可以到系统自带的文件管理器中查看,不可以写没存在的名字
contentValues
.
put
(
MediaStore
.
Images
.
Media
.
RELATIVE_PATH
,
Environment
.
DIRECTORY_DCIM
)
var
uri
=
context
.
contentResolver
.
insert
(
MediaStore
.
Images
.
Media
.
EXTERNAL_CONTENT_URI
,
contentValues
)
// LogUtil.v("-------uri= " + uri)
if
(
uri
!=
null
)
{
//若生成了uri,则表示该文件添加成功
//使用流将内容写入该uri中即可
val
outputStream
=
context
.
contentResolver
.
openOutputStream
(
uri
)
if
(
outputStream
!=
null
)
{
bitmap
.
compress
(
Bitmap
.
CompressFormat
.
JPEG
,
90
,
outputStream
)
outputStream
.
flush
()
outputStream
.
close
()
}
}
}
else
{
contentValues
.
put
(
MediaStore
.
Images
.
Media
.
DATA
,
Environment
.
DIRECTORY_DCIM
)
MediaStore
.
Images
.
Media
.
insertImage
(
context
.
contentResolver
,
bitmap
,
fileName
,
null
)
var
outputStream
=
FileOutputStream
(
file
)
if
(
file
.
exists
())
{
file
.
delete
()
}
else
{
file
.
createNewFile
()
}
bitmap
.
compress
(
Bitmap
.
CompressFormat
.
JPEG
,
90
,
outputStream
)
outputStream
.
flush
()
outputStream
.
close
()
}
// LogUtil.e("------ " + file?.toUri())
// context.sendBroadcast(
// Intent(
// Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
// file?.toUri()
// )
// )
}
catch
(
e
:
java
.
lang
.
Exception
)
{
e
.
printStackTrace
()
}
}
}
\ No newline at end of file
maplibrary/src/main/java/com/sd/maplibrary/utils/SmoothMoveUtils.java
0 → 100644
View file @
c6411612
package
com.sd.maplibrary.utils
;
import
android.animation.Animator
;
import
android.animation.AnimatorListenerAdapter
;
import
android.animation.ValueAnimator
;
import
android.view.animation.LinearInterpolator
;
import
com.minedata.minenavi.mapdal.LatLng
;
public
class
SmoothMoveUtils
{
public
interface
OnPositionUpdateListener
{
/**
* 每帧回调:插值点 + 朝向角度 bearing
*/
void
onUpdate
(
LatLng
interpolatedLatLng
,
float
bearing
);
/**
* 动画结束
*/
void
onFinish
();
}
public
static
void
startSmoothMove
(
LatLng
from
,
LatLng
to
,
long
durationMillis
,
OnPositionUpdateListener
listener
)
{
if
(
from
==
null
||
to
==
null
||
listener
==
null
||
durationMillis
<=
0
)
{
return
;
}
ValueAnimator
animator
=
ValueAnimator
.
ofFloat
(
0
f
,
1
f
);
animator
.
setDuration
(
durationMillis
);
animator
.
setInterpolator
(
new
LinearInterpolator
());
float
bearing
=
calculateBearing
(
from
,
to
);
animator
.
addUpdateListener
(
animation
->
{
float
fraction
=
(
float
)
animation
.
getAnimatedValue
();
double
lat
=
from
.
latitude
+
(
to
.
latitude
-
from
.
latitude
)
*
fraction
;
double
lng
=
from
.
longitude
+
(
to
.
longitude
-
from
.
longitude
)
*
fraction
;
LatLng
interpolated
=
new
LatLng
(
lat
,
lng
);
listener
.
onUpdate
(
interpolated
,
bearing
);
// 实时位置 + 朝向角
});
animator
.
addListener
(
new
AnimatorListenerAdapter
()
{
@Override
public
void
onAnimationEnd
(
Animator
animation
)
{
listener
.
onFinish
();
}
});
animator
.
start
();
}
/**
* 计算从起点 to 终点的方位角(bearing),单位为度(0~360°)
*/
private
static
float
calculateBearing
(
LatLng
from
,
LatLng
to
)
{
double
lat1
=
Math
.
toRadians
(
from
.
latitude
);
double
lon1
=
Math
.
toRadians
(
from
.
longitude
);
double
lat2
=
Math
.
toRadians
(
to
.
latitude
);
double
lon2
=
Math
.
toRadians
(
to
.
longitude
);
double
dLon
=
lon2
-
lon1
;
double
y
=
Math
.
sin
(
dLon
)
*
Math
.
cos
(
lat2
);
double
x
=
Math
.
cos
(
lat1
)
*
Math
.
sin
(
lat2
)
-
Math
.
sin
(
lat1
)
*
Math
.
cos
(
lat2
)
*
Math
.
cos
(
dLon
);
double
bearingRad
=
Math
.
atan2
(
y
,
x
);
return
(
float
)
((
Math
.
toDegrees
(
bearingRad
)
+
360
)
%
360
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment