Commit e02e65d3 authored by p x's avatar p x
Browse files

交互

parent 8d5907a7
......@@ -5,6 +5,9 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<application
android:name=".MyApplication"
......@@ -20,8 +23,8 @@
tools:targetApi="31">
<activity
android:name=".ui.LoginActivity"
android:exported="true"
android:configChanges="orientation"
android:exported="true"
android:screenOrientation="landscape">
<intent-filter>
......@@ -32,11 +35,21 @@
</activity>
<activity
android:name=".MainActivity"
android:exported="false"
android:screenOrientation="landscape"
android:configChanges="orientation"
android:launchMode="singleTask" />
android:exported="false"
android:launchMode="singleTask"
android:screenOrientation="landscape" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
......
package com.sd.geelyhmiweb
import android.webkit.JavascriptInterface
import com.sd.geelyhmiweb.dsbridge.CompletionHandler
import com.sd.geelyhmiweb.utils.FileIoUtils
import com.sd.geelyhmiweb.viewmodels.MainVM
class JsApi {
var mainVM:MainVM?=null
//同步API
@JavascriptInterface
fun testSyn(msg: String): String {
return msg.toString() + "[syn call]"
}
//异步API
@JavascriptInterface
fun testAsyn(msg: String, handler: CompletionHandler<String?>) {
handler.complete(msg.toString() + " [ asyn call]")
}
@JavascriptInterface
fun writeLog(msg: String) {
println("------------ writeLog")
mainVM?.writeLog(msg)
// FileIoUtils.writeToFile(gson.toJson(perceptionBean), "PerTarget_15_move.txt")
}
}
\ No newline at end of file
......@@ -12,14 +12,20 @@ import android.webkit.WebResourceResponse
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.sd.geelyhmiweb.databinding.ActivityMainBinding
import com.sd.geelyhmiweb.viewmodels.MainVM
import dagger.hilt.android.AndroidEntryPoint
import kotlin.getValue
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var mainVM: MainVM by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
......@@ -30,11 +36,13 @@ class MainActivity : AppCompatActivity() {
fun initWeb() {
// DWebView.setWebContentsDebuggingEnabled(true)
var jsApi = JsApi()
jsApi.mainVM = mainVM
binding.dwebview.addJavascriptObject(jsApi, null)
// DWebView.setWebContentsDebuggingEnabled(true)
binding.dwebview.settings.run {
// userAgentString="Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Mobile Safari/537.36"
javaScriptEnabled = true
javaScriptCanOpenWindowsAutomatically = true
loadWithOverviewMode = true
......@@ -95,7 +103,6 @@ class MainActivity : AppCompatActivity() {
binding.dwebview.webChromeClient = object : WebChromeClient() {
override fun onConsoleMessage(message: ConsoleMessage?): Boolean {
Log.d(
"---pxl ",
......
package com.sd.geelyhmiweb.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 java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.GregorianCalendar
import java.util.Locale
import java.util.TimeZone
/**
*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(FORMAT_DATE, Locale.CHINESE)
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// 分钟
/**
* 计算时间差
*/
fun timeDifferenceDay(start_time: String, end_time: String): Int {
var sDate = sdf.parse(start_time)
var eDate = sdf.parse(end_time)
var diff = (eDate.time - sDate.time).div(24 * 60 * 60 * 1000).toInt()// 将毫秒转换为天
return diff
}
/**
* 比价时间前后
*/
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 {
val sdf = SimpleDateFormat(format, Locale.CHINESE)
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
package com.sd.geelyhmiweb.utils
import android.os.Environment
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileWriter
import java.io.IOException
object FileIoUtils {
private var fileWriter: FileWriter? = null
suspend fun writeToFile(message: String, fileName: String) {
// if (MyContants.WRITE_LOG){
withContext(Dispatchers.IO) {
try {
val file = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
fileName
)
fileWriter = FileWriter(file, true) // true for append mode
fileWriter!!.append("$message\n")
fileWriter!!.flush() // Optional, to ensure immediate writing to file
} catch (e: IOException) {
Log.e("------writeToFile", "Error initializing log file", e)
}
}
// }
}
}
\ No newline at end of file
package com.sd.geelyhmiweb.viewmodels
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sd.geelyhmiweb.utils.FileIoUtils
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class MainVM @Inject constructor(
// private var loginRepo: LoginRepo,
@ApplicationContext var context: Context
) : ViewModel() {
fun writeLog(str: String){
viewModelScope.launch {
FileIoUtils.writeToFile(str, "log.txt")
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path
name="external-path"
path="." />
</paths>
</resources>
\ 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