物理按键

This commit is contained in:
844143714@qq,com 2026-04-27 22:48:58 +08:00
parent 5190f5d489
commit 4d12f780ea
5 changed files with 139 additions and 16 deletions

BIN
app/libs/ZY-Interface.jar Normal file

Binary file not shown.

View File

@ -52,7 +52,7 @@ public class pttActivity extends AppCompatActivity {
findViewById(R.id.login).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SendAtUtil.toLogin("gzzdweb01", "123456", "61.243.1.123", 1, 1);
SendAtUtil.toLogin("admin", "poc123456", "220.154.131.231", 1, 1);
}
});

View File

@ -131,17 +131,25 @@ class LoginActivity : AppCompatActivity() {
Toast.makeText(this@LoginActivity, "登录成功", Toast.LENGTH_SHORT).show()
// 1. 确保 PTT 引擎已初始化并登录
try {
// 确保 PTT 引擎已初始化
com.example.kingway.ptt.MyApplication.init(this@LoginActivity)
// 异步初始化 PTT 登录 (区分 Android 业务登录)
com.example.kingway.ptt.SendAtUtil.toLogin("gzzdweb01", "123456", "61.243.1.123", 1, 1)
} catch (e: Exception) {
Timber.tag("Login").e(e, "检查更新失败")
Timber.tag("PTT").e(e, "PTT init error")
}
// 初始化打印机 (异步)
// 2. 启动硬件 GPIO 监听
try {
com.stand.standapp.utils.GpioManager.init(this@LoginActivity)
com.stand.standapp.utils.GpioManager.startListening()
} catch (e: Exception) {
Timber.tag("GPIO").e(e, "GPIO init error")
}
// 3. 初始化打印机 (异步)
PrinterManager.init(this@LoginActivity)
startActivity(Intent(this@LoginActivity, MainActivity::class.java))
@ -150,6 +158,7 @@ class LoginActivity : AppCompatActivity() {
val msg = json.optString("msg", "登录失败")
Toast.makeText(this@LoginActivity, msg, Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
Timber.tag("Login").e(e, "解析响应失败")
Toast.makeText(this@LoginActivity, "服务器响应异常", Toast.LENGTH_SHORT).show()

View File

@ -37,9 +37,31 @@ class MainActivity : AppCompatActivity() {
Timber.tag("MainActivity").d("onPttLoginSuccess called from Native")
executeJs("onPttLoginSuccess")
}
// 硬件按键触发
@JvmStatic
fun onHardwarePttDown() {
instance?.runOnUiThread {
// 直接调用 JSBridge 对象的逻辑以复用保护机制
val jsInterface = instance?.mAgentWeb?.webCreator?.webView?.tag as? AndroidInterface
// 或者更直接一点,我们把逻辑抽离出来
instance?.pttInterface?.pttSpeakPlay()
// 通知 H5 更新 UI
executeJs("onHardwarePttDown")
}
}
@JvmStatic
fun onHardwarePttUp() {
instance?.runOnUiThread {
instance?.pttInterface?.pttSpeakRelease()
executeJs("onHardwarePttUp")
}
}
}
private var mAgentWeb: AgentWeb? = null
private var pttInterface: AndroidInterface? = null
private val mHandler = android.os.Handler(android.os.Looper.getMainLooper())
private val TIMEOUT_MS = 30000L
@ -79,21 +101,11 @@ class MainActivity : AppCompatActivity() {
}
})
.setWebViewClient(object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
cancelTimeoutTimer()
}
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
Timber.tag("WebError").e("URL: ${request?.url}, Error: ${error?.description} (Code: ${error?.errorCode})")
if (request?.isForMainFrame == true) {
showErrorPage()
}
super.onReceivedError(view, request, error)
}
// ...
})
.addJavascriptInterface("android", AndroidInterface(this))
.addJavascriptInterface("android", AndroidInterface(this).also { pttInterface = it })
.createAgentWeb()
.ready()
.go(finalUrl)

View File

@ -0,0 +1,102 @@
package com.stand.standapp.utils
import android.app.ZysjSystemManager
import android.content.Context
import android.os.Handler
import android.os.Looper
import com.stand.standapp.MainActivity
import timber.log.Timber
/**
* 硬件 GPIO 监听管理类 (用于物理 PTT 按键)
*/
object GpioManager {
private var mZysjSystemManager: ZysjSystemManager? = null
private var mIsRunning = false
private var mThread: Thread? = null
private var lastGpioValue = 1 // 默认松开状态 (1)
fun init(context: Context) {
if (mZysjSystemManager != null) return
try {
mZysjSystemManager = context.applicationContext.getSystemService("zysj") as? ZysjSystemManager
Timber.tag("GPIO").i("ZysjSystemManager initialized: ${mZysjSystemManager != null}")
} catch (e: Exception) {
Timber.tag("GPIO").e(e, "Failed to get ZysjSystemManager")
}
}
fun startListening() {
if (mIsRunning) return
mIsRunning = true
mThread = Thread {
Timber.tag("GPIO").i("Start GPIO listening thread")
while (mIsRunning) {
try {
// 硬件轮询频率优化50ms 既能保证响应速度,又能降低 CPU 消耗
Thread.sleep(50)
val manager = mZysjSystemManager ?: continue
// 获取 GPIO 1 的值 (0 按下, 1 松开)
val currentValue = manager.get_zysj_gpio_value(1)
if (currentValue != lastGpioValue) {
Timber.tag("GPIO").d("GPIO 1 Value changed: $lastGpioValue -> $currentValue")
handleGpioChange(currentValue)
lastGpioValue = currentValue
}
} catch (e: Exception) {
Timber.tag("GPIO").e(e, "Error in GPIO loop")
}
}
}.apply { start() }
}
fun stopListening() {
mIsRunning = false
mThread = null
}
private var isSpeaking = false
private var lastSpeakTime = 0L
private val MIN_SPEAK_DURATION = 200L
private fun handleGpioChange(value: Int) {
// 切换到主线程处理逻辑,确保线程安全且方便使用 Handler
Handler(Looper.getMainLooper()).post {
if (value == 0) {
// 硬件按下 PTT
if (!isSpeaking) {
isSpeaking = true
lastSpeakTime = System.currentTimeMillis()
com.example.kingway.ptt.SendAtUtil.speakPlay()
Timber.tag("GPIO").d("PTT Speak Play (Hardware)")
}
} else {
// 硬件松开 PTT
if (isSpeaking) {
val now = System.currentTimeMillis()
val duration = now - lastSpeakTime
if (duration < MIN_SPEAK_DURATION) {
val delay = MIN_SPEAK_DURATION - duration
Timber.tag("GPIO").d("Hardware speak duration too short ($duration ms), delaying release by $delay ms")
Handler(Looper.getMainLooper()).postDelayed({
realRelease()
}, delay)
} else {
realRelease()
}
}
}
}
}
private fun realRelease() {
if (isSpeaking) {
isSpeaking = false
com.example.kingway.ptt.SendAtUtil.speakRelease()
Timber.tag("GPIO").d("PTT Speak Release (Hardware)")
}
}
}