Browse Source

feat(notification): 改进音频录制通知并添加导航功能

增强通知点击处理逻辑,添加特定页面导航功能
重构深链接处理逻辑,支持从通知跳转到会议记录页面
更新通知标题和图标,使用应用图标并优化显示文本
weicu
lxm 9 months ago
parent
commit
d8193cd85e
  1. 75
      android/app/src/main/kotlin/com/saitong/voitrans/MainActivity.kt
  2. 15
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/AudioRecordingForegroundService.kt

75
android/app/src/main/kotlin/com/saitong/voitrans/MainActivity.kt

@ -19,6 +19,11 @@ import io.flutter.plugin.common.MethodChannel // 添加这行导入
class MainActivity: FlutterActivity() {
private val TAG = "MainActivity"
private var pendingDeepLink: Intent? = null
private var pendingNavigationIntent: Intent? = null
private val EXTRA_NAVIGATE_TO = "com.saitong.voitrans.extra.NAVIGATE_TO"
private val NAVIGATE_TO_MEETING_RECORD = "meetingRecord"
private val ROUTE_MEETING_RECORD = "/meeting/record"
override fun onCreate(savedInstanceState: Bundle?) {
Log.d(TAG, "🚀 MainActivity onCreate 开始")
@ -36,6 +41,11 @@ class MainActivity: FlutterActivity() {
pendingDeepLink = intent
Log.d(TAG, "🔗 暂存深链接,等待Flutter引擎准备完成")
}
if (intent?.hasExtra(EXTRA_NAVIGATE_TO) == true) {
pendingNavigationIntent = intent
Log.d(TAG, "🧭 暂存导航意图,等待Flutter引擎准备完成")
}
// 设置日志级别,减少系统级日志
suppressSystemLogs()
@ -54,7 +64,7 @@ class MainActivity: FlutterActivity() {
Log.d(TAG, "New Intent extras: ${intent.extras}")
// 处理深链接
handleDeepLink(intent)
handleNavigationIntent(intent)
}
override fun provideFlutterEngine(context: Context): FlutterEngine? {
@ -106,17 +116,29 @@ class MainActivity: FlutterActivity() {
Handler(Looper.getMainLooper()).postDelayed({
pendingDeepLink?.let { intent ->
Log.d(TAG, "🔗 处理待处理的深链接")
handleDeepLink(intent)
handleNavigationIntent(intent)
pendingDeepLink = null
}
pendingNavigationIntent?.let { intent ->
Log.d(TAG, "🧭 处理待处理的导航意图")
handleNavigationIntent(intent)
pendingNavigationIntent = null
}
}, 1000) // 延迟1秒确保Flutter完全准备好
Log.d(TAG, "✅ configureFlutterEngine 完成")
}
// 处理深链接的统一方法
private fun handleDeepLink(intent: Intent?) {
private fun handleNavigationIntent(intent: Intent?) {
intent?.let {
val navigateTo = it.getStringExtra(EXTRA_NAVIGATE_TO)
if (navigateTo == NAVIGATE_TO_MEETING_RECORD) {
pushRouteToFlutter(ROUTE_MEETING_RECORD)
return
}
if (it.action == Intent.ACTION_VIEW && it.data != null) {
val uri = it.data
Log.d(TAG, "🔗 处理深链接: $uri")
@ -133,16 +155,7 @@ class MainActivity: FlutterActivity() {
"com.saitong.voitrans/deeplink"
)
val arguments = mapOf(
"url" to uri.toString(),
"scheme" to uri?.scheme,
"host" to uri?.host,
"path" to uri?.path,
"query" to uri?.query,
"queryParameters" to uri?.queryParameterNames?.associateWith {
uri.getQueryParameter(it)
}
)
val arguments = buildUrlArguments(uri.toString())
Log.d(TAG, "🔗 准备发送参数: $arguments")
@ -160,6 +173,41 @@ class MainActivity: FlutterActivity() {
}
}
private fun pushRouteToFlutter(route: String) {
try {
val engine = flutterEngine
if (engine == null) {
Log.w(TAG, "❌ FlutterEngine 为空,无法 pushRoute")
return
}
Handler(Looper.getMainLooper()).post {
try {
engine.navigationChannel.pushRoute(route)
} catch (e: Exception) {
Log.e(TAG, "❌ pushRoute 失败", e)
}
}
} catch (e: Exception) {
Log.e(TAG, "❌ pushRouteToFlutter 出错", e)
}
}
private fun buildUrlArguments(url: String): Map<String, Any?> {
return try {
val uri = android.net.Uri.parse(url)
mapOf(
"url" to url,
"scheme" to uri.scheme,
"host" to uri.host,
"path" to uri.path,
"query" to uri.query,
"queryParameters" to uri.queryParameterNames.associateWith { uri.getQueryParameter(it) }
)
} catch (e: Exception) {
mapOf("url" to url)
}
}
override fun onDestroy() {
super.onDestroy()
}
@ -242,4 +290,3 @@ class MainActivity: FlutterActivity() {
}
}
}

15
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/AudioRecordingForegroundService.kt

@ -113,8 +113,10 @@ class AudioRecordingForegroundService : Service() {
* @return 通知对象
*/
private fun createNotification(): Notification {
// 创建点击通知时的意图(可以打开应用主界面)
val intent = packageManager.getLaunchIntentForPackage(packageName)
val intent = (packageManager.getLaunchIntentForPackage(packageName) ?: Intent()).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
putExtra("com.saitong.voitrans.extra.NAVIGATE_TO", "meetingRecord")
}
val pendingIntent = PendingIntent.getActivity(
this,
0,
@ -123,14 +125,15 @@ class AudioRecordingForegroundService : Service() {
)
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("语音助手正在运行")
.setContentText("正在录制音频,点击返回应用")
.setSmallIcon(android.R.drawable.ic_btn_speak_now) // 使用系统默认麦克风图标
.setContentTitle("Voitrans")
.setContentText("Recording audio, tap to return to app")
.setSmallIcon(applicationInfo.icon)
.setContentIntent(pendingIntent)
.setOngoing(true) // 设置为持续通知,用户无法滑动删除
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setShowWhen(false)
.setAutoCancel(false) // 点击通知后不自动取消
.build()
}
}
}

Loading…
Cancel
Save