|
|
@ -1,6 +1,7 @@ |
|
|
package com.yunqiinnovation.chat_api |
|
|
package com.yunqiinnovation.chat_api |
|
|
|
|
|
|
|
|
import android.Manifest |
|
|
import android.Manifest |
|
|
|
|
|
import android.app.ActivityManager |
|
|
import android.content.ContentUris |
|
|
import android.content.ContentUris |
|
|
import android.content.ContentValues |
|
|
import android.content.ContentValues |
|
|
import android.content.Context |
|
|
import android.content.Context |
|
|
@ -12,10 +13,12 @@ import android.os.Build |
|
|
import android.provider.AlarmClock |
|
|
import android.provider.AlarmClock |
|
|
import android.provider.CalendarContract |
|
|
import android.provider.CalendarContract |
|
|
import android.provider.ContactsContract |
|
|
import android.provider.ContactsContract |
|
|
|
|
|
import android.provider.Settings |
|
|
import android.telephony.SmsManager |
|
|
import android.telephony.SmsManager |
|
|
import android.util.Log |
|
|
import android.util.Log |
|
|
import androidx.core.content.ContextCompat |
|
|
import androidx.core.content.ContextCompat |
|
|
import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED |
|
|
import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED |
|
|
|
|
|
import org.json.JSONObject |
|
|
import java.text.SimpleDateFormat |
|
|
import java.text.SimpleDateFormat |
|
|
import java.util.* |
|
|
import java.util.* |
|
|
|
|
|
|
|
|
@ -24,6 +27,9 @@ import java.util.* |
|
|
* 提供内置的系统函数,与 iOS 版本保持一致 |
|
|
* 提供内置的系统函数,与 iOS 版本保持一致 |
|
|
*/ |
|
|
*/ |
|
|
class SystemFunctionHandler(private val context: Context? = null) { |
|
|
class SystemFunctionHandler(private val context: Context? = null) { |
|
|
|
|
|
companion object { |
|
|
|
|
|
const val TAG = "SystemFunctionHandler" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 注册所有系统函数 |
|
|
* 注册所有系统函数 |
|
|
@ -41,17 +47,17 @@ class SystemFunctionHandler(private val context: Context? = null) { |
|
|
handler = ExitInteractionHandler(context) |
|
|
handler = ExitInteractionHandler(context) |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
// 注册翻译模式函数 |
|
|
// // 注册翻译模式函数 |
|
|
client.registerLocalFunction( |
|
|
// client.registerLocalFunction( |
|
|
name = "enter_translation_mode", |
|
|
// name = "enter_translation_mode", |
|
|
description = "用户请求进入实时翻译模式时,启动实时翻译功能", |
|
|
// description = "用户请求进入实时翻译模式时,启动实时翻译功能", |
|
|
parameters = mapOf( |
|
|
// parameters = mapOf( |
|
|
"type" to "object", |
|
|
// "type" to "object", |
|
|
"properties" to emptyMap<String, Any>(), |
|
|
// "properties" to emptyMap<String, Any>(), |
|
|
"required" to emptyList<String>() |
|
|
// "required" to emptyList<String>() |
|
|
), |
|
|
// ), |
|
|
handler = TranslationModeHandler(context) |
|
|
// handler = TranslationModeHandler(context) |
|
|
) |
|
|
// ) |
|
|
|
|
|
|
|
|
// 注册发送短信函数 |
|
|
// 注册发送短信函数 |
|
|
client.registerLocalFunction( |
|
|
client.registerLocalFunction( |
|
|
@ -227,6 +233,171 @@ class SystemFunctionHandler(private val context: Context? = null) { |
|
|
handler = ExitNavigationHandler(context) |
|
|
handler = ExitNavigationHandler(context) |
|
|
) |
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 检查权限并根据应用状态采取不同行为 |
|
|
|
|
|
* @param permission 需要检查的权限 |
|
|
|
|
|
* @param permissionName 权限名称(用于显示给用户) |
|
|
|
|
|
* @param functionName 功能名称(用于日志和提示) |
|
|
|
|
|
* @return 是否拥有权限 |
|
|
|
|
|
*/ |
|
|
|
|
|
internal fun checkPermissionAndGuide(permission: String, permissionName: String, functionName: String): Boolean { |
|
|
|
|
|
val ctx = context ?: return false |
|
|
|
|
|
|
|
|
|
|
|
if (ContextCompat.checkSelfPermission(ctx, permission) != PackageManager.PERMISSION_GRANTED) { |
|
|
|
|
|
Log.w(TAG, "缺少${permissionName}权限,无法执行${functionName}") |
|
|
|
|
|
|
|
|
|
|
|
// 检查应用是否在前台 |
|
|
|
|
|
if (isAppInForeground()) { |
|
|
|
|
|
// 应用在前台,尝试发送广播通知主应用弹出权限申请对话框 |
|
|
|
|
|
try { |
|
|
|
|
|
val intent = Intent("com.yunqiinnovation.deepsound.action.REQUEST_PERMISSION").apply { |
|
|
|
|
|
setPackage(ctx.packageName) |
|
|
|
|
|
putExtra("permission", permission) |
|
|
|
|
|
putExtra("permissionName", permissionName) |
|
|
|
|
|
putExtra("functionName", functionName) |
|
|
|
|
|
addFlags(Intent.FLAG_RECEIVER_FOREGROUND) |
|
|
|
|
|
} |
|
|
|
|
|
ctx.sendBroadcast(intent) |
|
|
|
|
|
|
|
|
|
|
|
// 设置一个短暂延迟,让用户有时间响应权限请求 |
|
|
|
|
|
Thread.sleep(500) |
|
|
|
|
|
|
|
|
|
|
|
// 再次检查权限是否已授予 |
|
|
|
|
|
if (ContextCompat.checkSelfPermission(ctx, permission) == PackageManager.PERMISSION_GRANTED) { |
|
|
|
|
|
return true |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "请求权限失败: ${e.message}", e) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 如果权限仍未授予,引导用户到权限管理页面 |
|
|
|
|
|
try { |
|
|
|
|
|
val settingsIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { |
|
|
|
|
|
data = Uri.fromParts("package", ctx.packageName, null) |
|
|
|
|
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) |
|
|
|
|
|
} |
|
|
|
|
|
ctx.startActivity(settingsIntent) |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "打开权限设置页面失败: ${e.message}", e) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
return true |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 检查应用是否在前台运行 |
|
|
|
|
|
* @return 应用是否在前台 |
|
|
|
|
|
*/ |
|
|
|
|
|
internal fun isAppInForeground(): Boolean { |
|
|
|
|
|
val ctx = context ?: return false |
|
|
|
|
|
try { |
|
|
|
|
|
val activityManager = ctx.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager |
|
|
|
|
|
val appProcesses = activityManager.runningAppProcesses ?: return false |
|
|
|
|
|
val packageName = ctx.packageName |
|
|
|
|
|
|
|
|
|
|
|
for (appProcess in appProcesses) { |
|
|
|
|
|
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND |
|
|
|
|
|
&& appProcess.processName == packageName) { |
|
|
|
|
|
return true |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "检查应用状态失败: ${e.message}", e) |
|
|
|
|
|
} |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 根据联系人名称获取电话号码 |
|
|
|
|
|
* @param contact 联系人名称或电话号码 |
|
|
|
|
|
* @return 电话号码 |
|
|
|
|
|
*/ |
|
|
|
|
|
internal fun getPhoneNumberForContact(contact: String): String { |
|
|
|
|
|
val ctx = context ?: return "" |
|
|
|
|
|
|
|
|
|
|
|
// 如果输入的是电话号码(简单判断,包含数字和特殊符号) |
|
|
|
|
|
if (contact.matches(Regex("^[+\\d\\s\\-()]*\$")) && contact.any { it.isDigit() }) { |
|
|
|
|
|
// 移除非数字字符 |
|
|
|
|
|
return contact.replace(Regex("[^+\\d]"), "") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查读取联系人权限 |
|
|
|
|
|
if (!checkPermissionAndGuide(Manifest.permission.READ_CONTACTS, "读取联系人", "访问联系人")) { |
|
|
|
|
|
return "" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 从联系人数据库查询 |
|
|
|
|
|
try { |
|
|
|
|
|
val contentResolver = ctx.contentResolver |
|
|
|
|
|
val uri = Uri.withAppendedPath( |
|
|
|
|
|
ContactsContract.Contacts.CONTENT_FILTER_URI, |
|
|
|
|
|
Uri.encode(contact) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
val projection = arrayOf( |
|
|
|
|
|
ContactsContract.Contacts._ID, |
|
|
|
|
|
ContactsContract.Contacts.DISPLAY_NAME, |
|
|
|
|
|
ContactsContract.Contacts.HAS_PHONE_NUMBER |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
contentResolver.query(uri, projection, null, null, null)?.use { cursor -> |
|
|
|
|
|
if (cursor.moveToFirst()) { |
|
|
|
|
|
val hasPhoneNumber = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.HAS_PHONE_NUMBER)) |
|
|
|
|
|
|
|
|
|
|
|
if (hasPhoneNumber > 0) { |
|
|
|
|
|
val contactId = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID)) |
|
|
|
|
|
val phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI |
|
|
|
|
|
val phoneProjection = arrayOf(ContactsContract.CommonDataKinds.Phone.NUMBER) |
|
|
|
|
|
val phoneSelection = "${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} = ?" |
|
|
|
|
|
val phoneSelectionArgs = arrayOf(contactId) |
|
|
|
|
|
|
|
|
|
|
|
contentResolver.query(phoneUri, phoneProjection, phoneSelection, phoneSelectionArgs, null)?.use { phoneCursor -> |
|
|
|
|
|
if (phoneCursor.moveToFirst()) { |
|
|
|
|
|
return phoneCursor.getString(phoneCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "查询联系人信息失败: ${e.message}", e) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return "" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 获取默认日历ID |
|
|
|
|
|
*/ |
|
|
|
|
|
internal fun getDefaultCalendarId(): Long { |
|
|
|
|
|
val ctx = context ?: return -1L |
|
|
|
|
|
val projection = arrayOf(CalendarContract.Calendars._ID) |
|
|
|
|
|
var calendarId = -1L |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
val uri = CalendarContract.Calendars.CONTENT_URI |
|
|
|
|
|
val selection = "(${CalendarContract.Calendars.VISIBLE} = 1) AND (${CalendarContract.Calendars.IS_PRIMARY} = 1)" |
|
|
|
|
|
ctx.contentResolver.query(uri, projection, selection, null, null)?.use { cursor -> |
|
|
|
|
|
if (cursor.moveToFirst()) { |
|
|
|
|
|
calendarId = cursor.getLong(0) |
|
|
|
|
|
} else { |
|
|
|
|
|
// 如果没有找到主日历,尝试找任何可见的日历 |
|
|
|
|
|
ctx.contentResolver.query(uri, projection, "${CalendarContract.Calendars.VISIBLE} = 1", null, null)?.use { c -> |
|
|
|
|
|
if (c.moveToFirst()) { |
|
|
|
|
|
calendarId = c.getLong(0) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "获取默认日历ID失败: ${e.message}", e) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return calendarId |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
@ -234,12 +405,25 @@ class SystemFunctionHandler(private val context: Context? = null) { |
|
|
*/ |
|
|
*/ |
|
|
private class ExitNavigationHandler(private val context: Context?) : FunctionHandler { |
|
|
private class ExitNavigationHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 发送广播通知退出交互 |
|
|
// 发送广播通知退出交互 |
|
|
val intent = Intent("com.yunqiinnovation.amap_service.EXIT_NAVIGATION").apply { |
|
|
val intent = Intent("com.yunqiinnovation.amap_service.EXIT_NAVIGATION").apply { |
|
|
setPackage(context?.packageName) // 设置包名使其成为显式 Intent |
|
|
setPackage(context.packageName) // 设置包名使其成为显式 Intent |
|
|
} |
|
|
} |
|
|
context?.sendBroadcast(intent) |
|
|
context.sendBroadcast(intent) |
|
|
return "{\"broadcast\":false,\"result\": \"已结束当前导航服务\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已结束当前导航服务") |
|
|
|
|
|
put("broadcast", false) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -248,9 +432,21 @@ private class ExitNavigationHandler(private val context: Context?) : FunctionHan |
|
|
*/ |
|
|
*/ |
|
|
private class ExitInteractionHandler(private val context: Context?) : FunctionHandler { |
|
|
private class ExitInteractionHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 发送广播通知退出交互 |
|
|
// 发送广播通知退出交互 |
|
|
context?.sendBroadcast(Intent("com.yunqiinnovation.deepsound.EXIT_INTERACTION")) |
|
|
context.sendBroadcast(Intent("com.yunqiinnovation.deepsound.EXIT_INTERACTION")) |
|
|
return "{\"result\": \"已结束当前交互\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已结束当前交互") |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -259,9 +455,21 @@ private class ExitInteractionHandler(private val context: Context?) : FunctionHa |
|
|
*/ |
|
|
*/ |
|
|
private class TranslationModeHandler(private val context: Context?) : FunctionHandler { |
|
|
private class TranslationModeHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 发送广播通知进入翻译模式 |
|
|
// 发送广播通知进入翻译模式 |
|
|
context?.sendBroadcast(Intent("com.yunqiinnovation.deepsound.ENTER_TRANSLATION_MODE")) |
|
|
context.sendBroadcast(Intent("com.yunqiinnovation.deepsound.ENTER_TRANSLATION_MODE")) |
|
|
return "{\"result\": \"已进入翻译模式\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已进入翻译模式") |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -274,24 +482,75 @@ private class SendTextMessageHandler(private val context: Context?) : FunctionHa |
|
|
val message = arguments["message"] as? String |
|
|
val message = arguments["message"] as? String |
|
|
|
|
|
|
|
|
if (contact == null || message == null) { |
|
|
if (contact == null || message == null) { |
|
|
return "{\"result\": \"缺少必要参数\"}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "invalid_arguments") |
|
|
|
|
|
put("message", "缺少必要参数:contact 或 message") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val handler = context.let { SystemFunctionHandler(it) } |
|
|
|
|
|
|
|
|
return try { |
|
|
return try { |
|
|
val smsIntent = Intent(Intent.ACTION_SENDTO).apply { |
|
|
// 检查发送短信权限 |
|
|
data = Uri.parse("smsto:$contact") |
|
|
if (!handler.checkPermissionAndGuide(Manifest.permission.SEND_SMS, "发送短信", "发送短信")) { |
|
|
putExtra("sms_body", message) |
|
|
return JSONObject().apply { |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "permission_denied") |
|
|
|
|
|
put("message", "需要短信权限才能发送短信,请在权限管理中开启短信权限") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (context?.packageManager?.queryIntentActivities(smsIntent, 0)?.isNotEmpty() == true) { |
|
|
val phoneNumber = handler.getPhoneNumberForContact(contact) |
|
|
context.startActivity(smsIntent) |
|
|
if (phoneNumber.isEmpty()) { |
|
|
"{\"result\": \"已打开短信应用\"}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "contact_not_found") |
|
|
|
|
|
put("message", "未找到联系人信息: $contact") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 使用SmsManager发送短信 |
|
|
|
|
|
val smsManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { |
|
|
|
|
|
context.getSystemService(SmsManager::class.java) |
|
|
} else { |
|
|
} else { |
|
|
"{\"result\": \"无法打开短信应用\"}" |
|
|
@Suppress("DEPRECATION") |
|
|
|
|
|
SmsManager.getDefault() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 处理长短信 |
|
|
|
|
|
val parts = smsManager.divideMessage(message) |
|
|
|
|
|
if (parts.size == 1) { |
|
|
|
|
|
smsManager.sendTextMessage(phoneNumber, null, message, null, null) |
|
|
|
|
|
} else { |
|
|
|
|
|
smsManager.sendMultipartTextMessage(phoneNumber, null, parts, null, null) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("result", "已成功向${contact}发送短信") |
|
|
|
|
|
put("phone", phoneNumber) |
|
|
|
|
|
put("message", message) |
|
|
|
|
|
}.toString() |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
"{\"result\": \"发送短信失败:${e.message}\"}" |
|
|
Log.e(SystemFunctionHandler.TAG, "发送短信失败: ${e.message}", e) |
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "send_failed") |
|
|
|
|
|
put("message", "发送短信失败: ${e.message}") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -364,28 +623,73 @@ private class MakePhoneCallHandler(private val context: Context?) : FunctionHand |
|
|
val contact = arguments["contact"] as? String |
|
|
val contact = arguments["contact"] as? String |
|
|
|
|
|
|
|
|
if (contact == null) { |
|
|
if (contact == null) { |
|
|
return "{\"result\": \"缺少联系人参数\"}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "invalid_arguments") |
|
|
|
|
|
put("message", "缺少必要参数:contact") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val handler = context.let { SystemFunctionHandler(it) } |
|
|
|
|
|
|
|
|
return try { |
|
|
return try { |
|
|
// 检查拨打电话权限 |
|
|
// 检查拨打电话权限 |
|
|
if (!checkPermissionAndGuide(context!!,Manifest.permission.CALL_PHONE, "拨打电话", "拨打电话")) { |
|
|
if (!handler.checkPermissionAndGuide(Manifest.permission.CALL_PHONE, "拨打电话", "拨打电话")) { |
|
|
"{\"result\": \"需要电话权限才能拨打电话,请在权限管理中开启电话权限\"}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "permission_denied") |
|
|
|
|
|
put("message", "需要电话权限才能拨打电话,请在权限管理中开启电话权限") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val phoneNumber = getPhoneNumberForContact(contact) |
|
|
val phoneNumber = handler.getPhoneNumberForContact(contact) |
|
|
if (phoneNumber.isEmpty()) { |
|
|
if (phoneNumber.isEmpty()) { |
|
|
"{\"result\": \"未找到联系人信息: $contact\"}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "contact_not_found") |
|
|
|
|
|
put("message", "未找到联系人信息: $contact") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 创建拨号意图 |
|
|
// 创建拨号意图(使用ACTION_CALL直接拨打) |
|
|
val intent = Intent(Intent.ACTION_CALL) |
|
|
val intent = Intent(Intent.ACTION_CALL).apply { |
|
|
intent.data = Uri.parse("tel:$phoneNumber") |
|
|
data = Uri.parse("tel:$phoneNumber") |
|
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
context?.startActivity(intent) |
|
|
} |
|
|
"{\"result\": \"正在拨打${contact}的电话\"}" |
|
|
context.startActivity(intent) |
|
|
|
|
|
|
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("result", "正在拨打${contact}的电话") |
|
|
|
|
|
put("phone", phoneNumber) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} catch (e: SecurityException) { |
|
|
|
|
|
Log.e(SystemFunctionHandler.TAG, "拨打电话权限被拒绝: ${e.message}", e) |
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "permission_denied") |
|
|
|
|
|
put("message", "权限被拒绝,无法拨打电话") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
Log.e("ChatApi", "拨打电话失败: ${e.message}", e) |
|
|
Log.e(SystemFunctionHandler.TAG, "拨打电话失败: ${e.message}", e) |
|
|
"{\"result\": \"权限不足或者为查询到联系人\"}" |
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "call_failed") |
|
|
|
|
|
put("message", "拨打电话失败: ${e.message}") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
// return try { |
|
|
// return try { |
|
|
// val callIntent = Intent(Intent.ACTION_DIAL).apply { |
|
|
// val callIntent = Intent(Intent.ACTION_DIAL).apply { |
|
|
@ -549,38 +853,149 @@ private class SetReminderHandler(private val context: Context?) : FunctionHandle |
|
|
val timeString = arguments["time"] as? String |
|
|
val timeString = arguments["time"] as? String |
|
|
|
|
|
|
|
|
if (title == null || timeString == null) { |
|
|
if (title == null || timeString == null) { |
|
|
return "{\"result\": \"缺少必要参数\"}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "invalid_arguments") |
|
|
|
|
|
put("message", "缺少必要参数:title 或 time") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val handler = context.let { SystemFunctionHandler(it) } |
|
|
|
|
|
|
|
|
|
|
|
return try { |
|
|
|
|
|
// 解析时间 |
|
|
|
|
|
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()) |
|
|
|
|
|
val time = formatter.parse(timeString)?.time ?: run { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "invalid_time_format") |
|
|
|
|
|
put("message", "提醒时间格式无效,请使用'yyyy-MM-dd HH:mm'格式") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查日历权限 |
|
|
|
|
|
if (!handler.checkPermissionAndGuide(Manifest.permission.WRITE_CALENDAR, "日历写入", "设置提醒")) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "permission_denied") |
|
|
|
|
|
put("message", "需要日历权限才能创建提醒,请在权限管理中开启日历权限") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 直接使用ContentProvider写入日历 |
|
|
|
|
|
val endTime = time + 3600000 // 默认1小时后结束 |
|
|
|
|
|
|
|
|
|
|
|
// 获取默认日历ID |
|
|
|
|
|
val calendarId = handler.getDefaultCalendarId() |
|
|
|
|
|
if (calendarId == -1L) { |
|
|
|
|
|
Log.w(SystemFunctionHandler.TAG, "未找到默认日历") |
|
|
|
|
|
// 如果没有找到日历,尝试使用Intent创建 |
|
|
|
|
|
return tryCreateWithIntent(context, title, content, time) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建事件 |
|
|
|
|
|
val eventValues = ContentValues().apply { |
|
|
|
|
|
put(CalendarContract.Events.CALENDAR_ID, calendarId) |
|
|
|
|
|
put(CalendarContract.Events.TITLE, title) |
|
|
|
|
|
put(CalendarContract.Events.DESCRIPTION, content) |
|
|
|
|
|
put(CalendarContract.Events.DTSTART, time) |
|
|
|
|
|
put(CalendarContract.Events.DTEND, endTime) |
|
|
|
|
|
put(CalendarContract.Events.HAS_ALARM, 1) |
|
|
|
|
|
put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().id) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val eventUri = context.contentResolver.insert(CalendarContract.Events.CONTENT_URI, eventValues) |
|
|
|
|
|
if (eventUri == null) { |
|
|
|
|
|
Log.e(SystemFunctionHandler.TAG, "插入日历事件失败") |
|
|
|
|
|
return tryCreateWithIntent(context, title, content, time) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 获取事件ID |
|
|
|
|
|
val eventId = ContentUris.parseId(eventUri) |
|
|
|
|
|
|
|
|
|
|
|
// 添加提醒(15分钟前提醒) |
|
|
|
|
|
val reminderValues = ContentValues().apply { |
|
|
|
|
|
put(CalendarContract.Reminders.EVENT_ID, eventId) |
|
|
|
|
|
put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT) |
|
|
|
|
|
put(CalendarContract.Reminders.MINUTES, 15) // 提前15分钟提醒 |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val reminderUri = context.contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, reminderValues) |
|
|
|
|
|
if (reminderUri != null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已成功创建提醒: $title") |
|
|
|
|
|
put("title", title) |
|
|
|
|
|
put("content", content) |
|
|
|
|
|
put("time", timeString) |
|
|
|
|
|
put("eventId", eventId) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} else { |
|
|
|
|
|
// 仍然创建了事件,但没有提醒 |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已创建日历事件,但未设置提醒: $title") |
|
|
|
|
|
put("title", title) |
|
|
|
|
|
put("time", timeString) |
|
|
|
|
|
put("eventId", eventId) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(SystemFunctionHandler.TAG, "设置提醒失败: ${e.message}", e) |
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "reminder_failed") |
|
|
|
|
|
put("message", "设置提醒失败: ${e.message}") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun tryCreateWithIntent(context: Context, title: String, content: String, time: Long): String { |
|
|
|
|
|
return try { |
|
|
|
|
|
val calendarIntent = Intent(Intent.ACTION_INSERT).apply { |
|
|
|
|
|
data = CalendarContract.Events.CONTENT_URI |
|
|
|
|
|
putExtra(CalendarContract.Events.TITLE, title) |
|
|
|
|
|
putExtra(CalendarContract.Events.DESCRIPTION, content) |
|
|
|
|
|
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time) |
|
|
|
|
|
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, time + 3600000) |
|
|
|
|
|
putExtra(CalendarContract.Events.HAS_ALARM, 1) |
|
|
|
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (context.packageManager?.queryIntentActivities(calendarIntent, 0)?.isNotEmpty() == true) { |
|
|
|
|
|
context.startActivity(calendarIntent) |
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("result", "已打开日历应用创建提醒") |
|
|
|
|
|
put("title", title) |
|
|
|
|
|
put("content", content) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} else { |
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "no_calendar_app") |
|
|
|
|
|
put("message", "未找到可用的日历应用") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "intent_failed") |
|
|
|
|
|
put("message", "创建日历事件失败: ${e.message}") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
return setReminder(title,content,timeString) |
|
|
|
|
|
// return try { |
|
|
|
|
|
// // 解析时间 |
|
|
|
|
|
// val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault()) |
|
|
|
|
|
// val date = formatter.parse(timeString) |
|
|
|
|
|
// |
|
|
|
|
|
// if (date == null) { |
|
|
|
|
|
// return "{\"result\": \"时间格式错误\"}" |
|
|
|
|
|
// } |
|
|
|
|
|
// |
|
|
|
|
|
// // 创建日历事件 |
|
|
|
|
|
// val calendarIntent = Intent(Intent.ACTION_INSERT).apply { |
|
|
|
|
|
// data = CalendarContract.Events.CONTENT_URI |
|
|
|
|
|
// putExtra(CalendarContract.Events.TITLE, title) |
|
|
|
|
|
// putExtra(CalendarContract.Events.DESCRIPTION, content) |
|
|
|
|
|
// putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, date.time) |
|
|
|
|
|
// putExtra(CalendarContract.EXTRA_EVENT_END_TIME, date.time + 60 * 60 * 1000) // 默认1小时 |
|
|
|
|
|
// putExtra(CalendarContract.Events.HAS_ALARM, 1) |
|
|
|
|
|
// flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
|
|
// } |
|
|
|
|
|
// |
|
|
|
|
|
// if (context?.packageManager?.queryIntentActivities(calendarIntent, 0)?.isNotEmpty() == true) { |
|
|
|
|
|
// context.startActivity(calendarIntent) |
|
|
|
|
|
// "{\"result\": \"提醒设置成功\"}" |
|
|
|
|
|
// } else { |
|
|
|
|
|
// "{\"result\": \"无法打开日历应用\"}" |
|
|
|
|
|
// } |
|
|
|
|
|
// } catch (e: Exception) { |
|
|
|
|
|
// "{\"result\": \"设置提醒失败:${e.message}\"}" |
|
|
|
|
|
// } |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -592,16 +1007,61 @@ private class GetCurrentTimeHandler : FunctionHandler { |
|
|
val format = arguments["format"] as? String |
|
|
val format = arguments["format"] as? String |
|
|
|
|
|
|
|
|
return try { |
|
|
return try { |
|
|
val formatter = if (!format.isNullOrEmpty()) { |
|
|
val calendar = Calendar.getInstance() |
|
|
SimpleDateFormat(format, Locale.getDefault()) |
|
|
val date = calendar.time |
|
|
} else { |
|
|
|
|
|
SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss", Locale.CHINA) |
|
|
val timeStr = when (format?.lowercase(Locale.getDefault())) { |
|
|
|
|
|
"short" -> { |
|
|
|
|
|
SimpleDateFormat("HH:mm", Locale.getDefault()).format(date) |
|
|
|
|
|
} |
|
|
|
|
|
"date" -> { |
|
|
|
|
|
SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault()).format(date) |
|
|
|
|
|
} |
|
|
|
|
|
"time" -> { |
|
|
|
|
|
SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(date) |
|
|
|
|
|
} |
|
|
|
|
|
"full" -> { |
|
|
|
|
|
SimpleDateFormat("yyyy年MM月dd日 EEEE HH:mm:ss", Locale.getDefault()).format(date) |
|
|
|
|
|
} |
|
|
|
|
|
"iso" -> { |
|
|
|
|
|
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault()).format(date) |
|
|
|
|
|
} |
|
|
|
|
|
else -> { |
|
|
|
|
|
SimpleDateFormat("yyyy年MM月dd日 HH:mm", Locale.getDefault()).format(date) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 获取星期几 |
|
|
|
|
|
val weekDay = when (calendar.get(Calendar.DAY_OF_WEEK)) { |
|
|
|
|
|
Calendar.SUNDAY -> "星期日" |
|
|
|
|
|
Calendar.MONDAY -> "星期一" |
|
|
|
|
|
Calendar.TUESDAY -> "星期二" |
|
|
|
|
|
Calendar.WEDNESDAY -> "星期三" |
|
|
|
|
|
Calendar.THURSDAY -> "星期四" |
|
|
|
|
|
Calendar.FRIDAY -> "星期五" |
|
|
|
|
|
Calendar.SATURDAY -> "星期六" |
|
|
|
|
|
else -> "" |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val currentTime = formatter.format(Date()) |
|
|
// 根据格式决定是否添加星期几 |
|
|
"{\"result\": \"$currentTime\", \"time\": \"$currentTime\"}" |
|
|
val resultTime = when { |
|
|
|
|
|
format == "short" || format == "time" -> timeStr |
|
|
|
|
|
format == "full" -> timeStr // full格式已经包含了星期 |
|
|
|
|
|
else -> "$timeStr $weekDay" |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
JSONObject().apply { |
|
|
|
|
|
put("result", resultTime) |
|
|
|
|
|
put("time", resultTime) |
|
|
|
|
|
put("timestamp", date.time) |
|
|
|
|
|
}.toString() |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
"{\"result\": \"获取时间失败:${e.message}\"}" |
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "time_error") |
|
|
|
|
|
put("message", "获取时间失败: ${e.message}") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -612,21 +1072,24 @@ private class GetCurrentTimeHandler : FunctionHandler { |
|
|
private class GetCurrentLocationHandler(private val context: Context?) : FunctionHandler { |
|
|
private class GetCurrentLocationHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
if (context == null) { |
|
|
if (context == null) { |
|
|
return "{\"result\": \"上下文未初始化\", \"success\": false}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 检查位置权限 |
|
|
val handler = context.let { SystemFunctionHandler(it) } |
|
|
val hasPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
|
|
|
|
|
ContextCompat.checkSelfPermission( |
|
|
|
|
|
context, |
|
|
|
|
|
android.Manifest.permission.ACCESS_FINE_LOCATION |
|
|
|
|
|
) == PackageManager.PERMISSION_GRANTED |
|
|
|
|
|
} else { |
|
|
|
|
|
true |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!hasPermission) { |
|
|
// 检查位置权限 |
|
|
return "{\"result\": \"位置权限被拒绝。请前往设置中启用位置权限\", \"success\": false}" |
|
|
if (!handler.checkPermissionAndGuide(Manifest.permission.ACCESS_FINE_LOCATION, "位置信息", "获取位置")) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "permission_denied") |
|
|
|
|
|
put("message", "需要位置权限才能获取当前位置,请在权限管理中开启位置权限") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 检查位置服务是否启用 |
|
|
// 检查位置服务是否启用 |
|
|
@ -635,12 +1098,29 @@ private class GetCurrentLocationHandler(private val context: Context?) : Functio |
|
|
locationManager?.isProviderEnabled(LocationManager.NETWORK_PROVIDER) == true |
|
|
locationManager?.isProviderEnabled(LocationManager.NETWORK_PROVIDER) == true |
|
|
|
|
|
|
|
|
if (!isLocationEnabled) { |
|
|
if (!isLocationEnabled) { |
|
|
return "{\"result\": \"位置服务未启用。请前往设置中启用位置服务\", \"success\": false}" |
|
|
// 尝试引导用户打开位置服务 |
|
|
|
|
|
try { |
|
|
|
|
|
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) |
|
|
|
|
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
|
|
context.startActivity(intent) |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(SystemFunctionHandler.TAG, "打开位置设置失败: ${e.message}", e) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "location_disabled") |
|
|
|
|
|
put("message", "位置服务未启用,请打开GPS或网络定位") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 注意:实际的位置获取需要异步处理,这里只返回提示信息 |
|
|
// 注意:这里简化了实现,实际应该获取真实位置 |
|
|
// 在实际应用中应该使用 LocationCallback 或 Coroutines 来获取实时位置 |
|
|
// 在生产环境中应该使用 LocationManager 或 FusedLocationProviderClient 获取实际位置 |
|
|
return "{\"result\": \"需要通过位置服务获取当前位置\", \"success\": true}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "位置服务已启用,可以获取位置信息") |
|
|
|
|
|
put("note", "需要实现实际的位置获取逻辑") |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -649,12 +1129,26 @@ private class GetCurrentLocationHandler(private val context: Context?) : Functio |
|
|
*/ |
|
|
*/ |
|
|
private class MediaPlayHandler(private val context: Context?) : FunctionHandler { |
|
|
private class MediaPlayHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 发送媒体播放广播 |
|
|
// 发送媒体播放广播 |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_PLAY").apply { |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_PLAY").apply { |
|
|
setPackage(context?.packageName) // 设置包名使其成为显式 Intent |
|
|
setPackage(context.packageName) |
|
|
} |
|
|
} |
|
|
context?.sendBroadcast(intent) |
|
|
context.sendBroadcast(intent) |
|
|
return "{\"notreply\":true,\"broadcast\":false,\"result\": \"已开始播放媒体\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已开始播放媒体") |
|
|
|
|
|
put("notreply", true) |
|
|
|
|
|
put("broadcast", false) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -663,27 +1157,55 @@ private class MediaPlayHandler(private val context: Context?) : FunctionHandler |
|
|
*/ |
|
|
*/ |
|
|
private class MediaPauseHandler(private val context: Context?) : FunctionHandler { |
|
|
private class MediaPauseHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Log.d("MediaPauseHandler", "📤 正在发送广播 context = $context") |
|
|
Log.d("MediaPauseHandler", "📤 正在发送广播 context = $context") |
|
|
// 发送媒体暂停广播 |
|
|
// 发送媒体暂停广播 |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_PAUSE").apply { |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_PAUSE").apply { |
|
|
setPackage(context?.packageName) // 设置包名使其成为显式 Intent |
|
|
setPackage(context.packageName) |
|
|
} |
|
|
} |
|
|
context?.sendBroadcast(intent) |
|
|
context.sendBroadcast(intent) |
|
|
return "{\"notreply\":true,\"broadcast\":false,\"result\": \"已暂停媒体播放\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已暂停媒体播放") |
|
|
|
|
|
put("notreply", true) |
|
|
|
|
|
put("broadcast", false) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
/** |
|
|
/** |
|
|
* 媒体暂停处理器 |
|
|
* 媒体关闭处理器 |
|
|
*/ |
|
|
*/ |
|
|
private class MediaCloseHandler(private val context: Context?) : FunctionHandler { |
|
|
private class MediaCloseHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
Log.d("MediaPauseHandler", "📤 正在发送广播 context = $context") |
|
|
if (context == null) { |
|
|
// 发送媒体暂停广播 |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Log.d("MediaCloseHandler", "📤 正在发送广播 context = $context") |
|
|
|
|
|
// 发送媒体关闭广播 |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_CLOSE").apply { |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_CLOSE").apply { |
|
|
setPackage(context?.packageName) // 设置包名使其成为显式 Intent |
|
|
setPackage(context.packageName) |
|
|
} |
|
|
} |
|
|
context?.sendBroadcast(intent) |
|
|
context.sendBroadcast(intent) |
|
|
return "{\"notreply\":true,\"broadcast\":false,\"result\": \"已关闭媒体播放\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已关闭媒体播放") |
|
|
|
|
|
put("notreply", true) |
|
|
|
|
|
put("broadcast", false) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
/** |
|
|
/** |
|
|
@ -691,13 +1213,26 @@ private class MediaCloseHandler(private val context: Context?) : FunctionHandler |
|
|
*/ |
|
|
*/ |
|
|
private class MediaPreviousHandler(private val context: Context?) : FunctionHandler { |
|
|
private class MediaPreviousHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 发送切换上一首广播 |
|
|
// 发送切换上一首广播 |
|
|
// context?.applicationContext?.sendBroadcast(Intent("com.yunqiinnovation.music_service.MEDIA_PREVIOUS")) |
|
|
|
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_PREVIOUS").apply { |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_PREVIOUS").apply { |
|
|
setPackage(context?.packageName) // 设置包名使其成为显式 Intent |
|
|
setPackage(context.packageName) |
|
|
} |
|
|
} |
|
|
context?.sendBroadcast(intent) |
|
|
context.sendBroadcast(intent) |
|
|
return "{\"notreply\":true,\"broadcast\":false,\"result\": \"已切换到上一首\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已切换到上一首") |
|
|
|
|
|
put("notreply", true) |
|
|
|
|
|
put("broadcast", false) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -706,13 +1241,26 @@ private class MediaPreviousHandler(private val context: Context?) : FunctionHand |
|
|
*/ |
|
|
*/ |
|
|
private class MediaNextHandler(private val context: Context?) : FunctionHandler { |
|
|
private class MediaNextHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
|
|
|
if (context == null) { |
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 发送切换下一首广播 |
|
|
// 发送切换下一首广播 |
|
|
// context?.applicationContext?.sendBroadcast(Intent("com.yunqiinnovation.music_service.MEDIA_NEXT")) |
|
|
|
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_NEXT").apply { |
|
|
val intent = Intent("com.yunqiinnovation.music_service.MEDIA_NEXT").apply { |
|
|
setPackage(context?.packageName) // 设置包名使其成为显式 Intent |
|
|
setPackage(context.packageName) |
|
|
} |
|
|
} |
|
|
context?.sendBroadcast(intent) |
|
|
context.sendBroadcast(intent) |
|
|
return "{\"notreply\":true,\"broadcast\":false,\"result\": \"已切换到下一首\"}" |
|
|
|
|
|
|
|
|
return JSONObject().apply { |
|
|
|
|
|
put("result", "已切换到下一首") |
|
|
|
|
|
put("notreply", true) |
|
|
|
|
|
put("broadcast", false) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -722,7 +1270,12 @@ private class MediaNextHandler(private val context: Context?) : FunctionHandler |
|
|
private class OpenRecorderHandler(private val context: Context?) : FunctionHandler { |
|
|
private class OpenRecorderHandler(private val context: Context?) : FunctionHandler { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
override suspend fun handle(arguments: Map<String, Any>): String { |
|
|
if (context == null) { |
|
|
if (context == null) { |
|
|
return "{\"result\": \"上下文未初始化\"}" |
|
|
return JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "context_error") |
|
|
|
|
|
put("message", "上下文未初始化") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return try { |
|
|
return try { |
|
|
@ -739,18 +1292,32 @@ private class OpenRecorderHandler(private val context: Context?) : FunctionHandl |
|
|
when { |
|
|
when { |
|
|
context.packageManager?.queryIntentActivities(recordIntent, 0)?.isNotEmpty() == true -> { |
|
|
context.packageManager?.queryIntentActivities(recordIntent, 0)?.isNotEmpty() == true -> { |
|
|
context.startActivity(recordIntent) |
|
|
context.startActivity(recordIntent) |
|
|
"{\"result\": \"已打开录音机\"}" |
|
|
JSONObject().apply { |
|
|
|
|
|
put("result", "已打开录音机") |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
context.packageManager?.queryIntentActivities(recorderIntent, 0)?.isNotEmpty() == true -> { |
|
|
context.packageManager?.queryIntentActivities(recorderIntent, 0)?.isNotEmpty() == true -> { |
|
|
context.startActivity(recorderIntent) |
|
|
context.startActivity(recorderIntent) |
|
|
"{\"result\": \"已打开音频应用\"}" |
|
|
JSONObject().apply { |
|
|
|
|
|
put("result", "已打开音频应用") |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
else -> { |
|
|
else -> { |
|
|
"{\"result\": \"无法打开录音机应用\"}" |
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "no_recorder_app") |
|
|
|
|
|
put("message", "无法打开录音机应用") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
"{\"result\": \"打开录音机失败:${e.message}\"}" |
|
|
JSONObject().apply { |
|
|
|
|
|
put("error", JSONObject().apply { |
|
|
|
|
|
put("code", "recorder_failed") |
|
|
|
|
|
put("message", "打开录音机失败: ${e.message}") |
|
|
|
|
|
}) |
|
|
|
|
|
}.toString() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |