From 8f2ca1ecfbab709571b03a33668fe1f02fee603a Mon Sep 17 00:00:00 2001 From: Jonah Hirsch Date: Sun, 12 Sep 2021 17:37:01 -0700 Subject: [PATCH 1/4] Fix TaskerPluginRunner always using default NotificationProperties --- .../taskerpluginlibrary/action/TaskerPluginRunnerAction.kt | 2 +- .../taskerpluginlibrary/runner/TaskerPluginRunner.kt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/TaskerPluginRunnerAction.kt b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/TaskerPluginRunnerAction.kt index fc53e55..9d8c811 100644 --- a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/TaskerPluginRunnerAction.kt +++ b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/TaskerPluginRunnerAction.kt @@ -14,7 +14,7 @@ abstract class TaskerPluginRunnerAction() : TaskerP internal fun runWithIntent(context: IntentServiceParallel?, taskerIntent: Intent?) :RunnerActionResult{ if (context == null) return RunnerActionResult(false) if (taskerIntent == null) return RunnerActionResult(false) - context.startForegroundIfNeeded() + startForegroundIfNeeded(context) try { val input = taskerIntent.getTaskerInput(context, getInputClass(taskerIntent)) var result = run(context, input) diff --git a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt index 39a2af8..a80466c 100644 --- a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt +++ b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt @@ -47,6 +47,11 @@ abstract class TaskerPluginRunner { TaskerPluginRunner.startForegroundIfNeeded(this, notificationProperties) } + @TargetApi(Build.VERSION_CODES.O) + fun startForegroundIfNeeded(intentServiceParallel: IntentServiceParallel) { + TaskerPluginRunner.startForegroundIfNeeded(intentServiceParallel, notificationProperties) + } + companion object { const val NOTIFICATION_CHANNEL_ID = "taskerpluginforegroundd" From a83bb83d1a040cfdc7203b48c5cb450d528a0c9a Mon Sep 17 00:00:00 2001 From: Jonah Hirsch Date: Sun, 12 Sep 2021 17:47:39 -0700 Subject: [PATCH 2/4] Add ability to fully customize the Foreground Service notification Introduces two new optional parameters to NotificationProperties' default constructor: * notificationChannelId: This allows developers to customize the Notification Channel ID, so they can put the notification in the exact channel they desire * notificationBuilderExtender: Accepts a lambda that can modify the Notification.Builder so developers can fully customize the Foreground Service notification --- .../runner/TaskerPluginRunner.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt index a80466c..adc22f5 100644 --- a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt +++ b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/runner/TaskerPluginRunner.kt @@ -28,12 +28,15 @@ abstract class TaskerPluginRunner { val notificationChannelDescriptionResId: Int = R.string.tasker_plugin_service_description, val titleResId: Int = R.string.app_name, val textResId: Int = R.string.running_tasker_plugin, - val iconResId: Int = R.mipmap.ic_launcher) { + val iconResId: Int = R.mipmap.ic_launcher, + val notificationChannelId: String = NOTIFICATION_CHANNEL_ID, + val notificationBuilderExtender: Notification.Builder.(context: Context) -> Notification.Builder = {this}) { @TargetApi(Build.VERSION_CODES.O) - fun getNotification(context: Context) = Notification.Builder(context, NOTIFICATION_CHANNEL_ID) + fun getNotification(context: Context) = Notification.Builder(context, notificationChannelId) .setContentTitle(context.getString(titleResId)) .setContentText(context.getString(textResId)) .setSmallIcon(Icon.createWithResource(context, iconResId)) + .notificationBuilderExtender(context) .build() } @@ -54,11 +57,11 @@ abstract class TaskerPluginRunner { companion object { - const val NOTIFICATION_CHANNEL_ID = "taskerpluginforegroundd" + private const val NOTIFICATION_CHANNEL_ID = "taskerpluginforegroundd" @TargetApi(Build.VERSION_CODES.O) - fun Service.createNotificationChannel(channelId: String, notificationProperties: NotificationProperties) { + fun Service.createNotificationChannel(notificationProperties: NotificationProperties) { val notificationManager = getSystemService(NotificationManager::class.java) - val channel = NotificationChannel(channelId, getString(notificationProperties.notificationChannelNameResId), NotificationManager.IMPORTANCE_NONE) + val channel = NotificationChannel(notificationProperties.notificationChannelId, getString(notificationProperties.notificationChannelNameResId), NotificationManager.IMPORTANCE_NONE) channel.description = getString(notificationProperties.notificationChannelDescriptionResId) notificationManager.createNotificationChannel(channel) } @@ -69,8 +72,7 @@ abstract class TaskerPluginRunner { @TargetApi(Build.VERSION_CODES.O) fun startForegroundIfNeeded(intentService: Service, notificationProperties: NotificationProperties = NotificationProperties()) { if (!intentService.hasToRunServicesInForeground) return - val channelId = NOTIFICATION_CHANNEL_ID - intentService.createNotificationChannel(channelId, notificationProperties) + intentService.createNotificationChannel(notificationProperties) val notification: Notification = notificationProperties.getNotification(intentService) intentService.startForeground(this.hashCode(), notification) } From 44abf54a550fab55d90fabf4861a6344aaf0c2ce Mon Sep 17 00:00:00 2001 From: Jonah Hirsch Date: Sun, 12 Sep 2021 18:09:28 -0700 Subject: [PATCH 3/4] By sending an Intent such as: ``` Intent(context, IntentServiceAction::class.java).apply { action = IntentServiceAction.ACTION_STOP } ``` Any running actions will be stopped with an InterruptedException --- .../action/ActionReceivers.kt | 23 +++++++++++++++++++ .../src/main/res/values/strings.xml | 1 + 2 files changed, 24 insertions(+) diff --git a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/ActionReceivers.kt b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/ActionReceivers.kt index 5668e99..27b6d82 100644 --- a/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/ActionReceivers.kt +++ b/taskerpluginlibrary/src/main/java/com/joaomgcd/taskerpluginlibrary/action/ActionReceivers.kt @@ -3,8 +3,11 @@ package com.joaomgcd.taskerpluginlibrary.action import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import com.joaomgcd.taskerpluginlibrary.R import com.joaomgcd.taskerpluginlibrary.extensions.runFromTasker +import com.joaomgcd.taskerpluginlibrary.runner.ArgsSignalFinish import com.joaomgcd.taskerpluginlibrary.runner.IntentServiceParallel +import com.joaomgcd.taskerpluginlibrary.runner.TaskerPluginResultError import net.dinglisch.android.tasker.TaskerPlugin @@ -20,11 +23,31 @@ class BroadcastReceiverAction : BroadcastReceiver() { } class IntentServiceAction : IntentServiceParallel("IntentServiceTaskerAction") { + private var taskerIntent: Intent? = null + override fun onHandleIntent(intent: Intent) { startForegroundIfNeeded() + taskerIntent = intent val result = TaskerPluginRunnerAction.runFromIntent(this, intent) if (!result.hasStartedForeground) { startForegroundIfNeeded() } } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + if (intent?.action.equals(ACTION_STOP)) { + stopSelf() + taskerIntent?.let { + TaskerPluginResultError( + InterruptedException(getString(R.string.cancelled)) + ).signalFinish(ArgsSignalFinish(this, it)) + } + return START_NOT_STICKY + } + return super.onStartCommand(intent, flags, startId) + } + + companion object { + const val ACTION_STOP = "ACTION_STOP" + } } \ No newline at end of file diff --git a/taskerpluginlibrary/src/main/res/values/strings.xml b/taskerpluginlibrary/src/main/res/values/strings.xml index 4a295fa..113c81d 100644 --- a/taskerpluginlibrary/src/main/res/values/strings.xml +++ b/taskerpluginlibrary/src/main/res/values/strings.xml @@ -7,4 +7,5 @@ If there\'s an error, contains an error code Error Message If there\'s an error, contains an error message + Cancelled From b7c970c7616f972281d7fc1cc57404ec01a979d7 Mon Sep 17 00:00:00 2001 From: Jonah Hirsch Date: Sun, 12 Sep 2021 18:13:52 -0700 Subject: [PATCH 4/4] Add sample Cancellable action --- app/src/main/AndroidManifest.xml | 9 ++++ .../tasker/cancellable/Cancellable.kt | 50 +++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 3 files changed, 61 insertions(+) create mode 100644 app/src/main/java/com/joaomgcd/taskerpluginsample/tasker/cancellable/Cancellable.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 27b71bc..de2eb19 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -104,6 +104,15 @@ + + + + + + val intent = Intent(context, IntentServiceAction::class.java).apply { + action = IntentServiceAction.ACTION_STOP + } + val pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + val text = context.getString(R.string.cancel) + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val action = Notification.Action.Builder(Icon.createWithResource(context, R.mipmap.ic_launcher), text, pendingIntent).build() + addAction(action) + } else { + addAction(R.mipmap.ic_launcher, text, pendingIntent) + } + } + + override fun run(context: Context, input: TaskerInput): TaskerPluginResult { + Thread.sleep(10000) + return TaskerPluginResultSucess() + } +} + +class CancellableHelper(config: TaskerPluginConfig) : TaskerPluginConfigHelperNoOutputOrInput(config) { + override val runnerClass = CancellableRunner::class.java + override fun addToStringBlurb(input: TaskerInput, blurbBuilder: StringBuilder) { + blurbBuilder.append("This will start a task that takes 10 seconds that can be cancelled from its Notification.") + } +} + +class CancellableActivity : ActivityConfigTaskerNoOutputOrInput() { + override fun getNewHelper(config: TaskerPluginConfig) = CancellableHelper(config) +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 071c3b3..39a3a00 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -53,4 +53,6 @@ The time it took for the background work to complete in millis Result Text user input in the dialog + + Cancel