Commit 5616a99e authored by p x's avatar p x
Browse files

first

parent 67ef9b69
Pipeline #3086 failed with stages
in 0 seconds
/**
*
*/
package com.sd.shupathwebview.utils;
import java.text.SimpleDateFormat;
import java.util.Locale;
import com.amap.api.location.AMapLocation;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;
/**
* 辅助工具类
* @创建时间: 2015年11月24日 上午11:46:50
* @项目名称: AMapLocationDemo2.x
* @author hongming.wang
* @文件名称: Utils.java
* @类型名称: Utils
*/
public class AmapUtils {
/**
* 开始定位
*/
public final static int MSG_LOCATION_START = 0;
/**
* 定位完成
*/
public final static int MSG_LOCATION_FINISH = 1;
/**
* 停止定位
*/
public final static int MSG_LOCATION_STOP= 2;
public final static String KEY_URL = "URL";
public final static String URL_H5LOCATION = "file:///android_asset/sdkLoc.html";
/**
* 根据定位结果返回定位信息的字符串
* @param location
* @return
*/
public synchronized static String getLocationStr(AMapLocation location){
if(null == location){
return null;
}
StringBuffer sb = new StringBuffer();
//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
if(location.getErrorCode() == 0){
sb.append("定位成功" + "\n");
sb.append("定位类型: " + location.getLocationType() + "\n");
sb.append("经 度 : " + location.getLongitude() + "\n");
sb.append("纬 度 : " + location.getLatitude() + "\n");
sb.append("精 度 : " + location.getAccuracy() + "米" + "\n");
sb.append("提供者 : " + location.getProvider() + "\n");
sb.append("速 度 : " + location.getSpeed() + "米/秒" + "\n");
sb.append("角 度 : " + location.getBearing() + "\n");
// 获取当前提供定位服务的卫星个数
sb.append("星 数 : " + location.getSatellites() + "\n");
sb.append("国 家 : " + location.getCountry() + "\n");
sb.append("省 : " + location.getProvince() + "\n");
sb.append("市 : " + location.getCity() + "\n");
sb.append("城市编码 : " + location.getCityCode() + "\n");
sb.append("区 : " + location.getDistrict() + "\n");
sb.append("区域 码 : " + location.getAdCode() + "\n");
sb.append("地 址 : " + location.getAddress() + "\n");
sb.append("兴趣点 : " + location.getPoiName() + "\n");
//定位完成的时间
sb.append("定位时间: " + formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
} else {
//定位失败
sb.append("定位失败" + "\n");
sb.append("错误码:" + location.getErrorCode() + "\n");
sb.append("错误信息:" + location.getErrorInfo() + "\n");
sb.append("错误描述:" + location.getLocationDetail() + "\n");
}
//定位之后的回调时间
sb.append("回调时间: " + formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
return sb.toString();
}
private static SimpleDateFormat sdf = null;
public static String formatUTC(long l, String strPattern) {
if (TextUtils.isEmpty(strPattern)) {
strPattern = "yyyy-MM-dd HH:mm:ss";
}
if (sdf == null) {
try {
sdf = new SimpleDateFormat(strPattern, Locale.CHINA);
} catch (Throwable e) {
}
} else {
sdf.applyPattern(strPattern);
}
return sdf == null ? "NULL" : sdf.format(l);
}
/**
* 获取app的名称
* @param context
* @return
*/
public static String getAppName(Context context) {
String appName = "";
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(
context.getPackageName(), 0);
int labelRes = packageInfo.applicationInfo.labelRes;
appName = context.getResources().getString(labelRes);
} catch (Throwable e) {
e.printStackTrace();
}
return appName;
}
}
package com.sd.shupathwebview.utils
import android.os.Environment
import android.util.Log
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
object CustomLog {
const val LOG_FILE_NAME: String = "app_log.txt"
const val LOG_TAG: String = "CustomLog"
var fileWriter: FileWriter? = null
init {
try {
val logFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), LOG_FILE_NAME)
// val logFile = File("D:\\", LOG_FILE_NAME)
fileWriter = FileWriter(logFile, true) // true for append mode
} catch (e: IOException) {
Log.e(LOG_TAG, "Error initializing log file", e)
}
}
fun clearLog(){
val logFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), LOG_FILE_NAME)
if (logFile.exists()){
logFile.deleteOnExit()
}
}
fun d(tag: String?, message: String) {
Log.d(tag, message)
writeToFile(tag, message)
}
fun i(tag: String?, message: String) {
Log.i(tag, message)
writeToFile(tag, message)
}
fun e(tag: String?, message: String) {
Log.e(tag, message)
writeToFile(tag, message)
}
private fun writeToFile(tag: String?, message: String) {
if (fileWriter != null) {
try {
val sdf: SimpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val timeStamp: String = sdf.format(Date())
fileWriter!!.append("$timeStamp - $tag: $message\n")
fileWriter!!.flush() // Optional, to ensure immediate writing to file
} catch (e: IOException) {
Log.e(LOG_TAG, "Error writing to log file", e)
}
}
}
}
\ No newline at end of file
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()
}
}
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
package com.sd.shupathwebview.utils
object MyContants {
/**从obu来的数据**/
const val obu_data="obu_data"
/***JS方法名***/
const val getOBUData="getOBUData"
const val getDeviceData="getDeviceData"
}
\ No newline at end of file
package com.sd.shupathwebview.utils
import android.content.Context
import android.view.Gravity
import android.widget.Toast
/**
*author:pc-20171125
*data:2019/11/8 11:18
*/
object ToastHelper {
/**
* 短时间显示Toast
*
* @param message
*/
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()
// }
}
package com.sd.shupathwebview.viewmodels
import android.content.Context
import android.icu.text.DecimalFormat
import android.location.Location
import android.text.TextUtils
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationClientOption.AMapLocationMode
import com.amap.api.location.AMapLocationClientOption.AMapLocationProtocol
import com.amap.api.location.AMapLocationListener
import com.amap.api.location.AMapLocationQualityReport
import com.sd.shupathwebview.bean.MyLoc
import com.sd.shupathwebview.utils.AmapUtils
import com.sd.shupathwebview.utils.CustomLog
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
@HiltViewModel
class AMapLoc @Inject constructor(@ApplicationContext var context: Context) : ViewModel() {
val TAG = AMapLoc::class.java::getSimpleName.toString()
private var locationClient: AMapLocationClient? = null
private var locationOption: AMapLocationClientOption? = null
private var myLoc = MyLoc()
var myLocValue = MutableLiveData<MyLoc>()
/**
* 初始化定位
*
* @since 2.8.0
* @author hongming.wang
*/
fun initLocation() {
//初始化client
try {
locationClient = AMapLocationClient(context)
locationOption = getDefaultOption()
//设置定位参数
locationClient?.setLocationOption(locationOption)
// 设置定位监听
locationClient?.setLocationListener(locationListener)
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 默认的定位参数
* @since 2.8.0
* @author hongming.wang
*/
private fun getDefaultOption(): AMapLocationClientOption {
val mOption = AMapLocationClientOption()
mOption.setLocationMode(AMapLocationMode.Hight_Accuracy) //可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
mOption.setGpsFirst(false) //可选,设置是否gps优先,只在高精度模式下有效。默认关闭
mOption.setHttpTimeOut(30000) //可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.setInterval(1000) //可选,设置定位间隔。默认为2秒
mOption.setNeedAddress(false) //可选,设置是否返回逆地理地址信息。默认是true
mOption.setOnceLocation(false) //可选,设置是否单次定位。默认是false
mOption.setOnceLocationLatest(false) //可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationProtocol.HTTP) //可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
mOption.setSensorEnable(false) //可选,设置是否使用传感器。默认是false
mOption.setWifiScan(true) //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差
mOption.setLocationCacheEnable(true) //可选,设置是否使用缓存定位,默认为true
mOption.setGeoLanguage(AMapLocationClientOption.GeoLanguage.DEFAULT) //可选,设置逆地理信息的语言,默认值为默认语言(根据所在地区选择语言)
return mOption
}
private fun getTrancesportOption(): AMapLocationClientOption {
val mOption = AMapLocationClientOption()
/**
* 设置签到场景,相当于设置为:
* option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
* option.setOnceLocation(false);
* option.setOnceLocationLatest(false);
* option.setMockEnable(false);
* option.setWifiScan(true);
*
* 其他属性均为模式属性。
* 如果要改变其中的属性,请在在设置定位场景之后进行
*/
mOption.setHttpTimeOut(1000) //可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效
mOption.setInterval(2000) //可选,设置定位间隔。默认为2秒
mOption.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Transport)
return mOption
}
/**
* 定位监听
*/
var locationListener: AMapLocationListener = AMapLocationListener { location ->
if (null != location) {
val sb = StringBuffer()
//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明
if (location.errorCode == 0) {
sb.append("定位成功" + "\n")
sb.append("定位类型: " + location.locationType + "\n")
sb.append("经 度 : " + location.longitude + "\n")
sb.append("纬 度 : " + location.latitude + "\n")
sb.append("精 度 : " + location.accuracy + "米" + "\n")
sb.append("提供者 : " + location.provider + "\n")
sb.append("速 度 : " + location.speed + "米/秒" + "\n")
sb.append("角 度 : " + location.bearing + "\n")
// 获取当前提供定位服务的卫星个数
sb.append("星 数 : " + location.satellites + "\n")
sb.append("国 家 : " + location.country + "\n")
sb.append("省 : " + location.province + "\n")
sb.append("市 : " + location.city + "\n")
sb.append("城市编码 : " + location.cityCode + "\n")
sb.append("区 : " + location.district + "\n")
sb.append("区域 码 : " + location.adCode + "\n")
sb.append("地 址 : " + location.address + "\n")
sb.append("兴趣点 : " + location.poiName + "\n")
//定位完成的时间
sb.append(
"定位时间: " + AmapUtils.formatUTC(
location.time,
"yyyy-MM-dd HH:mm:ss"
) + "\n"
)
} else {
//定位失败
sb.append("定位失败" + "\n")
sb.append("错误码:" + location.errorCode + "\n")
sb.append("错误信息:" + location.errorInfo + "\n")
sb.append("错误描述:" + location.locationDetail + "\n")
}
sb.append("***定位质量报告***").append("\n")
sb.append("* WIFI开关:")
.append(if (location.locationQualityReport.isWifiAble) "开启" else "关闭")
.append("\n")
sb.append("* GPS状态:")
.append(getGPSStatusString(location.locationQualityReport.gpsStatus)).append("\n")
sb.append("* GPS星数:").append(location.locationQualityReport.gpsSatellites)
.append("\n")
sb.append("* 网络类型:" + location.locationQualityReport.networkType).append("\n")
sb.append("* 网络耗时:" + location.locationQualityReport.netUseTime).append("\n")
sb.append("****************").append("\n")
//定位之后的回调时间
sb.append(
"回调时间: " + AmapUtils.formatUTC(
System.currentTimeMillis(),
"yyyy-MM-dd HH:mm:ss"
) + "\n"
)
//解析定位结果,
val result = sb.toString()
CustomLog.d(TAG, result)
setMyLocation(location,result)
} else {
CustomLog.d(TAG, "定位失败,loc is null")
}
}
private fun setMyLocation(location: Location,debugString: String="") {
var decimalFormat = DecimalFormat("#.00000000")
var strLat = decimalFormat.format(location.latitude)
var strLng = decimalFormat.format(location.longitude)
myLoc.lat = strLat.toDouble()
myLoc.lng = strLng.toDouble()
myLoc.speed = location.speed
myLoc.accuracy = location.accuracy
myLoc.bearing = location.bearing
// myLoc.com_time = location.time
myLoc.debugStr = debugString
println("--------lng = ${myLoc.lat} lng = ${myLoc.lng}")
myLocValue.value = myLoc
// val loc = location.latitude.toString() + " " + location.longitude.toString()
}
/**
* 获取GPS状态的字符串
* @param statusCode GPS状态码
* @return
*/
private fun getGPSStatusString(statusCode: Int): String {
var str = ""
when (statusCode) {
AMapLocationQualityReport.GPS_STATUS_OK -> str = "GPS状态正常"
AMapLocationQualityReport.GPS_STATUS_NOGPSPROVIDER -> str =
"手机中没有GPS Provider,无法进行GPS定位"
AMapLocationQualityReport.GPS_STATUS_OFF -> str = "GPS关闭,建议开启GPS,提高定位质量"
AMapLocationQualityReport.GPS_STATUS_MODE_SAVING -> str =
"选择的定位模式中不包含GPS定位,建议选择包含GPS定位的模式,提高定位质量"
AMapLocationQualityReport.GPS_STATUS_NOGPSPERMISSION -> str =
"没有GPS定位权限,建议开启gps定位权限"
}
return str
}
/**
* 开始定位
*
* @since 2.8.0
* @author hongming.wang
*/
fun startLocation() {
try {
//根据控件的选择,重新设置定位参数
// resetOption()
// 设置定位参数
locationClient?.setLocationOption(locationOption)
// 启动定位
locationClient?.startLocation()
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
/**
* 停止定位
*
* @since 2.8.0
* @author hongming.wang
*/
fun stopLocation() {
try {
// 停止定位
locationClient?.stopLocation()
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
/**
* 销毁定位
*
* @since 2.8.0
* @author hongming.wang
*/
fun destroyLocation() {
if (null != locationClient) {
/**
* 如果AMapLocationClient是在当前Activity实例化的,
* 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
*/
locationClient?.onDestroy()
locationClient = null
locationOption = null
}
}
}
\ No newline at end of file
package com.sd.shupathwebview.viewmodels
import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.icu.text.DecimalFormat
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.util.Log
import androidx.annotation.RequiresPermission
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.sd.shupathwebview.bean.MyLoc
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
@HiltViewModel
class MyLocVM @Inject constructor(
// @Assisted private val savedStateHandle: SavedStateHandle
@ApplicationContext var context: Context
) : ViewModel() {
private var locationManager =
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
private var locationProvider: String = ""
private var location: Location? = null
private var myLoc = MyLoc()
var myLocValue = MutableLiveData<MyLoc>()
@RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
fun getLocation(): LiveData<MyLoc> {
//1.获取位置管理器
// locationManager = mContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
//2.获取位置提供器,GPS或是NetWork
if (!getProvider().isNullOrEmpty()) {
if (location != null) {
setMyLocation(location!!)
}
// 监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
locationManager.requestLocationUpdates(locationProvider, 1, 0f, locationListener)
}
return myLocValue
}
@SuppressLint("MissingPermission")
fun getLastLocation(): String {
//1.获取位置管理器
// locationManager = mContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
//2.获取位置提供器,GPS或是NetWork
if (getProvider().isNullOrEmpty()) {
return ""
}
var locate = locationManager?.getLastKnownLocation(locationProvider)
if (locate != null) {
setMyLocation(locate)
}
return locate?.latitude.toString() + " " + locate?.longitude.toString()
}
private fun getProvider(): String {
val providers: List<String> = locationManager.getProviders(true)
if (providers.contains(LocationManager.GPS_PROVIDER)) {
//如果是GPS定位
// Log.d("TAG", "如果是GPS定位")
locationProvider = LocationManager.NETWORK_PROVIDER
} else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
//如果是网络定位
// Log.d("TAG", "如果是网络定位")
locationProvider = LocationManager.NETWORK_PROVIDER
} else {
Log.d("TAG", "没有可用的位置提供器")
return ""
}
return locationProvider
}
private fun setMyLocation(location: Location) {
this.location = location
var decimalFormat = DecimalFormat("#.000000000")
var strLat = decimalFormat.format(location.latitude)
var strLng = decimalFormat.format(location.longitude)
myLoc.lat = strLat.toDouble()
myLoc.lng = strLng.toDouble()
myLoc.speed = location.speed
myLoc.bearing = location.bearing
println("--------lng = ${myLoc.lat} lng = ${myLoc.lng}")
myLocValue.value = myLoc
// val loc = location.latitude.toString() + " " + location.longitude.toString()
}
var locationListener = object : LocationListener {
override fun onLocationChanged(location: Location) {
// location.getAccuracy()//精确度
println("--------location.latitude = ${location.latitude} longitude ${location.longitude}")
setMyLocation(location)
}
}
fun desLis() {
if (locationManager != null) {
locationManager.removeUpdates(locationListener);
}
}
}
\ No newline at end of file
package com.sd.shupathwebview.works
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.net.InetSocketAddress
import java.net.StandardSocketOptions
import java.nio.ByteBuffer
import java.nio.channels.AsynchronousSocketChannel
import java.nio.channels.CompletionHandler
import java.nio.charset.Charset
import java.util.concurrent.Executors
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
class AioClient {
// private val TCP_URL = "192.168.60.113"
private val TCP_URL = "192.168.60.176"
private val PORT = 8080
private lateinit var channel: AsynchronousSocketChannel
fun connectAIO() {
channel = AsynchronousSocketChannel.open()
channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true)
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true)
channel.setOption(StandardSocketOptions.TCP_NODELAY, true)
// val connectFuture: Future<Void> =
// channel.connect(InetSocketAddress(TCP_URL, PORT))
// var cd=connectFuture.get()
// var a=0
// return cd // 等待连接完成
channel.connect<Void?>(
InetSocketAddress(TCP_URL, PORT),
null,
object : CompletionHandler<Void?, Void?> {
override fun completed(result: Void?, attachment: Void?) {
System.out.println("----连接成功")
read1()
// heart()
}
override fun failed(exc: Throwable?, attachment: Void?) {
System.err.println("-------连接失败: " + exc?.message);
}
}
)
}
fun write() {
// 异步写入数据
val buffer = ByteBuffer.wrap("----Hello Server".toByteArray())
val writeResult: Future<Int> = channel.write(buffer)
var a = writeResult.get()
var b = 1
}
fun read() {
CoroutineScope(Dispatchers.IO).launch {
val response = ByteBuffer.allocate(1024)
val readResult: Future<Int> = channel.read(response)
var result = readResult.get()
response.flip()
if (result ?: 0 > 0) {
response.flip()
val data = ByteArray(response.limit())
response.get(data)
var str = data.toString(Charset.forName("UTF-8"))
System.out.println("-----read1 clent 数据部分= : " + String(data))
}
}
}
fun read1() {
println("----------channel.isOpen " + channel.isOpen)
val response = ByteBuffer.allocate(8192)
channel.read(response, response, object : CompletionHandler<Int, ByteBuffer> {
override fun completed(result: Int?, attachment: ByteBuffer?) {
println("-----read()1 = result = ${result}")
if (result ?: 0 > 0) {
response.flip()
// val data = ByteArray(response.remaining())
val data = ByteArray(response.limit())
response.get(data)
var str = data.toString(Charset.forName("UTF-8"))
System.out.println("-----read1 clent 数据部分= : " + String(data))
}
}
override fun failed(exc: Throwable?, attachment: ByteBuffer?) {
System.out.println("-----read1 clent 读取失败= : " + exc?.message)
}
})
}
fun heart() {
var heartbeatExecutor = Executors.newScheduledThreadPool(1)
// 启动心跳线程
heartbeatExecutor.scheduleAtFixedRate({
try {
channel.write(ByteBuffer.wrap(ByteArray(0)))
} catch (e: Exception) {
// reconnect()
}
}, 0, 30, TimeUnit.SECONDS)
}
}
// fun read() {
// CoroutineScope(Dispatchers.IO).launch {
// val response = ByteBuffer.allocate(1024)
//
// val readResult: Future<Int> = channel.read(response)
// readResult.get()
// response.flip()
// //// // 解析字段
// var deviceId = response.get() // 设备ID
// var temperature = response.getShort(); // 温度
// var humidity = response.getFloat(); // 湿度
////
// System.out.println("Device ID: " + deviceId);
// System.out.println("Temperature: " + temperature);
// System.out.println("Humidity: " + humidity);
//
// val data = ByteArray(response.remaining())
// response.get(data);
// System.out.println("-----clent 数据部分= : " + String(data))
// }
// }
package com.sd.shupathwebview.works
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.pm.ServiceInfo
import androidx.core.app.NotificationCompat
import androidx.work.CoroutineWorker
import androidx.work.ForegroundInfo
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import com.sd.shupathwebview.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.InetSocketAddress
import java.net.StandardSocketOptions
import java.nio.ByteBuffer
import java.nio.channels.AsynchronousSocketChannel
import java.nio.channels.CompletionHandler
import java.nio.charset.Charset
/**
* 链接任务
*/
class SocketWorker constructor(val appContext: Context, workerParams: WorkerParameters) :
CoroutineWorker(appContext, workerParams) {
init {
}
// private val notificationManager = appContext.getSystemService(Context.NOTIFICATION_SERVICE) as
// NotificationManager
val notificationId = 51
// var client = AioClient()
private val TCP_URL = "192.168.60.176"
private val PORT = 8080
private lateinit var channel: AsynchronousSocketChannel
override suspend fun doWork(): Result {
setForeground(createForegroundInfo())
return Result.success()
}
// fun connectAIO() {
// channel = AsynchronousSocketChannel.open()
// channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true)
// channel.setOption(StandardSocketOptions.SO_REUSEADDR, true)
// channel.setOption(StandardSocketOptions.TCP_NODELAY, true)
//// val connectFuture: Future<Void> =
//// channel.connect(InetSocketAddress(TCP_URL, PORT))
//// var cd=connectFuture.get()
//// return cd // 等待连接完成
// channel.connect<Void?>(
// InetSocketAddress(TCP_URL, PORT),
// null,
// object : CompletionHandler<Void?, Void?> {
//
// override fun completed(result: Void?, attachment: Void?) {
// System.out.println("----连接成功")
// read1()
//// heart()
// }
//
// override fun failed(exc: Throwable?, attachment: Void?) {
// System.err.println("-------连接失败: " + exc?.message);
// }
// }
// )
// }
fun read1() {
var aa = channel.isOpen
val response = ByteBuffer.allocate(8192)
channel.read(response, response, object : CompletionHandler<Int, ByteBuffer> {
override fun completed(result: Int?, attachment: ByteBuffer?) {
println("-----read()1 = result = ${result}")
if (result ?: 0 > 0) {
response.flip()
// val data = ByteArray(response.remaining())
val data = ByteArray(response.limit())
response.get(data)
var str = data.toString(Charset.forName("UTF-8"))
System.out.println("-----read1 clent 数据部分= : " + String(data))
}
}
override fun failed(exc: Throwable?, attachment: ByteBuffer?) {
System.out.println("-----read1 clent 读取失败= : " + exc?.message)
}
})
}
// Creates an instance of ForegroundInfo which can be used to update the
// ongoing notification.
private fun createForegroundInfo(progress: String = ""): ForegroundInfo {
val mNotificationManager =
appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// 通知渠道的id
val id = "my_channel_01"
// 用户可以看到的通知渠道的名字.
val name: CharSequence = appContext.getString(R.string.app_name)
val description = appContext.getString(R.string.app_name)
val importance = NotificationManager.IMPORTANCE_HIGH
val mChannel = NotificationChannel(id, name, importance)
mNotificationManager.createNotificationChannel(mChannel)
val title = appContext.getString(R.string.notification_title)
val notification = NotificationCompat.Builder(appContext, id)
.setContentTitle(title)
.setTicker(title)
.setContentText(title)
.setSmallIcon(R.mipmap.ic_launcher)
// Create the notification to display while the service is running
.build()
return ForegroundInfo(
notificationId,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
)
}
private fun createChannel() {
// Create a Notification channel
// 通知渠道的id
// val CHANNEL_ID = "my_channel_01"
// val notification: Notification = Notification.Builder(this)
// .setContentTitle("")
// .setContentText("")
// .setChannelId(CHANNEL_ID)
// .build()
// ServiceCompat.startForeground(SystemForegroundService.getInstance(), notification)
}
}
\ No newline at end of file
package com.sd.shupathwebview.works
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.sd.shupathwebview.dsbridge.DWebView
import com.sd.shupathwebview.dsbridge.OnReturnValue
import com.sd.shupathwebview.network.NettyReceiveClient
import com.sd.shupathwebview.utils.CustomLog
import com.sd.shupathwebview.utils.FileIoUtils
import com.sd.shupathwebview.utils.MyContants
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel
class TcpConntctVM @Inject constructor(
// @Assisted private val savedStateHandle: SavedStateHandle
@ApplicationContext var context: Context
) : ViewModel() {
var obuStr = ""
private var nettyReceiveClient = NettyReceiveClient()
// var socketWorker = OneTimeWorkRequestBuilder<SocketWorker>().build()
fun startWork() {
var socketWorker = OneTimeWorkRequestBuilder<SocketWorker>()
.setInputData(workDataOf("nettyReceiveClient" to nettyReceiveClient))
.build()
// val oneWorker = OneTimeWorkRequest.Builder(OneWorker::class).build()
WorkManager.getInstance(context).enqueue(socketWorker)
// WorkManager.getInstance(context).getWorkInfoByIdLiveData(socketWorker.id)
// .observe(owner!!, { it ->
// println("-----connectWorker.state = ${it?.state}")
// if (it?.state?.isFinished == true) {
// println("-------connectWorker isFinished")
// }
// })
}
var mockList = mutableListOf<String>()
fun readMockData() {
viewModelScope.launch {
// withContext(Dispatchers.IO) {
var result =
FileIoUtils.getAssetMock(context, "OBU_MOCK/BSM-1-JJ-CY-10hz-S0ms.pf", mockList)
CustomLog.d("---pxl", "模拟数据读完了 result = $result")
// mockList.forEach{
// CustomLog.d("---pxl","每行模拟数据= $it")
// }
// }
}
}
fun sendMockData(dwebview: DWebView) {
viewModelScope.launch {
mockList.forEach {
CustomLog.d("---pxl ", "准备给webview的模拟数据是 = ${it}")
dwebview.callHandler(
MyContants.getOBUData,
arrayOf(it),
object : OnReturnValue<String> {
override fun onValue(retValue: String?) {
CustomLog.d(
"---pxl ",
"getOBUData Android 收到webview的回调 onValue= ${retValue.toString()}"
)
}
})
CustomLog.d("---pxl ", "getOBUData 睡200ms")
delay(200)
}
}
}
fun stopWork() {
nettyReceiveClient.close()
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:background="#675662"
tools:context=".MainActivity">
<com.sd.shupathwebview.dsbridge.DWebView
android:id="@+id/dwebview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
</LinearLayout>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment