Compare commits

...

5 Commits
v3.3.3 ... main

15 changed files with 454 additions and 31 deletions

View File

@ -6,6 +6,10 @@
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature
android:name="android.hardware.camera.flash"
android:required="false" />
<uses-permission android:name="com.android.permission.GET_INSTALLED_APPS" />
<uses-permission
@ -74,6 +78,7 @@
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:name=".App"

View File

@ -10,4 +10,6 @@ data class AlarmSetting(
var music: String = "", //音乐文件
var repeatTimes: Int = 5, //振动重复次数0=无限循环,-1=禁用
var vibrate: String = "---___===___", //振动律动:=强振动, -弱震动, _不振动, 时长都是100ms
var flashTimes: Int = 5, //闪烁次数0=无限循环,-1=禁用
var flash: String = "XXOOXXOO", //闪烁律动X亮灯, O灭灯, 时长都是100ms
) : Serializable

View File

@ -14,6 +14,7 @@ data class TelegramSetting(
val proxyAuthenticator: Boolean = false,
val proxyUsername: String = "",
val proxyPassword: String = "",
val parseMode: String = "HTML",
) : Serializable {
fun getMethodCheckId(): Int {
@ -27,4 +28,12 @@ data class TelegramSetting(
else -> R.id.rb_proxyNone
}
}
}
fun getParseModeCheckId(): Int {
return when (parseMode) {
"TEXT" -> R.id.rb_parse_mode_text
"MarkdownV2" -> R.id.rb_parse_mode_markdown
else -> R.id.rb_parse_mode_html
}
}
}

View File

@ -38,6 +38,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import java.io.File
import java.util.Date
import java.util.Locale
@Page(name = "Alarm")
@Suppress("PrivatePropertyName", "DEPRECATION")
@ -103,10 +104,12 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
binding!!.rgAlarmState.check(R.id.rb_start_alarm)
binding!!.layoutAlarmSettings.visibility = View.VISIBLE
binding!!.layoutVibrateSettings.visibility = View.VISIBLE
binding!!.layoutFlashSettings.visibility = View.VISIBLE
} else {
binding!!.rgAlarmState.check(R.id.rb_stop_alarm)
binding!!.layoutAlarmSettings.visibility = View.GONE
binding!!.layoutVibrateSettings.visibility = View.GONE
binding!!.layoutFlashSettings.visibility = View.GONE
}
}
binding!!.xsbVolume.setDefaultValue(settingVo.volume)
@ -114,8 +117,14 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
binding!!.etMusicPath.setText(settingVo.music)
binding!!.xsbRepeatTimes.setDefaultValue(if (settingVo.repeatTimes >= 0) settingVo.repeatTimes else 0)
binding!!.etVibrationEffect.setText(settingVo.vibrate)
binding!!.xsbFlashTimes.setDefaultValue(if (settingVo.flashTimes >= 0) settingVo.flashTimes else 0)
binding!!.etFlashEffect.setText(settingVo.flash)
binding!!.sbEnableMusic.isChecked = settingVo.playTimes >= 0
binding!!.sbEnableVibrate.isChecked = settingVo.repeatTimes >= 0
binding!!.sbEnableFlash.isChecked = settingVo.flashTimes >= 0
binding!!.layoutAlarmSettingsContent.visibility = if (settingVo.playTimes >= 0) View.VISIBLE else View.GONE
binding!!.layoutVibrateSettingsContent.visibility = if (settingVo.repeatTimes >= 0) View.VISIBLE else View.GONE
binding!!.layoutFlashSettingsContent.visibility = if (settingVo.flashTimes >= 0) View.VISIBLE else View.GONE
}
override fun onDestroyView() {
@ -135,13 +144,20 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
binding!!.xsbPlayTimes.setOnSeekBarListener { _, _ ->
checkSetting(true)
}
binding!!.xsbRepeatTimes.setOnSeekBarListener { _, _ ->
checkSetting(true)
}
binding!!.rgAlarmState.setOnCheckedChangeListener { _, checkedId ->
binding!!.layoutAlarmSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
binding!!.layoutVibrateSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
binding!!.layoutFlashSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
checkSetting(true)
}
binding!!.btInsertVibrationEffect1.setOnClickListener(this)
binding!!.btInsertVibrationEffect2.setOnClickListener(this)
binding!!.btInsertVibrationEffect3.setOnClickListener(this)
binding!!.btInsertFlashEffect1.setOnClickListener(this)
binding!!.btInsertFlashEffect2.setOnClickListener(this)
}
@SingleClick
@ -163,6 +179,16 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
return
}
R.id.bt_insert_flash_effect_1 -> {
CommonUtils.insertOrReplaceText2Cursor(binding!!.etFlashEffect, "X")
return
}
R.id.bt_insert_flash_effect_2 -> {
CommonUtils.insertOrReplaceText2Cursor(binding!!.etFlashEffect, "O")
return
}
R.id.btn_file_picker -> {
// 申请储存权限
XXPermissions.with(this).permission(Permission.MANAGE_EXTERNAL_STORAGE).request(object : OnPermissionCallback {
@ -196,15 +222,20 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
}
R.id.btn_test -> {
val permissions = arrayListOf<String>()
permissions.add(Permission.WRITE_SETTINGS)
if (binding!!.sbEnableFlash.isChecked) {
permissions.add(Permission.CAMERA)
}
// 申请修改系统设置权限
XXPermissions.with(this).permission(Permission.WRITE_SETTINGS).request(object : OnPermissionCallback {
XXPermissions.with(this).permission(permissions).request(object : OnPermissionCallback {
@SuppressLint("SetTextI18n")
override fun onGranted(permissions: List<String>, all: Boolean) {
mCountDownHelper?.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
if (settingVo.playTimes < 0 && settingVo.repeatTimes < 0) {
if (settingVo.playTimes < 0 && settingVo.repeatTimes < 0 && settingVo.flashTimes < 0) {
XToastUtils.error(getString(R.string.alarm_settings_error))
return
}
@ -242,12 +273,17 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
}
R.id.btn_save -> {
val permissions = arrayListOf<String>()
permissions.add(Permission.WRITE_SETTINGS)
if (binding!!.sbEnableFlash.isChecked) {
permissions.add(Permission.CAMERA)
}
// 申请修改系统设置权限
XXPermissions.with(this).permission(Permission.WRITE_SETTINGS).request(object : OnPermissionCallback {
XXPermissions.with(this).permission(permissions).request(object : OnPermissionCallback {
@SuppressLint("SetTextI18n")
override fun onGranted(permissions: List<String>, all: Boolean) {
val settingVo = checkSetting()
if (settingVo.playTimes < 0 && settingVo.repeatTimes < 0) {
if (settingVo.playTimes < 0 && settingVo.repeatTimes < 0 && settingVo.flashTimes < 0) {
XToastUtils.error(getString(R.string.alarm_settings_error))
return
}
@ -285,11 +321,14 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
private fun checkSetting(updateView: Boolean = false): AlarmSetting {
val enableMusic = binding!!.sbEnableMusic.isChecked
val enableVibrate = binding!!.sbEnableVibrate.isChecked
val enableFlash = binding!!.sbEnableFlash.isChecked
val volume = binding!!.xsbVolume.selectedNumber
var playTimes = binding!!.xsbPlayTimes.selectedNumber
val music = binding!!.etMusicPath.text.toString().trim()
var repeatTimes = binding!!.xsbRepeatTimes.selectedNumber
val vibrationEffect = binding!!.etVibrationEffect.text.toString().trim()
var flashTimes = binding!!.xsbFlashTimes.selectedNumber
var flashEffect = binding!!.etFlashEffect.text.toString().trim()
val description = StringBuilder()
val action = if (binding!!.rgAlarmState.checkedRadioButtonId == R.id.rb_start_alarm) {
description.append(getString(R.string.start_alarm))
@ -309,6 +348,14 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
} else {
repeatTimes = -1
}
if (enableFlash) {
flashEffect.ifEmpty { "XXOOXXOO".also { binding!!.etFlashEffect.setText(it) } }
flashEffect = flashEffect.toUpperCase(Locale.ROOT).replace("1", "X").replace("0", "O")
description.append(", ").append(getString(R.string.alarm_flash_effect)).append(":").append(flashEffect)
description.append(", ").append(getString(R.string.alarm_repeat_times)).append(":").append(flashTimes)
} else {
flashTimes = -1
}
"start"
} else {
description.append(getString(R.string.stop_alarm))
@ -319,7 +366,7 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
binding!!.tvDescription.text = description.toString()
}
return AlarmSetting(description.toString(), action, volume, playTimes, music, repeatTimes, vibrationEffect)
return AlarmSetting(description.toString(), action, volume, playTimes, music, repeatTimes, vibrationEffect, flashTimes, flashEffect)
}
private fun findAudioFiles(directoryPath: String): List<String> {

View File

@ -133,6 +133,7 @@ class TelegramFragment : BaseFragment<FragmentSendersTelegramBinding?>(), View.O
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
binding!!.rgParseMode.check(settingVo.getParseModeCheckId())
}
}
})
@ -251,8 +252,13 @@ class TelegramFragment : BaseFragment<FragmentSendersTelegramBinding?>(), View.O
}
val method = if (binding!!.rgMethod.checkedRadioButtonId == R.id.rb_method_get) "GET" else "POST"
val parseMode = when (binding!!.rgParseMode.checkedRadioButtonId) {
R.id.rb_parse_mode_text -> "TEXT"
R.id.rb_parse_mode_markdown -> "MarkdownV2"
else -> "HTML"
}
return TelegramSetting(method, apiToken, chatId, proxyType, proxyHost, proxyPort, proxyAuthenticator, proxyUsername, proxyPassword)
return TelegramSetting(method, apiToken, chatId, proxyType, proxyHost, proxyPort, proxyAuthenticator, proxyUsername, proxyPassword, parseMode)
}
override fun onDestroyView() {

View File

@ -36,6 +36,7 @@ import com.idormy.sms.forwarder.utils.EXTRA_UPDATE_NOTIFICATION
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_ID
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_NAME
import com.idormy.sms.forwarder.utils.FRONT_NOTIFY_ID
import com.idormy.sms.forwarder.utils.FlashUtils
import com.idormy.sms.forwarder.utils.INTENT_FRPC_APPLY_FILE
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.SettingUtils
@ -97,6 +98,10 @@ class ForegroundService : Service() {
private lateinit var vibrationUtils: VibrationUtils
private var isVibrating = false
// 闪光灯控制
private lateinit var flashUtils: FlashUtils
private var isFlash = false
// 音乐播放器
private var alarmPlayer: MediaPlayer? = null
private var alarmPlayTimes = 0
@ -106,6 +111,10 @@ class ForegroundService : Service() {
if (vibrationUtils.isVibrating) {
vibrationUtils.stopVibration()
}
//停止闪光灯
if (flashUtils.isFlashing) {
flashUtils.stopFlashing()
}
//停止播放音乐
alarmPlayer?.release()
alarmPlayer = null
@ -182,6 +191,11 @@ class ForegroundService : Service() {
isVibrating = true
vibrationUtils.startVibration(alarm.vibrate, alarm.repeatTimes)
}
//闪光灯提醒
if (alarm.flashTimes >= 0) {
isFlash = true
flashUtils.startFlashing(alarm.flash, alarm.flashTimes)
}
}
}
@ -200,6 +214,9 @@ class ForegroundService : Service() {
//初始化振动
vibrationUtils = VibrationUtils(this)
//初始化闪光灯
flashUtils = FlashUtils(this)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@ -235,7 +252,7 @@ class ForegroundService : Service() {
override fun onDestroy() {
//非纯客户端模式
if (!SettingUtils.enablePureClientMode) stopForegroundService()
flashUtils.release()
super.onDestroy()
}
@ -319,6 +336,10 @@ class ForegroundService : Service() {
if (vibrationUtils.isVibrating) {
vibrationUtils.stopVibration()
}
//停止闪光灯
if (flashUtils.isFlashing) {
flashUtils.stopFlashing()
}
} catch (e: Exception) {
handleException(e, "stopForegroundService")
}

View File

@ -0,0 +1,116 @@
@file:Suppress("DEPRECATION")
package com.idormy.sms.forwarder.utils
import android.content.Context
import android.hardware.Camera
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraManager
import android.os.Build
import android.os.Handler
import android.os.Looper
class FlashUtils(context: Context) {
private var cameraManager: CameraManager? = null
private var cameraId: String? = null
private var legacyCamera: Camera? = null
private var legacyParams: Camera.Parameters? = null
private var handler: Handler? = null
private val duration = 100L // 闪烁持续时间
var isFlashing = false
private set
init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
try {
cameraId = cameraManager?.cameraIdList?.get(0) // 获取后置摄像头 ID
} catch (e: CameraAccessException) {
e.printStackTrace()
}
} else {
try {
legacyCamera = Camera.open()
legacyParams = legacyCamera?.parameters
} catch (e: Exception) {
e.printStackTrace()
}
}
}
/**
* 按照模式控制闪光灯
* @param pattern 例如 "XXOOXXOO" X-O-
* @param repeatTimes 闪烁的重复次数0 表示无限循环
*/
fun startFlashing(pattern: String, repeatTimes: Int) {
if (isFlashing) return
isFlashing = true
handler = Handler(Looper.getMainLooper())
val sequence = pattern.toCharArray()
var index = 0
var repeatCount = 0
val runnable = object : Runnable {
override fun run() {
if (!isFlashing) return
val shouldFlash = sequence[index] == 'X' || sequence[index] == '1'
setFlashlight(shouldFlash)
index++
if (index >= sequence.size) {
index = 0
repeatCount++
if (repeatTimes != 0 && repeatCount >= repeatTimes) {
stopFlashing()
return
}
}
handler?.postDelayed(this, duration)
}
}
handler?.post(runnable)
}
/**
* 关闭闪光灯并停止模式
*/
fun stopFlashing() {
isFlashing = false
handler?.removeCallbacksAndMessages(null)
setFlashlight(false) // 确保停止后灯是关闭的
}
/**
* 设置闪光灯状态兼容 Android 4.4+
*/
private fun setFlashlight(enable: Boolean) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
cameraManager?.setTorchMode(cameraId!!, enable)
} else {
legacyParams?.flashMode = if (enable) Camera.Parameters.FLASH_MODE_TORCH else Camera.Parameters.FLASH_MODE_OFF
legacyCamera?.parameters = legacyParams
if (enable) legacyCamera?.startPreview() else legacyCamera?.stopPreview()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 释放旧 API 资源
*/
fun release() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
legacyCamera?.stopPreview()
legacyCamera?.release()
legacyCamera = null
}
}
}

View File

@ -67,7 +67,11 @@ class BarkUtils {
if (!TextUtils.isEmpty(setting.level)) msgMap["level"] = setting.level
if (!TextUtils.isEmpty(setting.sound)) msgMap["sound"] = setting.sound
if (!TextUtils.isEmpty(setting.badge)) msgMap["badge"] = setting.badge
if (!TextUtils.isEmpty(setting.url)) msgMap["url"] = setting.url
if (!TextUtils.isEmpty(setting.url)) {
val replacedUrl = msgInfo.getContentForSend(setting.url)
msgMap["url"] = replacedUrl
}
if (!TextUtils.isEmpty(setting.call)) msgMap["call"] = setting.call
//自动复制

View File

@ -58,13 +58,29 @@ class TelegramUtils private constructor() {
val request = if (setting.method == "GET") {
requestUrl += "?chat_id=" + setting.chatId + "&text=" + URLEncoder.encode(content, "UTF-8")
if (setting.parseMode.isNotEmpty() && setting.parseMode != "TEXT") {
requestUrl += "&parse_mode=" + setting.parseMode
}
Log.i(TAG, "requestUrl:$requestUrl")
XHttp.get(requestUrl)
} else {
val bodyMap: MutableMap<String, Any> = mutableMapOf()
bodyMap["chat_id"] = setting.chatId
bodyMap["text"] = content
bodyMap["parse_mode"] = "HTML"
when (setting.parseMode) {
"MarkdownV2" -> {
bodyMap["parse_mode"] = "MarkdownV2"
bodyMap["text"] = escapeMarkdownV2(content)
}
"HTML" -> {
bodyMap["parse_mode"] = "HTML"
bodyMap["text"] = content
}
else -> {
bodyMap["text"] = content
}
}
bodyMap["disable_web_page_preview"] = "true"
val requestMsg: String = Gson().toJson(bodyMap)
Log.i(TAG, "requestMsg:$requestMsg")
@ -155,5 +171,18 @@ class TelegramUtils private constructor() {
}
return buffer.toString()
}
// 用于转义 MarkdownV2 特殊字符的方法
private fun escapeMarkdownV2(text: String): String {
// TODO: MarkdownV2 要求转义以下字符,实测不能全部转义(丢失格式)
//val specialChars = listOf('_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!')
val specialChars = listOf('-')
var escapedText = text
for (char in specialChars) {
// 将每个字符替换为带反斜杠的形式
escapedText = escapedText.replace(char.toString(), "\\$char")
}
return escapedText
}
}
}
}

View File

@ -102,6 +102,44 @@
</LinearLayout>
<LinearLayout
style="@style/BarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/parse_mode"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/rg_parse_mode"
style="@style/rg_style"
android:layout_marginStart="5dp"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_parse_mode_text"
style="@style/rg_rb_style"
android:text="@string/parse_mode_text" />
<RadioButton
android:id="@+id/rb_parse_mode_html"
style="@style/rg_rb_style"
android:checked="true"
android:text="@string/parse_mode_html" />
<RadioButton
android:id="@+id/rb_parse_mode_markdown"
style="@style/rg_rb_style"
android:text="@string/parse_mode_markdown" />
</RadioGroup>
</LinearLayout>
<LinearLayout
style="@style/BarStyle"
android:layout_width="match_parent"
@ -306,4 +344,4 @@
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -209,7 +209,6 @@
</LinearLayout>
<LinearLayout
android:id="@+id/layout_vibrate_settings"
style="@style/BarStyle"
@ -326,6 +325,116 @@
</LinearLayout>
<LinearLayout
android:id="@+id/layout_flash_settings"
style="@style/BarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/alarm_flash_settings"
android:textStyle="bold"
tools:ignore="RelativeOverlap" />
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
android:id="@+id/sb_enable_flash"
style="@style/SwitchButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout_flash_settings_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="5dp"
android:background="?attr/xui_config_color_separator_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/alarm_flash_effect"
android:textStyle="bold" />
<com.xuexiang.xui.widget.edittext.ClearEditText
android:id="@+id/et_flash_effect"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:hint="@string/alarm_flash_effect_tips"
android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
android:id="@+id/bt_insert_flash_effect_1"
style="@style/insertButtonStyle"
android:text="@string/alarm_flash_effect_1" />
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
android:id="@+id/bt_insert_flash_effect_2"
style="@style/insertButtonStyle"
android:layout_marginStart="5dp"
android:text="@string/alarm_flash_effect_2" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/alarm_repeat_times"
android:textStyle="bold" />
<com.xuexiang.xui.widget.picker.XSeekBar
android:id="@+id/xsb_flash_times"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:padding="0dp"
app:xsb_max="30"
app:xsb_min="0" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -309,6 +309,10 @@
<string name="TelegramApiToken">ApiToken or Custom Proxy Address (startwith http)</string>
<string name="TelegramChatId">ChatId</string>
<string name="Method" formatted="false">Method</string>
<string name="parse_mode">Parse Mode</string>
<string name="parse_mode_text">Text</string>
<string name="parse_mode_html">Html</string>
<string name="parse_mode_markdown">MarkdownV2</string>
<string name="SmsSimSlot">SIM Slot</string>
<string name="same_source">Same source</string>
@ -1161,7 +1165,12 @@
<string name="alarm_vibration_effect_1">Strong vibration</string>
<string name="alarm_vibration_effect_2">Weak vibration</string>
<string name="alarm_vibration_effect_3">No vibration</string>
<string name="alarm_settings_error">At least one of Play Music/Vibrate Phone must be enabled</string>
<string name="alarm_flash_settings">Flash Phone</string>
<string name="alarm_flash_effect">Flash Effect</string>
<string name="alarm_flash_effect_tips">Syntax: 1 or X [turn on flash], 0 or O [turn off flash], each time 100ms</string>
<string name="alarm_flash_effect_1">Turn on flash 100ms</string>
<string name="alarm_flash_effect_2">Turn off flash 100ms</string>
<string name="alarm_settings_error">At least one of Play Music/Vibrate Phone/Flash Phone must be enabled</string>
<string name="invalid_tag" formatted="false">%s tag is invalid: %s</string>
<string name="invalid_task_name">Please input task name.</string>

View File

@ -15,7 +15,7 @@
<string name="insert_tag_call_type">通话类型</string>
<string name="insert_tag_location">定位信息</string>
<string name="insert_tag_location_longitude">定位经度</string>
<string name="insert_tag_location_latitude">定位</string>
<string name="insert_tag_location_latitude">定位</string>
<string name="insert_tag_location_address">定位地址</string>
<string name="insert_tag_battery_pct">电池电量</string>
<string name="insert_tag_battery_status">电池状态</string>
@ -310,6 +310,10 @@
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
<string name="Method" formatted="false">请求方式</string>
<string name="parse_mode">解析模式</string>
<string name="parse_mode_text">Text</string>
<string name="parse_mode_html">Html</string>
<string name="parse_mode_markdown">MarkdownV2</string>
<string name="SmsSimSlot">发送卡槽</string>
<string name="same_source">原进原出</string>
@ -729,7 +733,7 @@
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
<string name="location_longitude">经度:%s</string>
<string name="location_latitude">度:%s</string>
<string name="location_latitude">度:%s</string>
<string name="location_address">地址:%s</string>
<string name="location_time">时间:%s</string>
<string name="location_provider">供应商:%s</string>
@ -1094,7 +1098,7 @@
<string name="calc_type_distance">根据GPS坐标计算距离</string>
<string name="calc_type_address">根据地址关键字判断</string>
<string name="longitude">经度</string>
<string name="latitude"></string>
<string name="latitude"></string>
<string name="distance1">以经纬度为中心,</string>
<string name="distance2">米半径建立电子围栏</string>
<string name="current_coordinates">当前坐标</string>
@ -1162,7 +1166,12 @@
<string name="alarm_vibration_effect_1">强振动 100ms</string>
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
<string name="alarm_vibration_effect_3">不振动 100ms</string>
<string name="alarm_settings_error">播放音乐/振动手机必须至少开启一个</string>
<string name="alarm_flash_settings">闪烁手机</string>
<string name="alarm_flash_effect">闪光效果</string>
<string name="alarm_flash_effect_tips">语法1或X[开启闪光灯], 0或O[关闭闪光灯], 每次100ms</string>
<string name="alarm_flash_effect_1">开启闪光灯 100ms</string>
<string name="alarm_flash_effect_2">关闭闪光灯 100ms</string>
<string name="alarm_settings_error">播放音乐/振动手机/闪烁手机必须至少开启一个</string>
<string name="invalid_tag" formatted="false">%s 标签无效:%s</string>
<string name="invalid_task_name">请输入任务名称</string>

View File

@ -218,8 +218,14 @@
<string name="switch_rule_status">啟用該條轉發規則</string>
<string name="invalid_match_value">匹配的值不可為空</string>
<string name="invalid_call_type">通話類型不正確只能填寫1到6的任意一個數字</string>
<!--SenderActivity-->
<string name="mon">星期一</string>
<string name="tue">星期二</string>
<string name="wed">星期三</string>
<string name="thu">星期四</string>
<string name="fri">星期五</string>
<string name="sat">星期六</string>
<string name="sun">星期日</string>
<!--SenderActivity-->
<string name="delete_sender_title">發送通道操作確認</string>
<string name="delete_sender_tips">刪除發送通道後會級聯刪除其相關的轉發規則、轉發日誌的所有記錄!\n\n確定刪除該條發送通道</string>
<string name="delete_sender_toast">該條發送通道已經刪除!</string>
@ -304,6 +310,10 @@
<string name="TelegramApiToken">ApiToken 或 自定義代理地址(http開頭)</string>
<string name="TelegramChatId">被通知人(或群組)的ChatId</string>
<string name="Method" formatted="false">請求方式</string>
<string name="parse_mode">解析模式</string>
<string name="parse_mode_text">Text</string>
<string name="parse_mode_html">Html</string>
<string name="parse_mode_markdown">MarkdownV2</string>
<string name="SmsSimSlot">發送卡槽</string>
<string name="same_source">原進原出</string>
@ -1156,7 +1166,13 @@
<string name="alarm_vibration_effect_1">強振動 100ms</string>
<string name="alarm_vibration_effect_2">弱振動 100ms</string>
<string name="alarm_vibration_effect_3">不振動 100ms</string>
<string name="alarm_settings_error">播放音樂/振動手機必須至少開啟一個</string>
<string name="alarm_flash_settings">閃爍手機</string>
<string name="alarm_flash_effect">閃光效果</string>
<string name="alarm_flash_effect_tips">語法1或X[開啟閃光燈]0或O[關閉閃光燈]每次300毫秒</string>
<string name="alarm_flash_effect_1">開啟閃光燈 300毫秒</string>
<string name="alarm_flash_effect_2">關閉閃光燈 300毫秒</string>
<string name="alarm_settings_error">播放音樂/振動手機/閃爍手機必須至少開啟一個</string>
<string name="invalid_tag" formatted="false">%s 標籤無效:%s</string>
<string name="invalid_task_name">請輸入任務名稱</string>
@ -1180,10 +1196,4 @@
<string name="start_discovery">搜索裝置</string>
<string name="invalid_bluetooth_mac_address">藍牙裝置MAC地址無效例如AA:BB:CC:DD:EE:FF</string>
<string name="auto_start_redmi"><![CDATA[紅米手機:授權管理 -> 自啟動管理 -> 允許應用自啟動]]></string>
<string name="mon">星期一</string>
<string name="tue">星期二</string>
<string name="wed">星期三</string>
<string name="thu">星期四</string>
<string name="fri">星期五</string>
<string name="sat">星期六</string>
</resources>

View File

@ -44,7 +44,7 @@
<string name="insert_tag_call_type">通话类型</string>
<string name="insert_tag_location">定位信息</string>
<string name="insert_tag_location_longitude">定位经度</string>
<string name="insert_tag_location_latitude">定位</string>
<string name="insert_tag_location_latitude">定位</string>
<string name="insert_tag_location_address">定位地址</string>
<string name="insert_tag_battery_pct">电池电量</string>
<string name="insert_tag_battery_status">电池状态</string>
@ -339,6 +339,10 @@
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
<string name="Method" formatted="false">请求方式</string>
<string name="parse_mode">解析模式</string>
<string name="parse_mode_text">Text</string>
<string name="parse_mode_html">Html</string>
<string name="parse_mode_markdown">MarkdownV2</string>
<string name="SmsSimSlot">发送卡槽</string>
<string name="same_source">原进原出</string>
@ -758,7 +762,7 @@
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
<string name="location_longitude">经度:%s</string>
<string name="location_latitude">度:%s</string>
<string name="location_latitude">度:%s</string>
<string name="location_address">地址:%s</string>
<string name="location_time">时间:%s</string>
<string name="location_provider">供应商:%s</string>
@ -1123,7 +1127,7 @@
<string name="calc_type_distance">根据GPS坐标计算距离</string>
<string name="calc_type_address">根据地址关键字判断</string>
<string name="longitude">经度</string>
<string name="latitude"></string>
<string name="latitude"></string>
<string name="distance1">以经纬度为中心,</string>
<string name="distance2">米半径建立电子围栏</string>
<string name="current_coordinates">当前坐标</string>
@ -1191,7 +1195,12 @@
<string name="alarm_vibration_effect_1">强振动 100ms</string>
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
<string name="alarm_vibration_effect_3">不振动 100ms</string>
<string name="alarm_settings_error">播放音乐/振动手机必须至少开启一个</string>
<string name="alarm_flash_settings">闪烁手机</string>
<string name="alarm_flash_effect">闪光效果</string>
<string name="alarm_flash_effect_tips">语法1或X[开启闪光灯], 0或O[关闭闪光灯], 每次100ms</string>
<string name="alarm_flash_effect_1">开启闪光灯 100ms</string>
<string name="alarm_flash_effect_2">关闭闪光灯 100ms</string>
<string name="alarm_settings_error">播放音乐/振动手机/闪烁手机必须至少开启一个</string>
<string name="invalid_tag" formatted="false">%s 标签无效:%s</string>
<string name="invalid_task_name">请输入任务名称</string>