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
SuZhouAvp
Commits
1ccbc004
Commit
1ccbc004
authored
Jun 06, 2025
by
p x
Browse files
first
parent
032ec619
Pipeline
#3090
failed with stages
in 0 seconds
Changes
75
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
app/src/main/java/com/sd/cavphmi/net/RequestBodyUtil.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.net
import
com.google.gson.Gson
import
okhttp3.MediaType.Companion.toMediaTypeOrNull
import
okhttp3.RequestBody
import
okhttp3.RequestBody.Companion.toRequestBody
object
RequestBodyUtil
{
/**
* 将参数封装成requestBody形式上传参数
* @param param 参数
* @return RequestBody
*/
fun
toRequestBody
(
map
:
Map
<
String
,
Any
>):
RequestBody
{
val
gson
=
Gson
()
var
param
=
gson
.
toJson
(
map
)
return
param
.
toRequestBody
(
"application/json;charset=UTF-8"
.
toMediaTypeOrNull
())
}
fun
toRequestBody
(
any
:
Any
):
RequestBody
{
var
gson
=
Gson
()
return
gson
.
toJson
(
any
)
.
toRequestBody
(
"application/json;charset=UTF-8"
.
toMediaTypeOrNull
())
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/net/RetrofitApi.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.net
import
com.google.gson.GsonBuilder
import
com.sd.cavphmi.MyAppcation
import
com.sd.cavphmi.utils.MyContants
import
okhttp3.Cache
import
retrofit2.Retrofit
import
retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import
retrofit2.converter.gson.GsonConverterFactory
import
retrofit2.converter.scalars.ScalarsConverterFactory
import
java.io.File
object
RetrofitApi
{
// val CLIENT_BASIC = Credentials.basic("river-chief-server", "123456")
var
retrofitBuild
:
Retrofit
.
Builder
var
cache
:
Cache
init
{
//设置缓存路径
val
httpCacheDirectory
=
File
(
MyAppcation
.
instance
().
applicationContext
.
externalCacheDir
,
"okhttp"
)
//设置缓存
cache
=
Cache
(
httpCacheDirectory
,
50
*
1024
*
1024
)
val
mGson
=
GsonBuilder
()
// .registerTypeAdapter(HttpErrorBean::class.java, HttpErrorTypeAdapter())
// .setLenient() // 设置GSON的非严格模式setLenient()
.
create
()
retrofitBuild
=
Retrofit
.
Builder
()
.
baseUrl
(
MyContants
.
HOST
)
.
addConverterFactory
(
ScalarsConverterFactory
.
create
())
.
addConverterFactory
(
GsonConverterFactory
.
create
(
mGson
))
.
addCallAdapterFactory
(
RxJava3CallAdapterFactory
.
create
())
}
// fun getSSlSocketFactory(): SslData {
// val trustManagerFactory: TrustManagerFactory = TrustManagerFactory.getInstance(
// TrustManagerFactory.getDefaultAlgorithm()
// )
// trustManagerFactory.init(null as KeyStore?)
// val trustManagers: Array<TrustManager> = trustManagerFactory.getTrustManagers()
// check(!(trustManagers.size != 1 || trustManagers[0] !is X509TrustManager)) {
// ("Unexpected default trust managers:"
// + Arrays.toString(trustManagers))
// }
// val trustManager = trustManagers[0] as X509TrustManager
//
//
// val sslContext = SSLContext.getInstance("TLS")
// sslContext.init(null, arrayOf<TrustManager>(trustManager), null)
// val sslSocketFactory = sslContext.socketFactory
//
// return SslData(sslSocketFactory, trustManager)
// }
//
// data class SslData(val sslSocketFactory: SSLSocketFactory, var trustManager: X509TrustManager)
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/ui/BootActivity.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.ui
import
android.Manifest
import
android.content.Intent
import
androidx.lifecycle.ViewModelProvider
import
com.minedata.minenavi.SDKInitializer
import
com.minedata.minenavi.SDKInitializer.InitListener
import
com.minedata.minenavi.mapdal.CoordType
import
com.minedata.minenavi.poiquery.SearchUrlType
import
com.permissionx.guolindev.PermissionX
import
com.sd.cavphmi.BR
import
com.sd.cavphmi.R
import
com.sd.cavphmi.base.BaseActivity
import
com.sd.cavphmi.base.MyBaseViewModel
import
com.sd.cavphmi.databinding.ActivityBootBinding
import
com.sd.cavphmi.utils.ToastHelper
import
dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class
BootActivity
:
BaseActivity
<
ActivityBootBinding
,
MyBaseViewModel
>()
{
// private val tcpUpVM: TcpUpVM by viewModels()
override
fun
getStatuBarColor
():
Int
{
return
-
1
}
override
fun
initContentView
():
Int
{
return
R
.
layout
.
activity_boot
}
override
fun
initViewModel
():
MyBaseViewModel
{
return
ViewModelProvider
(
this
).
get
(
MyBaseViewModel
::
class
.
java
)
}
override
fun
initVariableId
():
Int
{
return
BR
.
vm
}
// private var latLngInfo: LatLngInfo? = null
override
fun
initView
()
{
// tcpUpVM.owner=this
// tcpUpVM.upWork()
// viewModel.testWork()
initMap
()
requestPers
()
}
// fun getLatLngInfo() {
// latLngInfo = intent.getParcelableExtra<LatLngInfo>(MyContants.LAT_LNG_INFO)
//// var lat = intent.getDoubleExtra("LAT", 0.0)
//// var lng = intent.getDoubleExtra("LNG", 0.0)
// println("---------智慧 boot lng = ${latLngInfo?.lng} lat = ${latLngInfo?.lat}")
//// println("---------智慧 直接传 lat = $lat lng = $lng")
// }
private
fun
starMain
()
{
// requestPers()
binding
.
imageView
.
postDelayed
({
var
jump
=
Intent
(
this
,
MainActivity
::
class
.
java
)
startActivity
(
jump
)
finish
()
},
1000
)
}
fun
initMap
()
{
// 隐私合规接口
SDKInitializer
.
setAgreePrivacy
(
true
)
// if (SDKInitializer.getServerHost().equals("mineservice.minedata.cn")) {
// SDKInitializer.setStyleUrl(
// MineMap.UrlType.basicMap,
// "https://service.minedata.cn/map/solu/style/1359221494104252416"
// )
// }
// 设置地图坐标系
SDKInitializer
.
setCoordType
(
CoordType
.
GCJ02
)
SDKInitializer
.
setSearchUrlType
(
SearchUrlType
.
v1
)
SDKInitializer
.
initialize
(
this
,
object
:
InitListener
{
override
fun
onInitSuccess
()
{
println
(
"---Map onInitSuccess map"
)
}
override
fun
onInitFailed
(
msg
:
String
?)
{
println
(
"---Map onInitFailed msg = ${msg}"
)
}
})
}
fun
requestPers
()
{
var
list
=
listOf
(
Manifest
.
permission
.
ACCESS_COARSE_LOCATION
,
Manifest
.
permission
.
ACCESS_FINE_LOCATION
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
,
Manifest
.
permission
.
READ_PHONE_STATE
,
)
PermissionX
.
init
(
this
)
.
permissions
(
list
)
.
onExplainRequestReason
{
scope
,
deniedList
->
scope
.
showRequestReasonDialog
(
deniedList
,
"Adas 需要同意以下授权才能正常使用"
,
"好的"
,
"取消"
)
}
// .onForwardToSettings { scope, deniedList ->
// scope.showForwardToSettingsDialog(deniedList, "您需要手动在‘设置’中允许必要的权限", "OK", "Cancel")
// }
.
request
{
allGranted
,
grantedList
,
deniedList
->
if
(
allGranted
)
{
// ToastHelper.showShort(this, "All permissions are granted")
starMain
()
}
else
{
ToastHelper
.
showShort
(
this
,
"权限被拒"
)
binding
.
root
.
postDelayed
({
finish
()
},
150
)
}
}
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/ui/MainActivity.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.ui
import
androidx.lifecycle.ViewModelProvider
import
com.sd.cavphmi.BR
import
com.sd.cavphmi.R
import
com.sd.cavphmi.base.BaseActivity
import
com.sd.cavphmi.base.MyBaseViewModel
import
com.sd.cavphmi.databinding.ActivityMainBinding
import
dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class
MainActivity
:
BaseActivity
<
ActivityMainBinding
,
MyBaseViewModel
>()
{
override
fun
getStatuBarColor
():
Int
{
return
-
1
}
override
fun
initContentView
():
Int
{
return
R
.
layout
.
activity_main
}
override
fun
initViewModel
():
MyBaseViewModel
{
return
ViewModelProvider
(
this
).
get
(
MyBaseViewModel
::
class
.
java
)
}
override
fun
initVariableId
():
Int
{
return
BR
.
vm
}
override
fun
initView
()
{
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/DateUtils.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.utils
import
android.graphics.Color
import
android.text.SpannableString
import
android.text.style.ForegroundColorSpan
import
android.text.style.RelativeSizeSpan
import
androidx.core.text.set
import
com.minedata.minenavi.addons.DistanceBean
import
com.minedata.minenavi.util.MineNaviUtil
import
java.text.ParseException
import
java.text.SimpleDateFormat
import
java.util.*
/**
*author:pc-20171125
*data:2019/11/7 15:59
* 时间工具类
*/
object
DateUtils
{
val
FORMAT_YEAR
=
"yyyy"
val
FORMAT_MONTH_DAY
=
"MM月dd日"
val
FORMAT_DATE
=
"yyyy-MM-dd"
val
FORMAT_DATE_NO_SLASHES
=
"yyyyMMdd"
val
FORMAT_TIME
=
"HH:mm"
val
FORMAT_MONTH_DAY_TIME
=
"MM月dd日 HH:mm"
val
FORMAT_DATE_TIME
=
"yyyy-MM-dd HH:mm"
val
FORMAT_DATE1_TIME
=
"yyyy/MM/dd HH:mm"
val
FORMAT_DATE_TIME_SECOND
=
"yyyy-MM-dd HH:mm:ss"
val
FORMAT_MM_DD
=
"MM.dd"
val
FORMAT_YYYY_MM_DD
=
"yyyy.MM.dd"
val
FORMAT_DATE_CHINA
=
"yyyy年MM月dd日"
val
FORMAT_DATE_TIME_CHINA
=
"yyyy年MM月dd日 HH:mm"
// 显示聊天记录的格式
val
CHAT_TIME
=
"mm:ss"
private
val
sdf
=
SimpleDateFormat
()
private
val
YEAR
=
365
*
24
*
60
*
60
// 年
private
val
MONTH
=
30
*
24
*
60
*
60
// 月
private
val
DAY
=
24
*
60
*
60
// 天
private
val
HOUR
=
60
*
60
// 小时
private
val
MINUTE
=
60
// 分钟
/**
**计算预计用时
* @param speed 米/秒
* @param dis 米
**/
fun
getExpectedTime
(
speed
:
Int
,
dis
:
Int
):
String
{
if
(
speed
==
0
||
dis
==
0
)
return
"剩余0分"
var
mUtils
=
Utils
()
var
remainingTime
=
dis
/
speed
val
s_arriveTime
=
MineNaviUtil
.
relativeTimeStringFromNow
(
remainingTime
,
mUtils
.
is24Hour
()
)
var
stringBuilder
=
StringBuilder
()
if
(
s_arriveTime
.
contains
(
"天"
))
{
stringBuilder
.
append
(
"预计"
)
.
append
(
s_arriveTime
.
substring
(
0
,
s_arriveTime
.
indexOf
(
"天"
)
+
1
)
+
""
)
.
append
(
s_arriveTime
.
substring
(
s_arriveTime
.
indexOf
(
"天"
)
+
1
,
s_arriveTime
.
length
))
.
append
(
"到达"
)
}
else
if
(
s_arriveTime
.
contains
(
"日"
))
{
stringBuilder
.
append
(
"预计"
)
.
append
(
s_arriveTime
.
substring
(
0
,
s_arriveTime
.
indexOf
(
"日"
)
+
1
)
+
""
)
.
append
(
s_arriveTime
.
substring
(
s_arriveTime
.
indexOf
(
"日"
)
+
1
,
s_arriveTime
.
length
))
.
append
(
"到达"
)
}
else
{
stringBuilder
.
append
(
"预计"
).
append
(
s_arriveTime
).
append
(
"到达"
)
}
return
stringBuilder
.
toString
()
}
fun
getExpectedTime
(
speed
:
Int
,
distanceBean
:
DistanceBean
):
String
{
if
(
speed
==
0
||
distanceBean
.
distanceValue
.
toFloat
()
==
0f
)
return
"剩余0.0分"
var
dis
=
0
//单位米
if
(
distanceBean
.
distanceUnit
.
contains
(
"公里"
))
{
dis
=
distanceBean
.
distanceValue
.
toInt
()
*
1000
}
var
mUtils
=
Utils
()
var
remainingTime
=
dis
/
speed
val
s_arriveTime
=
MineNaviUtil
.
relativeTimeStringFromNow
(
remainingTime
,
mUtils
.
is24Hour
()
)
var
stringBuilder
=
StringBuilder
()
if
(
s_arriveTime
.
contains
(
"天"
))
{
stringBuilder
.
append
(
"预计"
)
.
append
(
s_arriveTime
.
substring
(
0
,
s_arriveTime
.
indexOf
(
"天"
)
+
1
)
+
""
)
.
append
(
s_arriveTime
.
substring
(
s_arriveTime
.
indexOf
(
"天"
)
+
1
,
s_arriveTime
.
length
))
.
append
(
"到达"
)
}
else
if
(
s_arriveTime
.
contains
(
"日"
))
{
stringBuilder
.
append
(
"预计"
)
.
append
(
s_arriveTime
.
substring
(
0
,
s_arriveTime
.
indexOf
(
"日"
)
+
1
)
+
""
)
.
append
(
s_arriveTime
.
substring
(
s_arriveTime
.
indexOf
(
"日"
)
+
1
,
s_arriveTime
.
length
))
.
append
(
"到达"
)
}
else
{
stringBuilder
.
append
(
"预计"
).
append
(
s_arriveTime
).
append
(
"到达"
)
}
return
stringBuilder
.
toString
()
}
/**
* 计算时间差
*/
fun
timeDifference
(
start_time
:
String
,
end_time
:
String
):
Long
{
var
star
=
stringToDate
(
start_time
,
FORMAT_TIME
)
?.
time
?:
0
var
end
=
stringToDate
(
end_time
,
FORMAT_TIME
)
?.
time
?:
0
var
longExpend
=
end
-
star
return
longExpend
}
/**
* 比价时间前后
*/
fun
diffBeforeAfter
(
start_time
:
String
,
end_time
:
String
):
Boolean
{
if
(
end_time
.
isNullOrEmpty
())
{
return
false
}
var
star
=
stringToDate
(
start_time
,
FORMAT_TIME
)
var
end
=
stringToDate
(
end_time
,
FORMAT_TIME
)
return
star
?.
before
(
end
)
?:
false
}
/**
* 根据时间戳获取描述性时间,如3分钟前,1天前
*
* @param timestamp 时间戳 单位为毫秒
* @return 时间字符串
*/
fun
getDescriptionTimeFromTimestamp
(
timestamp
:
Long
):
String
{
val
currentTime
=
System
.
currentTimeMillis
()
// 与现在时间相差秒数
val
timeGap
=
(
currentTime
-
timestamp
)
/
1000
println
(
"timeGap: $timeGap"
)
val
timeStr
:
String
if
(
timeGap
>
YEAR
)
{
timeStr
=
(
timeGap
/
YEAR
).
toString
()
+
"年前"
}
else
if
(
timeGap
>
MONTH
)
{
timeStr
=
(
timeGap
/
MONTH
).
toString
()
+
"个月前"
}
else
if
(
timeGap
>
DAY
)
{
// 1天以上
timeStr
=
(
timeGap
/
DAY
).
toString
()
+
"天前"
}
else
if
(
timeGap
>
HOUR
)
{
// 1小时-24小时
timeStr
=
(
timeGap
/
HOUR
).
toString
()
+
"小时前"
}
else
if
(
timeGap
>
MINUTE
)
{
// 1分钟-59分钟
timeStr
=
(
timeGap
/
MINUTE
).
toString
()
+
"分钟前"
}
else
{
// 1秒钟-59秒钟
timeStr
=
"刚刚"
}
return
timeStr
}
/**
* 获取当前日期的指定格式的字符串
*
* @param format 指定的日期时间格式,若为null或""则使用指定的格式"yyyy-MM-dd HH:MM"
*/
fun
getCurrentTime
(
format
:
String
=
FORMAT_DATE
):
String
{
sdf
.
applyPattern
(
format
)
return
sdf
.
format
(
Date
())
}
/**
* 格林威治时间
*/
fun
getCurrentTimeGMT
():
String
{
val
cd
=
Calendar
.
getInstance
()
cd
.
add
(
Calendar
.
HOUR
,
+
8
)
val
sdf
=
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
,
Locale
.
US
)
sdf
.
timeZone
=
TimeZone
.
getTimeZone
(
"GMT"
)
// 设置时区为GMT
return
sdf
.
format
(
cd
.
getTime
())
}
/**
* date类型转换为String类型
* formatType格式为yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 HH时mm分ss秒
* data Date类型的时间
*/
fun
dateToString
(
data
:
Date
?,
formatType
:
String
):
String
{
return
SimpleDateFormat
(
formatType
).
format
(
data
)
}
/**
* long类型转换为String类型
* currentTime要转换的long类型的时间
* formatType要转换的string类型的时间格式
*/
@JvmStatic
fun
longToString
(
currentTime
:
Long
,
formatType
:
String
):
String
{
val
strTime
:
String
// long类型转成Date类型
val
date
=
longToDate
(
currentTime
,
formatType
)
// date类型转成String
strTime
=
dateToString
(
date
,
formatType
)
return
strTime
}
/**
* string类型转换为date类型
* strTime要转换的string类型的时间,formatType要转换的格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日
* HH时mm分ss秒,
* strTime的时间格式必须要与formatType的时间格式相同
*/
fun
stringToDate
(
strTime
:
String
,
formatType
:
String
):
Date
?
{
val
formatter
=
SimpleDateFormat
(
formatType
)
var
date
:
Date
?
=
null
try
{
date
=
formatter
.
parse
(
strTime
)
}
catch
(
e
:
ParseException
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
()
}
return
date
}
/**
* long转换为Date类型
* currentTime要转换的long类型的时间
* formatType要转换的时间格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 HH时mm分ss秒
*/
fun
longToDate
(
currentTime
:
Long
,
formatType
:
String
):
Date
?
{
// 根据long类型的毫秒数生命一个date类型的时间
val
dateOld
=
Date
(
currentTime
)
// 把date类型的时间转换为string
val
sDateTime
=
dateToString
(
dateOld
,
formatType
)
// 把String类型转换为Date类型
return
stringToDate
(
sDateTime
,
formatType
)
}
/**
* string类型转换为long类型
*
* strTime要转换的String类型的时间
* formatType时间格式
* strTime的时间格式和formatType的时间格式必须相同
*/
fun
stringToLong
(
strTime
:
String
,
formatType
:
String
):
Long
{
// String类型转成date类型
val
date
=
stringToDate
(
strTime
,
formatType
)
return
if
(
date
==
null
)
{
0
}
else
{
// date类型转成long类型
dateToLong
(
date
)
}
}
/**
* date类型转换为long类型
* date要转换的date类型的时间
*/
fun
dateToLong
(
date
:
Date
):
Long
{
return
date
.
time
}
/**
* 仿照微信中的消息时间显示逻辑,将时间戳(单位:毫秒)转换为友好的显示格式.
*
* 1)7天之内的日期显示逻辑是:今天、昨天(-1d)、前天(-2d)、星期?(只显示总计7天之内的星期数,即<=-4d);<br></br>
*
* 2)7天之外(即>7天)的逻辑:直接显示完整日期时间。
*
* @param srcDate 要处理的源日期时间对象
* @param mustIncludeTime true表示输出的格式里一定会包含“时间:分钟”,否则不包含(参考微信,不包含时分的情况,用于首页“消息”中显示时)
* @return 输出格式形如:“10:30”、“昨天 12:04”、“前天 20:51”、“星期二”、“2019/2/21 12:09”等形式
* @author 即时通讯网([url = http : / / www.52im.net]http : / / www.52im.net[ / url])
* @since 4.5
*/
fun
getTimeStringAutoShort2
(
srcDate
:
Date
,
mustIncludeTime
:
Boolean
):
String
{
var
ret
=
""
try
{
val
gcCurrent
=
GregorianCalendar
()
gcCurrent
.
time
=
Date
()
val
currentYear
=
gcCurrent
.
get
(
GregorianCalendar
.
YEAR
)
val
currentMonth
=
gcCurrent
.
get
(
GregorianCalendar
.
MONTH
)
+
1
val
currentDay
=
gcCurrent
.
get
(
GregorianCalendar
.
DAY_OF_MONTH
)
val
gcSrc
=
GregorianCalendar
()
gcSrc
.
time
=
srcDate
val
srcYear
=
gcSrc
.
get
(
GregorianCalendar
.
YEAR
)
val
srcMonth
=
gcSrc
.
get
(
GregorianCalendar
.
MONTH
)
+
1
val
srcDay
=
gcSrc
.
get
(
GregorianCalendar
.
DAY_OF_MONTH
)
// 要额外显示的时间分钟
val
timeExtraStr
=
if
(
mustIncludeTime
)
" "
+
getTimeString
(
srcDate
,
"HH:mm"
)
else
""
// 当年
if
(
currentYear
==
srcYear
)
{
val
currentTimestamp
=
gcCurrent
.
timeInMillis
val
srcTimestamp
=
gcSrc
.
timeInMillis
// 相差时间(单位:毫秒)
val
delta
=
currentTimestamp
-
srcTimestamp
// 当天(月份和日期一致才是)
if
(
currentMonth
==
srcMonth
&&
currentDay
==
srcDay
)
{
// 时间相差60秒以内
if
(
delta
<
60
*
1000
)
ret
=
"刚刚"
else
ret
=
getTimeString
(
srcDate
,
"HH:mm"
)
// 否则当天其它时间段的,直接显示“时:分”的形式
}
else
{
// 昨天(以“现在”的时候为基准-1天)
val
yesterdayDate
=
GregorianCalendar
()
yesterdayDate
.
add
(
GregorianCalendar
.
DAY_OF_MONTH
,
-
1
)
// 前天(以“现在”的时候为基准-2天)
val
beforeYesterdayDate
=
GregorianCalendar
()
beforeYesterdayDate
.
add
(
GregorianCalendar
.
DAY_OF_MONTH
,
-
2
)
// 用目标日期的“月”和“天”跟上方计算出来的“昨天”进行比较,是最为准确的(如果用时间戳差值
// 的形式,是不准确的,比如:现在时刻是2019年02月22日1:00、而srcDate是2019年02月21日23:00,
// 这两者间只相差2小时,直接用“delta/(3600 * 1000)” > 24小时来判断是否昨天,就完全是扯蛋的逻辑了)
if
(
srcMonth
==
yesterdayDate
.
get
(
GregorianCalendar
.
MONTH
)
+
1
&&
srcDay
==
yesterdayDate
.
get
(
GregorianCalendar
.
DAY_OF_MONTH
)
)
{
ret
=
"昨天$timeExtraStr"
// -1d
}
else
if
(
srcMonth
==
beforeYesterdayDate
.
get
(
GregorianCalendar
.
MONTH
)
+
1
&&
srcDay
==
beforeYesterdayDate
.
get
(
GregorianCalendar
.
DAY_OF_MONTH
)
)
{
ret
=
"前天$timeExtraStr"
// -2d
}
else
{
// 跟当前时间相差的小时数
val
deltaHour
=
delta
/
(
3600
*
1000
)
// 如果小于 7*24小时就显示星期几
if
(
deltaHour
<
7
*
24
)
{
val
weekday
=
arrayOf
(
"星期日"
,
"星期一"
,
"星期二"
,
"星期三"
,
"星期四"
,
"星期五"
,
"星期六"
)
// 取出当前是星期几
val
weedayDesc
=
weekday
[
gcSrc
.
get
(
GregorianCalendar
.
DAY_OF_WEEK
)
-
1
]
ret
=
weedayDesc
+
timeExtraStr
}
else
ret
=
getTimeString
(
srcDate
,
"yyyy/M/d"
)
+
timeExtraStr
// 否则直接显示完整日期时间
}
// “前天”判断逻辑同上
}
// 当年 && 当天之外的时间(即昨天及以前的时间)
}
else
ret
=
getTimeString
(
srcDate
,
"yyyy/M/d"
)
+
timeExtraStr
}
catch
(
e
:
Exception
)
{
System
.
err
.
println
(
"【DEBUG-getTimeStringAutoShort】计算出错:"
+
e
.
message
+
" 【NO】"
)
}
return
ret
}
/**
* * 返回指定pattern样的日期时间字符串。
*
* @param dt
* @param pattern
* @return 如果时间转换成功则返回结果,否则返回空字符串""
* @author 即时通讯网([url=http://www.52im.net]http://www.52im.net[/url])
*/
fun
getTimeString
(
dt
:
Date
,
pattern
:
String
):
String
{
try
{
val
sdf
=
SimpleDateFormat
(
pattern
)
//"yyyy-MM-dd HH:mm:ss"
sdf
.
timeZone
=
TimeZone
.
getDefault
()
return
sdf
.
format
(
dt
)
}
catch
(
e
:
Exception
)
{
return
""
}
}
/**
* 获取会议时间
*/
public
fun
getConfTime
(
beginTime
:
String
,
endTime
:
String
):
String
{
//开始时间long
val
beginTimeLong
=
stringToLong
(
beginTime
,
FORMAT_DATE_TIME_SECOND
)
//结束时间long
val
endTimeLong
=
stringToLong
(
endTime
,
FORMAT_DATE_TIME_SECOND
)
//开始的年月
val
beginDate
=
longToString
(
beginTimeLong
,
FORMAT_DATE
)
val
endDate
=
longToString
(
endTimeLong
,
FORMAT_DATE
)
var
confTime
=
""
//开始的日期系统
if
(
beginDate
.
equals
(
endDate
))
{
confTime
=
"${
longToString
(
beginTimeLong
,
FORMAT_DATE_TIME
)
}-
$
{
longToString
(
endTimeLong
,
FORMAT_TIME
)}
"
}
else
{
confTime
=
"${
longToString
(
beginTimeLong
,
FORMAT_DATE_TIME
)
}-
$
{
longToString
(
endTimeLong
,
FORMAT_DATE_TIME
)}
"
}
return
confTime
}
/**
* 格式化时间
*
* @param longTime 时间
* @return 格式后的时间
* @history 2013-8-26 v1.0.0 cWX176935 create
* @since 1.1
*/
fun
formatTimeFString
(
longTime
:
Long
):
String
{
var
time
=
"%2d:%2d"
val
min
=
parseLongToInt
(
longTime
/
60
)
val
sec
=
parseLongToInt
(
longTime
%
60
)
time
=
String
.
format
(
time
,
min
,
sec
)
return
time
.
replace
(
' '
,
'0'
)
}
/**
* 格式化时间
*
* @param longTime 时间
* @return 格式后的时间 格式为1分1秒
* @history 2013-8-26 v1.0.0 cWX176935 create
* @since 1.1
*/
fun
longToString
(
longTime
:
Long
):
String
{
var
time
=
"%2d:%2d"
val
min
=
parseLongToInt
(
longTime
/
60
)
val
sec
=
parseLongToInt
(
longTime
%
60
)
var
timeBuilder
=
StringBuilder
()
if
(
min
>
0
)
{
timeBuilder
.
append
(
"${min}分"
)
}
timeBuilder
.
append
(
"${sec}秒"
)
return
timeBuilder
.
toString
()
}
/**
* @param value
* @return
*/
private
fun
parseLongToInt
(
value
:
Long
):
Int
{
return
Math
.
round
(
value
.
toFloat
())
}
/**
* 时间转 中文易读格式
*/
fun
secToTime
(
sec
:
Long
):
String
{
var
timeStr
=
""
var
hour
=
"00"
var
minute
=
"00"
var
second
=
"00"
hour
=
String
.
format
(
"%02d"
,
(
sec
/
3600
).
toInt
())
var
surplusMin
=
sec
%
3600
minute
=
String
.
format
(
"%02d"
,
(
surplusMin
/
60
).
toInt
())
var
surplusSec
=
surplusMin
%
60
second
=
String
.
format
(
"%02d"
,
surplusSec
)
timeStr
=
"${hour}:${minute}:${second}"
return
timeStr
}
/**
* 在订单详情里 时间转 中文易读格式
*/
fun
secToTimeOrderDetail
(
sec
:
Long
):
SpannableString
{
var
timeStr
=
""
var
hour
=
"00"
var
minute
=
"00"
var
second
=
"00"
hour
=
String
.
format
(
"%02d"
,
(
sec
/
3600
).
toInt
())
var
surplusMin
=
sec
%
3600
minute
=
String
.
format
(
"%02d"
,
(
surplusMin
/
60
).
toInt
())
// var surplusSec = surplusMin % 60
// second = String.format("%02d", surplusSec)
timeStr
=
"${hour} 小时 ${minute} 分钟"
var
star
=
0
var
end
=
star
+
hour
.
count
()
val
sizeSpan1
=
RelativeSizeSpan
(
1.4f
)
val
sizeSpan2
=
RelativeSizeSpan
(
1.4f
)
var
spanStr
=
SpannableString
(
timeStr
)
spanStr
.
set
(
star
..
end
,
sizeSpan1
)
star
=
end
+
4
end
=
star
+
minute
.
count
()
spanStr
.
set
(
star
..
end
,
sizeSpan2
)
return
spanStr
}
/**
* 子订单剩余时间 中文易读格式
*/
fun
orderGrabbingDecToTime
(
sec
:
Long
):
SpannableString
{
var
timeStr
:
SpannableString
var
day
=
"00"
var
hour
=
"00"
var
minute
=
"00"
var
second
=
"00"
day
=
String
.
format
(
"%02d"
,
(
sec
/
(
3600
*
24
)).
toInt
())
var
surplusHour
=
sec
%
(
3600
*
24
)
hour
=
String
.
format
(
"%02d"
,
(
surplusHour
/
3600
).
toInt
())
var
surplusMin
=
sec
%
3600
minute
=
String
.
format
(
"%02d"
,
(
surplusMin
/
60
).
toInt
())
var
surplusSec
=
surplusMin
%
60
second
=
String
.
format
(
"%02d"
,
surplusSec
)
timeStr
=
SpannableString
(
"有效期还剩 ${day}天: ${hour}小时: ${minute}分: ${second}秒"
)
var
foregroundColorSpan1
=
ForegroundColorSpan
(
Color
.
parseColor
(
"#F95F2C"
))
var
foregroundColorSpan2
=
ForegroundColorSpan
(
Color
.
parseColor
(
"#F95F2C"
))
var
foregroundColorSpan3
=
ForegroundColorSpan
(
Color
.
parseColor
(
"#F95F2C"
))
var
foregroundColorSpan4
=
ForegroundColorSpan
(
Color
.
parseColor
(
"#F95F2C"
))
var
star
=
6
var
end
=
6
+
day
.
count
()
timeStr
.
set
(
star
..
end
,
foregroundColorSpan1
)
star
=
end
+
3
end
=
star
+
hour
.
count
()
timeStr
.
set
(
star
,
end
,
foregroundColorSpan2
)
star
=
end
+
4
end
=
star
+
minute
.
count
()
timeStr
.
set
(
star
..
end
,
foregroundColorSpan3
)
star
=
end
+
3
end
=
star
+
second
.
count
()
timeStr
.
set
(
star
..
end
,
foregroundColorSpan4
)
return
timeStr
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/DisplayUtil.kt
0 → 100644
View file @
1ccbc004
package
com.ltzw.adasdriver.utils
import
android.app.Activity
import
android.content.Context
import
android.content.res.Configuration
import
android.content.res.Resources
import
android.os.Build
import
android.provider.Settings
import
android.util.DisplayMetrics
import
android.util.TypedValue
/**
*author:pc-20171125
*data:2019/11/7 16:08
*/
object
DisplayUtil
{
fun
getDpi
():
Int
{
return
Resources
.
getSystem
().
displayMetrics
.
densityDpi
}
fun
px2dp
(
pxValue
:
Float
):
Int
{
val
scale
=
Resources
.
getSystem
().
displayMetrics
.
density
return
(
pxValue
/
scale
+
0.5f
).
toInt
()
}
fun
dp2px
(
dipValue
:
Float
):
Int
{
val
scale
=
Resources
.
getSystem
().
displayMetrics
.
density
return
(
dipValue
*
scale
+
0.5f
).
toInt
()
}
fun
px2sp
(
pxValue
:
Float
):
Int
{
val
fontScale
=
Resources
.
getSystem
().
displayMetrics
.
scaledDensity
return
(
pxValue
/
fontScale
+
0.5f
).
toInt
()
}
fun
sp2px
(
spValue
:
Float
):
Int
{
val
fontScale
=
Resources
.
getSystem
().
displayMetrics
.
scaledDensity
return
(
spValue
*
fontScale
+
0.5f
).
toInt
()
}
private
val
mTmpValue
=
TypedValue
()
fun
getXmlDef
(
context
:
Context
,
id
:
Int
):
Int
{
synchronized
(
mTmpValue
)
{
val
value
:
TypedValue
=
mTmpValue
context
.
resources
.
getValue
(
id
,
value
,
true
)
return
TypedValue
.
complexToFloat
(
value
.
data
).
toInt
()
}
}
fun
getNavigationBarHeight
(
context
:
Context
):
Int
{
val
mInPortrait
=
context
.
resources
.
configuration
.
orientation
==
Configuration
.
ORIENTATION_PORTRAIT
val
result
=
0
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
ICE_CREAM_SANDWICH
)
{
if
(
hasNavBar
(
context
as
Activity
))
{
val
key
:
String
if
(
mInPortrait
)
{
key
=
"navigation_bar_height"
}
else
{
key
=
"navigation_bar_height_landscape"
}
return
getInternalDimensionSize
(
context
,
key
)
}
}
return
result
}
private
fun
hasNavBar
(
activity
:
Activity
):
Boolean
{
//判断小米手机是否开启了全面屏,开启了,直接返回false
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
)
{
if
(
Settings
.
Global
.
getInt
(
activity
.
contentResolver
,
"force_fsg_nav_bar"
,
0
)
!=
0
)
{
return
false
}
}
//其他手机根据屏幕真实高度与显示高度是否相同来判断
val
windowManager
=
activity
.
windowManager
val
d
=
windowManager
.
defaultDisplay
val
realDisplayMetrics
=
DisplayMetrics
()
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
)
{
d
.
getRealMetrics
(
realDisplayMetrics
)
}
val
realHeight
=
realDisplayMetrics
.
heightPixels
val
realWidth
=
realDisplayMetrics
.
widthPixels
val
displayMetrics
=
DisplayMetrics
()
d
.
getMetrics
(
displayMetrics
)
val
displayHeight
=
displayMetrics
.
heightPixels
val
displayWidth
=
displayMetrics
.
widthPixels
return
realWidth
-
displayWidth
>
0
||
realHeight
-
displayHeight
>
0
}
private
fun
getInternalDimensionSize
(
context
:
Context
,
key
:
String
):
Int
{
var
result
=
0
try
{
val
resourceId
=
context
.
resources
.
getIdentifier
(
key
,
"dimen"
,
"android"
)
if
(
resourceId
>
0
)
{
result
=
Math
.
round
(
context
.
resources
.
getDimensionPixelSize
(
resourceId
)
*
Resources
.
getSystem
().
displayMetrics
.
density
/
context
.
resources
.
displayMetrics
.
density
)
}
}
catch
(
ignored
:
Resources
.
NotFoundException
)
{
return
0
}
return
result
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/MobileUtils.kt
0 → 100644
View file @
1ccbc004
package
com.ltzw.adasdriver.utils
import
android.os.Build
object
MobileUtils
{
// if (ModelUtils.isEMUI() && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
// mPwdEt.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL);
// mPwdEt.setTransformationMethod(PasswordTransformationMethod.getInstance());
// }
fun
isMIUI
():
Boolean
{
val
manufacturer
:
String
=
Build
.
MANUFACTURER
return
"xiaomi"
.
equals
(
manufacturer
,
ignoreCase
=
true
)
}
fun
isEMUI
():
Boolean
{
val
manufacturer
:
String
=
Build
.
MANUFACTURER
return
"HUAWEI"
.
equals
(
manufacturer
,
ignoreCase
=
true
)
}
fun
isOPPO
():
Boolean
{
val
manufacturer
:
String
=
Build
.
MANUFACTURER
return
"OPPO"
.
equals
(
manufacturer
,
ignoreCase
=
true
)
}
fun
isVIVO
():
Boolean
{
val
manufacturer
:
String
=
Build
.
MANUFACTURER
return
"vivo"
.
equals
(
manufacturer
,
ignoreCase
=
true
)
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/MyContants.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.utils
object
MyContants
{
const
val
IS_DEBUG
=
true
var
HOST
=
if
(
IS_DEBUG
)
"http://laravel.suiyigou.shop/"
else
"https://api.suixinsuiyi.cn/"
var
PORT
=
if
(
IS_DEBUG
)
"123"
else
"34534"
var
SOCKET_HOSTNAME
=
if
(
IS_DEBUG
)
"192.168.60.77"
else
""
var
SOCKET_RECEIVE_PORT
=
if
(
IS_DEBUG
)
8082
else
0
var
DOWNLOAD_APP_URL
=
"https://app.mi.com/download/1325540?id=com.sxsy.easyclient&ref=search&nonce=-6756103978404716128%3A26875199&appClientId=2882303761517485445&appSignature=BJDg3ZbQJhRoaomIe0kkGJ32i6hbX9HduukAmwpZqpQ"
const
val
PERMISSON_REQUESTCODE
:
Int
=
10
const
val
online
=
true
/**
* 智旅APK传智*/
const
val
LAT_LNG_INFO
=
"LAT_LNG_INFO"
/***当前速度***/
var
CUR_SPEED
=
0
const
val
MOCK_LAT
=
39.9129
const
val
MOCK_LNG
=
116.3723
// var CUR_LAT = MOCK_LAT
// var CUR_LNG = MOCK_LNG
var
CUR_LAT
=
0.0
var
CUR_LNG
=
0.0
// const val MOCK_LAT = 39.56
// const val MOCK_LNG = 116.20
// 116.372641,39.913242
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/MyPres.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.utils
import
androidx.security.crypto.EncryptedSharedPreferences
import
com.sd.cavphmi.MyAppcation
object
MyPres
{
private
const
val
PREFS_NAME
=
"adas"
private
const
val
MASTER_KEY_ALIAS
=
"masterkeyalias"
private
val
sharedPreferences
by
lazy
{
EncryptedSharedPreferences
.
create
(
PREFS_NAME
,
MASTER_KEY_ALIAS
,
MyAppcation
.
instance
().
applicationContext
,
EncryptedSharedPreferences
.
PrefKeyEncryptionScheme
.
AES256_SIV
,
EncryptedSharedPreferences
.
PrefValueEncryptionScheme
.
AES256_GCM
)
}
var
token
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"token"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"token"
,
""
)
?:
""
}
var
hisSearch
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"hisSearch"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"hisSearch"
,
""
)
?:
""
}
/**
* 全类型历史搜素
*/
var
curLat
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"curLat"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"curLat"
,
""
)
?:
""
}
/**
* 专题资料历史搜素
*/
var
curLng
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"curLng"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"curLng"
,
""
)
?:
""
}
/**
* 资料历史搜素
*/
var
dataSearch
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"dataSearch"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"dataSearch"
,
""
)
?:
""
}
/**
* 问答历史搜素
*/
var
qaSearch
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"qaSearch"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"qaSearch"
,
""
)
?:
""
}
/**
* 首次授权
*/
var
isFrist
:
Boolean
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putBoolean
(
"isFrist"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getBoolean
(
"isFrist"
,
true
)
}
/**
* 邀请码
*/
var
invCode
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"invcode"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"invcode"
,
""
)
?:
""
}
/**
* 个人电话
*/
var
mobile
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"mobile"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"mobile"
,
""
)
?:
""
}
/**
* 删除领域
*/
var
goodField
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"goodField"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"goodField"
,
""
)
?:
""
}
var
userId
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"userId"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"userId"
,
""
)
?:
""
}
/**
* 极光推送ID
*/
var
registrationId
:
String
set
(
value
)
{
with
(
sharedPreferences
.
edit
())
{
putString
(
"registrationId"
,
value
)
commit
()
}
}
get
()
{
return
sharedPreferences
.
getString
(
"registrationId"
,
""
)
?:
""
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/ScreenUtil.java
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.utils
;
import
static
android
.
content
.
Context
.
WINDOW_SERVICE
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.content.res.Configuration
;
import
android.content.res.Resources
;
import
android.database.ContentObserver
;
import
android.graphics.Point
;
import
android.graphics.Rect
;
import
android.graphics.drawable.Drawable
;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Handler
;
import
android.provider.Settings
;
import
android.util.DisplayMetrics
;
import
android.util.Log
;
import
android.view.Display
;
import
android.view.DisplayCutout
;
import
android.view.View
;
import
android.view.Window
;
import
android.view.WindowInsets
;
import
android.view.WindowManager
;
import
android.view.inputmethod.InputMethodManager
;
import
android.widget.EditText
;
import
androidx.annotation.RequiresApi
;
import
com.gyf.barlibrary.BarHide
;
import
com.gyf.barlibrary.ImmersionBar
;
import
com.sd.cavphmi.R
;
import
java.lang.reflect.Method
;
import
java.util.List
;
/**
* 获取一些屏幕相关的信息
*/
public
class
ScreenUtil
{
private
static
final
String
PHONE_FLAG_XIAO_MI
=
"xiaomi"
;
private
static
final
String
PHONE_FLAG_HUA_WEI
=
"HUAWEI"
;
private
static
final
String
PHONE_FLAG_OPPO
=
"oppo"
;
private
static
final
String
PHONE_FLAG_VIVO
=
"vivo"
;
public
static
final
int
NAVIGATION_BAR_ON_RIGHT
=
1
;
public
static
final
int
NAVIGATION_BAR_ON_LiFT
=
3
;
private
Context
mContext
;
private
Window
mWindow
;
private
WindowManager
mWindowManager
;
private
View
statusView
;
private
int
mNavigationBarHeight
;
private
boolean
isUserChangeSystemBrightness
=
false
;
private
int
mCurrentSystemBrightness
=
100
;
private
DisplayMetrics
mDisplayMetrics
;
private
int
mNotchWidth
=
0
;
private
int
mNotchHeight
=
0
;
private
int
mHorizontalMaxWidth
;
public
void
init
(
Context
context
,
Window
window
)
{
mContext
=
context
;
mWindow
=
window
;
mWindowManager
=
(
WindowManager
)
mContext
.
getSystemService
(
WINDOW_SERVICE
);
mHorizontalMaxWidth
=
Utils
.
getInstance
().
dp2Px
(
465
);
}
private
static
class
SingletonHolder
{
public
static
final
ScreenUtil
instance
=
new
ScreenUtil
();
}
public
static
ScreenUtil
getInstance
()
{
return
SingletonHolder
.
instance
;
}
public
int
getNotchWidth
()
{
if
(
mNotchWidth
!=
0
)
{
return
mNotchWidth
;
}
int
notchWidth
=
0
;
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
//小米8升级到MIUI 11后获取的刘海宽度有问题 为676 官方为560,有问题会影响自定义状态栏,为防止其他型号手机升级有问题,以下数据写死
//来源 https://dev.mi.com/console/doc/detail?pId=1341
if
(
Build
.
MODEL
.
equals
(
"MI 8"
)
||
Build
.
MODEL
.
equals
(
"MI 8 Explorer Edition"
)
||
Build
.
MODEL
.
equals
(
"MI 8 UD"
))
{
notchWidth
=
560
;
}
else
if
(
Build
.
MODEL
.
equals
(
"MI 8 SE"
))
{
notchWidth
=
540
;
}
else
if
(
Build
.
MODEL
.
equals
(
"MI8Lite"
))
{
notchWidth
=
296
;
}
else
if
(
Build
.
MODEL
.
equals
(
"POCO F1"
))
{
notchWidth
=
588
;
}
else
if
(
Build
.
MODEL
.
equals
(
"Redmi 6 Pro"
))
{
notchWidth
=
352
;
}
else
if
(
Build
.
MODEL
.
equals
(
"Redmi Note 7"
))
{
notchWidth
=
116
;
}
if
(
notchWidth
!=
0
)
{
return
notchWidth
;
}
DisplayCutout
displayCutout
=
getDisplayCutout
((
Activity
)
mContext
);
if
(
displayCutout
!=
null
)
{
List
<
Rect
>
boundingRects
=
displayCutout
.
getBoundingRects
();
if
(
boundingRects
.
size
()
!=
0
)
{
int
left
=
boundingRects
.
get
(
0
).
left
;
int
screenWidth
=
getScreenWidth
();
if
(
left
>
screenWidth
/
2
)
{
//刘海描述右边的区域
notchWidth
=
screenWidth
-
(
screenWidth
-
left
)
*
2
;
}
else
{
notchWidth
=
screenWidth
-
left
*
2
;
}
}
}
}
else
{
if
(
isXiaoMiPhone
())
{
notchWidth
=
getXiaoMiNotchSize
(
mContext
)[
0
];
}
else
if
(
isHUAWEIPhone
())
{
notchWidth
=
getHuaWeiNotchSize
(
mContext
)[
0
];
}
else
if
(
isOPPOPhone
())
{
notchWidth
=
324
;
}
else
if
(
isVivoPhone
())
{
notchWidth
=
Utils
.
getInstance
().
dp2Px
(
100
);
}
}
mNotchWidth
=
notchWidth
;
return
notchWidth
;
}
public
int
getNotchHeight
()
{
if
(
mNotchHeight
!=
0
)
{
return
mNotchHeight
;
}
int
notchHeight
=
0
;
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
DisplayCutout
displayCutout
=
getDisplayCutout
((
Activity
)
mContext
);
if
(
displayCutout
!=
null
)
{
//通过cutout是否为null判断目前是否开启了刘海屏
List
<
Rect
>
boundingRects
=
displayCutout
.
getBoundingRects
();
if
(
boundingRects
.
size
()
!=
0
)
{
Rect
rect
=
boundingRects
.
get
(
0
);
notchHeight
=
rect
.
height
();
//如果刘海的高度大于150,证明是横屏,有问题,取width()
if
(
notchHeight
>
150
)
{
notchHeight
=
rect
.
width
();
}
}
}
else
{
return
notchHeight
;
}
}
else
{
if
(
isXiaoMiPhone
())
{
notchHeight
=
getXiaoMiNotchSize
(
mContext
)[
1
];
}
else
if
(
isHUAWEIPhone
())
{
notchHeight
=
getHuaWeiNotchSize
(
mContext
)[
1
];
}
else
if
(
isOPPOPhone
())
{
notchHeight
=
80
;
}
else
if
(
isVivoPhone
())
{
notchHeight
=
Utils
.
getInstance
().
dp2Px
(
32
);
// 32dp为状态栏高度,刘海高度为27dp
}
}
if
(
notchHeight
==
0
)
{
notchHeight
=
getStatusBarHeight
();
}
mNotchHeight
=
notchHeight
;
return
notchHeight
;
}
public
int
getLiuHaiping
()
{
if
(
mNotchHeight
!=
0
)
{
return
mNotchHeight
;
}
int
notchHeight
=
0
;
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
DisplayCutout
displayCutout
=
getDisplayCutout
((
Activity
)
mContext
);
if
(
displayCutout
!=
null
)
{
//通过cutout是否为null判断目前是否开启了刘海屏
List
<
Rect
>
boundingRects
=
displayCutout
.
getBoundingRects
();
if
(
boundingRects
.
size
()
!=
0
)
{
Rect
rect
=
boundingRects
.
get
(
0
);
notchHeight
=
rect
.
height
();
//如果刘海的高度大于150,证明是横屏,有问题,取width()
if
(
notchHeight
>
150
)
{
notchHeight
=
rect
.
width
();
}
}
}
else
{
return
notchHeight
;
}
}
else
{
if
(
isXiaoMiPhone
())
{
notchHeight
=
getXiaoMiNotchSize
(
mContext
)[
1
];
}
else
if
(
isHUAWEIPhone
())
{
notchHeight
=
getHuaWeiNotchSize
(
mContext
)[
1
];
}
else
if
(
isOPPOPhone
())
{
notchHeight
=
80
;
}
else
if
(
isVivoPhone
())
{
notchHeight
=
Utils
.
getInstance
().
dp2Px
(
32
);
// 32dp为状态栏高度,刘海高度为27dp
}
}
return
notchHeight
;
}
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
M
)
private
DisplayCutout
getDisplayCutout
(
Activity
activity
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
View
decorView
=
activity
.
getWindow
().
getDecorView
();
if
(
decorView
!=
null
)
{
WindowInsets
windowInsets
=
decorView
.
getRootWindowInsets
();
if
(
windowInsets
!=
null
)
{
return
windowInsets
.
getDisplayCutout
();
}
}
}
return
null
;
}
/**
* 获取状态栏高度
*/
public
int
getStatusBarHeight
()
{
int
statusBarHeight
=
0
;
try
{
Class
<?>
clazz
=
Class
.
forName
(
"com.android.internal.R$dimen"
);
Object
object
=
clazz
.
newInstance
();
int
height
=
Integer
.
parseInt
(
clazz
.
getField
(
"status_bar_height"
).
get
(
object
).
toString
());
statusBarHeight
=
mContext
.
getResources
().
getDimensionPixelSize
(
height
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
if
(
statusBarHeight
==
0
)
{
int
resourceId
=
mContext
.
getResources
().
getIdentifier
(
"status_bar_height"
,
"dimen"
,
"android"
);
if
(
resourceId
>
0
)
{
statusBarHeight
=
mContext
.
getResources
().
getDimensionPixelSize
(
resourceId
);
}
}
if
(
statusBarHeight
==
0
)
{
Rect
rectangle
=
new
Rect
();
mWindow
.
getDecorView
().
getWindowVisibleDisplayFrame
(
rectangle
);
statusBarHeight
=
rectangle
.
top
;
}
return
statusBarHeight
;
}
/**
* 能否用自定义状态栏
*/
public
boolean
useCustomStatusBar
()
{
if
(!
canUseImmersive
())
{
return
false
;
}
if
(
isXiaoMiOpenHideFullScreenToggle
(
mContext
))
{
return
false
;
}
return
true
;
}
/**
* 获取小米手机刘海屏宽高 int[0] 为宽度 int[1] 为高度
*/
private
int
[]
getXiaoMiNotchSize
(
Context
context
)
{
int
[]
ret
=
new
int
[]{
0
,
0
};
int
resourceWidthId
=
context
.
getResources
().
getIdentifier
(
"notch_width"
,
"dimen"
,
"android"
);
if
(
resourceWidthId
>
0
)
{
ret
[
0
]
=
(
context
.
getResources
().
getDimensionPixelSize
(
resourceWidthId
))
+
10
;
}
int
resourceHeightId
=
context
.
getResources
().
getIdentifier
(
"notch_height"
,
"dimen"
,
"android"
);
if
(
resourceHeightId
>
0
)
{
ret
[
1
]
=
context
.
getResources
().
getDimensionPixelSize
(
resourceHeightId
)
+
30
;
}
return
ret
;
}
/**
* 获取华为手机刘海屏宽高 int[0] 为宽度 int[1] 为高度
*/
private
int
[]
getHuaWeiNotchSize
(
Context
context
)
{
int
[]
ret
=
new
int
[]{
0
,
0
};
try
{
ClassLoader
cl
=
context
.
getClassLoader
();
Class
HwNotchSizeUtil
=
cl
.
loadClass
(
"com.huawei.android.util.HwNotchSizeUtil"
);
Method
get
=
HwNotchSizeUtil
.
getMethod
(
"getNotchSize"
);
ret
=
(
int
[])
get
.
invoke
(
HwNotchSizeUtil
);
}
catch
(
ClassNotFoundException
e
)
{
Log
.
e
(
"test"
,
"getNotchSize ClassNotFoundException"
);
}
catch
(
NoSuchMethodException
e
)
{
Log
.
e
(
"test"
,
"getNotchSize NoSuchMethodException"
);
}
catch
(
Exception
e
)
{
Log
.
e
(
"test"
,
"getNotchSize Exception"
);
}
finally
{
return
ret
;
}
}
public
boolean
isXiaoMiPhone
()
{
return
Build
.
MANUFACTURER
.
equalsIgnoreCase
(
PHONE_FLAG_XIAO_MI
);
}
public
boolean
isHUAWEIPhone
()
{
return
Build
.
MANUFACTURER
.
equalsIgnoreCase
(
PHONE_FLAG_HUA_WEI
);
}
public
boolean
isOPPOPhone
()
{
return
Build
.
MANUFACTURER
.
equalsIgnoreCase
(
PHONE_FLAG_OPPO
);
}
public
boolean
isVivoPhone
()
{
return
Build
.
MANUFACTURER
.
equalsIgnoreCase
(
PHONE_FLAG_VIVO
);
}
/**
* 小米是否开启了隐藏全面屏的开关(系统设置里)
*/
public
boolean
isXiaoMiOpenHideFullScreenToggle
(
Context
context
)
{
return
ImmersionBar
.
hasNotchScreen
((
Activity
)
context
)
&&
isXiaoMiPhone
()
&&
Settings
.
Global
.
getInt
(
context
.
getContentResolver
(),
"force_black"
,
0
)
==
1
;
}
/**
* 获取当前屏幕的亮度
*
* @param context
* @return 返回是一个int值 在0 ~ 255之间
*/
public
int
getSystemBrightness
(
Context
context
)
{
int
nowBrightnessValue
=
0
;
try
{
nowBrightnessValue
=
Settings
.
System
.
getInt
(
context
.
getContentResolver
(),
Settings
.
System
.
SCREEN_BRIGHTNESS
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
nowBrightnessValue
;
}
/**
* 设置当前系统屏幕亮度值 0 ~ 255
*
* @param context
* @param paramInt 设置的值
*/
public
void
setSystemScreenBrightness
(
Context
context
,
int
paramInt
)
{
try
{
Settings
.
System
.
putInt
(
context
.
getContentResolver
(),
Settings
.
System
.
SCREEN_BRIGHTNESS
,
paramInt
);
}
catch
(
Exception
localException
)
{
localException
.
printStackTrace
();
}
}
/**
* 判断是否开启了自动亮度调节
* 自动 = 1 SCREEN_BRIGHTNESS_MODE_AUTOMATIC
* 手动 = 0 SCREEN_BRIGHTNESS_MODE_MANUAL
*
* @param context
* @return
*/
public
boolean
isAutoBrightness
(
Context
context
)
{
boolean
isAutoBrightness
=
false
;
try
{
isAutoBrightness
=
Settings
.
System
.
getInt
(
context
.
getContentResolver
(),
Settings
.
System
.
SCREEN_BRIGHTNESS_MODE
)
==
Settings
.
System
.
SCREEN_BRIGHTNESS_MODE_AUTOMATIC
;
}
catch
(
Settings
.
SettingNotFoundException
e
)
{
e
.
printStackTrace
();
}
return
isAutoBrightness
;
}
/**
* 改变App当前Window亮度
* lp.screenBrightness 范围 0.0 ~ 1.0之间
*
* @param brightness
* @param context activity的context
*/
public
void
changeAppBrightness
(
Context
context
,
float
brightness
)
{
Window
window
=
((
Activity
)
context
).
getWindow
();
WindowManager
.
LayoutParams
lp
=
window
.
getAttributes
();
if
(
brightness
==
-
1
)
{
lp
.
screenBrightness
=
WindowManager
.
LayoutParams
.
BRIGHTNESS_OVERRIDE_NONE
;
}
else
{
lp
.
screenBrightness
=
brightness
;
}
window
.
setAttributes
(
lp
);
}
/**
* 停止自动亮度调节
*
* @param context
*/
public
void
stopAutoBrightness
(
Context
context
)
{
Settings
.
System
.
putInt
(
context
.
getContentResolver
(),
Settings
.
System
.
SCREEN_BRIGHTNESS_MODE
,
Settings
.
System
.
SCREEN_BRIGHTNESS_MODE_MANUAL
);
}
/**
* 开启亮度自动调节
*
* @param context
*/
public
void
startAutoBrightness
(
Context
context
)
{
Settings
.
System
.
putInt
(
context
.
getContentResolver
(),
Settings
.
System
.
SCREEN_BRIGHTNESS_MODE
,
Settings
.
System
.
SCREEN_BRIGHTNESS_MODE_AUTOMATIC
);
}
public
void
cleanup
()
{
mContext
.
getContentResolver
().
unregisterContentObserver
(
mBrightnessObserver
);
}
/**
* 设置降低屏幕亮度策略
*
* @param enable 是否打开
*/
public
void
enableScreenBrightnessDarkStrategy
(
boolean
enable
)
{
if
(
Utils
.
getInstance
().
isCharging
()
||
isAutoBrightness
(
mContext
))
{
return
;
}
if
(
enable
)
{
isUserChangeSystemBrightness
=
false
;
mCurrentSystemBrightness
=
getSystemBrightness
(
mContext
);
setSystemScreenBrightness
(
mContext
,
mCurrentSystemBrightness
/
2
);
mContext
.
getContentResolver
().
registerContentObserver
(
Settings
.
System
.
getUriFor
(
Settings
.
System
.
SCREEN_BRIGHTNESS
),
false
,
mBrightnessObserver
);
}
else
{
mContext
.
getContentResolver
().
unregisterContentObserver
(
mBrightnessObserver
);
if
(!
isUserChangeSystemBrightness
)
setSystemScreenBrightness
(
mContext
,
mCurrentSystemBrightness
);
}
}
/**
* 注册光观察者: context.getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS), false, mBrightnessObserver);
* 应用销毁解观察者: context.getContentResolver().unregisterContentObserver(mBrightnessObserver);
* 如果开启自动亮度调节,获取系统亮度,是一个值,调节bar,获取系统亮度还是那个值
* 如果关闭自动亮度调节,获取的亮度是一个值,调节bar,获取系统亮度是调节后的值
* 如果开启自动亮度调节,此方法监听不到系统亮度变化
*/
private
ContentObserver
mBrightnessObserver
=
new
ContentObserver
(
new
Handler
())
{
@Override
public
void
onChange
(
boolean
selfChange
,
Uri
uri
)
{
super
.
onChange
(
selfChange
,
uri
);
isUserChangeSystemBrightness
=
true
;
}
};
public
Window
getWindow
()
{
return
mWindow
;
}
/**
* 获取屏幕宽 可用显示区域大小
*/
public
int
getScreenWidth
()
{
mDisplayMetrics
=
new
DisplayMetrics
();
mWindowManager
.
getDefaultDisplay
().
getMetrics
(
mDisplayMetrics
);
return
mDisplayMetrics
.
widthPixels
;
}
public
int
getScreenHeight
()
{
mDisplayMetrics
=
new
DisplayMetrics
();
mWindowManager
.
getDefaultDisplay
().
getMetrics
(
mDisplayMetrics
);
return
mDisplayMetrics
.
heightPixels
;
}
/**
* 获取横向屏幕可用显示区域最大宽度
*/
public
int
getHorizontalMaxWidth
()
{
int
screenWidthTwoFifths
=
getScreenWidth
()
*
2
/
5
;
if
(
screenWidthTwoFifths
>
mHorizontalMaxWidth
)
{
return
mHorizontalMaxWidth
;
}
else
{
return
screenWidthTwoFifths
;
}
}
/**
* 地图显示的高,获取的是正常竖屏的高
*/
public
int
getMapShowHeight
()
{
int
mapShowHeight
;
if
(
canUseImmersive
())
{
mapShowHeight
=
getRealScreenHeight
()
-
getNavigationBarHeight
();
}
else
{
mapShowHeight
=
getRealScreenHeight
()
-
getNavigationBarHeight
()
-
getStatusBarHeight
();
}
return
mapShowHeight
;
}
/**
* 通过反射拿到屏幕实际的高度(包括状态栏和导航栏),获取的是正常竖屏的高
*/
private
int
getRealScreenHeight
()
{
int
dpi
=
0
;
Display
display
=
((
Activity
)
mContext
).
getWindowManager
().
getDefaultDisplay
();
DisplayMetrics
dm
=
new
DisplayMetrics
();
@SuppressWarnings
(
"rawtypes"
)
Class
c
;
try
{
c
=
Class
.
forName
(
"android.view.Display"
);
@SuppressWarnings
(
"unchecked"
)
Method
method
=
c
.
getMethod
(
"getRealMetrics"
,
DisplayMetrics
.
class
);
method
.
invoke
(
display
,
dm
);
if
(
isScreenLandscape
())
{
dpi
=
dm
.
widthPixels
;
}
else
{
dpi
=
dm
.
heightPixels
;
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
if
(
dpi
==
0
)
{
if
(
isScreenLandscape
())
{
dpi
=
getScreenWidth
();
}
else
{
if
(
ImmersionBar
.
hasNotchScreen
((
Activity
)
mContext
))
{
dpi
=
getAvailableScreenHeight
()
+
getNotchHeight
()
+
getNavigationBarHeight
();
}
else
{
dpi
=
getAvailableScreenHeight
()
+
getStatusBarHeight
()
+
getNavigationBarHeight
();
}
}
}
return
dpi
;
}
/**
* 计算屏幕可用高度(此方法会受到软键盘 状态栏 底部导航栏的影响,不适合view自绘中调用,性能会有损耗)
* rect的top 是指 如果状态栏显示 则top值是状态栏高度 如果不显示则为0
* rect的bottom 是指 如果底部导航栏显示 bottom是屏幕的高度减去导航栏的高度 如果底部导航栏不显示 bottom的值是屏幕高度
*/
private
int
horizontalAvailableScreenHeight
,
verticalAvailableScreenHeight
;
private
int
getAvailableScreenHeight
()
{
if
(
isScreenLandscape
())
{
if
(
horizontalAvailableScreenHeight
==
0
)
{
Rect
rect
=
new
Rect
();
mWindow
.
getDecorView
().
getWindowVisibleDisplayFrame
(
rect
);
horizontalAvailableScreenHeight
=
rect
.
right
-
rect
.
left
;
}
return
horizontalAvailableScreenHeight
;
}
else
{
if
(
verticalAvailableScreenHeight
==
0
)
{
Rect
rect
=
new
Rect
();
mWindow
.
getDecorView
().
getWindowVisibleDisplayFrame
(
rect
);
verticalAvailableScreenHeight
=
rect
.
bottom
-
rect
.
top
;
}
return
verticalAvailableScreenHeight
;
}
}
/**
* 设置是否全屏
*/
// public void enableFullScreen(boolean enable) {
// if (ImmersionBar.hasNotchScreen((Activity) mContext)) {
// setStatusBarVisible(!enable);
// } else {
// if (enable) {
// ImmersionBar.with((Activity) mContext)
// .hideBar(BarHide.FLAG_HIDE_STATUS_BAR)
// .init();
// } else {
// ImmersionBar.with((Activity) mContext)
// .hideBar(BarHide.FLAG_SHOW_BAR)
// .init();
// }
// }
// }
/**
* 设置状态栏是否可见
*/
private
void
setStatusBarVisible
(
boolean
show
)
{
int
uiFlags
;
if
(
show
)
{
uiFlags
=
View
.
SYSTEM_UI_FLAG_LAYOUT_STABLE
;
uiFlags
|=
0x00001000
;
}
else
{
uiFlags
=
View
.
SYSTEM_UI_FLAG_LAYOUT_STABLE
|
View
.
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
View
.
SYSTEM_UI_FLAG_FULLSCREEN
;
uiFlags
|=
0x00001000
;
}
mWindow
.
getDecorView
().
setSystemUiVisibility
(
uiFlags
);
}
/**
* 获取导航栏虚拟按键的高度,如果虚拟按键隐藏就返回0,否则返回虚拟按键的高度
*/
public
int
getNavigationBarHeight
()
{
if
(
isNavigationBarShow
())
{
return
calculateNavigationBarHeight
();
}
else
{
mNavigationBarHeight
=
0
;
return
mNavigationBarHeight
;
}
}
/**
* 获取忽略导航栏隐藏来获取导航栏的高,即算导航栏显示时候的高
*/
public
int
getNavigationBarHeightIgnoreHide
()
{
if
(
mNavigationBarHeight
!=
0
)
{
return
mNavigationBarHeight
;
}
else
{
return
calculateNavigationBarHeight
();
}
}
/**
* 计算虚拟按键的高度
*/
private
int
calculateNavigationBarHeight
()
{
if
(
mNavigationBarHeight
==
0
)
{
try
{
Class
<?>
clazz
=
Class
.
forName
(
"com.android.internal.R$dimen"
);
Object
object
=
clazz
.
newInstance
();
int
height
=
Integer
.
parseInt
(
clazz
.
getField
(
"navigation_bar_height"
).
get
(
object
).
toString
());
mNavigationBarHeight
=
mContext
.
getResources
().
getDimensionPixelSize
(
height
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
if
(
mNavigationBarHeight
==
0
)
{
Resources
res
=
mContext
.
getResources
();
int
resourceId
=
res
.
getIdentifier
(
"navigation_bar_height"
,
"dimen"
,
"android"
);
if
(
resourceId
>
0
)
{
mNavigationBarHeight
=
res
.
getDimensionPixelSize
(
resourceId
);
}
}
if
(
mNavigationBarHeight
==
0
)
{
Rect
rect
=
new
Rect
();
mWindow
.
getDecorView
().
getWindowVisibleDisplayFrame
(
rect
);
Point
realSize
=
new
Point
();
mWindowManager
.
getDefaultDisplay
().
getRealSize
(
realSize
);
mNavigationBarHeight
=
realSize
.
y
-
rect
.
bottom
;
}
return
mNavigationBarHeight
;
}
/**
* 是否保持屏幕常亮
*
* @param enable true为保持常亮
*/
public
void
enableKeepScreenOn
(
boolean
enable
)
{
if
(
enable
)
{
mWindow
.
addFlags
(
WindowManager
.
LayoutParams
.
FLAG_KEEP_SCREEN_ON
);
}
else
{
mWindow
.
clearFlags
(
WindowManager
.
LayoutParams
.
FLAG_KEEP_SCREEN_ON
);
}
}
public
void
setNotchShowContent
(
boolean
isShow
)
{
setNotchShowContent
(
mWindow
,
isShow
);
}
/**
* 设置刘海区是否显示内容
*
* @param window 当前显示的window
* @param isShow 刘海区域是否显示内容,如果false即刘海区域变黑,不显示内容
*/
public
void
setNotchShowContent
(
Window
window
,
boolean
isShow
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
if
(
isShow
)
{
WindowManager
.
LayoutParams
lp
=
window
.
getAttributes
();
lp
.
layoutInDisplayCutoutMode
=
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
;
window
.
setAttributes
(
lp
);
}
else
{
WindowManager
.
LayoutParams
lp
=
window
.
getAttributes
();
lp
.
layoutInDisplayCutoutMode
=
WindowManager
.
LayoutParams
.
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
;
window
.
setAttributes
(
lp
);
}
}
}
/**
* 判断虚拟导航栏是否显示
*
* @return true(显示虚拟导航栏),false(不显示或不支持虚拟导航栏)
*/
private
boolean
isNavigationBarShow
()
{
//判断小米手机是否开启了全面屏,开启了,直接返回false
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
)
{
if
(
Settings
.
Global
.
getInt
(
mContext
.
getContentResolver
(),
"force_fsg_nav_bar"
,
0
)
!=
0
)
{
return
false
;
}
}
if
(
Build
.
VERSION
.
SDK_INT
==
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
||
isHUAWEIPhone
())
{
int
screenRealHeight
=
getRealScreenHeight
();
int
statusBarHeight
=
getStatusBarHeight
();
int
screenAvailableHeight
=
getAvailableScreenHeight
();
return
screenAvailableHeight
+
statusBarHeight
<
screenRealHeight
;
}
else
{
//其他手机根据屏幕真实高度与显示高度是否相同来判断
Display
d
=
mWindowManager
.
getDefaultDisplay
();
DisplayMetrics
realDisplayMetrics
=
new
DisplayMetrics
();
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
)
{
d
.
getRealMetrics
(
realDisplayMetrics
);
}
int
realHeight
=
realDisplayMetrics
.
heightPixels
;
int
realWidth
=
realDisplayMetrics
.
widthPixels
;
DisplayMetrics
displayMetrics
=
new
DisplayMetrics
();
d
.
getMetrics
(
displayMetrics
);
int
displayHeight
=
displayMetrics
.
heightPixels
;
int
displayWidth
=
displayMetrics
.
widthPixels
;
return
(
realWidth
-
displayWidth
)
>
0
||
(
realHeight
-
displayHeight
)
>
0
;
}
}
/**
* 判断手机是否使用了沉浸式
*
* @return true 表示使用了 false表示没使用
*/
public
boolean
canUseImmersive
()
{
return
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
M
;
}
/**
* 判断当前屏幕方向是否为横屏
*
* @param context 当前需要判断是否是横屏的Activity的Context
* @return true 横屏 false 竖屏
*/
public
boolean
isScreenLandscape
(
Context
context
)
{
Configuration
mConfiguration
=
context
.
getResources
().
getConfiguration
();
//获取设置的配置信息
int
ori
=
mConfiguration
.
orientation
;
//获取屏幕方向
return
ori
==
Configuration
.
ORIENTATION_LANDSCAPE
;
}
/**
* 判断当前屏幕横屏方向
*/
public
int
horizontalDirection
()
{
return
((
Activity
)
mContext
).
getWindowManager
().
getDefaultDisplay
().
getRotation
();
}
/**
* 判断当前屏幕方向是否为横屏,注意 此方法适用于关于MainActivity的横竖屏判断
*
* @return true 横屏 false 竖屏
*/
public
boolean
isScreenLandscape
()
{
return
isScreenLandscape
(
mContext
);
}
// public int getDimen10Px() {
// return mContext.getResources().getDimensionPixelOffset(R.dimen.nz_px_10);
// }
//
// public int getDimen20Px() {
// return mContext.getResources().getDimensionPixelOffset(R.dimen.nz_px_20);
// }
//
// //主页面底部抽拉菜单适配刘海屏
// public int getAdaptationLiuHaipingHeigh() {
// if (getLiuHaiping() == 0) {
// return mContext.getResources().getDimensionPixelSize(R.dimen.nz_px_56);
// }
// return getLiuHaiping();
// }
private
Drawable
mShadowDrawable
;
private
Rect
mDrawablePadding
;
public
Rect
getShadowBgRect
(
int
drawableResId
)
{
mShadowDrawable
=
mContext
.
getResources
().
getDrawable
(
drawableResId
);
mDrawablePadding
=
new
Rect
();
mShadowDrawable
.
getPadding
(
mDrawablePadding
);
return
mDrawablePadding
;
}
public
void
closeSoftInput
(
Context
context
,
EditText
et
){
InputMethodManager
imm
=
(
InputMethodManager
)
context
.
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
// 对于当前焦点的View
imm
.
hideSoftInputFromWindow
(
et
.
getWindowToken
(),
0
);
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/SystemUtils.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.utils
import
android.app.Activity
import
android.app.ActivityManager
import
android.content.*
import
android.content.pm.PackageManager
import
android.content.res.Resources
import
android.net.Uri
import
android.os.Build
import
android.os.PowerManager
import
android.provider.Settings
import
android.telephony.TelephonyManager
import
android.view.View
import
android.view.WindowManager
import
android.view.inputmethod.InputMethodManager
import
android.widget.EditText
import
androidx.annotation.RequiresPermission
import
androidx.core.content.ContextCompat
import
androidx.core.content.FileProvider
import
com.ltzw.adasdriver.utils.MobileUtils
import
java.io.File
object
SystemUtils
{
fun
getScreenWidth
():
Int
{
val
dm
=
Resources
.
getSystem
().
displayMetrics
return
dm
.
widthPixels
}
fun
getScreenHeight
():
Int
{
val
dm
=
Resources
.
getSystem
().
displayMetrics
return
dm
.
heightPixels
}
/**
* 调用系统打电话
*
* @param phone
*/
fun
callSystemTell
(
context
:
Context
,
phone
:
String
)
{
if
(!
phone
.
isNullOrEmpty
())
{
try
{
// var intent = Intent(Intent.ACTION_DIAL, phone.toUri())
var
intent
=
Intent
(
Intent
.
ACTION_DIAL
,
Uri
.
parse
(
"tel:$phone"
))
context
.
startActivity
(
intent
)
}
catch
(
e
:
ActivityNotFoundException
)
{
}
}
}
/**
* 获取当前应用程序的版本号
*/
fun
getAppVersionCode
(
context
:
Context
):
Int
{
var
version
=
0
try
{
version
=
context
.
packageManager
.
getPackageInfo
(
context
.
packageName
,
0
).
versionCode
}
catch
(
e
:
PackageManager
.
NameNotFoundException
)
{
throw
RuntimeException
(
context
.
javaClass
.
simpleName
+
"the application not found"
)
}
return
version
}
/**
* 获取当前应用程序的版本号
*/
fun
getAppVersionName
(
context
:
Context
):
String
{
var
version
=
"0"
try
{
version
=
context
.
packageManager
.
getPackageInfo
(
context
.
packageName
,
0
).
versionName
.
toString
()
}
catch
(
e
:
PackageManager
.
NameNotFoundException
)
{
throw
RuntimeException
(
"the application not found"
)
}
return
version
}
/**
* 关闭软键盘
*/
fun
closeKeyboard
(
view
:
View
,
context
:
Context
)
{
val
imm
=
ContextCompat
.
getSystemService
(
context
,
InputMethodManager
::
class
.
java
)
imm
?.
hideSoftInputFromWindow
(
view
.
windowToken
,
InputMethodManager
.
HIDE_NOT_ALWAYS
)
}
/**
* 打卡软键盘
*/
fun
showKeyboard
(
view
:
View
,
context
:
Context
)
{
view
.
isFocusable
=
true
view
.
requestFocus
()
val
imm
=
ContextCompat
.
getSystemService
(
context
,
InputMethodManager
::
class
.
java
)
imm
?.
showSoftInput
(
view
,
0
)
}
/**
* 适配华为安全键盘
*/
fun
etHuaWeiKeybroad
(
et
:
EditText
)
{
if
(
MobileUtils
.
isEMUI
()
&&
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
O_MR1
)
{
with
(
et
)
{
inputType
=
android
.
text
.
InputType
.
TYPE_CLASS_TEXT
or
android
.
text
.
InputType
.
TYPE_TEXT_VARIATION_NORMAL
transformationMethod
=
android
.
text
.
method
.
PasswordTransformationMethod
.
getInstance
()
}
}
}
fun
setStatusBarColor
(
activity
:
Activity
,
colorId
:
Int
)
{
val
window
=
activity
.
window
window
.
clearFlags
(
WindowManager
.
LayoutParams
.
FLAG_TRANSLUCENT_STATUS
)
window
.
addFlags
(
WindowManager
.
LayoutParams
.
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
)
window
.
statusBarColor
=
ContextCompat
.
getColor
(
activity
,
colorId
)
}
/**
* 通过上下文找到activity
*/
fun
findActivity
(
context
:
Context
):
Activity
?
{
if
(
context
is
Activity
)
{
return
context
}
return
if
(
context
is
ContextWrapper
)
{
val
wrapper
=
context
as
ContextWrapper
findActivity
(
wrapper
.
baseContext
)
}
else
{
null
}
}
@RequiresPermission
(
"android.permission.READ_PRIVILEGED_PHONE_STATE"
)
fun
getPhoneIMEI
(
context
:
Context
):
String
?
{
val
tm
=
ContextCompat
.
getSystemService
(
context
,
TelephonyManager
::
class
.
java
)
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
O
)
{
return
tm
?.
deviceId
}
else
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
Q
)
{
return
tm
?.
getImei
(
0
)
}
else
{
return
Settings
.
System
.
getString
(
context
.
contentResolver
,
Settings
.
Secure
.
ANDROID_ID
)
}
}
/**
* 复制文字到剪切板
*/
fun
copyTextClip
(
context
:
Context
,
text
:
String
)
{
// 得到剪贴板管理器
val
cmb
=
ContextCompat
.
getSystemService
(
context
,
ClipboardManager
::
class
.
java
)
var
clipData
=
ClipData
.
newPlainText
(
""
,
text
)
cmb
?.
setPrimaryClip
(
clipData
)
}
fun
exitApp
(
context
:
Context
)
{
// val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val
activityManager
=
ContextCompat
.
getSystemService
(
context
,
ActivityManager
::
class
.
java
)
val
appTaskList
=
activityManager
?.
appTasks
if
(
appTaskList
!=
null
)
{
for
(
appTask
in
appTaskList
)
{
appTask
.
finishAndRemoveTask
()
}
}
}
fun
openThridUrl
(
url
:
String
,
context
:
Context
)
{
var
myurl
=
url
if
(!
url
.
startsWith
(
"http://"
)
&&
!
url
.
startsWith
(
"https://"
))
{
myurl
=
"http://$url"
}
try
{
val
uri
=
Uri
.
parse
(
myurl
)
val
intent
=
Intent
(
Intent
.
ACTION_VIEW
,
uri
)
context
.
startActivity
(
intent
)
}
catch
(
e
:
ActivityNotFoundException
)
{
// LogUtil.e("--------", "没找到Activity url=$url")
}
}
//android获取一个用于打开HTML文件的intent
fun
openHtmlFileIntent
(
urlParam
:
String
,
context
:
Context
)
{
val
intent
=
Intent
(
"android.intent.action.VIEW"
)
intent
.
addCategory
(
"android.intent.category.DEFAULT"
)
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
// val uri = Uri.fromFile(File(urlParam))
var
file
=
File
(
urlParam
)
var
uri
:
Uri
?
if
(
Build
.
VERSION
.
SDK_INT
>=
24
)
{
intent
.
addFlags
(
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
)
uri
=
FileProvider
.
getUriForFile
(
context
,
"com.zhaolaobao.fileProvider"
,
file
)
}
else
{
uri
=
Uri
.
fromFile
(
file
)
}
var
type
=
""
/* 取得扩展名 */
var
suffix
=
urlParam
.
substringAfterLast
(
"."
).
toLowerCase
()
println
(
"----url 后缀 = ${suffix}"
)
when
(
suffix
)
{
"pdf"
->
type
=
"application/pdf"
"ppt"
,
"pptx"
->
type
=
"application/vnd.ms-powerpoint"
// "pptx" -> type =
// "application/vnd.openxmlformats-officedocument.presentationml.presentation"
"doc"
->
type
=
"application/msword"
"docx"
->
type
=
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
"xls"
,
"xlsx"
->
type
=
"application/vnd.ms-excel"
"txt"
->
type
=
"text/plain"
else
->
type
=
"*/*"
}
intent
.
setDataAndType
(
uri
,
type
)
try
{
context
.
startActivity
(
intent
)
}
catch
(
e
:
ActivityNotFoundException
)
{
ToastHelper
.
showShort
(
context
,
"不支持打开"
)
}
}
/**
*跳转到应用外部打开
*/
fun
openFile
(
file
:
File
,
context
:
Context
)
{
var
intent
=
Intent
(
Intent
.
ACTION_VIEW
)
intent
.
addCategory
(
"android.intent.category.DEFAULT"
)
var
uri
:
Uri
?
if
(
Build
.
VERSION
.
SDK_INT
>=
24
)
{
intent
.
addFlags
(
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
)
uri
=
FileProvider
.
getUriForFile
(
context
,
"com.zhaolaobao.fileProvider"
,
file
)
}
else
{
uri
=
Uri
.
fromFile
(
file
)
}
var
type
=
""
/* 取得扩展名 */
var
end
=
file
.
name
.
substringAfterLast
(
"."
).
toLowerCase
()
when
(
end
)
{
"pdf"
->
type
=
"application/pdf"
"ppt"
->
type
=
"application/vnd.ms-powerpoint"
"pptx"
->
type
=
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
"doc"
->
type
=
"application/msword"
"docx"
->
type
=
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
"xls"
->
type
=
"application/vnd.ms-excel"
"xlsx"
->
type
=
"application/vnd.ms-excel"
"txt"
->
type
=
"text/plain"
else
->
type
=
"*/*"
}
intent
.
setDataAndType
(
uri
,
type
)
try
{
context
.
startActivity
(
intent
)
}
catch
(
e
:
ActivityNotFoundException
)
{
// context.toast("不支持打开")
}
}
/**
* 登录超时
*/
fun
timeOutLoginActivity
(
context
:
Context
)
{
context
.
startActivity
(
Intent
().
apply
{
// flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
action
=
"goLoginActivity"
putExtra
(
"is_login_timeout"
,
true
)
})
}
/**
* 账户禁用
*/
fun
accountDisLoginActivity
(
context
:
Context
)
{
context
.
startActivity
(
Intent
().
apply
{
flags
=
Intent
.
FLAG_ACTIVITY_NEW_TASK
or
Intent
.
FLAG_ACTIVITY_CLEAR_TASK
action
=
"goLoginActivity"
putExtra
(
"is_login_timeout"
,
false
)
})
}
/**
* 应用是否在电池白名单里
*/
fun
isIgnoringBatteryOptimizations
(
context
:
Context
):
Boolean
{
var
isIgnoring
=
false
val
powerManager
=
ContextCompat
.
getSystemService
(
context
,
PowerManager
::
class
.
java
)
if
(
powerManager
!=
null
)
{
isIgnoring
=
powerManager
.
isIgnoringBatteryOptimizations
(
context
.
packageName
)
}
return
isIgnoring
}
}
\ No newline at end of file
app/src/main/java/com/sd/cavphmi/utils/ToastHelper.kt
0 → 100644
View file @
1ccbc004
package
com.sd.cavphmi.utils
import
android.content.Context
import
android.text.SpannableString
import
android.view.Gravity
import
android.view.LayoutInflater
import
android.widget.TextView
import
android.widget.Toast
/**
*author:pc-20171125
*data:2019/11/8 11:18
*/
object
ToastHelper
{
/**
* 短时间显示Toast
*/
fun
showShort
(
context
:
Context
,
message
:
String
)
{
Toast
.
makeText
(
context
,
message
,
Toast
.
LENGTH_SHORT
).
run
{
show
()
}
}
// /**
// * 短时间显示Toast
// */
// fun showShort(context: Context, message: String) {
// Toast.makeText(context, message, Toast.LENGTH_SHORT).run {
// setGravity(Gravity.CENTER, 0, 0)
// show()
// }
// }
// /**
// * 短时间显示Toast
// *
// * @param message
// */
// fun showShort(message: Int) {
// if (isShow)
// Toast.makeText(BaseApp.context, message, Toast.LENGTH_SHORT).show()
// }
// /**
// * 长时间显示Toast
// *
// * @param message
// */
// fun showLong(message: CharSequence) {
// if (isShow)
// Toast.makeText(BaseApp.context, message, Toast.LENGTH_LONG).show()
// }
}
app/src/main/java/com/sd/cavphmi/utils/Utils.java
0 → 100644
View file @
1ccbc004
/*********************************************************************************************************************************
* NaviCore Corporate MIT License 0.1
* Copyright (c) 2019 GIS Core R&D Department, NavInfo Corp.
*
* Permission is hereby granted, free of charge, to any entity within the corporation(Entity) obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction, including without
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit Entities to whom the Software is furnished to do so, subject to the following conditions:
*
* 1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. and
* 2. The above copyright notice, this permission notice and the acknowledgments below shall be displayed in UI or web pages
* if the Software is redistributed in binary form or as web service.
*
* Acknowledgments: "This work uses NaviZeroAndroid provided by GIS Core R&D Department, NavInfo Corp."
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* You may also get a copy of the license at http://navicore.cn/license/NC_MIT_0.1
**********************************************************************************************************************************/
package
com.sd.cavphmi.utils
;
import
android.annotation.TargetApi
;
import
android.app.Activity
;
import
android.app.ActivityManager
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.IntentFilter
;
import
android.content.pm.ActivityInfo
;
import
android.content.pm.PackageInfo
;
import
android.content.pm.PackageManager
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Paint
;
import
android.graphics.Point
;
import
android.graphics.PorterDuff
;
import
android.graphics.PorterDuffXfermode
;
import
android.media.AudioManager
;
import
android.os.BatteryManager
;
import
android.os.Build
;
import
android.os.CountDownTimer
;
import
android.os.Handler
;
import
android.os.StatFs
;
import
android.text.TextUtils
;
import
android.util.Base64
;
import
android.view.View
;
import
android.view.animation.AlphaAnimation
;
import
android.view.animation.Animation
;
import
android.view.animation.AnimationSet
;
import
android.view.animation.TranslateAnimation
;
import
android.view.inputmethod.InputMethodManager
;
import
android.widget.EditText
;
import
android.widget.Toast
;
import
com.minedata.minenavi.SDKInitializer
;
import
com.minedata.minenavi.addons.DistanceBean
;
import
com.minedata.minenavi.addons.TimeBean
;
import
com.minedata.minenavi.map.MineMap
;
import
com.minedata.minenavi.mapdal.DistanceStringInfo
;
import
com.minedata.minenavi.mapdal.NativeEnv
;
import
com.minedata.minenavi.util.MineNaviUtil
;
import
java.io.BufferedReader
;
import
java.io.FileReader
;
import
java.security.MessageDigest
;
import
java.text.ParseException
;
import
java.text.SimpleDateFormat
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Random
;
import
java.util.Timer
;
import
java.util.TimerTask
;
public
class
Utils
{
private
Context
mContext
;
private
AudioManager
mAudioManager
;
private
PackageManager
mPackageManager
;
private
float
mDpiFactor
=
2.0f
;
private
boolean
mIsInited
=
false
;
private
Timer
mTimer
;
private
Context
mApplicationContext
;
private
CountDownTimer
mCountDownTimer
;
private
static
class
SingletonHolder
{
public
static
final
Utils
instance
=
new
Utils
();
}
public
static
Utils
getInstance
()
{
return
SingletonHolder
.
instance
;
}
public
void
init
(
Context
context
)
{
if
(
mIsInited
)
{
return
;
}
mContext
=
context
;
mApplicationContext
=
context
.
getApplicationContext
();
mTimer
=
new
Timer
();
mAudioManager
=
(
AudioManager
)
mContext
.
getSystemService
(
Context
.
AUDIO_SERVICE
);
mPackageManager
=
mContext
.
getPackageManager
();
mDpiFactor
=
context
.
getResources
().
getDisplayMetrics
().
density
;
mIsInited
=
true
;
}
/**
* 获取当前音量值
*/
public
int
getCurrentVolume
()
{
return
mAudioManager
.
getStreamVolume
(
AudioManager
.
STREAM_MUSIC
);
}
/**
* 获取音量最大值
*/
public
int
getMaxVolume
()
{
return
mAudioManager
.
getStreamMaxVolume
(
AudioManager
.
STREAM_MUSIC
);
}
/**
* 设置当前的音量
*/
public
void
setVolume
(
int
volumeValue
)
{
mAudioManager
.
setStreamVolume
(
AudioManager
.
STREAM_MUSIC
,
volumeValue
,
AudioManager
.
FLAG_PLAY_SOUND
);
//设置值为Val
}
/**
* APP是否处于前台
*/
public
boolean
isAppOnForeground
()
{
ActivityManager
activityManager
=
(
ActivityManager
)
mContext
.
getApplicationContext
().
getSystemService
(
Context
.
ACTIVITY_SERVICE
);
String
packageName
=
mContext
.
getApplicationContext
().
getPackageName
();
List
<
ActivityManager
.
RunningAppProcessInfo
>
appProcesses
=
activityManager
.
getRunningAppProcesses
();
if
(
appProcesses
==
null
)
return
false
;
for
(
ActivityManager
.
RunningAppProcessInfo
appProcess
:
appProcesses
)
{
if
(
appProcess
.
processName
.
equals
(
packageName
)
&&
appProcess
.
importance
==
ActivityManager
.
RunningAppProcessInfo
.
IMPORTANCE_FOREGROUND
)
{
return
true
;
}
}
return
false
;
}
/**
* 判断设备是否正在充电
*/
public
boolean
isCharging
()
{
IntentFilter
ifilter
=
new
IntentFilter
(
Intent
.
ACTION_BATTERY_CHANGED
);
Intent
batteryStatus
=
mContext
.
registerReceiver
(
null
,
ifilter
);
int
status
=
batteryStatus
.
getIntExtra
(
BatteryManager
.
EXTRA_STATUS
,
-
1
);
boolean
isCharging
=
status
==
BatteryManager
.
BATTERY_STATUS_CHARGING
||
status
==
BatteryManager
.
BATTERY_STATUS_FULL
;
return
isCharging
;
}
/**
* 获取屏幕的高,如果横屏的话,返回的高就是屏幕的宽,如果是竖屏的话,返回的高就是屏幕的高,获取的高是从状态栏到导航栏整体的高
*
* @param activity 当前的activity
* @return 屏幕的高
*/
@TargetApi
(
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
)
public
int
getWindowHeight
(
Activity
activity
)
{
Point
realSize
=
new
Point
();
activity
.
getWindowManager
().
getDefaultDisplay
().
getRealSize
(
realSize
);
return
realSize
.
y
;
}
/**
* 获取屏幕的高,如果横屏的话,返回的高就是屏幕的宽,如果是竖屏的话,返回的高就是屏幕的高,获取的高是从状态栏到导航栏整体的高
*
* @param activity 当前的activity
* @return 屏幕的高
*/
@TargetApi
(
Build
.
VERSION_CODES
.
JELLY_BEAN_MR1
)
public
int
getWindowWidth
(
Activity
activity
)
{
Point
realSize
=
new
Point
();
activity
.
getWindowManager
().
getDefaultDisplay
().
getRealSize
(
realSize
);
return
realSize
.
x
;
}
/**
* 平移动画
*/
private
TranslateAnimation
mTranslateAnimation
;
public
void
translateAnimation
(
View
view
,
float
fromX
,
float
toX
,
float
fromY
,
float
toY
,
long
duration
,
Animation
.
AnimationListener
animationListener
,
boolean
isFillAfter
)
{
mTranslateAnimation
=
new
TranslateAnimation
(
Animation
.
RELATIVE_TO_SELF
,
fromX
,
Animation
.
RELATIVE_TO_SELF
,
toX
,
Animation
.
RELATIVE_TO_SELF
,
fromY
,
Animation
.
RELATIVE_TO_SELF
,
toY
);
mTranslateAnimation
.
setDuration
(
duration
);
mTranslateAnimation
.
setFillAfter
(
isFillAfter
);
if
(
animationListener
!=
null
)
{
mTranslateAnimation
.
setAnimationListener
(
animationListener
);
}
view
.
startAnimation
(
mTranslateAnimation
);
}
/**
* 混合动画动画
*/
public
void
translateAnimationWithAbsolute
(
View
view
,
float
fromAlpha
,
float
toAlpha
,
long
alaphDuration
,
long
startTime
,
float
fromX
,
float
toX
,
float
fromY
,
float
toY
,
long
translateDuration
,
long
animationSetDuration
,
Animation
.
AnimationListener
animationListener
,
boolean
isFillAfter
)
{
//途径点1——————————添加文字移动平移动画 333
AnimationSet
animationSet
=
new
AnimationSet
(
true
);
AlphaAnimation
animationa
=
new
AlphaAnimation
(
fromAlpha
,
toAlpha
);
animationa
.
setDuration
(
alaphDuration
);
animationa
.
setStartTime
(
startTime
);
animationSet
.
addAnimation
(
animationa
);
TranslateAnimation
translateAnimation
=
new
TranslateAnimation
(
Animation
.
ABSOLUTE
,
fromX
,
Animation
.
ABSOLUTE
,
toX
,
Animation
.
ABSOLUTE
,
fromY
,
Animation
.
ABSOLUTE
,
toY
);
translateAnimation
.
setDuration
(
translateDuration
);
animationSet
.
addAnimation
(
translateAnimation
);
animationSet
.
setDuration
(
animationSetDuration
);
animationSet
.
setAnimationListener
(
animationListener
);
animationSet
.
setFillAfter
(
isFillAfter
);
view
.
startAnimation
(
animationSet
);
}
public
boolean
isTranslateAnimationHasEnded
()
{
if
(
mTranslateAnimation
==
null
)
{
return
true
;
}
return
mTranslateAnimation
.
hasEnded
();
}
/**
* 地图是否是2d模式
*/
public
final
boolean
isMap2dStyle
(
MineMap
mineMap
)
{
return
mineMap
.
getElevation
()
==
90
;
}
/**
* 地图是否是3d模式
*/
public
final
boolean
isMap3dStyle
(
MineMap
mineMap
)
{
return
mineMap
.
getElevation
()
!=
90
;
}
/**
* 延时操作
*
* @param runnable
* @param delayed
*/
private
Handler
delayedViewOperateHandler
=
new
Handler
();
public
void
doDelayedViewOperate
(
Runnable
runnable
,
long
delayed
)
{
delayedViewOperateHandler
.
postDelayed
(
runnable
,
delayed
);
}
public
Handler
getDelayedViewOperateHandler
()
{
return
delayedViewOperateHandler
;
}
public
void
cleanup
()
{
if
(
mTimer
!=
null
)
{
mTimer
.
cancel
();
mTimer
=
null
;
}
}
/**
* 秒转换成分钟,向上取整
*
* @param secondTime 秒
* @return 取整后的分钟
*/
public
final
int
second2Minute
(
int
secondTime
)
{
return
(
secondTime
+
59
)
/
60
;
}
/**
* 将以秒为单位的时间格式化
*
* @param secondTime 秒
* @return 得到格式化的时间
*/
public
String
formatTime
(
int
secondTime
)
{
String
sTotalTime
;
int
minutes
=
second2Minute
(
secondTime
);
if
(
minutes
<
60
)
{
sTotalTime
=
minutes
+
"分钟"
;
}
else
{
int
remainMin
=
minutes
%
60
;
sTotalTime
=
minutes
/
60
+
"小时"
+
(
remainMin
==
0
?
""
:
remainMin
+
"分"
);
}
return
sTotalTime
;
}
/**
* 格式化到千米,如果距离不小于100km或整千米,保留整数;否则保留小数点后一位,比如 110000 -> 110,8000 -> 8, 8001 -> 8, 800 -> 0.8, 99 -> 0
*
* @param distance 距离,单位:米
* @return 格式化后以千米表示的结果,不包含单位
*/
public
String
formatDistanceToKm
(
int
distance
)
{
String
distanceValue
;
if
(
distance
>=
100000
||
distance
%
1000
==
0
)
{
distanceValue
=
String
.
valueOf
(
distance
/
1000
);
}
else
{
distanceValue
=
String
.
format
(
Locale
.
getDefault
(),
"%.1f"
,
(
distance
/
100
)
/
10.0
);
}
return
distanceValue
;
}
public
DistanceBean
formatDistance
(
int
distance
,
boolean
isEnglishDistanceUnit
)
{
DistanceStringInfo
distanceStringInfo
=
MineNaviUtil
.
distance2String
(
distance
,
isEnglishDistanceUnit
?
MineNaviUtil
.
DistanceUnit
.
english
:
MineNaviUtil
.
DistanceUnit
.
normal
,
false
);
String
distanceValue
=
""
;
String
distanceUnit
=
""
;
switch
(
distanceStringInfo
.
unit
)
{
case
MineNaviUtil
.
GisUnit
.
m
:
distanceUnit
=
isEnglishDistanceUnit
?
"m"
:
"米"
;
break
;
case
MineNaviUtil
.
GisUnit
.
km
:
distanceUnit
=
isEnglishDistanceUnit
?
"km"
:
"公里"
;
break
;
case
MineNaviUtil
.
GisUnit
.
mi
:
distanceUnit
=
isEnglishDistanceUnit
?
"mile"
:
"英里"
;
break
;
case
MineNaviUtil
.
GisUnit
.
ft
:
distanceUnit
=
isEnglishDistanceUnit
?
"ft"
:
"英尺"
;
break
;
}
distanceValue
=
distanceStringInfo
.
distanceString
.
split
(
distanceUnit
)[
0
];
return
new
DistanceBean
(
distanceValue
,
distanceUnit
);
}
public
TimeBean
calcTimeBean
(
int
time
)
{
int
totalMinute
=
(
time
+
59
)
/
60
;
int
timeHour
=
totalMinute
/
60
;
int
timeMinute
=
totalMinute
%
60
;
return
new
TimeBean
(
timeHour
,
timeMinute
);
}
/**
* 弹出/隐藏键盘
*/
public
void
enableInputMethod
(
boolean
enable
,
EditText
editText
)
{
InputMethodManager
inputManager
=
(
InputMethodManager
)
mContext
.
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
if
(
enable
)
{
//弹出键盘
inputManager
.
toggleSoftInput
(
0
,
InputMethodManager
.
HIDE_NOT_ALWAYS
);
}
else
{
//隐藏键盘
inputManager
.
hideSoftInputFromWindow
(
editText
.
getWindowToken
(),
0
);
}
}
/**
* 弹出/隐藏键盘 : 防止焦点丢失
*/
public
void
enableInputMethodWithFocus
(
boolean
enable
,
EditText
editText
)
{
InputMethodManager
inputManager
=
(
InputMethodManager
)
mContext
.
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
editText
.
setFocusable
(
enable
);
editText
.
setFocusableInTouchMode
(
enable
);
editText
.
requestFocus
();
if
(
enable
)
{
//弹出键盘
editText
.
requestFocus
();
inputManager
.
showSoftInput
(
editText
,
0
);
}
else
{
//隐藏键盘
inputManager
.
hideSoftInputFromWindow
(
editText
.
getWindowToken
(),
0
);
}
}
/**
* 光标移到文字后
*/
public
void
setSelectionEnd
(
EditText
editText
)
{
if
(
editText
!=
null
)
{
String
b
=
editText
.
getText
().
toString
();
editText
.
setSelection
(
b
.
length
());
}
}
/**
* 无焦点情况下隐藏键盘
*/
public
void
hideKeyboard
(
Context
context
)
{
Activity
activity
=
(
Activity
)
context
;
InputMethodManager
imm
=
(
InputMethodManager
)
mContext
.
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
View
v
=
activity
.
getWindow
().
peekDecorView
();
if
(
null
!=
v
)
{
imm
.
hideSoftInputFromWindow
(
v
.
getWindowToken
(),
0
);
}
}
public
String
getStrDistance
(
Point
point1
,
Point
point2
)
{
int
distance
=
MineNaviUtil
.
distance
(
point1
,
point2
);
return
MineNaviUtil
.
distance2String
(
distance
,
MineNaviUtil
.
DistanceUnit
.
normal
,
false
).
distanceString
;
}
public
int
dp2Px
(
float
dp
)
{
return
(
int
)
(
dp
*
mDpiFactor
+
0.5f
);
}
public
int
px2Dp
(
int
px
)
{
return
(
int
)
(
px
/
mDpiFactor
+
0.5f
);
}
/**
* 判断系统当前是24小时制还是 12小时制
*/
public
boolean
is24Hour
()
{
return
android
.
text
.
format
.
DateFormat
.
is24HourFormat
(
mContext
);
}
/**
* 将流量大小(B)格式化为显示文本,规则如下:<br>
* 1. 小于1K时,显示xxB,例如2B<br>
* 2. 小于1M时,显示xxKB,例如250KB<br>
* 3. 小于1G时,显示xxMB,例如250MB<br>
* 4. 不小于1G时,显示xx.xGB,例如1.0GB, 10.5GB
*
* @param size 流量大小,单位:字节
*/
public
String
formatTrafficDataSize
(
long
size
)
{
if
(
size
<
1024
)
{
return
size
+
"B"
;
}
else
if
(
size
<
1024
*
1024
)
{
return
size
/
1024
+
"KB"
;
}
else
if
(
size
<
10
*
1024
*
1024
)
{
return
String
.
format
(
"%.1fM"
,
size
/
(
1024.0
*
1024
));
}
else
if
(
size
<
1024L
*
1024
*
1024
)
{
return
size
/
(
1024
*
1024
)
+
"MB"
;
}
else
{
return
String
.
format
(
"%.1fGB"
,
size
/
(
1024.0
*
1024
*
1024
));
}
}
/**
* 获取版本号名字
*/
public
String
getVerName
()
{
String
verName
=
""
;
try
{
verName
=
mPackageManager
.
getPackageInfo
(
mApplicationContext
.
getPackageName
(),
0
).
versionName
;
}
catch
(
PackageManager
.
NameNotFoundException
e
)
{
e
.
printStackTrace
();
}
return
verName
;
}
/**
* 获取版本号
*/
public
int
getVersionCode
()
{
int
versionCode
=
0
;
try
{
versionCode
=
mPackageManager
.
getPackageInfo
(
mApplicationContext
.
getPackageName
(),
0
).
versionCode
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
versionCode
;
}
/**
* 获取app名字
*/
public
String
getAppName
()
{
String
appName
=
""
;
try
{
PackageInfo
packageInfo
=
mPackageManager
.
getPackageInfo
(
mApplicationContext
.
getPackageName
(),
0
);
appName
=
packageInfo
.
applicationInfo
.
loadLabel
(
mPackageManager
).
toString
();
}
catch
(
PackageManager
.
NameNotFoundException
e
)
{
e
.
printStackTrace
();
}
return
appName
;
}
/**
* 全角转半角
*
* @return 半角字符串
*/
public
String
toDBC
(
String
input
)
{
char
c
[]
=
input
.
toCharArray
();
for
(
int
i
=
0
;
i
<
c
.
length
;
i
++)
{
if
(
c
[
i
]
==
'\u3000'
)
{
c
[
i
]
=
' '
;
}
else
if
(
c
[
i
]
>
'\
uFF00
'
&&
c
[
i
]
<
'\
uFF5F
'
)
{
c
[
i
]
=
(
char
)
(
c
[
i
]
-
65248
);
}
}
return
new
String
(
c
);
}
/**
* 系统Toast
*/
public
void
showToast
(
Context
context
,
String
msg
)
{
Toast
toast
=
Toast
.
makeText
(
context
,
msg
,
Toast
.
LENGTH_SHORT
);
toast
.
setText
(
msg
);
toast
.
show
();
}
public
void
scheduleTimerTask
(
TimerTask
timerTask
,
long
time
)
{
if
(
mTimer
!=
null
&&
timerTask
!=
null
)
{
mTimer
.
schedule
(
timerTask
,
time
);
}
}
/**
* 软件运行环境是否是手机
*
* @return
*/
public
boolean
isMobilePhone
()
{
try
{
if
(
ScreenUtil
.
getInstance
().
isScreenLandscape
()
&&
getTotalRam
(
mContext
)
<=
2.0f
&&
getSdcardAvailableSize
(
SDKInitializer
.
getAppPath
())
<
(
25L
*
1024
*
1024
*
1024
))
{
return
false
;
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
true
;
}
/**
* 根据包名获取当前数据存储的路径后缀
*/
public
String
getCurrentStoragePathSuffix
()
{
String
suffix
=
""
;
if
(
isTestVersion
())
{
suffix
=
"/mapbar/NaviZero"
;
}
else
if
(
isReleaseVersion
())
{
suffix
=
"/mapbar/NaviZeroRelease"
;
}
return
suffix
;
}
public
boolean
isTestVersion
()
{
String
packageName
=
mContext
.
getPackageName
();
return
TextUtils
.
equals
(
"com.mapbar.navigation.zero"
,
packageName
);
}
public
boolean
isReleaseVersion
()
{
String
packageName
=
mContext
.
getPackageName
();
return
TextUtils
.
equals
(
"com.mapbar.navigation.zero.release"
,
packageName
);
}
public
String
getLoginAppName
()
{
return
isTestVersion
()
?
"naviZeroBeta"
:
"naviZeroRelease"
;
}
/**
* 获取SD卡大小
*
* @param sdcardPath
* @return
*/
public
long
getSdcardAvailableSize
(
String
sdcardPath
)
{
long
size
=
0
;
StatFs
statFs
=
new
StatFs
(
sdcardPath
);
int
blockSize
=
statFs
.
getBlockSize
();
int
totalBlocks
=
statFs
.
getBlockCount
();
size
=
(
long
)
totalBlocks
*
blockSize
;
return
size
;
}
public
float
getTotalRam
(
Context
context
)
{
String
path
=
"/proc/meminfo"
;
String
firstLine
=
null
;
float
totalRam
=
0
;
try
{
FileReader
fileReader
=
new
FileReader
(
path
);
BufferedReader
br
=
new
BufferedReader
(
fileReader
,
8192
);
firstLine
=
br
.
readLine
().
split
(
"\\s+"
)[
1
];
br
.
close
();
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
if
(
firstLine
!=
null
)
{
totalRam
=
Float
.
valueOf
(
firstLine
)
/
(
1024
*
1024
);
}
return
totalRam
;
}
public
Bitmap
createCircleBitmap
(
Bitmap
resource
)
{
//获取图片的宽度
int
width
=
resource
.
getWidth
();
Paint
paint
=
new
Paint
();
//设置抗锯齿
paint
.
setAntiAlias
(
true
);
//创建一个与原bitmap一样宽度的正方形bitmap
Bitmap
circleBitmap
=
Bitmap
.
createBitmap
(
width
,
width
,
Bitmap
.
Config
.
ARGB_8888
);
//以该bitmap为低创建一块画布
Canvas
canvas
=
new
Canvas
(
circleBitmap
);
//以(width/2, width/2)为圆心,width/2为半径画一个圆
canvas
.
drawCircle
(
width
/
2
,
width
/
2
,
width
/
2
,
paint
);
//设置画笔为取交集模式
paint
.
setXfermode
(
new
PorterDuffXfermode
(
PorterDuff
.
Mode
.
SRC_IN
));
//裁剪图片
canvas
.
drawBitmap
(
resource
,
0
,
0
,
paint
);
return
circleBitmap
;
}
private
SimpleDateFormat
mSimpleDateFormat
;
/**
* local时间转换成UTC时间
*
* @param date 时间格式 例: 2019-5-21 14:12:38
* @return 返回格式化好的时间 例: 2019-5-21 22:12:38
*/
public
String
formatLocalDate
(
String
date
)
{
if
(
mSimpleDateFormat
==
null
)
{
mSimpleDateFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
}
Date
localDate
=
null
;
try
{
localDate
=
mSimpleDateFormat
.
parse
(
date
);
}
catch
(
ParseException
e
)
{
e
.
printStackTrace
();
}
long
localTimeInMillis
=
localDate
.
getTime
()
+
60
*
60
*
8
*
1000
;
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
setTimeInMillis
(
localTimeInMillis
);
return
mSimpleDateFormat
.
format
(
calendar
.
getTime
());
}
/**
* /**
* 使用SHA1算法对字符串进行加密
*
* @param str 要签名的字符串
* @return SHA1 签名后的内容
*/
public
static
String
sha1Digest
(
String
str
)
{
if
(
str
==
null
||
str
.
length
()
==
0
)
{
return
null
;
}
char
hexDigits
[]
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
};
try
{
MessageDigest
mdTemp
=
MessageDigest
.
getInstance
(
"SHA1"
);
mdTemp
.
update
(
str
.
getBytes
(
"UTF-8"
));
byte
[]
md
=
mdTemp
.
digest
();
int
j
=
md
.
length
;
char
buf
[]
=
new
char
[
j
*
2
];
int
k
=
0
;
for
(
int
i
=
0
;
i
<
j
;
i
++)
{
byte
byte0
=
md
[
i
];
buf
[
k
++]
=
hexDigits
[
byte0
>>>
4
&
0xf
];
buf
[
k
++]
=
hexDigits
[
byte0
&
0xf
];
}
return
new
String
(
buf
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
/**
* 随机字符串
*
* @return 随机字符串
*/
public
static
String
randomString
()
{
String
str
=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
;
Random
random
=
new
Random
();
StringBuffer
sb
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
int
number
=
random
.
nextInt
(
str
.
length
());
char
charAt
=
str
.
charAt
(
number
);
sb
.
append
(
charAt
);
}
return
sb
.
toString
();
}
/**
* 开启横竖屏模式
*
* @param activity 需要开启横竖屏的activity
* @param isOpen 是否打开
*/
public
void
enableHorizontalAndVerticalScreenMode
(
Activity
activity
,
boolean
isOpen
)
{
activity
.
setRequestedOrientation
(
isOpen
?
ActivityInfo
.
SCREEN_ORIENTATION_UNSPECIFIED
:
ActivityInfo
.
SCREEN_ORIENTATION_PORTRAIT
);
}
/**
* 开启横竖屏模式
*
* @param isOpen 是否打开
*/
public
void
enableHorizontalAndVerticalScreenMode
(
boolean
isOpen
)
{
enableHorizontalAndVerticalScreenMode
((
Activity
)
mContext
,
isOpen
);
}
/**
* 是否有网络连接
*
* @return
*/
public
boolean
isHaveNetwork
()
{
int
netWorkState
=
NativeEnv
.
getNetworkStatus
(
mContext
);
if
(
netWorkState
==
NativeEnv
.
NetworkStatus
.
unavailable
)
{
return
false
;
}
return
true
;
}
public
boolean
isNumber
(
String
str
)
{
for
(
int
i
=
str
.
length
();
--
i
>=
0
;
)
{
int
chr
=
str
.
charAt
(
i
);
if
(
chr
<
48
||
chr
>
57
)
return
false
;
}
return
true
;
}
/***
* MD5加密
*/
public
static
String
string2MD5
(
String
inStr
)
{
MessageDigest
md5
=
null
;
try
{
md5
=
MessageDigest
.
getInstance
(
"MD5"
);
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
e
.
toString
());
e
.
printStackTrace
();
return
""
;
}
byte
[]
md5Bytes
=
md5
.
digest
(
inStr
.
getBytes
());
StringBuffer
hexValue
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
md5Bytes
.
length
;
i
++)
{
int
val
=
((
int
)
md5Bytes
[
i
])
&
0xff
;
if
(
val
<
16
)
hexValue
.
append
(
"0"
);
hexValue
.
append
(
Integer
.
toHexString
(
val
));
}
return
hexValue
.
toString
().
toUpperCase
();
}
public
static
String
base64
(
String
str
)
{
return
Base64
.
encodeToString
(
str
.
getBytes
(),
Base64
.
DEFAULT
);
}
public
static
String
location2String
(
Point
pt
)
{
return
String
.
format
(
"%.5f,%.5f"
,
pt
.
x
/
100000.0
,
pt
.
y
/
100000.0
);
}
public
static
Point
string2Location
(
String
str
)
{
try
{
String
[]
parts
=
str
.
split
(
","
);
return
new
Point
((
int
)
(
Float
.
valueOf
(
parts
[
0
])
*
100000
),
(
int
)
(
Float
.
valueOf
(
parts
[
1
])
*
100000
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
}
app/src/main/res/drawable-xhdpi/angle.png
0 → 100644
View file @
1ccbc004
2.38 KB
app/src/main/res/drawable-xhdpi/drive_mode.png
0 → 100644
View file @
1ccbc004
2.87 KB
app/src/main/res/drawable-xhdpi/speed.png
0 → 100644
View file @
1ccbc004
20.8 KB
app/src/main/res/drawable-xhdpi/stop.png
0 → 100644
View file @
1ccbc004
800 Bytes
app/src/main/res/drawable-xhdpi/xinhao1.png
0 → 100644
View file @
1ccbc004
302 Bytes
app/src/main/res/drawable-xhdpi/xinhao2.png
0 → 100644
View file @
1ccbc004
296 Bytes
app/src/main/res/drawable-xhdpi/xinhao3.png
0 → 100644
View file @
1ccbc004
321 Bytes
Prev
1
2
3
4
Next
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