新增:转发日志增加筛选器方便搜索/批量删除 #433

pull/473/head
pppscn 2 months ago
parent 75b0e48815
commit 5e0537e1e2

@ -1,7 +1,15 @@
package com.idormy.sms.forwarder.database.dao
import androidx.paging.PagingSource
import androidx.room.*
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Transaction
import androidx.room.Update
import androidx.sqlite.db.SupportSQLiteQuery
import com.idormy.sms.forwarder.database.entity.Msg
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
import io.reactivex.Completable
@ -22,6 +30,9 @@ interface MsgDao {
@Query("DELETE FROM Msg where type=:type")
fun deleteAll(type: String): Completable
@RawQuery
fun deleteAll(sql: SupportSQLiteQuery): Int
@Query("DELETE FROM Msg")
fun deleteAll()
@ -41,4 +52,8 @@ interface MsgDao {
@Query("SELECT * FROM Msg WHERE type = :type ORDER BY id DESC")
fun pagingSource(type: String): PagingSource<Int, MsgAndLogs>
@Transaction
@RawQuery(observedEntities = [MsgAndLogs::class])
fun pagingSource(query: SupportSQLiteQuery): PagingSource<Int, MsgAndLogs>
}

@ -6,19 +6,27 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.sqlite.db.SimpleSQLiteQuery
import com.idormy.sms.forwarder.database.dao.MsgDao
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
import com.idormy.sms.forwarder.database.ext.ioThread
import com.xuexiang.xutil.data.DateUtils
import kotlinx.coroutines.flow.Flow
class MsgViewModel(private val dao: MsgDao) : ViewModel() {
private var type: String = "sms"
private var filter: MutableMap<String, Any> = mutableMapOf()
fun setType(type: String): MsgViewModel {
this.type = type
return this
}
fun setFilter(filter: MutableMap<String, Any>): MsgViewModel {
this.filter = filter
return this
}
val allMsg: Flow<PagingData<MsgAndLogs>> = Pager(
config = PagingConfig(
pageSize = 10,
@ -26,11 +34,69 @@ class MsgViewModel(private val dao: MsgDao) : ViewModel() {
initialLoadSize = 10
)
) {
dao.pagingSource(type)
if (filter.isEmpty()) {
dao.pagingSource(type)
} else {
val sb = StringBuilder().apply {
append("SELECT * FROM Msg WHERE type = '$type'")
append(getOtherCondition())
append(" ORDER BY id DESC")
}
//Log.d("MsgViewModel", "sql: $sb")
val query = SimpleSQLiteQuery(sb.toString())
dao.pagingSource(query)
}
}.flow.cachedIn(viewModelScope)
fun delete(id: Long) = ioThread {
dao.delete(id)
}
fun deleteAll() = ioThread {
if (filter.isEmpty()) {
dao.deleteAll(type)
} else {
val sb = StringBuilder().apply {
append("DELETE FROM Msg WHERE type = '$type'")
append(getOtherCondition())
}
//Log.d("MsgViewModel", "sql: $sb")
val query = SimpleSQLiteQuery(sb.toString())
dao.deleteAll(query)
}
}
private fun getOtherCondition(): String {
return StringBuilder().apply {
filter["from"]?.toString()?.takeIf { it.isNotEmpty() }?.let { append(" AND `from` LIKE '%$it%'") }
filter["content"]?.toString()?.takeIf { it.isNotEmpty() }?.let { append(" AND content LIKE '%$it%'") }
filter["title"]?.toString()?.takeIf { it.isNotEmpty() }?.let { append(" AND sim_info LIKE '%$it%'") }
filter["start_time"]?.toString()?.takeIf { it.isNotEmpty() }?.let {
val date = DateUtils.string2Date(it, DateUtils.yyyyMMddHHmmss.get())
append(" AND time >= '${date.time}'")
}
filter["end_time"]?.toString()?.takeIf { it.isNotEmpty() }?.let {
val date = DateUtils.string2Date(it, DateUtils.yyyyMMddHHmmss.get())
append(" AND time <= '${date.time}'")
}
if (filter["sim_slot"] is Int && filter["sim_slot"] != -1) {
append(" AND sim_slot = ${filter["sim_slot"]}")
}
val callTypeFilter = filter["call_type"] as? MutableList<*>
if (!callTypeFilter.isNullOrEmpty()) {
val callTypeString = callTypeFilter.joinToString(",") { it.toString() }
append(" AND call_type IN ($callTypeString)")
}
val forwardStatusFilter = filter["forward_status"] as? MutableList<*>
if (!forwardStatusFilter.isNullOrEmpty()) {
val forwardStatusString = forwardStatusFilter.joinToString(",") { it.toString() }
val subSql = "SELECT DISTINCT msg_id FROM Logs WHERE type = '$type' and forward_status IN ($forwardStatusString)"
append(" AND id in ($subSql)")
}
}.toString()
}
}

@ -99,25 +99,32 @@ data class MsgInfo(
)
.replaceTag(getString(R.string.tag_device_name), extraDeviceMark.trim(), needJson)
.replaceTag(getString(R.string.tag_app_version), AppUtils.getAppVersionName(), needJson)
.replaceTag(getString(R.string.tag_call_type),
CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call), needJson)
.replaceTag(
getString(R.string.tag_call_type),
CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call), needJson
)
.replaceTag(getString(R.string.tag_ipv4), TaskUtils.ipv4, needJson)
.replaceTag(getString(R.string.tag_ipv6), TaskUtils.ipv6, needJson)
.replaceTag(getString(R.string.tag_battery_pct), "%.0f%%".format(TaskUtils.batteryPct), needJson)
.replaceTag(getString(R.string.tag_battery_status), BatteryUtils.getStatus(TaskUtils.batteryStatus), needJson)
.replaceTag(getString(R.string.tag_battery_plugged), BatteryUtils.getPlugged(TaskUtils.batteryPlugged), needJson)
.replaceTag(getString(R.string.tag_battery_info), TaskUtils.batteryInfo, needJson)
.replaceTag(getString(R.string.tag_battery_info_simple),
.replaceTag(
getString(R.string.tag_battery_info_simple),
"%.0f%%".format(TaskUtils.batteryPct)
+ with(BatteryUtils.getPlugged(TaskUtils.batteryPlugged)) {
if (this == getString(R.string.battery_unknown)) "" else " - $this"
}
},
needJson
)
.replaceTag(
getString(R.string.tag_net_type), with(NetworkUtils.getNetStateType()) {
if (this == NetworkUtils.NetState.NET_NO || this == NetworkUtils.NetState.NET_UNKNOWN)
this.name
this.name.removePrefix("NET_")
},
needJson
)
.replaceTag(getString(R.string.tag_net_type), with(NetworkUtils.getNetStateType()) {
if (this == NetworkUtils.NetState.NET_NO || this == NetworkUtils.NetState.NET_UNKNOWN)
this.name
this.name.removePrefix("NET_")
})
.replaceAppNameTag(from, needJson)
.replaceLocationTag(needJson)
.regexReplace(regexReplace)

