这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
1. 取消app顶部样式
在AndroidManifest.xml
文件中修改android:theme
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
复制代码
2. 配置WebView
2.1. 在布局文件activity_main.xml
文件中添加WebView
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
复制代码
2.2. 配置WebView
属性
webView = findViewById<WebView>(R.id.web_view).apply {
loadUrl("file:///android_asset/dist/index.html") //这行从assets里面读取H5页面
// loadUrl("file:///${filesDir.path}/web/dist/index.html") //这行从本地文件读取H5页面。当前配置路径:/data/user/0/com.holland.myapp[包名]/files
//暴露调用方法。当前调用方式:window.$App.functionName[方法名](arg...)
addJavascriptInterface(JsInterface(this@MainActivity), "$App")
settings.apply {
//设置支持JS
javaScriptEnabled = true
//设置支持缩放
setSupportZoom(false)
//设置支持DomStorage
domStorageEnabled = true
}
//设置为app打开,而非网页打开
this.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
Log.d("shouldOverrideUrlLoading", "url: $url")
if (Uri.parse(url).host != HttpUtil.myServerHost) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
return true
}
return false
}
}
//打印h5 err日志
this.webChromeClient = object : WebChromeClient() {
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
when (consoleMessage.messageLevel()) {
MessageLevel.ERROR -> Log.e("H5", consoleMessage.message())
}
return super.onConsoleMessage(consoleMessage)
}
}
}
复制代码
2.2.1 配置调用方法JavascriptInterface
package com.holland.myapp.js_interface
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.webkit.JavascriptInterface
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.holland.myapp.CameraActivity
import com.holland.myapp.common.ActivityResultCode
import com.holland.myapp.util.CameraUtil
class JsInterface(private val activity: Activity) {
//使用安卓提示消息
@JavascriptInterface
fun onToast(msg: String?) = Toast.makeText(
activity,
if (msg == null) "消息为空" else if (msg.isBlank()) "消息为空" else msg,
Toast.LENGTH_SHORT
).show()
//使用CameraX拍照
@JavascriptInterface
fun onCameraX() = activity.startActivityForResult(
Intent(activity, CameraActivity::class.java),
ActivityResultCode.REQUEST_TAKE_PHOTO_CAMERA_X.ordinal
)
//使用Camera拍照
@JavascriptInterface
fun onCamera() =
// Request camera permissions
if (CameraActivity.REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(
activity, it
) == PackageManager.PERMISSION_GRANTED
}) {
CameraUtil.openCamera(activity)
} else {
ActivityCompat.requestPermissions(
activity,
CameraActivity.REQUIRED_PERMISSIONS,
CameraActivity.REQUEST_CODE_PERMISSIONS
)
}
}
复制代码
2.3. 配置当前Activity
属性
//设置返回事件
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val jsCall = JsCall(webView) //自定义回调方法
when (requestCode) {
ActivityResultCode.REQUEST_TAKE_PHOTO_CAMERA.ordinal -> {
jsCall.appCallJs(1, CameraUtil.currentPhotoPath)
}
else -> {
}
}
}
//设置返回键赋值给H5页面
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (webView.canGoBack()) {
webView.goBack()
return true
} else {
exitProcess(0)
}
}
return super.onKeyDown(keyCode, event)
}
复制代码
2.3.1 配置自定义回调方法JsCall
package com.holland.myapp.js_interface
import android.annotation.SuppressLint
import android.webkit.WebView
class JsCall(private val webView: WebView) {
/**
* @param type 1: 方法回调类型
* @param args 2: 参数列表
*/
@SuppressLint("ObsoleteSdkInt")
fun appCallJs(type: Int, vararg args: String) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("appCallJs(${composeParameter(type, *args)});", null)
} else {
webView.loadUrl("javascript:appCallJs(${composeParameter(type, *args)});")
}
}
private fun composeParameter(type: Int, vararg args: String): String {
return if (args.isEmpty()) {
"'$type'"
} else {
return "'$type',${args.map { "'$it'" }.reduce { acc, s -> "$acc,$s" }}"
}
}
}
复制代码
3. 配置H5(vue实现)
3.1. 页面
<template>
<div>
<van-field v-model="toast" center clearable label="安卓提示" placeholder="请输入提示内容">
<template #button>
<van-button size="small" type="primary" @click="onToast(toast)">发送</van-button>
</template>
</van-field>
<van-button type="info" @click="onCamera()">Camera拍照接口</van-button>
<van-button type="info" @click="onCameraX()">CameraX拍照接口</van-button>
<van-button type="info" @click="test()">测试按钮</van-button>
</div>
</template>
<script>
//引入与Android通信的方法
import AppInterface from "../uitl/AppInterface";
export default {
name: 'HomePage',
mixins: [AppInterface],
data() {
return {
toast: null,
}
}
}
</script>
复制代码
3.2 配置与Android通信的方法
export default {
methods: {
onToast(message) {
if (window.$App) $App.onToast(message)
},
onCamera() {
if (window.$App) $App.onCamera()
},
onCameraX() {
if (window.$App) $App.onCameraX()
}
}
}
window.appCallJs = function (type, args0, args1, args2, args3, args4, args5, args6, args7, args8, args9) {
switch (type) {
case '1':
/**
* 拍照完成,摄像机回传本地图片路径
* @param arg0 本地图片路径
*/
break;
default:
if (window.$App) window.$App.onToast(`收到参数: ${type}, ${args0}, ${args1}, ${args2}, ${args3}, ${args4}, ${args5}, ${args6}, ${args7}, ${args8}, ${args9}`)
}
}
复制代码
4. 实现效果
4.1. 总体页面
4.1. 使用安卓提示
4.2. 使用CameraX
4.3. H5报错提示
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END