diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 34e9ebac..eff8f18c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -272,6 +272,14 @@ + + + + + + 0) String.format(getString(R.string.duration_minute), timeAfterOn.toString()) else "" + description = String.format(getString(R.string.time_after_screen_on_description), duration) + action = Intent.ACTION_SCREEN_ON + } else { + val duration = if (timeAfterOff > 0) String.format(getString(R.string.duration_minute), timeAfterOff.toString()) else "" + description = String.format(getString(R.string.time_after_screen_off_description), duration) + action = Intent.ACTION_SCREEN_OFF + } + + timeAfterScreenOff = timeAfterOff + timeAfterScreenOn = timeAfterOn + } + + fun getActionCheckId(): Int { + return when (action) { + Intent.ACTION_SCREEN_ON -> R.id.rb_action_screen_on + else -> R.id.rb_action_screen_off + } + } +} diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/condition/LockScreenFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/condition/LockScreenFragment.kt new file mode 100644 index 00000000..a4959a8d --- /dev/null +++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/condition/LockScreenFragment.kt @@ -0,0 +1,159 @@ +package com.idormy.sms.forwarder.fragment.condition + +import android.annotation.SuppressLint +import android.content.Intent +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.google.gson.Gson +import com.idormy.sms.forwarder.R +import com.idormy.sms.forwarder.core.BaseFragment +import com.idormy.sms.forwarder.databinding.FragmentTasksConditionLockScreenBinding +import com.idormy.sms.forwarder.entity.task.LockScreenSetting +import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION +import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_CONDITION +import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION +import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION +import com.idormy.sms.forwarder.utils.TASK_CONDITION_LOCK_SCREEN +import com.idormy.sms.forwarder.utils.XToastUtils +import com.jeremyliao.liveeventbus.LiveEventBus +import com.xuexiang.xaop.annotation.SingleClick +import com.xuexiang.xpage.annotation.Page +import com.xuexiang.xrouter.annotation.AutoWired +import com.xuexiang.xrouter.launcher.XRouter +import com.xuexiang.xui.utils.CountDownButtonHelper +import com.xuexiang.xui.widget.actionbar.TitleBar + +@Page(name = "LockScreen") +@Suppress("PrivatePropertyName") +class LockScreenFragment : BaseFragment(), View.OnClickListener { + + private val TAG: String = LockScreenFragment::class.java.simpleName + var titleBar: TitleBar? = null + private var mCountDownHelper: CountDownButtonHelper? = null + + @JvmField + @AutoWired(name = KEY_EVENT_DATA_CONDITION) + var eventData: String? = null + + override fun initArgs() { + XRouter.getInstance().inject(this) + } + + override fun viewBindingInflate( + inflater: LayoutInflater, + container: ViewGroup, + ): FragmentTasksConditionLockScreenBinding { + return FragmentTasksConditionLockScreenBinding.inflate(inflater, container, false) + } + + override fun initTitle(): TitleBar? { + titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_lock_screen) + return titleBar + } + + /** + * 初始化控件 + */ + override fun initViews() { + //测试按钮增加倒计时,避免重复点击 + mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3) + mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener { + override fun onCountDown(time: Int) { + binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time) + } + + override fun onFinished() { + binding!!.btnTest.text = getString(R.string.test) + } + }) + + binding!!.rgAction.setOnCheckedChangeListener { _, checkedId -> + if (checkedId == R.id.rb_action_screen_off) { + binding!!.xsbTimeAfterScreenOff.visibility = View.VISIBLE + binding!!.xsbTimeAfterScreenOn.visibility = View.GONE + } else { + binding!!.xsbTimeAfterScreenOff.visibility = View.GONE + binding!!.xsbTimeAfterScreenOn.visibility = View.VISIBLE + } + } + + Log.d(TAG, "initViews eventData:$eventData") + if (eventData != null) { + val settingVo = Gson().fromJson(eventData, LockScreenSetting::class.java) + Log.d(TAG, "initViews settingVo:$settingVo") + binding!!.rgAction.check(settingVo.getActionCheckId()) + binding!!.xsbTimeAfterScreenOff.setDefaultValue(settingVo.timeAfterScreenOff) + binding!!.xsbTimeAfterScreenOn.setDefaultValue(settingVo.timeAfterScreenOn) + } else { + binding!!.xsbTimeAfterScreenOff.setDefaultValue(0) + binding!!.xsbTimeAfterScreenOn.setDefaultValue(0) + } + } + + @SuppressLint("SetTextI18n") + override fun initListeners() { + binding!!.btnTest.setOnClickListener(this) + binding!!.btnDel.setOnClickListener(this) + binding!!.btnSave.setOnClickListener(this) + LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) { + mCountDownHelper?.finish() + + if (it == "success") { + XToastUtils.success("测试通过", 30000) + } else { + XToastUtils.error(it, 30000) + } + } + } + + @SingleClick + override fun onClick(v: View) { + try { + when (v.id) { + R.id.btn_test -> { + mCountDownHelper?.start() + Thread { + try { + val settingVo = checkSetting() + Log.d(TAG, settingVo.toString()) + LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post("success") + } catch (e: Exception) { + LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post(e.message.toString()) + e.printStackTrace() + } + }.start() + return + } + + R.id.btn_del -> { + popToBack() + return + } + + R.id.btn_save -> { + val settingVo = checkSetting() + val intent = Intent() + intent.putExtra(KEY_BACK_DESCRIPTION_CONDITION, settingVo.description) + intent.putExtra(KEY_BACK_DATA_CONDITION, Gson().toJson(settingVo)) + setFragmentResult(TASK_CONDITION_LOCK_SCREEN, intent) + popToBack() + return + } + } + } catch (e: Exception) { + XToastUtils.error(e.message.toString(), 30000) + e.printStackTrace() + } + } + + //检查设置 + @SuppressLint("SetTextI18n") + private fun checkSetting(): LockScreenSetting { + val actionCheckId = binding!!.rgAction.checkedRadioButtonId + val timeAfterScreenOff = binding!!.xsbTimeAfterScreenOff.selectedNumber + val timeAfterScreenOn = binding!!.xsbTimeAfterScreenOn.selectedNumber + return LockScreenSetting(actionCheckId, timeAfterScreenOff, timeAfterScreenOn) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/LockScreenReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/LockScreenReceiver.kt new file mode 100644 index 00000000..847121dd --- /dev/null +++ b/app/src/main/java/com/idormy/sms/forwarder/receiver/LockScreenReceiver.kt @@ -0,0 +1,32 @@ +package com.idormy.sms.forwarder.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.util.Log +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.workDataOf +import com.idormy.sms.forwarder.utils.TASK_CONDITION_LOCK_SCREEN +import com.idormy.sms.forwarder.utils.TaskWorker +import com.idormy.sms.forwarder.workers.LockScreenWorker + +@Suppress("PropertyName") +class LockScreenReceiver : BroadcastReceiver() { + + val TAG: String = LockScreenReceiver::class.java.simpleName + + override fun onReceive(context: Context?, intent: Intent?) { + + if (context == null || (intent?.action != Intent.ACTION_SCREEN_OFF && intent?.action != Intent.ACTION_SCREEN_ON)) return + + Log.d(TAG, "onReceive: ${intent.action}") + val request = OneTimeWorkRequestBuilder().setInputData( + workDataOf( + TaskWorker.conditionType to TASK_CONDITION_LOCK_SCREEN, + TaskWorker.action to intent.action, + ) + ).build() + WorkManager.getInstance(context).enqueue(request) + } +} diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt index c5cc75d6..8b7edba3 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt +++ b/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt @@ -25,6 +25,7 @@ object TaskWorker { const val conditionType = "condition_type" const val msg = "msg" const val msgInfo = "msg_info" + const val action = "action" } //初始化相关 diff --git a/app/src/main/java/com/idormy/sms/forwarder/workers/LockScreenWorker.kt b/app/src/main/java/com/idormy/sms/forwarder/workers/LockScreenWorker.kt new file mode 100644 index 00000000..a2641f3b --- /dev/null +++ b/app/src/main/java/com/idormy/sms/forwarder/workers/LockScreenWorker.kt @@ -0,0 +1,80 @@ +package com.idormy.sms.forwarder.workers + +import android.content.Context +import android.content.Intent +import android.util.Log +import androidx.work.CoroutineWorker +import androidx.work.Data +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.WorkerParameters +import com.google.gson.Gson +import com.idormy.sms.forwarder.App +import com.idormy.sms.forwarder.database.AppDatabase +import com.idormy.sms.forwarder.entity.MsgInfo +import com.idormy.sms.forwarder.entity.task.LockScreenSetting +import com.idormy.sms.forwarder.entity.task.TaskSetting +import com.idormy.sms.forwarder.utils.TaskWorker +import java.util.Date +import java.util.concurrent.TimeUnit + +@Suppress("PrivatePropertyName", "DEPRECATION") +class LockScreenWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { + + private val TAG: String = LockScreenWorker::class.java.simpleName + + override suspend fun doWork(): Result { + + val conditionType = inputData.getInt(TaskWorker.conditionType, -1) + val action = inputData.getString(TaskWorker.action) + + val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) + for (task in taskList) { + Log.d(TAG, "task = $task") + + // 根据任务信息执行相应操作 + val conditionList = Gson().fromJson(task.conditions, Array::class.java).toMutableList() + if (conditionList.isEmpty()) { + Log.d(TAG, "任务${task.id}:conditionList is empty") + continue + } + val firstCondition = conditionList.firstOrNull() + if (firstCondition == null) { + Log.d(TAG, "任务${task.id}:firstCondition is null") + continue + } + + val lockScreenSetting = Gson().fromJson(firstCondition.setting, LockScreenSetting::class.java) + if (lockScreenSetting == null) { + Log.d(TAG, "任务${task.id}:lockScreenSetting is null") + continue + } + + if (action != lockScreenSetting.action) { + Log.d(TAG, "任务${task.id}:action is not match, action = $action, lockScreenSetting = $lockScreenSetting") + continue + } + + val duration = if (action == Intent.ACTION_SCREEN_ON) lockScreenSetting.timeAfterScreenOn else lockScreenSetting.timeAfterScreenOff + + //TODO:判断其他条件是否满足 + + //TODO: 组装消息体 && 执行具体任务 + val msgInfo = MsgInfo("task", task.name, lockScreenSetting.description, Date(), task.description) + val actionData = Data.Builder() + .putLong(TaskWorker.taskId, task.id) + .putString(TaskWorker.taskActions, task.actions) + .putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)) + .build() + val actionRequest = OneTimeWorkRequestBuilder() + .setInitialDelay(duration.toLong(), TimeUnit.MINUTES) + .setInputData(actionData).build() + WorkManager.getInstance().enqueue(actionRequest) + } + + return Result.success() + + + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_tasks_condition_battery.xml b/app/src/main/res/layout/fragment_tasks_condition_battery.xml index 363eb2e8..19fc132b 100644 --- a/app/src/main/res/layout/fragment_tasks_condition_battery.xml +++ b/app/src/main/res/layout/fragment_tasks_condition_battery.xml @@ -65,7 +65,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:xsb_insideRangeLineColor="#0bd97f" - app:xsb_insideRangeLineStrokeWidth="5dp" + app:xsb_insideRangeLineStrokeWidth="10dp" app:xsb_isShowBubble="true" app:xsb_isShowRuler="true" app:xsb_max="100" @@ -73,8 +73,9 @@ app:xsb_numberTextColor="#ffffff" app:xsb_numberTextSize="15sp" app:xsb_outsideRangeLineColor="#f0f0f0" - app:xsb_outsideRangeLineStrokeWidth="5dp" - app:xsb_rulerColor="@color/xui_config_color_gray_4" /> + app:xsb_outsideRangeLineStrokeWidth="10dp" + app:xsb_rulerColor="@color/xui_config_color_gray_4" + app:xsb_rulerInterval="ten" /> + app:xsb_outsideRangeLineStrokeWidth="10dp" + app:xsb_rulerColor="@color/xui_config_color_gray_4" + app:xsb_rulerInterval="ten" /> diff --git a/app/src/main/res/layout/fragment_tasks_condition_lock_screen.xml b/app/src/main/res/layout/fragment_tasks_condition_lock_screen.xml new file mode 100644 index 00000000..88d76fe2 --- /dev/null +++ b/app/src/main/res/layout/fragment_tasks_condition_lock_screen.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 2e4aaa19..4c4f8271 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1122,7 +1122,7 @@ SIM Status Battery Charge - Lock Screen + Screen Off/On Send Sms Notification Frpc Setting @@ -1200,4 +1200,10 @@ Any SIM SIM-1 SIM-2 + + Time After Screen Off (Minutes) + %sAfter Screen Off + Time After Screen On (Minutes) + %sAfter Screen On + %s minutes diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8de889eb..c58606ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1123,7 +1123,7 @@ SIM卡状态 电量使用 充电状态 - 屏幕锁定 + 锁屏解锁 发送短信 通道推送 Frpc设置 @@ -1201,4 +1201,10 @@ 不限卡槽 SIM-1 SIM-2 + + 屏幕锁定后多长时间(分钟) + 屏幕锁定%s后 + 屏幕解锁后多长时间(分钟) + 屏幕解锁%s后 + %s分钟