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

交互

parent 8d5907a7
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<application <application
android:name=".MyApplication" android:name=".MyApplication"
...@@ -20,8 +23,8 @@ ...@@ -20,8 +23,8 @@
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".ui.LoginActivity" android:name=".ui.LoginActivity"
android:exported="true"
android:configChanges="orientation" android:configChanges="orientation"
android:exported="true"
android:screenOrientation="landscape"> android:screenOrientation="landscape">
<intent-filter> <intent-filter>
...@@ -32,11 +35,21 @@ ...@@ -32,11 +35,21 @@
</activity> </activity>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="false"
android:screenOrientation="landscape"
android:configChanges="orientation" 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> </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 ...@@ -12,14 +12,20 @@ import android.webkit.WebResourceResponse
import android.webkit.WebSettings import android.webkit.WebSettings
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.sd.geelyhmiweb.databinding.ActivityMainBinding import com.sd.geelyhmiweb.databinding.ActivityMainBinding
import com.sd.geelyhmiweb.viewmodels.MainVM
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlin.getValue
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private var mainVM: MainVM by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
...@@ -30,11 +36,13 @@ class MainActivity : AppCompatActivity() { ...@@ -30,11 +36,13 @@ class MainActivity : AppCompatActivity() {
fun initWeb() { fun initWeb() {
// DWebView.setWebContentsDebuggingEnabled(true) var jsApi = JsApi()
jsApi.mainVM = mainVM
binding.dwebview.addJavascriptObject(jsApi, null)
// DWebView.setWebContentsDebuggingEnabled(true)
binding.dwebview.settings.run { 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" // 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 javaScriptEnabled = true
javaScriptCanOpenWindowsAutomatically = true javaScriptCanOpenWindowsAutomatically = true
loadWithOverviewMode = true loadWithOverviewMode = true
...@@ -95,7 +103,6 @@ class MainActivity : AppCompatActivity() { ...@@ -95,7 +103,6 @@ class MainActivity : AppCompatActivity() {
binding.dwebview.webChromeClient = object : WebChromeClient() { binding.dwebview.webChromeClient = object : WebChromeClient() {
override fun onConsoleMessage(message: ConsoleMessage?): Boolean { override fun onConsoleMessage(message: ConsoleMessage?): Boolean {
Log.d( Log.d(
"---pxl ", "---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