mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
751f1b3163 | ||
![]() |
45dc37aea9 | ||
![]() |
de9509fead | ||
![]() |
114052d1c6 | ||
![]() |
0391868790 |
@ -6,6 +6,10 @@
|
|||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.telephony"
|
android:name="android.hardware.telephony"
|
||||||
android:required="false" />
|
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 android:name="com.android.permission.GET_INSTALLED_APPS" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
@ -74,6 +78,7 @@
|
|||||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
|
@ -10,4 +10,6 @@ data class AlarmSetting(
|
|||||||
var music: String = "", //音乐文件
|
var music: String = "", //音乐文件
|
||||||
var repeatTimes: Int = 5, //振动重复次数,0=无限循环,-1=禁用
|
var repeatTimes: Int = 5, //振动重复次数,0=无限循环,-1=禁用
|
||||||
var vibrate: String = "---___===___", //振动律动:=强振动, -弱震动, _不振动, 时长都是100ms
|
var vibrate: String = "---___===___", //振动律动:=强振动, -弱震动, _不振动, 时长都是100ms
|
||||||
|
var flashTimes: Int = 5, //闪烁次数,0=无限循环,-1=禁用
|
||||||
|
var flash: String = "XXOOXXOO", //闪烁律动:X亮灯, O灭灯, 时长都是100ms
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
@ -14,6 +14,7 @@ data class TelegramSetting(
|
|||||||
val proxyAuthenticator: Boolean = false,
|
val proxyAuthenticator: Boolean = false,
|
||||||
val proxyUsername: String = "",
|
val proxyUsername: String = "",
|
||||||
val proxyPassword: String = "",
|
val proxyPassword: String = "",
|
||||||
|
val parseMode: String = "HTML",
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
fun getMethodCheckId(): Int {
|
fun getMethodCheckId(): Int {
|
||||||
@ -27,4 +28,12 @@ data class TelegramSetting(
|
|||||||
else -> R.id.rb_proxyNone
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -38,6 +38,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
|
|||||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
@Page(name = "Alarm")
|
@Page(name = "Alarm")
|
||||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
@ -103,10 +104,12 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
binding!!.rgAlarmState.check(R.id.rb_start_alarm)
|
binding!!.rgAlarmState.check(R.id.rb_start_alarm)
|
||||||
binding!!.layoutAlarmSettings.visibility = View.VISIBLE
|
binding!!.layoutAlarmSettings.visibility = View.VISIBLE
|
||||||
binding!!.layoutVibrateSettings.visibility = View.VISIBLE
|
binding!!.layoutVibrateSettings.visibility = View.VISIBLE
|
||||||
|
binding!!.layoutFlashSettings.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
binding!!.rgAlarmState.check(R.id.rb_stop_alarm)
|
binding!!.rgAlarmState.check(R.id.rb_stop_alarm)
|
||||||
binding!!.layoutAlarmSettings.visibility = View.GONE
|
binding!!.layoutAlarmSettings.visibility = View.GONE
|
||||||
binding!!.layoutVibrateSettings.visibility = View.GONE
|
binding!!.layoutVibrateSettings.visibility = View.GONE
|
||||||
|
binding!!.layoutFlashSettings.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding!!.xsbVolume.setDefaultValue(settingVo.volume)
|
binding!!.xsbVolume.setDefaultValue(settingVo.volume)
|
||||||
@ -114,8 +117,14 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
binding!!.etMusicPath.setText(settingVo.music)
|
binding!!.etMusicPath.setText(settingVo.music)
|
||||||
binding!!.xsbRepeatTimes.setDefaultValue(if (settingVo.repeatTimes >= 0) settingVo.repeatTimes else 0)
|
binding!!.xsbRepeatTimes.setDefaultValue(if (settingVo.repeatTimes >= 0) settingVo.repeatTimes else 0)
|
||||||
binding!!.etVibrationEffect.setText(settingVo.vibrate)
|
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!!.sbEnableMusic.isChecked = settingVo.playTimes >= 0
|
||||||
binding!!.sbEnableVibrate.isChecked = settingVo.repeatTimes >= 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() {
|
override fun onDestroyView() {
|
||||||
@ -135,13 +144,20 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
binding!!.xsbPlayTimes.setOnSeekBarListener { _, _ ->
|
binding!!.xsbPlayTimes.setOnSeekBarListener { _, _ ->
|
||||||
checkSetting(true)
|
checkSetting(true)
|
||||||
}
|
}
|
||||||
|
binding!!.xsbRepeatTimes.setOnSeekBarListener { _, _ ->
|
||||||
|
checkSetting(true)
|
||||||
|
}
|
||||||
binding!!.rgAlarmState.setOnCheckedChangeListener { _, checkedId ->
|
binding!!.rgAlarmState.setOnCheckedChangeListener { _, checkedId ->
|
||||||
binding!!.layoutAlarmSettings.visibility = if (checkedId == R.id.rb_start_alarm) View.VISIBLE else View.GONE
|
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)
|
checkSetting(true)
|
||||||
}
|
}
|
||||||
binding!!.btInsertVibrationEffect1.setOnClickListener(this)
|
binding!!.btInsertVibrationEffect1.setOnClickListener(this)
|
||||||
binding!!.btInsertVibrationEffect2.setOnClickListener(this)
|
binding!!.btInsertVibrationEffect2.setOnClickListener(this)
|
||||||
binding!!.btInsertVibrationEffect3.setOnClickListener(this)
|
binding!!.btInsertVibrationEffect3.setOnClickListener(this)
|
||||||
|
binding!!.btInsertFlashEffect1.setOnClickListener(this)
|
||||||
|
binding!!.btInsertFlashEffect2.setOnClickListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SingleClick
|
@SingleClick
|
||||||
@ -163,6 +179,16 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
return
|
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 -> {
|
R.id.btn_file_picker -> {
|
||||||
// 申请储存权限
|
// 申请储存权限
|
||||||
XXPermissions.with(this).permission(Permission.MANAGE_EXTERNAL_STORAGE).request(object : OnPermissionCallback {
|
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 -> {
|
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")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onGranted(permissions: List<String>, all: Boolean) {
|
override fun onGranted(permissions: List<String>, all: Boolean) {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
try {
|
try {
|
||||||
val settingVo = checkSetting()
|
val settingVo = checkSetting()
|
||||||
Log.d(TAG, settingVo.toString())
|
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))
|
XToastUtils.error(getString(R.string.alarm_settings_error))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -242,12 +273,17 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
}
|
}
|
||||||
|
|
||||||
R.id.btn_save -> {
|
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")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onGranted(permissions: List<String>, all: Boolean) {
|
override fun onGranted(permissions: List<String>, all: Boolean) {
|
||||||
val settingVo = checkSetting()
|
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))
|
XToastUtils.error(getString(R.string.alarm_settings_error))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -285,11 +321,14 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
private fun checkSetting(updateView: Boolean = false): AlarmSetting {
|
private fun checkSetting(updateView: Boolean = false): AlarmSetting {
|
||||||
val enableMusic = binding!!.sbEnableMusic.isChecked
|
val enableMusic = binding!!.sbEnableMusic.isChecked
|
||||||
val enableVibrate = binding!!.sbEnableVibrate.isChecked
|
val enableVibrate = binding!!.sbEnableVibrate.isChecked
|
||||||
|
val enableFlash = binding!!.sbEnableFlash.isChecked
|
||||||
val volume = binding!!.xsbVolume.selectedNumber
|
val volume = binding!!.xsbVolume.selectedNumber
|
||||||
var playTimes = binding!!.xsbPlayTimes.selectedNumber
|
var playTimes = binding!!.xsbPlayTimes.selectedNumber
|
||||||
val music = binding!!.etMusicPath.text.toString().trim()
|
val music = binding!!.etMusicPath.text.toString().trim()
|
||||||
var repeatTimes = binding!!.xsbRepeatTimes.selectedNumber
|
var repeatTimes = binding!!.xsbRepeatTimes.selectedNumber
|
||||||
val vibrationEffect = binding!!.etVibrationEffect.text.toString().trim()
|
val vibrationEffect = binding!!.etVibrationEffect.text.toString().trim()
|
||||||
|
var flashTimes = binding!!.xsbFlashTimes.selectedNumber
|
||||||
|
var flashEffect = binding!!.etFlashEffect.text.toString().trim()
|
||||||
val description = StringBuilder()
|
val description = StringBuilder()
|
||||||
val action = if (binding!!.rgAlarmState.checkedRadioButtonId == R.id.rb_start_alarm) {
|
val action = if (binding!!.rgAlarmState.checkedRadioButtonId == R.id.rb_start_alarm) {
|
||||||
description.append(getString(R.string.start_alarm))
|
description.append(getString(R.string.start_alarm))
|
||||||
@ -309,6 +348,14 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
} else {
|
} else {
|
||||||
repeatTimes = -1
|
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"
|
"start"
|
||||||
} else {
|
} else {
|
||||||
description.append(getString(R.string.stop_alarm))
|
description.append(getString(R.string.stop_alarm))
|
||||||
@ -319,7 +366,7 @@ class AlarmFragment : BaseFragment<FragmentTasksActionAlarmBinding?>(), View.OnC
|
|||||||
binding!!.tvDescription.text = description.toString()
|
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> {
|
private fun findAudioFiles(directoryPath: String): List<String> {
|
||||||
|
@ -133,6 +133,7 @@ class TelegramFragment : BaseFragment<FragmentSendersTelegramBinding?>(), View.O
|
|||||||
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
|
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
|
||||||
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
|
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
|
||||||
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
|
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 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() {
|
override fun onDestroyView() {
|
||||||
|
@ -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_ID
|
||||||
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_NAME
|
import com.idormy.sms.forwarder.utils.FRONT_CHANNEL_NAME
|
||||||
import com.idormy.sms.forwarder.utils.FRONT_NOTIFY_ID
|
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.INTENT_FRPC_APPLY_FILE
|
||||||
import com.idormy.sms.forwarder.utils.Log
|
import com.idormy.sms.forwarder.utils.Log
|
||||||
import com.idormy.sms.forwarder.utils.SettingUtils
|
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||||
@ -97,6 +98,10 @@ class ForegroundService : Service() {
|
|||||||
private lateinit var vibrationUtils: VibrationUtils
|
private lateinit var vibrationUtils: VibrationUtils
|
||||||
private var isVibrating = false
|
private var isVibrating = false
|
||||||
|
|
||||||
|
// 闪光灯控制
|
||||||
|
private lateinit var flashUtils: FlashUtils
|
||||||
|
private var isFlash = false
|
||||||
|
|
||||||
// 音乐播放器
|
// 音乐播放器
|
||||||
private var alarmPlayer: MediaPlayer? = null
|
private var alarmPlayer: MediaPlayer? = null
|
||||||
private var alarmPlayTimes = 0
|
private var alarmPlayTimes = 0
|
||||||
@ -106,6 +111,10 @@ class ForegroundService : Service() {
|
|||||||
if (vibrationUtils.isVibrating) {
|
if (vibrationUtils.isVibrating) {
|
||||||
vibrationUtils.stopVibration()
|
vibrationUtils.stopVibration()
|
||||||
}
|
}
|
||||||
|
//停止闪光灯
|
||||||
|
if (flashUtils.isFlashing) {
|
||||||
|
flashUtils.stopFlashing()
|
||||||
|
}
|
||||||
//停止播放音乐
|
//停止播放音乐
|
||||||
alarmPlayer?.release()
|
alarmPlayer?.release()
|
||||||
alarmPlayer = null
|
alarmPlayer = null
|
||||||
@ -182,6 +191,11 @@ class ForegroundService : Service() {
|
|||||||
isVibrating = true
|
isVibrating = true
|
||||||
vibrationUtils.startVibration(alarm.vibrate, alarm.repeatTimes)
|
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)
|
vibrationUtils = VibrationUtils(this)
|
||||||
|
|
||||||
|
//初始化闪光灯
|
||||||
|
flashUtils = FlashUtils(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
@ -235,7 +252,7 @@ class ForegroundService : Service() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
//非纯客户端模式
|
//非纯客户端模式
|
||||||
if (!SettingUtils.enablePureClientMode) stopForegroundService()
|
if (!SettingUtils.enablePureClientMode) stopForegroundService()
|
||||||
|
flashUtils.release()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +336,10 @@ class ForegroundService : Service() {
|
|||||||
if (vibrationUtils.isVibrating) {
|
if (vibrationUtils.isVibrating) {
|
||||||
vibrationUtils.stopVibration()
|
vibrationUtils.stopVibration()
|
||||||
}
|
}
|
||||||
|
//停止闪光灯
|
||||||
|
if (flashUtils.isFlashing) {
|
||||||
|
flashUtils.stopFlashing()
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
handleException(e, "stopForegroundService")
|
handleException(e, "stopForegroundService")
|
||||||
}
|
}
|
||||||
|
116
app/src/main/java/com/idormy/sms/forwarder/utils/FlashUtils.kt
Normal file
116
app/src/main/java/com/idormy/sms/forwarder/utils/FlashUtils.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -67,7 +67,11 @@ class BarkUtils {
|
|||||||
if (!TextUtils.isEmpty(setting.level)) msgMap["level"] = setting.level
|
if (!TextUtils.isEmpty(setting.level)) msgMap["level"] = setting.level
|
||||||
if (!TextUtils.isEmpty(setting.sound)) msgMap["sound"] = setting.sound
|
if (!TextUtils.isEmpty(setting.sound)) msgMap["sound"] = setting.sound
|
||||||
if (!TextUtils.isEmpty(setting.badge)) msgMap["badge"] = setting.badge
|
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
|
if (!TextUtils.isEmpty(setting.call)) msgMap["call"] = setting.call
|
||||||
|
|
||||||
//自动复制
|
//自动复制
|
||||||
|
@ -58,13 +58,29 @@ class TelegramUtils private constructor() {
|
|||||||
|
|
||||||
val request = if (setting.method == "GET") {
|
val request = if (setting.method == "GET") {
|
||||||
requestUrl += "?chat_id=" + setting.chatId + "&text=" + URLEncoder.encode(content, "UTF-8")
|
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")
|
Log.i(TAG, "requestUrl:$requestUrl")
|
||||||
XHttp.get(requestUrl)
|
XHttp.get(requestUrl)
|
||||||
} else {
|
} else {
|
||||||
val bodyMap: MutableMap<String, Any> = mutableMapOf()
|
val bodyMap: MutableMap<String, Any> = mutableMapOf()
|
||||||
bodyMap["chat_id"] = setting.chatId
|
bodyMap["chat_id"] = setting.chatId
|
||||||
bodyMap["text"] = content
|
when (setting.parseMode) {
|
||||||
bodyMap["parse_mode"] = "HTML"
|
"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"
|
bodyMap["disable_web_page_preview"] = "true"
|
||||||
val requestMsg: String = Gson().toJson(bodyMap)
|
val requestMsg: String = Gson().toJson(bodyMap)
|
||||||
Log.i(TAG, "requestMsg:$requestMsg")
|
Log.i(TAG, "requestMsg:$requestMsg")
|
||||||
@ -155,5 +171,18 @@ class TelegramUtils private constructor() {
|
|||||||
}
|
}
|
||||||
return buffer.toString()
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,44 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</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
|
<LinearLayout
|
||||||
style="@style/BarStyle"
|
style="@style/BarStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -306,4 +344,4 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -209,7 +209,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_vibrate_settings"
|
android:id="@+id/layout_vibrate_settings"
|
||||||
style="@style/BarStyle"
|
style="@style/BarStyle"
|
||||||
@ -326,6 +325,116 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</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>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
@ -309,6 +309,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken or Custom Proxy Address (startwith http)</string>
|
<string name="TelegramApiToken">ApiToken or Custom Proxy Address (startwith http)</string>
|
||||||
<string name="TelegramChatId">ChatId</string>
|
<string name="TelegramChatId">ChatId</string>
|
||||||
<string name="Method" formatted="false">Method</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="SmsSimSlot">SIM Slot</string>
|
||||||
<string name="same_source">Same source</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_1">Strong vibration</string>
|
||||||
<string name="alarm_vibration_effect_2">Weak vibration</string>
|
<string name="alarm_vibration_effect_2">Weak vibration</string>
|
||||||
<string name="alarm_vibration_effect_3">No 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_tag" formatted="false">%s tag is invalid: %s</string>
|
||||||
<string name="invalid_task_name">Please input task name.</string>
|
<string name="invalid_task_name">Please input task name.</string>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<string name="insert_tag_call_type">通话类型</string>
|
<string name="insert_tag_call_type">通话类型</string>
|
||||||
<string name="insert_tag_location">定位信息</string>
|
<string name="insert_tag_location">定位信息</string>
|
||||||
<string name="insert_tag_location_longitude">定位经度</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_location_address">定位地址</string>
|
||||||
<string name="insert_tag_battery_pct">电池电量</string>
|
<string name="insert_tag_battery_pct">电池电量</string>
|
||||||
<string name="insert_tag_battery_status">电池状态</string>
|
<string name="insert_tag_battery_status">电池状态</string>
|
||||||
@ -310,6 +310,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
||||||
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
||||||
<string name="Method" formatted="false">请求方式</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="SmsSimSlot">发送卡槽</string>
|
||||||
<string name="same_source">原进原出</string>
|
<string name="same_source">原进原出</string>
|
||||||
@ -729,7 +733,7 @@
|
|||||||
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
||||||
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
||||||
<string name="location_longitude">经度:%s</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_address">地址:%s</string>
|
||||||
<string name="location_time">时间:%s</string>
|
<string name="location_time">时间:%s</string>
|
||||||
<string name="location_provider">供应商:%s</string>
|
<string name="location_provider">供应商:%s</string>
|
||||||
@ -1094,7 +1098,7 @@
|
|||||||
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
||||||
<string name="calc_type_address">根据地址关键字判断</string>
|
<string name="calc_type_address">根据地址关键字判断</string>
|
||||||
<string name="longitude">经度</string>
|
<string name="longitude">经度</string>
|
||||||
<string name="latitude">维度</string>
|
<string name="latitude">纬度</string>
|
||||||
<string name="distance1">以经纬度为中心,</string>
|
<string name="distance1">以经纬度为中心,</string>
|
||||||
<string name="distance2">米半径建立电子围栏</string>
|
<string name="distance2">米半径建立电子围栏</string>
|
||||||
<string name="current_coordinates">当前坐标</string>
|
<string name="current_coordinates">当前坐标</string>
|
||||||
@ -1162,7 +1166,12 @@
|
|||||||
<string name="alarm_vibration_effect_1">强振动 100ms</string>
|
<string name="alarm_vibration_effect_1">强振动 100ms</string>
|
||||||
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
|
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
|
||||||
<string name="alarm_vibration_effect_3">不振动 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_tag" formatted="false">%s 标签无效:%s</string>
|
||||||
<string name="invalid_task_name">请输入任务名称</string>
|
<string name="invalid_task_name">请输入任务名称</string>
|
||||||
|
@ -218,8 +218,14 @@
|
|||||||
<string name="switch_rule_status">啟用該條轉發規則</string>
|
<string name="switch_rule_status">啟用該條轉發規則</string>
|
||||||
<string name="invalid_match_value">匹配的值不可為空</string>
|
<string name="invalid_match_value">匹配的值不可為空</string>
|
||||||
<string name="invalid_call_type">通話類型不正確,只能填寫1到6的任意一個數字</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>
|
<string name="sun">星期日</string>
|
||||||
|
<!--SenderActivity-->
|
||||||
<string name="delete_sender_title">發送通道操作確認</string>
|
<string name="delete_sender_title">發送通道操作確認</string>
|
||||||
<string name="delete_sender_tips">刪除發送通道後會級聯刪除其相關的轉發規則、轉發日誌的所有記錄!\n\n確定刪除該條發送通道?</string>
|
<string name="delete_sender_tips">刪除發送通道後會級聯刪除其相關的轉發規則、轉發日誌的所有記錄!\n\n確定刪除該條發送通道?</string>
|
||||||
<string name="delete_sender_toast">該條發送通道已經刪除!</string>
|
<string name="delete_sender_toast">該條發送通道已經刪除!</string>
|
||||||
@ -304,6 +310,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken 或 自定義代理地址(http開頭)</string>
|
<string name="TelegramApiToken">ApiToken 或 自定義代理地址(http開頭)</string>
|
||||||
<string name="TelegramChatId">被通知人(或群組)的ChatId</string>
|
<string name="TelegramChatId">被通知人(或群組)的ChatId</string>
|
||||||
<string name="Method" formatted="false">請求方式</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="SmsSimSlot">發送卡槽</string>
|
||||||
<string name="same_source">原進原出</string>
|
<string name="same_source">原進原出</string>
|
||||||
@ -1156,7 +1166,13 @@
|
|||||||
<string name="alarm_vibration_effect_1">強振動 100ms</string>
|
<string name="alarm_vibration_effect_1">強振動 100ms</string>
|
||||||
<string name="alarm_vibration_effect_2">弱振動 100ms</string>
|
<string name="alarm_vibration_effect_2">弱振動 100ms</string>
|
||||||
<string name="alarm_vibration_effect_3">不振動 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_tag" formatted="false">%s 標籤無效:%s</string>
|
||||||
<string name="invalid_task_name">請輸入任務名稱</string>
|
<string name="invalid_task_name">請輸入任務名稱</string>
|
||||||
@ -1180,10 +1196,4 @@
|
|||||||
<string name="start_discovery">搜索裝置</string>
|
<string name="start_discovery">搜索裝置</string>
|
||||||
<string name="invalid_bluetooth_mac_address">藍牙裝置MAC地址無效,例如:AA:BB:CC:DD:EE:FF</string>
|
<string name="invalid_bluetooth_mac_address">藍牙裝置MAC地址無效,例如:AA:BB:CC:DD:EE:FF</string>
|
||||||
<string name="auto_start_redmi"><![CDATA[紅米手機:授權管理 -> 自啟動管理 -> 允許應用自啟動]]></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>
|
</resources>
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
<string name="insert_tag_call_type">通话类型</string>
|
<string name="insert_tag_call_type">通话类型</string>
|
||||||
<string name="insert_tag_location">定位信息</string>
|
<string name="insert_tag_location">定位信息</string>
|
||||||
<string name="insert_tag_location_longitude">定位经度</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_location_address">定位地址</string>
|
||||||
<string name="insert_tag_battery_pct">电池电量</string>
|
<string name="insert_tag_battery_pct">电池电量</string>
|
||||||
<string name="insert_tag_battery_status">电池状态</string>
|
<string name="insert_tag_battery_status">电池状态</string>
|
||||||
@ -339,6 +339,10 @@
|
|||||||
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
<string name="TelegramApiToken">ApiToken 或 自定义代理地址(http开头)</string>
|
||||||
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
<string name="TelegramChatId">被通知人(或群组)的ChatId</string>
|
||||||
<string name="Method" formatted="false">请求方式</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="SmsSimSlot">发送卡槽</string>
|
||||||
<string name="same_source">原进原出</string>
|
<string name="same_source">原进原出</string>
|
||||||
@ -758,7 +762,7 @@
|
|||||||
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
||||||
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
||||||
<string name="location_longitude">经度:%s</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_address">地址:%s</string>
|
||||||
<string name="location_time">时间:%s</string>
|
<string name="location_time">时间:%s</string>
|
||||||
<string name="location_provider">供应商:%s</string>
|
<string name="location_provider">供应商:%s</string>
|
||||||
@ -1123,7 +1127,7 @@
|
|||||||
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
||||||
<string name="calc_type_address">根据地址关键字判断</string>
|
<string name="calc_type_address">根据地址关键字判断</string>
|
||||||
<string name="longitude">经度</string>
|
<string name="longitude">经度</string>
|
||||||
<string name="latitude">维度</string>
|
<string name="latitude">纬度</string>
|
||||||
<string name="distance1">以经纬度为中心,</string>
|
<string name="distance1">以经纬度为中心,</string>
|
||||||
<string name="distance2">米半径建立电子围栏</string>
|
<string name="distance2">米半径建立电子围栏</string>
|
||||||
<string name="current_coordinates">当前坐标</string>
|
<string name="current_coordinates">当前坐标</string>
|
||||||
@ -1191,7 +1195,12 @@
|
|||||||
<string name="alarm_vibration_effect_1">强振动 100ms</string>
|
<string name="alarm_vibration_effect_1">强振动 100ms</string>
|
||||||
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
|
<string name="alarm_vibration_effect_2">弱振动 100ms</string>
|
||||||
<string name="alarm_vibration_effect_3">不振动 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_tag" formatted="false">%s 标签无效:%s</string>
|
||||||
<string name="invalid_task_name">请输入任务名称</string>
|
<string name="invalid_task_name">请输入任务名称</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user