mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 09:27:41 +08:00
parent
032837615f
commit
dd798e42cc
@ -202,6 +202,9 @@
|
||||
<service
|
||||
android:name=".service.HttpService"
|
||||
android:enabled="true" />
|
||||
<service
|
||||
android:name=".service.NetworkStateService"
|
||||
android:enabled="true" />
|
||||
<service
|
||||
android:name=".service.BatteryService"
|
||||
android:enabled="true" />
|
||||
|
@ -23,6 +23,7 @@ import com.idormy.sms.forwarder.receiver.CactusReceiver
|
||||
import com.idormy.sms.forwarder.service.BatteryService
|
||||
import com.idormy.sms.forwarder.service.ForegroundService
|
||||
import com.idormy.sms.forwarder.service.HttpService
|
||||
import com.idormy.sms.forwarder.service.NetworkStateService
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.utils.sdkinit.UMengInit
|
||||
import com.idormy.sms.forwarder.utils.sdkinit.XBasicLibInit
|
||||
@ -60,6 +61,7 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
||||
var SimInfoList: MutableMap<Int, SimInfo> = mutableMapOf()
|
||||
|
||||
//已安装App信息
|
||||
var LoadingAppList = false
|
||||
var UserAppList: MutableList<AppUtils.AppInfo> = mutableListOf()
|
||||
var SystemAppList: MutableList<AppUtils.AppInfo> = mutableListOf()
|
||||
|
||||
@ -118,38 +120,14 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
||||
startService(intent)
|
||||
}
|
||||
|
||||
//网络状态监听
|
||||
val networkStateServiceIntent = Intent(this, NetworkStateService::class.java)
|
||||
startService(networkStateServiceIntent)
|
||||
|
||||
//电池状态监听
|
||||
val batteryServiceIntent = Intent(this, BatteryService::class.java)
|
||||
startService(batteryServiceIntent)
|
||||
|
||||
//异步获取所有已安装 App 信息
|
||||
if (SettingUtils.enableLoadAppList) {
|
||||
val enableLoadUserAppList = SettingUtils.enableLoadUserAppList
|
||||
val enableLoadSystemAppList = SettingUtils.enableLoadSystemAppList
|
||||
val get = GlobalScope.async(Dispatchers.IO) {
|
||||
val appInfoList = AppUtils.getAppsInfo()
|
||||
for (appInfo in appInfoList) {
|
||||
if (appInfo.isSystem && enableLoadSystemAppList) {
|
||||
SystemAppList.add(appInfo)
|
||||
} else if (enableLoadUserAppList) {
|
||||
UserAppList.add(appInfo)
|
||||
}
|
||||
}
|
||||
UserAppList.sortBy { appInfo -> appInfo.name }
|
||||
SystemAppList.sortBy { appInfo -> appInfo.name }
|
||||
}
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
runCatching {
|
||||
get.await()
|
||||
Log.d("GlobalScope", "AppUtils.getAppsInfo() Done")
|
||||
//Log.d("GlobalScope", "UserAppList = $UserAppList")
|
||||
//Log.d("GlobalScope", "SystemAppList = $SystemAppList")
|
||||
}.onFailure {
|
||||
//Log.e("GlobalScope", it.message.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//启动HttpServer
|
||||
if (HttpServerUtils.enableServerAutorun) {
|
||||
startService(Intent(this, HttpService::class.java))
|
||||
|
@ -43,6 +43,8 @@ data class CloneInfo(
|
||||
var enableLoadSystemAppList: Boolean = false,
|
||||
@SerializedName("duplicate_messages_limits")
|
||||
var duplicateMessagesLimits: Int = 0,
|
||||
@SerializedName("enable_network_state_receiver")
|
||||
var enableNetworkStateReceiver: Boolean = false,
|
||||
@SerializedName("enable_battery_receiver")
|
||||
var enableBatteryReceiver: Boolean = false,
|
||||
@SerializedName("battery_level_min")
|
||||
|
@ -2,16 +2,23 @@ package com.idormy.sms.forwarder.fragment
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.adapter.AppListAdapter
|
||||
import com.idormy.sms.forwarder.core.BaseFragment
|
||||
import com.idormy.sms.forwarder.databinding.FragmentAppListBinding
|
||||
import com.idormy.sms.forwarder.utils.EVENT_LOAD_APP_LIST
|
||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.scwang.smartrefresh.layout.api.RefreshLayout
|
||||
import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener
|
||||
import com.xuexiang.xaop.annotation.SingleClick
|
||||
@ -21,12 +28,19 @@ import com.xuexiang.xui.utils.ResUtils
|
||||
import com.xuexiang.xui.utils.ThemeUtils
|
||||
import com.xuexiang.xui.utils.WidgetUtils
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||
import com.xuexiang.xutil.XUtil
|
||||
import com.xuexiang.xutil.app.AppUtils
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
@Page(name = "应用列表")
|
||||
class AppListFragment : BaseFragment<FragmentAppListBinding?>() {
|
||||
|
||||
private val TAG: String = AppListFragment::class.java.simpleName
|
||||
var appListAdapter: AppListAdapter? = null
|
||||
private val appListObserver = Observer { it: String ->
|
||||
Log.d(TAG, "EVENT_LOAD_APP_LIST: $it")
|
||||
appListAdapter?.refresh(getAppsList(false))
|
||||
}
|
||||
private var currentType: String = "user"
|
||||
|
||||
override fun viewBindingInflate(
|
||||
@ -95,6 +109,8 @@ class AppListFragment : BaseFragment<FragmentAppListBinding?>() {
|
||||
binding!!.refreshLayout.setDisableContentWhenLoading(true)
|
||||
appListAdapter?.refresh(getAppsList(false))
|
||||
binding!!.refreshLayout.finishRefresh()
|
||||
//监听已安装App信息列表加载完成事件
|
||||
LiveEventBus.get(EVENT_LOAD_APP_LIST, String::class.java).observeStickyForever(appListObserver)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
@ -104,18 +120,9 @@ class AppListFragment : BaseFragment<FragmentAppListBinding?>() {
|
||||
|
||||
private fun getAppsList(refresh: Boolean): MutableList<AppUtils.AppInfo> {
|
||||
if (refresh || (currentType == "user" && App.UserAppList.isEmpty()) || (currentType == "system" && App.SystemAppList.isEmpty())) {
|
||||
App.UserAppList.clear()
|
||||
App.SystemAppList.clear()
|
||||
val appInfoList = AppUtils.getAppsInfo()
|
||||
for (appInfo in appInfoList) {
|
||||
if (appInfo.isSystem) {
|
||||
App.SystemAppList.add(appInfo)
|
||||
} else {
|
||||
App.UserAppList.add(appInfo)
|
||||
}
|
||||
}
|
||||
App.UserAppList.sortBy { appInfo -> appInfo.name }
|
||||
App.SystemAppList.sortBy { appInfo -> appInfo.name }
|
||||
XToastUtils.info(getString(R.string.loading_app_list))
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
}
|
||||
|
||||
return if (currentType == "system") App.SystemAppList else App.UserAppList
|
||||
|
@ -8,6 +8,9 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.adapter.spinner.AppListAdapterItem
|
||||
@ -23,6 +26,8 @@ import com.idormy.sms.forwarder.database.viewmodel.RuleViewModel
|
||||
import com.idormy.sms.forwarder.databinding.FragmentRulesEditBinding
|
||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.xuexiang.xaop.annotation.SingleClick
|
||||
import com.xuexiang.xpage.annotation.Page
|
||||
import com.xuexiang.xrouter.annotation.AutoWired
|
||||
@ -32,7 +37,7 @@ import com.xuexiang.xui.utils.ResUtils
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
||||
import com.xuexiang.xutil.app.AppUtils
|
||||
import com.xuexiang.xutil.XUtil
|
||||
import io.reactivex.SingleObserver
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
@ -61,6 +66,10 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
||||
//已安装App信息列表
|
||||
private val appListSpinnerList = ArrayList<AppListAdapterItem>()
|
||||
private lateinit var appListSpinnerAdapter: AppListSpinnerAdapter<*>
|
||||
private val appListObserver = Observer { it: String ->
|
||||
Log.d(TAG, "EVENT_LOAD_APP_LIST: $it")
|
||||
initAppSpinner()
|
||||
}
|
||||
|
||||
@JvmField
|
||||
@AutoWired(name = KEY_RULE_ID)
|
||||
@ -105,6 +114,10 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
||||
binding!!.btInsertExtra.visibility = View.GONE
|
||||
binding!!.btInsertSender.visibility = View.GONE
|
||||
binding!!.btInsertContent.visibility = View.GONE
|
||||
//初始化APP下拉列表
|
||||
initAppSpinner()
|
||||
//监听已安装App信息列表加载完成事件
|
||||
LiveEventBus.get(EVENT_LOAD_APP_LIST, String::class.java).observeStickyForever(appListObserver)
|
||||
}
|
||||
"call" -> {
|
||||
titleBar?.setTitle(R.string.call_rule)
|
||||
@ -136,8 +149,6 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
||||
initForm()
|
||||
}
|
||||
|
||||
//初始化APP下拉列表
|
||||
initAppSpinner()
|
||||
}
|
||||
|
||||
override fun initListeners() {
|
||||
@ -408,68 +419,48 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
|
||||
}
|
||||
|
||||
//初始化APP下拉列表
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
private fun initAppSpinner() {
|
||||
if (ruleType != "app") return
|
||||
|
||||
//未开启异步获取已安装App信息开关时,规则编辑不显示已安装APP下拉框
|
||||
if (!SettingUtils.enableLoadUserAppList && !SettingUtils.enableLoadSystemAppList) return
|
||||
|
||||
val get = GlobalScope.async(Dispatchers.IO) {
|
||||
if ((SettingUtils.enableLoadUserAppList && App.UserAppList.isEmpty()) || (SettingUtils.enableLoadSystemAppList && App.SystemAppList.isEmpty())) {
|
||||
App.UserAppList.clear()
|
||||
App.SystemAppList.clear()
|
||||
val appInfoList = AppUtils.getAppsInfo()
|
||||
for (appInfo in appInfoList) {
|
||||
if (appInfo.isSystem) {
|
||||
App.SystemAppList.add(appInfo)
|
||||
} else {
|
||||
App.UserAppList.add(appInfo)
|
||||
}
|
||||
}
|
||||
App.UserAppList.sortBy { appInfo -> appInfo.name }
|
||||
App.SystemAppList.sortBy { appInfo -> appInfo.name }
|
||||
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) {
|
||||
XToastUtils.info(getString(R.string.loading_app_list))
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
return
|
||||
}
|
||||
|
||||
appListSpinnerList.clear()
|
||||
if (SettingUtils.enableLoadUserAppList) {
|
||||
for (appInfo in App.UserAppList) {
|
||||
if (TextUtils.isEmpty(appInfo.packageName)) continue
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
runCatching {
|
||||
get.await()
|
||||
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) return@runCatching
|
||||
|
||||
appListSpinnerList.clear()
|
||||
if (SettingUtils.enableLoadUserAppList) {
|
||||
for (appInfo in App.UserAppList) {
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
if (SettingUtils.enableLoadSystemAppList) {
|
||||
for (appInfo in App.SystemAppList) {
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
|
||||
//列表为空也不显示下拉框
|
||||
if (appListSpinnerList.isEmpty()) return@runCatching
|
||||
|
||||
appListSpinnerAdapter = AppListSpinnerAdapter(appListSpinnerList)
|
||||
//.setTextColor(ResUtils.getColor(R.color.green))
|
||||
//.setTextSize(12F)
|
||||
.setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
||||
binding!!.spApp.setAdapter(appListSpinnerAdapter)
|
||||
binding!!.spApp.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
||||
try {
|
||||
//val appInfo = appListSpinnerList[position]
|
||||
val appInfo = appListSpinnerAdapter.getItemSource(position) as AppListAdapterItem
|
||||
CommonUtils.insertOrReplaceText2Cursor(binding!!.etValue, appInfo.packageName.toString())
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString())
|
||||
}
|
||||
}
|
||||
binding!!.layoutAppList.visibility = View.VISIBLE
|
||||
}.onFailure {
|
||||
Log.e("GlobalScope", it.message.toString())
|
||||
if (SettingUtils.enableLoadSystemAppList) {
|
||||
for (appInfo in App.SystemAppList) {
|
||||
if (TextUtils.isEmpty(appInfo.packageName)) continue
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
|
||||
//列表为空也不显示下拉框
|
||||
if (appListSpinnerList.isEmpty()) return
|
||||
|
||||
appListSpinnerAdapter = AppListSpinnerAdapter(appListSpinnerList).setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
||||
binding!!.spApp.setAdapter(appListSpinnerAdapter)
|
||||
binding!!.spApp.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
||||
try {
|
||||
val appInfo = appListSpinnerAdapter.getItemSource(position) as AppListAdapterItem
|
||||
CommonUtils.insertOrReplaceText2Cursor(binding!!.etValue, appInfo.packageName.toString())
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString())
|
||||
}
|
||||
}
|
||||
binding!!.layoutAppList.visibility = View.VISIBLE
|
||||
|
||||
}
|
||||
|
||||
//初始化表单
|
||||
|
@ -18,6 +18,9 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.hjq.permissions.OnPermissionCallback
|
||||
import com.hjq.permissions.Permission
|
||||
import com.hjq.permissions.XXPermissions
|
||||
@ -30,6 +33,7 @@ import com.idormy.sms.forwarder.databinding.FragmentSettingsBinding
|
||||
import com.idormy.sms.forwarder.entity.SimInfo
|
||||
import com.idormy.sms.forwarder.receiver.BootReceiver
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.xuexiang.xaop.annotation.SingleClick
|
||||
import com.xuexiang.xpage.annotation.Page
|
||||
@ -46,13 +50,11 @@ import com.xuexiang.xui.widget.picker.widget.builder.TimePickerBuilder
|
||||
import com.xuexiang.xui.widget.picker.widget.listener.OnOptionsSelectListener
|
||||
import com.xuexiang.xutil.XUtil
|
||||
import com.xuexiang.xutil.XUtil.getPackageManager
|
||||
import com.xuexiang.xutil.app.AppUtils
|
||||
import com.xuexiang.xutil.app.AppUtils.getAppPackageName
|
||||
import com.xuexiang.xutil.data.DateUtils
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.*
|
||||
|
||||
|
||||
@Suppress("PropertyName", "SpellCheckingInspection")
|
||||
@Page(name = "通用设置")
|
||||
class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickListener {
|
||||
@ -63,6 +65,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
//已安装App信息列表
|
||||
private val appListSpinnerList = ArrayList<AppListAdapterItem>()
|
||||
private lateinit var appListSpinnerAdapter: AppListSpinnerAdapter<*>
|
||||
private val appListObserver = Observer { it: String ->
|
||||
Log.d(TAG, "EVENT_LOAD_APP_LIST: $it")
|
||||
initAppSpinner()
|
||||
}
|
||||
|
||||
override fun viewBindingInflate(
|
||||
inflater: LayoutInflater,
|
||||
@ -110,6 +116,9 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
SettingUtils.autoCleanLogsDays = newValue
|
||||
}
|
||||
|
||||
//监听网络状态变化
|
||||
switchNetworkStateReceiver(binding!!.sbNetworkStateReceiver)
|
||||
|
||||
//监听电池状态变化
|
||||
switchBatteryReceiver(binding!!.sbBatteryReceiver)
|
||||
//电量预警
|
||||
@ -157,7 +166,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
|
||||
//纯客户端模式
|
||||
switchDirectlyToClient(binding!!.sbDirectlyToClient)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
//初始化APP下拉列表
|
||||
initAppSpinner()
|
||||
}
|
||||
@ -172,6 +184,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
binding!!.btInsertExtra.setOnClickListener(this)
|
||||
binding!!.btInsertTime.setOnClickListener(this)
|
||||
binding!!.btInsertDeviceName.setOnClickListener(this)
|
||||
|
||||
//监听已安装App信息列表加载完成事件
|
||||
LiveEventBus.get(EVENT_LOAD_APP_LIST, String::class.java).observeStickyForever(appListObserver)
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@ -433,20 +449,18 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
SettingUtils.enableAppNotify = isChecked
|
||||
if (isChecked) {
|
||||
//检查权限是否获取
|
||||
XXPermissions.with(this)
|
||||
.permission(Permission.BIND_NOTIFICATION_LISTENER_SERVICE)
|
||||
.request(OnPermissionCallback { _, allGranted ->
|
||||
if (!allGranted) {
|
||||
SettingUtils.enableAppNotify = false
|
||||
sbEnableAppNotify.isChecked = false
|
||||
XToastUtils.error(R.string.tips_notification_listener)
|
||||
return@OnPermissionCallback
|
||||
}
|
||||
XXPermissions.with(this).permission(Permission.BIND_NOTIFICATION_LISTENER_SERVICE).request(OnPermissionCallback { _, allGranted ->
|
||||
if (!allGranted) {
|
||||
SettingUtils.enableAppNotify = false
|
||||
sbEnableAppNotify.isChecked = false
|
||||
XToastUtils.error(R.string.tips_notification_listener)
|
||||
return@OnPermissionCallback
|
||||
}
|
||||
|
||||
SettingUtils.enableAppNotify = true
|
||||
sbEnableAppNotify.isChecked = true
|
||||
CommonUtils.toggleNotificationListenerService(requireContext())
|
||||
})
|
||||
SettingUtils.enableAppNotify = true
|
||||
sbEnableAppNotify.isChecked = true
|
||||
CommonUtils.toggleNotificationListenerService(requireContext())
|
||||
})
|
||||
}
|
||||
}
|
||||
scbCancelAppNotify.isChecked = SettingUtils.enableCancelAppNotify
|
||||
@ -487,6 +501,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
return@setOnCheckedChangeListener
|
||||
}
|
||||
SettingUtils.enableLoadAppList = isChecked
|
||||
|
||||
XToastUtils.info(getString(R.string.loading_app_list))
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
}
|
||||
scbLoadUserApp.isChecked = SettingUtils.enableLoadUserAppList
|
||||
scbLoadUserApp.setOnCheckedChangeListener { _: SmoothCheckBox, isChecked: Boolean ->
|
||||
@ -496,6 +514,13 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
SettingUtils.enableLoadAppList = false
|
||||
XToastUtils.error(getString(R.string.load_app_list_toast))
|
||||
}
|
||||
if (isChecked && SettingUtils.enableLoadAppList && App.UserAppList.isEmpty()) {
|
||||
XToastUtils.info(getString(R.string.loading_app_list))
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
} else {
|
||||
initAppSpinner()
|
||||
}
|
||||
}
|
||||
scbLoadSystemApp.isChecked = SettingUtils.enableLoadSystemAppList
|
||||
scbLoadSystemApp.setOnCheckedChangeListener { _: SmoothCheckBox, isChecked: Boolean ->
|
||||
@ -505,6 +530,22 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
SettingUtils.enableLoadAppList = false
|
||||
XToastUtils.error(getString(R.string.load_app_list_toast))
|
||||
}
|
||||
if (isChecked && SettingUtils.enableLoadAppList && App.SystemAppList.isEmpty()) {
|
||||
XToastUtils.info(getString(R.string.loading_app_list))
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
} else {
|
||||
initAppSpinner()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//监听网络状态变化
|
||||
@SuppressLint("UseSwitchCompatOrMaterialCode")
|
||||
fun switchNetworkStateReceiver(sbNetworkStateReceiver: SwitchButton) {
|
||||
sbNetworkStateReceiver.isChecked = SettingUtils.enableNetworkStateReceiver
|
||||
sbNetworkStateReceiver.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||
SettingUtils.enableNetworkStateReceiver = isChecked
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,8 +594,6 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
sbBatteryCron.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||
binding!!.layoutBatteryCron.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||
SettingUtils.enableBatteryCron = isChecked
|
||||
//TODO:BatteryReportCronTask
|
||||
//BatteryReportCronTask.getSingleton().updateTimer()
|
||||
}
|
||||
}
|
||||
|
||||
@ -568,11 +607,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
calendar.time = DateUtils.getNowDate()
|
||||
val mTimePicker = TimePickerBuilder(context) { date: Date?, _: View? ->
|
||||
etBatteryCronStartTime.setText(DateUtils.date2String(date, DateUtils.HHmm.get()))
|
||||
//TODO:BatteryReportCronTask
|
||||
//BatteryReportCronTask.getSingleton().updateTimer()
|
||||
}
|
||||
//.setTimeSelectChangeListener { date: Date? -> etBatteryCronStartTime.setText(DateUtils.date2String(date, DateUtils.HHmm.get())) }
|
||||
.setType(false, false, false, true, true, false).setTitleText(getString(R.string.time_picker)).setSubmitText(getString(R.string.ok)).setCancelText(getString(R.string.cancel)).setDate(calendar).build()
|
||||
}.setType(false, false, false, true, true, false).setTitleText(getString(R.string.time_picker)).setSubmitText(getString(R.string.ok)).setCancelText(getString(R.string.cancel)).setDate(calendar).build()
|
||||
mTimePicker.show()
|
||||
}
|
||||
|
||||
@ -1077,68 +1112,47 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
}
|
||||
|
||||
//初始化APP下拉列表
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
private fun initAppSpinner() {
|
||||
if (!SettingUtils.enableAppNotify) return
|
||||
|
||||
//未开启异步获取已安装App信息开关时,规则编辑不显示已安装APP下拉框
|
||||
//未开启异步获取已安装App信息开关时,不显示已安装APP下拉框
|
||||
if (!SettingUtils.enableLoadUserAppList && !SettingUtils.enableLoadSystemAppList) return
|
||||
|
||||
val get = GlobalScope.async(Dispatchers.IO) {
|
||||
if ((SettingUtils.enableLoadUserAppList && App.UserAppList.isEmpty()) || (SettingUtils.enableLoadSystemAppList && App.SystemAppList.isEmpty())) {
|
||||
App.UserAppList.clear()
|
||||
App.SystemAppList.clear()
|
||||
val appInfoList = AppUtils.getAppsInfo()
|
||||
for (appInfo in appInfoList) {
|
||||
if (appInfo.isSystem) {
|
||||
App.SystemAppList.add(appInfo)
|
||||
} else {
|
||||
App.UserAppList.add(appInfo)
|
||||
}
|
||||
}
|
||||
App.UserAppList.sortBy { appInfo -> appInfo.name }
|
||||
App.SystemAppList.sortBy { appInfo -> appInfo.name }
|
||||
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) {
|
||||
//XToastUtils.info(getString(R.string.loading_app_list))
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
return
|
||||
}
|
||||
|
||||
appListSpinnerList.clear()
|
||||
if (SettingUtils.enableLoadUserAppList) {
|
||||
for (appInfo in App.UserAppList) {
|
||||
if (TextUtils.isEmpty(appInfo.packageName)) continue
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
runCatching {
|
||||
get.await()
|
||||
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) return@runCatching
|
||||
|
||||
appListSpinnerList.clear()
|
||||
if (SettingUtils.enableLoadUserAppList) {
|
||||
for (appInfo in App.UserAppList) {
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
if (SettingUtils.enableLoadSystemAppList) {
|
||||
for (appInfo in App.SystemAppList) {
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
|
||||
//列表为空也不显示下拉框
|
||||
if (appListSpinnerList.isEmpty()) return@runCatching
|
||||
|
||||
appListSpinnerAdapter = AppListSpinnerAdapter(appListSpinnerList)
|
||||
//.setTextColor(ResUtils.getColor(R.color.green))
|
||||
//.setTextSize(12F)
|
||||
.setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
||||
binding!!.spApp.setAdapter(appListSpinnerAdapter)
|
||||
binding!!.spApp.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
||||
try {
|
||||
//val appInfo = appListSpinnerList[position]
|
||||
val appInfo = appListSpinnerAdapter.getItemSource(position) as AppListAdapterItem
|
||||
CommonUtils.insertOrReplaceText2Cursor(binding!!.etAppList, appInfo.packageName.toString() + "\n")
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString())
|
||||
}
|
||||
}
|
||||
binding!!.spApp.visibility = View.VISIBLE
|
||||
}.onFailure {
|
||||
Log.e("GlobalScope", it.message.toString())
|
||||
if (SettingUtils.enableLoadSystemAppList) {
|
||||
for (appInfo in App.SystemAppList) {
|
||||
if (TextUtils.isEmpty(appInfo.packageName)) continue
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
|
||||
//列表为空也不显示下拉框
|
||||
if (appListSpinnerList.isEmpty()) return
|
||||
|
||||
appListSpinnerAdapter = AppListSpinnerAdapter(appListSpinnerList).setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
||||
binding!!.spApp.setAdapter(appListSpinnerAdapter)
|
||||
binding!!.spApp.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
||||
try {
|
||||
val appInfo = appListSpinnerAdapter.getItemSource(position) as AppListAdapterItem
|
||||
CommonUtils.insertOrReplaceText2Cursor(binding!!.etAppList, appInfo.packageName.toString() + "\n")
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString())
|
||||
}
|
||||
}
|
||||
binding!!.layoutSpApp.visibility = View.VISIBLE
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -69,6 +69,9 @@ class BatteryService : Service() {
|
||||
private val batteryReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||
@SuppressLint("DefaultLocale")
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
|
||||
if (intent.action != Intent.ACTION_BATTERY_CHANGED) return
|
||||
|
||||
//自动删除N天前的转发记录
|
||||
if (SettingUtils.autoCleanLogsDays > 0) {
|
||||
Log.d(TAG, "自动删除N天前的转发记录")
|
||||
@ -145,21 +148,12 @@ class BatteryService : Service() {
|
||||
private fun sendMessage(context: Context, msg: String) {
|
||||
Log.i(TAG, msg)
|
||||
try {
|
||||
val msgInfo = MsgInfo(
|
||||
"app",
|
||||
"88888888",
|
||||
msg,
|
||||
Date(),
|
||||
getString(R.string.battery_status_monitor),
|
||||
-1
|
||||
)
|
||||
val request = OneTimeWorkRequestBuilder<SendWorker>()
|
||||
.setInputData(
|
||||
workDataOf(
|
||||
Worker.sendMsgInfo to Gson().toJson(msgInfo),
|
||||
)
|
||||
val msgInfo = MsgInfo("app", "88888888", msg, Date(), getString(R.string.battery_status_monitor), -1)
|
||||
val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
|
||||
workDataOf(
|
||||
Worker.sendMsgInfo to Gson().toJson(msgInfo),
|
||||
)
|
||||
.build()
|
||||
).build()
|
||||
WorkManager.getInstance(context).enqueue(request)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "getLog e:" + e.message)
|
||||
|
@ -10,12 +10,16 @@ import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.activity.MainActivity
|
||||
import com.idormy.sms.forwarder.database.AppDatabase
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.xuexiang.xutil.XUtil
|
||||
import com.xuexiang.xutil.file.FileUtils
|
||||
import frpclib.Frpclib
|
||||
import io.reactivex.Single
|
||||
@ -86,6 +90,12 @@ class ForegroundService : Service() {
|
||||
CommonUtils.toggleNotificationListenerService(this)
|
||||
}
|
||||
|
||||
//异步获取所有已安装 App 信息
|
||||
if (SettingUtils.enableLoadAppList) {
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
}
|
||||
|
||||
if (FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so")) {
|
||||
//监听Frpc启动指令
|
||||
LiveEventBus.get(INTENT_FRPC_APPLY_FILE, String::class.java).observeStickyForever(frpcObserver)
|
||||
|
@ -0,0 +1,126 @@
|
||||
package com.idormy.sms.forwarder.service
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Service
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.workDataOf
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||
import com.idormy.sms.forwarder.utils.Worker
|
||||
import com.idormy.sms.forwarder.workers.SendWorker
|
||||
import com.xuexiang.xutil.app.ServiceUtils
|
||||
import com.xuexiang.xutil.net.NetworkUtils
|
||||
import java.util.*
|
||||
|
||||
@Suppress("DEPRECATION", "DeferredResultUnused")
|
||||
class NetworkStateService : Service() {
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Log.i(TAG, "onCreate--------------")
|
||||
|
||||
//纯客户端模式
|
||||
//if (SettingUtils.enablePureClientMode) return
|
||||
|
||||
val networkStateFilter = IntentFilter()
|
||||
networkStateFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
registerReceiver(networkStateReceiver, networkStateFilter)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
Log.i(TAG, "onStartCommand--------------")
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.i(TAG, "onDestroy--------------")
|
||||
super.onDestroy()
|
||||
|
||||
//纯客户端模式
|
||||
//if (SettingUtils.enablePureClientMode) return
|
||||
|
||||
unregisterReceiver(networkStateReceiver)
|
||||
}
|
||||
|
||||
// 接收电池信息更新的广播
|
||||
private val networkStateReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||
@SuppressLint("DefaultLocale")
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
|
||||
if (intent.action != ConnectivityManager.CONNECTIVITY_ACTION) return
|
||||
|
||||
if (!SettingUtils.enableNetworkStateReceiver) return
|
||||
|
||||
Log.i(TAG, "网络状态已经改变")
|
||||
|
||||
val msg = StringBuilder()
|
||||
|
||||
//枚举网络状态 NET_NO:没有网络 , NET_2G:2g网络 , NET_3G:3g网络, NET_4G:4g网络, NET_5G:5g网络, NET_WIFI:wifi, NET_ETHERNET:有线网络, NET_UNKNOWN:未知网络
|
||||
val netStateType = NetworkUtils.getNetStateType()
|
||||
Log.d(TAG, "netStateType: $netStateType")
|
||||
val netStateTypeName = when (netStateType) {
|
||||
NetworkUtils.NetState.NET_NO -> "没有网络"
|
||||
NetworkUtils.NetState.NET_2G -> "2G网络"
|
||||
NetworkUtils.NetState.NET_3G -> "3G网络"
|
||||
NetworkUtils.NetState.NET_4G -> "4G网络"
|
||||
NetworkUtils.NetState.NET_5G -> "5G网络"
|
||||
NetworkUtils.NetState.NET_WIFI -> "Wifi"
|
||||
NetworkUtils.NetState.NET_ETHERNET -> "有线网络"
|
||||
NetworkUtils.NetState.NET_UNKNOWN -> "未知网络"
|
||||
else -> "未知网络"
|
||||
}
|
||||
msg.append(getString(R.string.network_type)).append(": ").append(netStateTypeName).append("\n")
|
||||
|
||||
//获取网络运营商名称:中国移动、中国联通、中国电信
|
||||
if (netStateType == NetworkUtils.NetState.NET_2G || netStateType == NetworkUtils.NetState.NET_3G || netStateType == NetworkUtils.NetState.NET_4G || netStateType == NetworkUtils.NetState.NET_5G) {
|
||||
val operatorName = NetworkUtils.getNetworkOperatorName()
|
||||
msg.append(getString(R.string.operator_name)).append(": ").append(operatorName).append("\n")
|
||||
}
|
||||
|
||||
val inetAddress = NetworkUtils.getLocalInetAddress()
|
||||
var hostAddress: String = inetAddress?.hostAddress?.toString() ?: "127.0.0.1"
|
||||
msg.append(getString(R.string.host_address)).append(": ").append(hostAddress).append("\n")
|
||||
|
||||
if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpService")) {
|
||||
hostAddress = if (hostAddress.indexOf(':', 0, false) > 0) "[${hostAddress}]" else hostAddress
|
||||
msg.append(getString(R.string.http_server)).append(": ").append("http://${hostAddress}:5000")
|
||||
}
|
||||
|
||||
sendMessage(context, msg.toString())
|
||||
}
|
||||
}
|
||||
|
||||
//发送信息
|
||||
private fun sendMessage(context: Context, msg: String) {
|
||||
Log.i(TAG, msg)
|
||||
try {
|
||||
val msgInfo = MsgInfo("app", "77777777", msg, Date(), getString(R.string.network_state_monitor), -1)
|
||||
val request = OneTimeWorkRequestBuilder<SendWorker>().setInputData(
|
||||
workDataOf(
|
||||
Worker.sendMsgInfo to Gson().toJson(msgInfo),
|
||||
)
|
||||
).build()
|
||||
WorkManager.getInstance(context).enqueue(request)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "getLog e:" + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "NetworkStateReceiver"
|
||||
}
|
||||
}
|
@ -36,13 +36,11 @@ import com.xuexiang.xui.widget.imageview.preview.PreviewBuilder
|
||||
import com.xuexiang.xutil.XUtil
|
||||
import com.xuexiang.xutil.common.StringUtils
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* 常用工具类
|
||||
*/
|
||||
@Suppress("RegExpRedundantEscape", "unused")
|
||||
@Suppress("RegExpRedundantEscape", "unused", "RegExpUnnecessaryNonCapturingGroup")
|
||||
class CommonUtils private constructor() {
|
||||
companion object {
|
||||
/**
|
||||
@ -161,11 +159,19 @@ class CommonUtils private constructor() {
|
||||
|
||||
//焦点位置插入文本
|
||||
fun insertOrReplaceText2Cursor(editText: EditText, str: String) {
|
||||
if (TextUtils.isEmpty(str)) return
|
||||
|
||||
//避免出错:java.lang.IndexOutOfBoundsException: setSpan (36 ... 36) ends beyond length 20
|
||||
if (str.length > 20) {
|
||||
editText.text.append(str)
|
||||
return
|
||||
}
|
||||
|
||||
editText.isFocusable = true
|
||||
editText.requestFocus()
|
||||
val start = max(editText.selectionStart, 0)
|
||||
val end = max(editText.selectionEnd, 0)
|
||||
editText.text.replace(min(start, end), max(start, end), str, 0, str.length)
|
||||
val nSection: Int = editText.selectionStart
|
||||
editText.text.insert(nSection, str)
|
||||
editText.setSelection(nSection + str.length)
|
||||
}
|
||||
|
||||
//==========图片预览===========//
|
||||
|
@ -50,6 +50,8 @@ const val SP_SILENT_PERIOD_START = "silent_period_start"
|
||||
const val SP_SILENT_PERIOD_END = "silent_period_end"
|
||||
const val SP_AUTO_CLEAN_LOGS_DAYS = "auto_clean_logs_days"
|
||||
|
||||
const val SP_NET_STATE_RECEIVER = "enable_network_state_receiver"
|
||||
|
||||
const val SP_BATTERY_RECEIVER = "enable_battery_receiver"
|
||||
const val SP_BATTERY_STATUS = "battery_status"
|
||||
const val SP_BATTERY_LEVEL_MIN = "battery_level_min"
|
||||
@ -333,6 +335,8 @@ const val KEY_RULE_ID = "key_rule_id"
|
||||
const val KEY_RULE_TYPE = "key_rule_type"
|
||||
const val KEY_RULE_CLONE = "key_rule_clone"
|
||||
|
||||
const val EVENT_LOAD_APP_LIST = "EVENT_LOAD_APP_LIST"
|
||||
|
||||
const val EVENT_KEY_SIM_SLOT = "EVENT_KEY_SIM_SLOT"
|
||||
const val EVENT_KEY_PHONE_NUMBERS = "EVENT_KEY_PHONE_NUMBERS"
|
||||
|
||||
|
@ -160,6 +160,7 @@ class HttpServerUtils private constructor() {
|
||||
cloneInfo.enableLoadUserAppList = SettingUtils.enableLoadUserAppList
|
||||
cloneInfo.enableLoadSystemAppList = SettingUtils.enableLoadSystemAppList
|
||||
cloneInfo.duplicateMessagesLimits = SettingUtils.duplicateMessagesLimits
|
||||
cloneInfo.enableNetworkStateReceiver = SettingUtils.enableNetworkStateReceiver
|
||||
cloneInfo.enableBatteryReceiver = SettingUtils.enableBatteryReceiver
|
||||
cloneInfo.batteryLevelMin = SettingUtils.batteryLevelMin
|
||||
cloneInfo.batteryLevelMax = SettingUtils.batteryLevelMax
|
||||
@ -206,6 +207,7 @@ class HttpServerUtils private constructor() {
|
||||
SettingUtils.enableLoadUserAppList = cloneInfo.enableLoadUserAppList
|
||||
SettingUtils.enableLoadSystemAppList = cloneInfo.enableLoadSystemAppList
|
||||
SettingUtils.duplicateMessagesLimits = cloneInfo.duplicateMessagesLimits
|
||||
SettingUtils.enableNetworkStateReceiver = cloneInfo.enableNetworkStateReceiver
|
||||
SettingUtils.enableBatteryReceiver = cloneInfo.enableBatteryReceiver
|
||||
SettingUtils.batteryLevelMin = cloneInfo.batteryLevelMin
|
||||
SettingUtils.batteryLevelMax = cloneInfo.batteryLevelMax
|
||||
|
@ -69,6 +69,9 @@ class SettingUtils private constructor() {
|
||||
//自动删除N天前的转发记录
|
||||
var autoCleanLogsDays: Int by SharedPreference(SP_AUTO_CLEAN_LOGS_DAYS, 0)
|
||||
|
||||
//是否监听网络状态变化
|
||||
var enableNetworkStateReceiver: Boolean by SharedPreference(SP_NET_STATE_RECEIVER, false)
|
||||
|
||||
//是否监听电池状态变化
|
||||
var enableBatteryReceiver: Boolean by SharedPreference(SP_BATTERY_RECEIVER, false)
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
package com.idormy.sms.forwarder.workers
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.utils.EVENT_LOAD_APP_LIST
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.xuexiang.xutil.app.AppUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class LoadAppListWorker(
|
||||
context: Context,
|
||||
workerParams: WorkerParameters,
|
||||
) : CoroutineWorker(context, workerParams) {
|
||||
|
||||
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
|
||||
if (App.LoadingAppList) {
|
||||
Log.d("LoadAppListWorker", "LoadingAppList is true, return")
|
||||
return@withContext Result.success()
|
||||
}
|
||||
|
||||
App.LoadingAppList = true
|
||||
App.UserAppList.clear()
|
||||
App.SystemAppList.clear()
|
||||
val appInfoList = AppUtils.getAppsInfo()
|
||||
for (appInfo in appInfoList) {
|
||||
if (appInfo.isSystem) {
|
||||
App.SystemAppList.add(appInfo)
|
||||
} else {
|
||||
App.UserAppList.add(appInfo)
|
||||
}
|
||||
}
|
||||
App.UserAppList.sortBy { appInfo -> appInfo.name }
|
||||
App.SystemAppList.sortBy { appInfo -> appInfo.name }
|
||||
|
||||
|
||||
LiveEventBus.get(EVENT_LOAD_APP_LIST, String::class.java).post("finish")
|
||||
App.LoadingAppList = false
|
||||
Log.d("LoadAppListWorker", "LoadAppListWorker finish, App.LoadingAppList=${App.LoadingAppList}")
|
||||
|
||||
return@withContext Result.success()
|
||||
}
|
||||
|
||||
}
|
@ -329,40 +329,47 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="10dp"
|
||||
android:visibility="gone"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="2"
|
||||
android:text="@string/extra_app"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_app_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
android:hint="@string/extra_app_hint"
|
||||
android:inputType="textMultiLine"
|
||||
app:met_clearButton="true" />
|
||||
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_app_list"
|
||||
android:layout_width="match_parent"
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_sp_app"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/extra_app_hint"
|
||||
android:inputType="textMultiLine"
|
||||
app:met_clearButton="true" />
|
||||
android:text="@string/choose_app"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.xuexiang.xui.widget.spinner.editspinner.EditSpinner
|
||||
android:id="@+id/sp_app"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginStart="5dp"
|
||||
app:es_hint="@string/choose_app_hint"
|
||||
app:es_maxLength="20"
|
||||
app:es_maxLine="1" />
|
||||
@ -600,6 +607,64 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/network_state_monitor"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="@string/network_state_monitor_tips"
|
||||
android:textSize="10sp"
|
||||
tools:ignore="SmallSp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
style="@style/settingBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/network_state_change_remind"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="RelativeOverlap" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/network_state_change_remind_tips"
|
||||
android:textSize="9sp"
|
||||
tools:ignore="SmallSp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||
android:id="@+id/sb_network_state_receiver"
|
||||
style="@style/SwitchButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -542,6 +542,10 @@
|
||||
<string name="active_request_tips">Obtain instructions through passive reception or active polling to operate the machine</string>
|
||||
<string name="httpserver">Local HttpServer</string>
|
||||
<string name="httpserver_tips">Available under WiFi network, after startup, other machines in the LAN can directly call the local interface</string>
|
||||
<string name="network_state_monitor">Network State Monitor</string>
|
||||
<string name="network_state_monitor_tips">[Note] You need to manually create APP forwarding rules, package name: 77777777</string>
|
||||
<string name="network_state_change_remind">Network State Change Remind</string>
|
||||
<string name="network_state_change_remind_tips">Send a notification when the network status changes (connection mode/IP change)</string>
|
||||
<string name="battery_monitor">Battery Monitor</string>
|
||||
<string name="battery_monitor_tips">[Note] You need to manually create APP forwarding rules, package name: 88888888</string>
|
||||
<string name="keep_alive">Keep Alive</string>
|
||||
@ -995,4 +999,8 @@
|
||||
<string name="sender_del">Del Sender</string>
|
||||
<string name="sender_disabled">Sender is disabled</string>
|
||||
<string name="unknown_sender">Unknown sender</string>
|
||||
<string name="network_type">Network Type</string>
|
||||
<string name="operator_name">Operator Name</string>
|
||||
<string name="host_address">Host Address</string>
|
||||
<string name="loading_app_list">Loading app list async...</string>
|
||||
</resources>
|
||||
|
@ -543,6 +543,10 @@
|
||||
<string name="active_request_tips">通过 被动接收 或者 主动轮询 获取指令,从而操作本机</string>
|
||||
<string name="httpserver">被动接收本地 HttpServer</string>
|
||||
<string name="httpserver_tips">WiFi网络下可用,启动后局域网内其他机器可直接调用本机接口</string>
|
||||
<string name="network_state_monitor">网络状态监控</string>
|
||||
<string name="network_state_monitor_tips">【注意】需要手动创建APP转发规则,包名:77777777</string>
|
||||
<string name="network_state_change_remind">网络状态改变提醒</string>
|
||||
<string name="network_state_change_remind_tips">网络状态改变(连接方式/IP变化)时发出通知</string>
|
||||
<string name="battery_monitor">电池监控</string>
|
||||
<string name="battery_monitor_tips">【注意】需要手动创建APP转发规则,包名:88888888</string>
|
||||
<string name="keep_alive">保活措施</string>
|
||||
@ -996,4 +1000,8 @@
|
||||
<string name="sender_del">删除发送通道</string>
|
||||
<string name="sender_disabled">发送通道已禁用</string>
|
||||
<string name="unknown_sender">未知发送通道</string>
|
||||
<string name="network_type">网络类型</string>
|
||||
<string name="operator_name">运营商</string>
|
||||
<string name="host_address">本地IP</string>
|
||||
<string name="loading_app_list">正在异步加载应用列表...</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user