"vscode:/vscode.git/clone" did not exist on "cd1198f8c99e214d514005a8041f5919764c3042"
Commit 6704f076 authored by p x's avatar p x
Browse files

添加加载网页的方式

parent 5b3f0dc5
...@@ -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.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission <uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
......
package com.sd.geelyhmiweb package com.sd.geelyhmiweb
import android.util.Log
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import androidx.lifecycle.MutableLiveData
import com.sd.geelyhmiweb.dsbridge.CompletionHandler import com.sd.geelyhmiweb.dsbridge.CompletionHandler
import com.sd.geelyhmiweb.utils.FileIoUtils import com.sd.geelyhmiweb.utils.LocationUtils
import com.sd.geelyhmiweb.viewmodels.MainVM import com.sd.geelyhmiweb.viewmodels.MainVM
class JsApi { class JsApi {
var mainVM:MainVM?=null var mainVM: MainVM? = null
//定位字符串
var locStr = MutableLiveData("")
//同步API
@JavascriptInterface @JavascriptInterface
fun testSyn(msg: Object ): String { fun synLoc(arg: Any, handler: CompletionHandler<String>) {
return msg.toString() + "[syn call]" LocationUtils.getInstan().onJsLoc = object : LocationUtils.OnJsLoc {
override fun onJsLoc(str: String) {
// handler.complete(str);
// Log.d("------------js 调用 Android 获取异步位置=", str);
locStr.postValue(str)
}
}
LocationUtils.getInstan().getLocation()
} }
//异步API
@JavascriptInterface @JavascriptInterface
fun testAsyn(msg: Object , handler: CompletionHandler<String?>) { fun stopLoc(arg: Any?) {
handler.complete(msg.toString() + " [ asyn call]") LocationUtils.getInstan().stopLoc()
} }
@JavascriptInterface @JavascriptInterface
fun writeLog(msg: Object) { fun writeLog(msg: Object) {
// println("------------writeLog ${msg}") // println("------------writeLog ${msg}")
...@@ -30,4 +39,20 @@ class JsApi { ...@@ -30,4 +39,20 @@ class JsApi {
// FileIoUtils.writeToFile(gson.toJson(perceptionBean), "PerTarget_15_move.txt") // FileIoUtils.writeToFile(gson.toJson(perceptionBean), "PerTarget_15_move.txt")
} }
/* //同步API
@JavascriptInterface
fun testSyn(msg: Object): String {
return msg.toString() + "[syn call]"
}
//异步API
@JavascriptInterface
fun testAsyn(msg: Object, handler: CompletionHandler<String?>) {
handler.complete(msg.toString() + " [ asyn call]")
}*/
} }
\ No newline at end of file
...@@ -6,49 +6,54 @@ import android.util.Log ...@@ -6,49 +6,54 @@ import android.util.Log
import android.webkit.ConsoleMessage import android.webkit.ConsoleMessage
import android.webkit.SslErrorHandler import android.webkit.SslErrorHandler
import android.webkit.WebChromeClient import android.webkit.WebChromeClient
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse 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 androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.webkit.WebResourceErrorCompat import androidx.webkit.WebResourceErrorCompat
import androidx.webkit.WebViewAssetLoader import androidx.webkit.WebViewAssetLoader
import androidx.webkit.WebViewClientCompat import androidx.webkit.WebViewClientCompat
import com.sd.geelyhmiweb.databinding.ActivityMainBinding import com.sd.geelyhmiweb.databinding.ActivityMainBinding
import com.sd.geelyhmiweb.dsbridge.OnReturnValue
import com.sd.geelyhmiweb.utils.LocationUtils
import com.sd.geelyhmiweb.utils.MyContants
import com.sd.geelyhmiweb.viewmodels.MainVM 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() {
override fun onDestroy() {
super.onDestroy()
LocationUtils.getInstan().stopLoc()
binding.dwebview.destroy()
}
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private val mainVM: MainVM by viewModels() private val mainVM: MainVM by viewModels()
private lateinit var assetLoader: WebViewAssetLoader private lateinit var assetLoader: WebViewAssetLoader
override fun onDestroy() { private val jsApi = JsApi()
super.onDestroy()
binding.dwebview.destroy()
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
initWeb() LocationUtils.setLocManager(this)
}
fun initWeb() { // LocationUtils.getInstan().getLocation()
var jsApi = JsApi()
jsApi.mainVM = mainVM jsApi.mainVM = mainVM
initWeb()
initLis()
}
private fun initWeb() {
assetLoader = WebViewAssetLoader.Builder() assetLoader = WebViewAssetLoader.Builder()
.setHttpAllowed(true) .setHttpAllowed(true)
.addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(this)) .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(this))
...@@ -63,25 +68,37 @@ class MainActivity : AppCompatActivity() { ...@@ -63,25 +68,37 @@ class MainActivity : AppCompatActivity() {
javaScriptEnabled = true javaScriptEnabled = true
javaScriptCanOpenWindowsAutomatically = true javaScriptCanOpenWindowsAutomatically = true
loadWithOverviewMode = true loadWithOverviewMode = true
cacheMode = WebSettings.LOAD_DEFAULT
domStorageEnabled = true domStorageEnabled = true
databaseEnabled = true databaseEnabled = true
// 关键:禁用文件访问,强制走 AssetLoader 路由 // 关键:禁用文件访问,强制走 AssetLoader 路由
if (MyContants.LOAD_WEB_FILE == 1) {
setAllowFileAccess(true)
setAllowContentAccess(true)
setAllowFileAccessFromFileURLs(true)
setAllowUniversalAccessFromFileURLs(true)
} else if (MyContants.LOAD_WEB_FILE == 2) {
setAllowFileAccess(false) setAllowFileAccess(false)
setAllowContentAccess(false) setAllowContentAccess(false)
setAllowFileAccessFromFileURLs(false) setAllowFileAccessFromFileURLs(false)
setAllowUniversalAccessFromFileURLs(false) setAllowUniversalAccessFromFileURLs(false)
}
// 混合内容模式(若前端有 HTTP 资源,需配置;正式环境建议仅 HTTPS) // 混合内容模式(若前端有 HTTP 资源,需配置;正式环境建议仅 HTTPS)
setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW) setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW)
// 关键:禁用WebView的DNS缓存,强制走拦截逻辑
setCacheMode(WebSettings.LOAD_NO_CACHE)
// 禁用网络加载(仅加载本地资产) // 禁用网络加载(仅加载本地资产)
blockNetworkLoads = true // blockNetworkLoads = true
} }
val url = "file:///android_asset/dist/index.html"
// val url = "http://192.168.60.155:5173/" // val url = "http://192.168.60.155:5173/"
val websiteUrl = "http://appassets.androidplatform.net/assets/dist/index.html" val websiteUrl = "http://appassets.androidplatform.net/assets/dist/index.html"
binding.dwebview.loadUrl(websiteUrl) var url = if (MyContants.LOAD_WEB_FILE == 1) {
"file:///android_asset/dist/index.html"
} else {
websiteUrl
}
binding.dwebview.loadUrl(url)
binding.dwebview.webViewClient = object : WebViewClientCompat() { binding.dwebview.webViewClient = object : WebViewClientCompat() {
override fun shouldInterceptRequest( override fun shouldInterceptRequest(
...@@ -93,8 +110,13 @@ class MainActivity : AppCompatActivity() { ...@@ -93,8 +110,13 @@ class MainActivity : AppCompatActivity() {
// headers.put("sec-ch-ua-platform", "") // headers.put("sec-ch-ua-platform", "")
// headers.put("","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:139.0) Gecko/20100101 Firefox/139.0") // headers.put("","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:139.0) Gecko/20100101 Firefox/139.0")
// 优先拦截虚拟域名请求 // 优先拦截虚拟域名请求
if (MyContants.LOAD_WEB_FILE==1){
return super.shouldInterceptRequest(view, request)
}else if (MyContants.LOAD_WEB_FILE==2){
return assetLoader.shouldInterceptRequest(request.url)
}else{
return assetLoader.shouldInterceptRequest(request.url) return assetLoader.shouldInterceptRequest(request.url)
// return super.shouldInterceptRequest(view, request) }
} }
override fun onReceivedHttpError( override fun onReceivedHttpError(
...@@ -105,6 +127,14 @@ class MainActivity : AppCompatActivity() { ...@@ -105,6 +127,14 @@ class MainActivity : AppCompatActivity() {
super.onReceivedHttpError(view, request, errorResponse) super.onReceivedHttpError(view, request, errorResponse)
} }
override fun onReceivedError(
view: WebView,
request: WebResourceRequest,
error: WebResourceErrorCompat
) {
super.onReceivedError(view, request, error)
}
override fun onReceivedSslError( override fun onReceivedSslError(
view: WebView?, view: WebView?,
handler: SslErrorHandler?, handler: SslErrorHandler?,
...@@ -120,7 +150,7 @@ class MainActivity : AppCompatActivity() { ...@@ -120,7 +150,7 @@ class MainActivity : AppCompatActivity() {
override fun onConsoleMessage(message: ConsoleMessage?): Boolean { override fun onConsoleMessage(message: ConsoleMessage?): Boolean {
Log.d( Log.d(
"---pxl ", "---onConsoleMessage ",
"${message?.message()} -- From line " + "${message?.lineNumber()} of ${message?.sourceId()}" "${message?.message()} -- From line " + "${message?.lineNumber()} of ${message?.sourceId()}"
) )
return true return true
...@@ -130,4 +160,19 @@ class MainActivity : AppCompatActivity() { ...@@ -130,4 +160,19 @@ class MainActivity : AppCompatActivity() {
} }
private fun initLis() {
jsApi.locStr.observe(this) {
// handler.complete(str);
// Log.d("------------上报异步位置", it)
binding.dwebview.callHandler(
"retLoc", arrayOf<String>(it),
OnReturnValue<String> { retValue ->
/* Log.d(
"---jsbridge",
"call succeed,return value is $retValue"
)*/
})
}
}
} }
\ No newline at end of file
...@@ -26,11 +26,10 @@ class BootActivity : AppCompatActivity() { ...@@ -26,11 +26,10 @@ class BootActivity : AppCompatActivity() {
binding=ActivityBootBinding.inflate(layoutInflater) binding=ActivityBootBinding.inflate(layoutInflater)
// enableEdgeToEdge() // enableEdgeToEdge()
setContentView(binding.root) setContentView(binding.root)
// ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> requestPers()
// val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) }
// v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
// insets private fun jumpMain() {
// }
if (isAvp) { if (isAvp) {
startActivity(Intent(this, MainActivity::class.java)) startActivity(Intent(this, MainActivity::class.java))
} else { } else {
...@@ -38,8 +37,11 @@ class BootActivity : AppCompatActivity() { ...@@ -38,8 +37,11 @@ class BootActivity : AppCompatActivity() {
} }
} }
fun requestPers() { private fun requestPers() {
var pers = mutableListOf<String>() val pers = mutableListOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
pers.add(Manifest.permission.READ_EXTERNAL_STORAGE) pers.add(Manifest.permission.READ_EXTERNAL_STORAGE)
pers.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE) pers.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
...@@ -48,26 +50,27 @@ class BootActivity : AppCompatActivity() { ...@@ -48,26 +50,27 @@ class BootActivity : AppCompatActivity() {
} }
PermissionX.init(this) PermissionX.init(this)
.permissions(pers) .permissions(pers)
.onExplainRequestReason { scope, deniedList -> // .onExplainRequestReason { scope, deniedList ->
scope.showRequestReasonDialog( // scope.showRequestReasonDialog(
deniedList, // deniedList,
"需要同意以下授权才能正常使用", // "需要同意以下授权才能正常使用",
"好的", // "好的",
"取消" // "取消"
) // )
} // }
// .onForwardToSettings { scope, deniedList -> // .onForwardToSettings { scope, deniedList ->
// scope.showForwardToSettingsDialog(deniedList, "您需要手动在‘设置’中允许必要的权限", "OK", "Cancel") // scope.showForwardToSettingsDialog(deniedList, "您需要手动在‘设置’中允许必要的权限", "OK", "Cancel")
// } // }
.request { allGranted, grantedList, deniedList -> .request { allGranted, grantedList, deniedList ->
if (allGranted) { // if (allGranted) {
// ToastHelper.showShort(this, "All permissions are granted") // ToastHelper.showShort(this, "All permissions are granted")
} else { jumpMain()
ToastHelper.showShort(this, "权限被拒") // } else {
binding.root.postDelayed({ //// ToastHelper.showShort(this, "权限被拒")
finish() //// binding.root.postDelayed({
}, 150) //// finish()
} //// }, 150)
// }
} }
} }
......
package com.sd.geelyhmiweb.utils
import android.annotation.SuppressLint
import android.content.Context
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.util.Log
class LocationUtils {
companion object {
private var instance: LocationUtils? = null
fun setLocManager(mContext: Context) {
if (instance == null) {
instance = LocationUtils(mContext)
}
}
fun getInstan(): LocationUtils {
return instance!!
}
}
private lateinit var locationManager: LocationManager
private var locationProvider: String = ""
private var location: Location? = null
// private lateinit var locationUtils: LocationUtils
// mContext: Context
private constructor()
constructor(mContext: Context) {
locationManager = mContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
}
@SuppressLint("MissingPermission")
fun getLocation() {
//1.获取位置管理器
// locationManager = mContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
//2.获取位置提供器,GPS或是NetWork
if (getProvider().isNullOrEmpty()) {
return
}
if (location != null) {
setLocation(location!!)
}
// 监视地理位置变化,第二个和第三个参数分别为更新的最短时间minTime和最短距离minDistace
locationManager.requestLocationUpdates(locationProvider, 1, 0f, locationListener)
}
@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) {
setLocation(locate)
}
return locate?.latitude.toString() + " " + locate?.longitude.toString()
}
private fun getProvider(): String {
val providers: List<String> = locationManager.getProviders(true)
if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
//如果是网络定位
// Log.d("TAG", "如果是网络定位")
locationProvider = LocationManager.NETWORK_PROVIDER
} else if (providers.contains(LocationManager.GPS_PROVIDER)) {
//如果是GPS定位
// Log.d("TAG", "如果是GPS定位")
locationProvider = LocationManager.GPS_PROVIDER
} else {
Log.d("TAG", "没有可用的位置提供器")
return ""
}
return locationProvider
}
//获取经纬度
fun showLocation(mContext: Context): Location? {
return location
}
private fun setLocation(location: Location) {
this.location = location
val loc = "${location.longitude} ${location.latitude}"
onJsLoc?.onJsLoc(loc)
}
//定位监听
private var locationListener = object : LocationListener {
override fun onLocationChanged(location: Location) {
// location.getAccuracy()//精确度
// Log.d("------", "定位改变: $location")
setLocation(location)
}
}
//JS 定位回调
var onJsLoc: OnJsLoc? = null
interface OnJsLoc {
fun onJsLoc(str: String)
}
/***停止定位**/
fun stopLoc() {
if (locationManager != null) {
locationManager.removeUpdates(locationListener)
}
}
}
\ No newline at end of file
...@@ -3,6 +3,14 @@ package com.sd.geelyhmiweb.utils ...@@ -3,6 +3,14 @@ package com.sd.geelyhmiweb.utils
object MyContants { object MyContants {
const val IS_DEBUG = true const val IS_DEBUG = true
var HOST = if (IS_DEBUG) "http://laravel.suiyigou.shop/" else "https://api.suixinsuiyi.cn/" var HOST = if (IS_DEBUG) "http://laravel.suiyigou.shop/" else "https://api.suixinsuiyi.cn/"
/**
* 加载webview 的方式
* 1 = Cesium
* 2 = ThreeJS
*/
var LOAD_WEB_FILE=1
// var PORT = if (IS_DEBUG) "123" else "34534" // var PORT = if (IS_DEBUG) "123" else "34534"
// var SOCKET_HOSTNAME = // var SOCKET_HOSTNAME =
...@@ -11,5 +19,4 @@ object MyContants { ...@@ -11,5 +19,4 @@ object MyContants {
// if (IS_DEBUG) 8082 else 0 // if (IS_DEBUG) 8082 else 0
} }
\ 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