@ -1,10 +1,14 @@
package com.idormy.sms.forwarder.fragment
import android.annotation.SuppressLint
import android.text.InputType
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.RadioGroup
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
@ -14,7 +18,6 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.adapter.MsgPagingAdapter
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.LogsDetail
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
import com.idormy.sms.forwarder.database.entity.Rule
@ -28,20 +31,24 @@ import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.button.SmoothCheckBox
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xui.widget.picker.widget.TimePickerView
import com.xuexiang.xui.widget.picker.widget.builder.TimePickerBuilder
import com.xuexiang.xui.widget.picker.widget.configure.TimePickerType
import com.xuexiang.xutil.data.DateUtils
import com.xuexiang.xutil.resource.ResUtils.getColors
import com.xuexiang.xutil.resource.ResUtils.getStringArray
import io.reactivex.CompletableObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import com.xuexiang.xutil.tip.ToastUtils
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
@Suppress("PrivatePropertyName")
@Page(name = "转发日志")
class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnItemClickListener {
@ -52,6 +59,11 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
private val viewModel by viewModels<MsgViewModel> { BaseViewModelFactory(context) }
private var currentType: String = "sms"
//日志筛选
private var currentFilter: MutableMap<String, Any> = mutableMapOf()
private var logsFilterPopup: MaterialDialog? = null
private var timePicker: TimePickerView? = null
override fun viewBindingInflate(
inflater: LayoutInflater,
container: ViewGroup,
@ -68,27 +80,28 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
@SingleClick
override fun performAction(view: View) {
MaterialDialog.Builder(requireContext())
.content(R.string.delete_type_log_tips)
.content(if (currentFilter.isEmpty()) R.string.delete_type_log_tips else R.string.delete_filter_log_tips)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
Core.msg.deleteAll(currentType)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : CompletableObserver {
override fun onSubscribe(d: Disposable) {}
override fun onComplete() {
XToastUtils.success(R.string.delete_type_log_toast)
}
override fun onError(e: Throwable) {
e.message?.let { XToastUtils.error(it) }
}
})
try {
viewModel.setType(currentType).setFilter(currentFilter).deleteAll()
reloadData()
XToastUtils.success(if (currentFilter.isEmpty()) R.string.delete_type_log_toast else R.string.delete_filter_log_toast)
} catch (e: Exception) {
e.message?.let { XToastUtils.error(it) }
}
}
.show()
}
})
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_filter) {
@SingleClick
override fun performAction(view: View) {
initLogsFilterDialog()
logsFilterPopup?.show()
}
})
return titleBar
}
@ -115,9 +128,8 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
2 -> "app"
else -> "sms"
}
viewModel.setType(currentType)
adapter.refresh()
binding!!.recyclerView.scrollToPosition(0)
initLogsFilterDialog(true)
reloadData()
}
}
@ -128,7 +140,7 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
binding!!.refreshLayout.setOnRefreshListener { refreshLayout: RefreshLayout ->
//adapter.refresh()
lifecycleScope.launch {
viewModel.setType(currentType).allMsg.collectLatest { adapter.submitData(it) }
viewModel.setType(currentType).setFilter(currentFilter).allMsg.collectLatest { adapter.submitData(it) }
}
refreshLayout.finishRefresh()
}
@ -186,11 +198,6 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
.title(R.string.details)
.content(detailStr.toString())
.cancelable(true)
/*.positiveText(R.string.del)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(item.id)
XToastUtils.success(R.string.delete_log_toast)
}*/
.negativeText(R.string.resend)
.onNegative { _: MaterialDialog?, _: DialogAction? ->
XToastUtils.toast(R.string.resend_toast)
@ -201,4 +208,138 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
override fun onItemRemove(view: View?, id: Int) {}
private fun reloadData() {
viewModel.setType(currentType).setFilter(currentFilter)
adapter.refresh()
binding!!.recyclerView.scrollToPosition(0)
}
private fun initLogsFilterDialog(needInit: Boolean = false) {
if (logsFilterPopup == null || needInit) {
currentFilter = mutableMapOf()
val logsFilterDialog = View.inflate(requireContext(), R.layout.dialog_logs_filter, null)
val layoutTitle = logsFilterDialog.findViewById<LinearLayout>(R.id.layout_title)
val layoutSimSlot = logsFilterDialog.findViewById<LinearLayout>(R.id.layout_sim_slot)
val layoutCallType = logsFilterDialog.findViewById<LinearLayout>(R.id.layout_call_type)
when (currentType) {
"app" -> {
layoutTitle.visibility = View.VISIBLE
layoutSimSlot.visibility = View.GONE
layoutCallType.visibility = View.GONE
}
"call" -> {
layoutTitle.visibility = View.GONE
layoutSimSlot.visibility = View.VISIBLE
layoutCallType.visibility = View.VISIBLE
}
else -> {
layoutTitle.visibility = View.GONE
layoutSimSlot.visibility = View.VISIBLE
layoutCallType.visibility = View.GONE
}
}
val scbCallType1 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_call_type1)
val scbCallType2 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_call_type2)
val scbCallType3 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_call_type3)
val scbCallType4 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_call_type4)
val scbCallType5 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_call_type5)
val scbCallType6 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_call_type6)
val etFrom = logsFilterDialog.findViewById<EditText>(R.id.et_from)
val etContent = logsFilterDialog.findViewById<EditText>(R.id.et_content)
val etTitle = logsFilterDialog.findViewById<EditText>(R.id.et_title)
val rgSimSlot = logsFilterDialog.findViewById<RadioGroup>(R.id.rg_sim_slot)
val etStartTime = logsFilterDialog.findViewById<EditText>(R.id.et_start_time)
val scbForwardStatus0 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_forward_status_0)
val scbForwardStatus1 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_forward_status_1)
val scbForwardStatus2 = logsFilterDialog.findViewById<SmoothCheckBox>(R.id.scb_forward_status_2)
etStartTime.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
showTimePicker(etStartTime.text.toString().trim(), getString(R.string.start_time), etStartTime)
} else {
timePicker?.dismiss()
}
}
val etEndTime = logsFilterDialog.findViewById<EditText>(R.id.et_end_time)
etEndTime.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
showTimePicker(etEndTime.text.toString().trim(), getString(R.string.end_time), etEndTime)
} else {
timePicker?.dismiss()
}
}
logsFilterPopup = MaterialDialog.Builder(requireContext())
.iconRes(android.R.drawable.ic_menu_search)
.title(R.string.menu_logs)
.customView(logsFilterDialog, true)
.cancelable(false)
.autoDismiss(false)
.neutralText(R.string.reset)
.neutralColor(getColors(R.color.darkGrey))
.onNeutral { dialog: MaterialDialog?, _: DialogAction? ->
dialog?.dismiss()
currentFilter = mutableMapOf()
logsFilterPopup = null
reloadData()
}.positiveText(R.string.search).onPositive { dialog: MaterialDialog?, _: DialogAction? ->
currentFilter = mutableMapOf()
currentFilter["from"] = etFrom.text.toString().trim()
currentFilter["content"] = etContent.text.toString().trim()
currentFilter["title"] = etTitle.text.toString().trim()
currentFilter["start_time"] = etStartTime.text.toString().trim()
currentFilter["end_time"] = etEndTime.text.toString().trim()
currentFilter["sim_slot"] = if (currentType == "app") -1 else when (rgSimSlot.checkedRadioButtonId) {
R.id.rb_sim_slot_1 -> 0
R.id.rb_sim_slot_2 -> 1
else -> -1
}
if (currentType == "call") {
currentFilter["call_type"] = mutableListOf<Int>().apply {
if (scbCallType1.isChecked) add(1)
if (scbCallType2.isChecked) add(2)
if (scbCallType3.isChecked) add(3)
if (scbCallType4.isChecked) add(4)
if (scbCallType5.isChecked) add(5)
if (scbCallType6.isChecked) add(6)
}
}
currentFilter["forward_status"] = mutableListOf<Int>().apply {
if (scbForwardStatus0.isChecked) add(0)
if (scbForwardStatus1.isChecked) add(1)
if (scbForwardStatus2.isChecked) add(2)
}
reloadData()
dialog?.dismiss()
}.build()
}
}
private fun showTimePicker(time: String, title: String, et: EditText) {
et.inputType = InputType.TYPE_NULL
val calendar: Calendar = Calendar.getInstance()
calendar.time = try {
if (time.isEmpty()) Date() else DateUtils.string2Date(time, DateUtils.yyyyMMddHHmmss.get())
} catch (e: Exception) {
Date()
}
timePicker = TimePickerBuilder(context) { date, _ ->
ToastUtils.toast(DateUtils.date2String(date, DateUtils.yyyyMMddHHmmss.get()))
et.setText(DateUtils.date2String(date, DateUtils.yyyyMMddHHmmss.get()))
}
.setTimeSelectChangeListener { date ->
Log.i("pvTime", "onTimeSelectChanged")
et.setText(DateUtils.date2String(date, DateUtils.yyyyMMddHHmmss.get()))
}
.setType(TimePickerType.ALL)
.setTitleText(title)
.isDialog(true)
.setOutSideCancelable(false)
.setDate(calendar)
.build()
timePicker?.show(false)
}
}

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="23dp"
android:height="23dp"
android:viewportWidth="23"
android:viewportHeight="23">
<path
android:fillColor="#ffffffff"
android:pathData="m12.761,21.5c-0.337,0 -0.645,-0.078 -0.941,-0.235L9.255,19.832C8.627,19.492 8.233,18.83 8.24,18.11L8.24,9.934C8.236,9.812 8.178,9.697 8.083,9.625L2.159,4.85 2.095,4.775C1.541,4.218 1.412,3.389 1.722,2.665 2.023,1.952 2.727,1.49 3.497,1.5L19.482,1.5c0.771,0 1.471,0.455 1.79,1.165 0.316,0.71 0.18,1.549 -0.35,2.11l-0.078,0.075 -5.999,4.826c-0.088,0.075 -0.143,0.19 -0.143,0.31v9.548c0.017,1.07 -0.832,1.95 -1.895,1.967zM3.175,3.688 L9.075,8.423c0.462,0.374 0.733,0.93 0.733,1.525v8.176c0,0.143 0.065,0.285 0.194,0.35l2.561,1.41c0.126,0.061 0.276,0.061 0.401,0 0.119,-0.071 0.19,-0.204 0.19,-0.35L13.155,9.998c0,-0.594 0.262,-1.151 0.723,-1.528L19.792,3.688C19.88,3.569 19.894,3.405 19.826,3.273 19.761,3.138 19.625,3.052 19.479,3.052L3.497,3.052C3.352,3.045 3.212,3.134 3.151,3.273 3.08,3.405 3.09,3.565 3.175,3.688ZM20.702,11.809h-4.202c-0.418,-0.01 -0.748,-0.357 -0.741,-0.774 0,-0.428 0.333,-0.775 0.741,-0.775h4.202c0.407,0 0.74,0.347 0.74,0.775 0.017,0.411 -0.305,0.757 -0.713,0.774zM20.702,14.791h-4.202c-0.418,-0.01 -0.748,-0.357 -0.741,-0.774 0,-0.432 0.333,-0.778 0.741,-0.778h4.202c0.407,0 0.74,0.35 0.74,0.778 0.017,0.41 -0.305,0.757 -0.713,0.774zM20.702,17.774h-4.202c-0.418,-0.014 -0.748,-0.36 -0.741,-0.778 0,-0.424 0.333,-0.774 0.741,-0.774h4.202c0.407,0 0.74,0.35 0.74,0.774 0.014,0.418 -0.312,0.764 -0.727,0.778zM20.702,17.774"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

@ -0,0 +1,372 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
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="wrap_content"
android:layout_height="wrap_content"
android:text="@string/from"
android:textStyle="bold" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_from"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/logs_keyword_hint"
app:met_clearButton="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/config_margin_5dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title"
android:textStyle="bold" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/logs_keyword_hint"
app:met_clearButton="true" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/config_margin_5dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/msg"
android:textStyle="bold" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/logs_keyword_hint"
app:met_clearButton="true" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/config_margin_5dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/time"
android:textStyle="bold" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_start_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/start_time"
android:importantForAutofill="no"
android:inputType="none"
android:singleLine="true"
android:textAlignment="center"
android:textSize="@dimen/text_size_mini"
app:met_clearButton="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/config_margin_5dp"
android:text="@string/cyclic_to"
android:textStyle="bold" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_end_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/config_margin_5dp"
android:layout_weight="1"
android:hint="@string/end_time"
android:importantForAutofill="no"
android:inputType="none"
android:singleLine="true"
android:textAlignment="center"
android:textSize="@dimen/text_size_mini"
app:met_clearButton="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout_call_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/config_margin_5dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/type"
android:textStyle="bold" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_call_type3"
android:layout_width="15dp"
android:layout_height="15dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/missed_call"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_call_type1"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="5dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/incoming_call_ended"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_call_type2"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="5dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/outgoing_call_ended"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_call_type4"
android:layout_width="15dp"
android:layout_height="15dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/incoming_call_received"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_call_type5"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="5dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/incoming_call_answered"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_call_type6"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="5dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/outgoing_call_started"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_sim_slot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/config_margin_5dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/slot"
android:textStyle="bold" />
<RadioGroup
android:id="@+id/rg_sim_slot"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_sim_slot_0"
style="@style/rg_rb_style"
android:checked="true"
android:text="@string/battery_unlimited" />
<RadioButton
android:id="@+id/rb_sim_slot_1"
style="@style/rg_rb_style"
android:text="@string/sim_1" />
<RadioButton
android:id="@+id/rb_sim_slot_2"
style="@style/rg_rb_style"
android:text="@string/sim_2" />
</RadioGroup>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/config_margin_5dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/forward_status"
android:textStyle="bold" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_forward_status_2"
android:layout_width="15dp"
android:layout_height="15dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/success"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_forward_status_0"
android:layout_width="15dp"
android:layout_height="15dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/failed"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_forward_status_1"
android:layout_width="15dp"
android:layout_height="15dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text="@string/processing"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
</LinearLayout>
</LinearLayout>

@ -164,6 +164,8 @@
<string name="quit">Quit</string>
<string name="del">Delete</string>
<string name="save">Save</string>
<string name="reset">Reset</string>
<string name="search">Search</string>
<string name="submit">Submit</string>
<string name="send">Send</string>
<string name="test">Test</string>
@ -212,6 +214,8 @@
<string name="delete_log_toast">The log entry is deleted.</string>
<string name="delete_type_log_tips">Are you sure you want to delete all log records for this category?</string>
<string name="delete_type_log_toast">The category log record has been cleared!</string>
<string name="delete_filter_log_tips">Are you sure you want to delete all log records for the current filter?</string>
<string name="delete_filter_log_toast">All log records for the current filter have been deleted!</string>
<string name="resend_toast">Attempting to resend over the original sender</string>
<string name="rematch_toast">Rematching rule sending</string>
<string name="details">Details</string>
@ -630,33 +634,10 @@
<string name="time">Time: </string>
<string name="result">Result:</string>
<string name="original_result">Ori. Result:</string>
<string name="forward_status">Result:</string>
<string name="success">Success</string>
<string name="failed">Failed</string>
<string name="processing">Processing</string>
<string name="tag_from">{{FROM}}</string>
<string name="tag_sms">{{SMS}}</string>
<string name="tag_package_name">{{PACKAGE_NAME}}</string>
<string name="tag_app_name">{{APP_NAME}}</string>
<string name="tag_msg">{{MSG}}</string>
<string name="tag_card_slot">{{CARD_SLOT}}</string>
<string name="tag_card_subid">{{CARD_SUBID}}</string>
<string name="tag_receive_time">{{RECEIVE_TIME}}</string>
<string name="tag_current_time">{{CURRENT_TIME}}</string>
<string name="tag_device_name">{{DEVICE_NAME}}</string>
<string name="tag_app_version">{{APP_VERSION}}</string>
<string name="tag_title">{{TITLE}}</string>
<string name="tag_call_type">{{CALL_TYPE}}</string>
<string name="tag_location">{{LOCATION}}</string>
<string name="tag_location_longitude">{{LOCATION_LONGITUDE}}</string>
<string name="tag_location_latitude">{{LOCATION_LATITUDE}}</string>
<string name="tag_location_address">{{LOCATION_ADDRESS}}</string>
<string name="tag_battery_pct">{{BATTERY_PCT}}</string>
<string name="tag_battery_status">{{BATTERY_STATUS}}</string>
<string name="tag_battery_plugged">{{BATTERY_PLUGGED}}</string>
<string name="tag_battery_info">{{BATTERY_INFO}}</string>
<string name="tag_uid">{{UID}}</string>
<string name="tag_ipv4">{{IPV4}}</string>
<string name="tag_ipv6">{{IPV6}}</string>
<string name="rule_sms">SMS</string>
<string name="rule_call">CALL</string>
<string name="rule_app">APP</string>
@ -1022,6 +1003,7 @@
<string name="matched_rule">Matched rule</string>
<string name="copied_to_clipboard">Copied to clipboard:\n%s</string>
<string name="search_keyword">Search Keyword: %s</string>
<string name="search_condition">Search Condition: %s</string>
<string name="export_succeeded">Export configuration succeeded!</string>
<string name="export_failed">Export failed, please check write permission!</string>
<string name="export_failed_tips">Export failed: %s</string>
@ -1046,6 +1028,7 @@
<string name="main_title">Main title</string>
<string name="subtitle">Subtitle</string>
<string name="logs_keyword_hint">Input keywords to fuzzy match</string>
<string name="sms_keyword_hint">Input keywords to fuzzy match SMS content</string>
<string name="contact_keyword_hint">Pure numbers match numbers / non-numbers match names</string>
<string name="call_keyword_hint">Input keyword to fuzzy match mobile phone number</string>
@ -1279,7 +1262,9 @@
<string name="cyclic_from_week">From week</string>
<string name="cyclic_to">To</string>
<string name="start">Start</string>
<string name="start_time">Start Time</string>
<string name="end">End</string>
<string name="end_time">End Time</string>
<string name="interval_seconds_1">Starting from</string>
<string name="interval_seconds_2">second, execute every</string>
<string name="interval_seconds_3">seconds.</string>

@ -165,6 +165,8 @@
<string name="quit">退出</string>
<string name="del">删除</string>
<string name="save">保存</string>
<string name="reset">重置</string>
<string name="search">搜索</string>
<string name="submit">提交</string>
<string name="send">发送</string>
<string name="test">测试</string>
@ -213,6 +215,8 @@
<string name="delete_log_toast">该条日志记录已经删除!</string>
<string name="delete_type_log_tips">确定删除该分类的所有日志记录?</string>
<string name="delete_type_log_toast">该分类日志记录已经清空!</string>
<string name="delete_filter_log_tips">确定删除当前筛选的所有日志记录?</string>
<string name="delete_filter_log_toast">当前筛选的所有日志记录已经删除!</string>
<string name="resend_toast">正在尝试通过原发送通道重发</string>
<string name="rematch_toast">正在重新匹配规则发送</string>
<string name="details">详情</string>
@ -631,33 +635,10 @@
<string name="time">时间:</string>
<string name="result">转发结果:</string>
<string name="original_result">原转发状态:</string>
<string name="forward_status">状态:</string>
<string name="success">成功</string>
<string name="failed">失败</string>
<string name="processing">处理中</string>
<string name="tag_from">{{FROM}}</string>
<string name="tag_sms">{{SMS}}</string>
<string name="tag_package_name">{{PACKAGE_NAME}}</string>
<string name="tag_app_name">{{APP_NAME}}</string>
<string name="tag_msg">{{MSG}}</string>
<string name="tag_card_slot">{{CARD_SLOT}}</string>
<string name="tag_card_subid">{{CARD_SUBID}}</string>
<string name="tag_receive_time">{{RECEIVE_TIME}}</string>
<string name="tag_current_time">{{CURRENT_TIME}}</string>
<string name="tag_device_name">{{DEVICE_NAME}}</string>
<string name="tag_app_version">{{APP_VERSION}}</string>
<string name="tag_title">{{TITLE}}</string>
<string name="tag_call_type">{{CALL_TYPE}}</string>
<string name="tag_location">{{LOCATION}}</string>
<string name="tag_location_longitude">{{LOCATION_LONGITUDE}}</string>
<string name="tag_location_latitude">{{LOCATION_LATITUDE}}</string>
<string name="tag_location_address">{{LOCATION_ADDRESS}}</string>
<string name="tag_battery_pct">{{BATTERY_PCT}}</string>
<string name="tag_battery_status">{{BATTERY_STATUS}}</string>
<string name="tag_battery_plugged">{{BATTERY_PLUGGED}}</string>
<string name="tag_battery_info">{{BATTERY_INFO}}</string>
<string name="tag_uid">{{UID}}</string>
<string name="tag_ipv4">{{IPV4}}</string>
<string name="tag_ipv6">{{IPV6}}</string>
<string name="rule_sms">短信</string>
<string name="rule_call">来电</string>
<string name="rule_app">应用</string>
@ -1023,6 +1004,7 @@
<string name="matched_rule">匹配中规则</string>
<string name="copied_to_clipboard">已复制到剪贴板:\n%s</string>
<string name="search_keyword">搜索关键字: %s</string>
<string name="search_condition">搜索条件: %s</string>
<string name="export_succeeded">导出配置成功!</string>
<string name="export_failed">导出失败,请检查写入权限!</string>
<string name="export_failed_tips">导出失败: %s</string>
@ -1047,6 +1029,7 @@
<string name="main_title">主标题</string>
<string name="subtitle">副标题</string>
<string name="logs_keyword_hint">输入关键字模糊匹配</string>
<string name="sms_keyword_hint">输入关键字模糊匹配短信内容</string>
<string name="contact_keyword_hint">纯数字匹配号码/非数字匹配姓名</string>
<string name="call_keyword_hint">输入关键字模糊匹配手机号码</string>
@ -1280,7 +1263,9 @@
<string name="cyclic_from_week">从星期</string>
<string name="cyclic_to"></string>
<string name="start">起始</string>
<string name="start_time">起始时间</string>
<string name="end">结束</string>
<string name="end_time">结束时间</string>
<string name="interval_seconds_1"></string>
<string name="interval_seconds_2">秒开始,每</string>
<string name="interval_seconds_3">秒钟执行一次</string>

@ -164,7 +164,9 @@
<string name="discard">丟棄</string>
<string name="quit">退出</string>
<string name="del">刪除</string>
<string name="save">保存</string>
<string name="save">儲存</string>
<string name="reset">重置</string>
<string name="search">搜索</string>
<string name="submit">提交</string>
<string name="send">發送</string>
<string name="test">測試</string>
@ -213,6 +215,8 @@
<string name="delete_log_toast">該條日誌記錄已刪除!</string>
<string name="delete_type_log_tips">確定刪除該分類的所有日誌記錄?</string>
<string name="delete_type_log_toast">該分類日誌記錄已清空!</string>
<string name="delete_filter_log_tips">確定刪除當前篩選的所有日誌記錄?</string>
<string name="delete_filter_log_toast">當前篩選的所有日誌記錄已經刪除!</string>
<string name="resend_toast">正在嘗試通過原發送通道重發</string>
<string name="rematch_toast">正在重新匹配規則發送</string>
<string name="details">詳情</string>
@ -631,33 +635,10 @@
<string name="time">時間:</string>
<string name="result">轉發結果:</string>
<string name="original_result">原轉發狀態:</string>
<string name="forward_status">狀態:</string>
<string name="success">成功</string>
<string name="failed">失敗</string>
<string name="processing">處理中</string>
<string name="tag_from">{{FROM}}</string>
<string name="tag_sms">{{SMS}}</string>
<string name="tag_package_name">{{PACKAGE_NAME}}</string>
<string name="tag_app_name">{{APP_NAME}}</string>
<string name="tag_msg">{{MSG}}</string>
<string name="tag_card_slot">{{CARD_SLOT}}</string>
<string name="tag_card_subid">{{CARD_SUBID}}</string>
<string name="tag_receive_time">{{RECEIVE_TIME}}</string>
<string name="tag_current_time">{{CURRENT_TIME}}</string>
<string name="tag_device_name">{{DEVICE_NAME}}</string>
<string name="tag_app_version">{{APP_VERSION}}</string>
<string name="tag_title">{{TITLE}}</string>
<string name="tag_call_type">{{CALL_TYPE}}</string>
<string name="tag_location">{{LOCATION}}</string>
<string name="tag_location_longitude">{{LOCATION_LONGITUDE}}</string>
<string name="tag_location_latitude">{{LOCATION_LATITUDE}}</string>
<string name="tag_location_address">{{LOCATION_ADDRESS}}</string>
<string name="tag_battery_pct">{{BATTERY_PCT}}</string>
<string name="tag_battery_status">{{BATTERY_STATUS}}</string>
<string name="tag_battery_plugged">{{BATTERY_PLUGGED}}</string>
<string name="tag_battery_info">{{BATTERY_INFO}}</string>
<string name="tag_uid">{{UID}}</string>
<string name="tag_ipv4">{{IPV4}}</string>
<string name="tag_ipv6">{{IPV6}}</string>
<string name="rule_sms">簡訊</string>
<string name="rule_call">來電</string>
<string name="rule_app">應用</string>
@ -1023,6 +1004,7 @@
<string name="matched_rule">匹配中規則</string>
<string name="copied_to_clipboard">已複製到剪貼板:\n%s</string>
<string name="search_keyword">搜索關鍵字: %s</string>
<string name="search_condition">搜索條件:%s</string>
<string name="export_succeeded">導出配置成功!</string>
<string name="export_failed">導出失敗,請檢查寫入權限!</string>
<string name="export_failed_tips">導出失敗: %s</string>
@ -1047,6 +1029,7 @@
<string name="main_title">主標題</string>
<string name="subtitle">副標題</string>
<string name="logs_keyword_hint">輸入關鍵字模糊匹配</string>
<string name="sms_keyword_hint">輸入關鍵字模糊匹配簡訊內容</string>
<string name="contact_keyword_hint">純數字匹配號碼/非數字匹配姓名</string>
<string name="call_keyword_hint">輸入關鍵字模糊匹配手機號碼</string>
@ -1280,7 +1263,9 @@
<string name="cyclic_from_week">從星期</string>
<string name="cyclic_to"></string>
<string name="start">起始</string>
<string name="end">結束</string>
<string name="start_time">起始时间</string>
<string name="end">结束</string>
<string name="end_time">结束时间</string>
<string name="interval_seconds_1"></string>
<string name="interval_seconds_2">秒開始,每</string>
<string name="interval_seconds_3">秒鐘執行一次</string>

@ -1,4 +1,30 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="tag_from" translatable="false">{{FROM}}</string>
<string name="tag_sms" translatable="false">{{SMS}}</string>
<string name="tag_package_name" translatable="false">{{PACKAGE_NAME}}</string>
<string name="tag_app_name" translatable="false">{{APP_NAME}}</string>
<string name="tag_msg" translatable="false">{{MSG}}</string>
<string name="tag_card_slot" translatable="false">{{CARD_SLOT}}</string>
<string name="tag_card_subid" translatable="false">{{CARD_SUBID}}</string>
<string name="tag_receive_time" translatable="false">{{RECEIVE_TIME}}</string>
<string name="tag_current_time" translatable="false">{{CURRENT_TIME}}</string>
<string name="tag_device_name" translatable="false">{{DEVICE_NAME}}</string>
<string name="tag_app_version" translatable="false">{{APP_VERSION}}</string>
<string name="tag_title" translatable="false">{{TITLE}}</string>
<string name="tag_call_type" translatable="false">{{CALL_TYPE}}</string>
<string name="tag_location" translatable="false">{{LOCATION}}</string>
<string name="tag_location_longitude" translatable="false">{{LOCATION_LONGITUDE}}</string>
<string name="tag_location_latitude" translatable="false">{{LOCATION_LATITUDE}}</string>
<string name="tag_location_address" translatable="false">{{LOCATION_ADDRESS}}</string>
<string name="tag_battery_pct" translatable="false">{{BATTERY_PCT}}</string>
<string name="tag_battery_status" translatable="false">{{BATTERY_STATUS}}</string>
<string name="tag_battery_plugged" translatable="false">{{BATTERY_PLUGGED}}</string>
<string name="tag_battery_info" translatable="false">{{BATTERY_INFO}}</string>
<string name="tag_battery_info_simple" translatable="false">{{BATTERY_INFO_SIMPLE}}</string>
<string name="tag_uid" translatable="false">{{UID}}</string>
<string name="tag_ipv4" translatable="false">{{IPV4}}</string>
<string name="tag_ipv6" translatable="false">{{IPV6}}</string>
<string name="tag_net_type" translatable="false">{{NET_TYPE}}</string>
<string name="type_param_sms">短信</string>
<string name="type_param_call">通话</string>
@ -165,6 +191,8 @@
<string name="quit">退出</string>
<string name="del">删除</string>
<string name="save">保存</string>
<string name="reset">重置</string>
<string name="search">搜索</string>
<string name="submit">提交</string>
<string name="send">发送</string>
<string name="test">测试</string>
@ -213,6 +241,8 @@
<string name="delete_log_toast">该条日志记录已经删除!</string>
<string name="delete_type_log_tips">确定删除该分类的所有日志记录?</string>
<string name="delete_type_log_toast">该分类日志记录已经清空!</string>
<string name="delete_filter_log_tips">确定删除当前筛选的所有日志记录?</string>
<string name="delete_filter_log_toast">当前筛选的所有日志记录已经删除!</string>
<string name="resend_toast">正在尝试通过原发送通道重发</string>
<string name="rematch_toast">正在重新匹配规则发送</string>
<string name="details">详情</string>
@ -631,34 +661,10 @@
<string name="time">时间:</string>
<string name="result">转发结果:</string>
<string name="original_result">原转发状态:</string>
<string name="forward_status">状态:</string>
<string name="success">成功</string>
<string name="failed">失败</string>
<string name="processing">处理中</string>
<string name="tag_from">{{FROM}}</string>
<string name="tag_sms">{{SMS}}</string>
<string name="tag_package_name">{{PACKAGE_NAME}}</string>
<string name="tag_app_name">{{APP_NAME}}</string>
<string name="tag_msg">{{MSG}}</string>
<string name="tag_card_slot">{{CARD_SLOT}}</string>
<string name="tag_card_subid">{{CARD_SUBID}}</string>
<string name="tag_receive_time">{{RECEIVE_TIME}}</string>
<string name="tag_current_time">{{CURRENT_TIME}}</string>
<string name="tag_device_name">{{DEVICE_NAME}}</string>
<string name="tag_app_version">{{APP_VERSION}}</string>
<string name="tag_title">{{TITLE}}</string>
<string name="tag_call_type">{{CALL_TYPE}}</string>
<string name="tag_location">{{LOCATION}}</string>
<string name="tag_location_longitude">{{LOCATION_LONGITUDE}}</string>
<string name="tag_location_latitude">{{LOCATION_LATITUDE}}</string>
<string name="tag_location_address">{{LOCATION_ADDRESS}}</string>
<string name="tag_battery_pct">{{BATTERY_PCT}}</string>
<string name="tag_battery_status">{{BATTERY_STATUS}}</string>
<string name="tag_battery_plugged">{{BATTERY_PLUGGED}}</string>
<string name="tag_battery_info">{{BATTERY_INFO}}</string>
<string name="tag_battery_info_simple" translatable="false">{{BATTERY_INFO_SIMPLE}}</string>
<string name="tag_uid">{{UID}}</string>
<string name="tag_ipv4">{{IPV4}}</string>
<string name="tag_ipv6">{{IPV6}}</string>
<string name="rule_sms">短信</string>
<string name="rule_call">来电</string>
<string name="rule_app">应用</string>
@ -1024,6 +1030,7 @@
<string name="matched_rule">匹配中规则</string>
<string name="copied_to_clipboard">已复制到剪贴板:\n%s</string>
<string name="search_keyword">搜索关键字: %s</string>
<string name="search_condition">搜索条件: %s</string>
<string name="export_succeeded">导出配置成功!</string>
<string name="export_failed">导出失败,请检查写入权限!</string>
<string name="export_failed_tips">导出失败: %s</string>
@ -1048,6 +1055,7 @@
<string name="main_title">主标题</string>
<string name="subtitle">副标题</string>
<string name="logs_keyword_hint">输入关键字模糊匹配</string>
<string name="sms_keyword_hint">输入关键字模糊匹配短信内容</string>
<string name="contact_keyword_hint">纯数字匹配号码/非数字匹配姓名</string>
<string name="call_keyword_hint">输入关键字模糊匹配手机号码</string>
@ -1281,7 +1289,9 @@
<string name="cyclic_from_week">从星期</string>
<string name="cyclic_to"></string>
<string name="start">起始</string>
<string name="start_time">起始时间</string>
<string name="end">结束</string>
<string name="end_time">结束时间</string>
<string name="interval_seconds_1"></string>
<string name="interval_seconds_2">秒开始,每</string>
<string name="interval_seconds_3">秒钟执行一次</string>
@ -1451,5 +1461,4 @@
<string name="bluetooth_not_supported">不支持蓝牙设备</string>
<string name="start_discovery">搜索设备</string>
<string name="invalid_bluetooth_mac_address">蓝牙设备MAC地址无效例如AA:BB:CC:DD:EE:FF</string>
<string name="tag_net_type" translatable="false">{{NET_TYPE}}</string>
</resources>

Loading…
Cancel
Save