tasker: add start action
Add a tasker action to start AuxioService in a HIGHLY limited ammner. Resolves #754.
This commit is contained in:
parent
3fa5628a1e
commit
ea9c5d3c88
8 changed files with 114 additions and 15 deletions
|
@ -151,6 +151,9 @@ dependencies {
|
|||
// Speed dial
|
||||
implementation "com.leinardi.android:speed-dial:3.3.0"
|
||||
|
||||
// Tasker integration
|
||||
implementation 'com.joaomgcd:taskerpluginlibrary:0.4.10'
|
||||
|
||||
// Testing
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
|
||||
testImplementation "junit:junit:4.13.2"
|
||||
|
|
|
@ -135,5 +135,15 @@
|
|||
android:resource="@xml/widget_info" />
|
||||
</receiver>
|
||||
|
||||
<!-- Tasker 'start service' integration -->
|
||||
<activity
|
||||
android:name=".ActivityConfigBasicAction"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="My Tasker Action">
|
||||
<intent-filter>
|
||||
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
|
@ -55,13 +55,9 @@ class AuxioService : MediaLibraryService(), ForegroundListener {
|
|||
}
|
||||
|
||||
private fun onHandleForeground(intent: Intent?) {
|
||||
val nativeStart = intent?.getBooleanExtra(INTENT_KEY_NATIVE_START, false) ?: false
|
||||
val startId = intent?.getIntExtra(INTENT_KEY_START_ID, -1) ?: -1
|
||||
indexingFragment.start()
|
||||
if (!nativeStart) {
|
||||
// Some foreign code started us, no guarantees about foreground stability. Figure
|
||||
// out what to do.
|
||||
mediaSessionFragment.handleNonNativeStart()
|
||||
}
|
||||
mediaSessionFragment.start(startId)
|
||||
}
|
||||
|
||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||
|
@ -87,6 +83,7 @@ class AuxioService : MediaLibraryService(), ForegroundListener {
|
|||
if (change == ForegroundListener.Change.MEDIA_SESSION) {
|
||||
mediaSessionFragment.createNotification {
|
||||
startForeground(it.notificationId, it.notification)
|
||||
isForeground = true
|
||||
}
|
||||
}
|
||||
// Nothing changed, but don't show anything music related since we can always
|
||||
|
@ -95,16 +92,21 @@ class AuxioService : MediaLibraryService(), ForegroundListener {
|
|||
indexingFragment.createNotification {
|
||||
if (it != null) {
|
||||
startForeground(it.code, it.build())
|
||||
isForeground = true
|
||||
} else {
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
isForeground = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
var isForeground = false
|
||||
private set
|
||||
|
||||
// This is only meant for Auxio to internally ensure that it's state management will work.
|
||||
const val INTENT_KEY_NATIVE_START = BuildConfig.APPLICATION_ID + ".service.NATIVE_START"
|
||||
const val INTENT_KEY_START_ID = BuildConfig.APPLICATION_ID + ".service.START_ID"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,10 @@ object IntegerTable {
|
|||
const val INDEXER_NOTIFICATION_CODE = 0xA0A1
|
||||
/** MainActivity Intent request code */
|
||||
const val REQUEST_CODE = 0xA0C0
|
||||
/** Activity AuxioService Start ID */
|
||||
const val START_ID_ACTIVITY = 0xA050
|
||||
/** Tasker AuxioService Start ID */
|
||||
const val START_ID_TASKER = 0xA051
|
||||
/** RepeatMode.NONE */
|
||||
const val REPEAT_MODE_NONE = 0xA100
|
||||
/** RepeatMode.ALL */
|
||||
|
@ -133,7 +137,4 @@ object IntegerTable {
|
|||
const val PLAY_SONG_FROM_PLAYLIST = 0xA123
|
||||
/** PlaySong.ByItself */
|
||||
const val PLAY_SONG_BY_ITSELF = 0xA124
|
||||
const val PLAYER_COMMAND_INC_REPEAT_MODE = 0xA125
|
||||
const val PLAYER_COMMAND_TOGGLE_SHUFFLE = 0xA126
|
||||
const val PLAYER_COMMAND_EXIT = 0xA127
|
||||
}
|
||||
|
|
|
@ -71,11 +71,11 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
startService(
|
||||
Intent(this, AuxioService::class.java)
|
||||
.putExtra(AuxioService.INTENT_KEY_NATIVE_START, true))
|
||||
.putExtra(AuxioService.INTENT_KEY_START_ID, IntegerTable.START_ID_ACTIVITY))
|
||||
|
||||
if (!startIntentAction(intent)) {
|
||||
// No intent action to do, just restore the previously saved state.
|
||||
playbackModel.playDeferred(DeferredPlayback.RestoreState)
|
||||
playbackModel.playDeferred(DeferredPlayback.RestoreState(false))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,11 +109,23 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun handleNonNativeStart() {
|
||||
fun start(startedBy: Int) {
|
||||
// At minimum we want to ensure an active playback state.
|
||||
// TODO: Possibly also force to go foreground?
|
||||
logD("Handling non-native start.")
|
||||
playbackManager.playDeferred(DeferredPlayback.RestoreState)
|
||||
val action =
|
||||
when (startedBy) {
|
||||
IntegerTable.START_ID_ACTIVITY -> null
|
||||
IntegerTable.START_ID_TASKER ->
|
||||
DeferredPlayback.RestoreState(
|
||||
play = true, fallback = DeferredPlayback.ShuffleAll)
|
||||
// External services using Auxio better know what they are doing.
|
||||
else -> DeferredPlayback.RestoreState(play = false)
|
||||
}
|
||||
if (action != null) {
|
||||
logD("Initing service fragment using action $action")
|
||||
playbackManager.playDeferred(action)
|
||||
}
|
||||
}
|
||||
|
||||
fun hasNotification(): Boolean = exoHolder.sessionOngoing
|
||||
|
|
|
@ -276,7 +276,8 @@ data class QueueChange(val type: Type, val instructions: UpdateInstructions) {
|
|||
/** Possible long-running background tasks handled by the background playback task. */
|
||||
sealed interface DeferredPlayback {
|
||||
/** Restore the previously saved playback state. */
|
||||
data class RestoreState(val play: Boolean, val fallback: DeferredPlayback? = null) : DeferredPlayback
|
||||
data class RestoreState(val play: Boolean, val fallback: DeferredPlayback? = null) :
|
||||
DeferredPlayback
|
||||
|
||||
/**
|
||||
* Start shuffled playback of the entire music library. Analogous to the "Shuffle All" shortcut.
|
||||
|
|
70
app/src/main/java/org/oxycblt/auxio/tasker/Start.kt
Normal file
70
app/src/main/java/org/oxycblt/auxio/tasker/Start.kt
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Auxio Project
|
||||
* Start.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.tasker
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.joaomgcd.taskerpluginlibrary.action.TaskerPluginRunnerActionNoOutputOrInput
|
||||
import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfig
|
||||
import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfigHelperNoOutputOrInput
|
||||
import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfigNoInput
|
||||
import com.joaomgcd.taskerpluginlibrary.input.TaskerInput
|
||||
import com.joaomgcd.taskerpluginlibrary.runner.TaskerPluginResult
|
||||
import com.joaomgcd.taskerpluginlibrary.runner.TaskerPluginResultSucess
|
||||
import org.oxycblt.auxio.AuxioService
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
|
||||
class StartActionHelper(config: TaskerPluginConfig<Unit>) :
|
||||
TaskerPluginConfigHelperNoOutputOrInput<StartActionRunner>(config) {
|
||||
override val runnerClass: Class<StartActionRunner>
|
||||
get() = StartActionRunner::class.java
|
||||
|
||||
override fun addToStringBlurb(input: TaskerInput<Unit>, blurbBuilder: StringBuilder) {
|
||||
blurbBuilder.append(
|
||||
"Starts Auxio using the previously saved state. If no saved state is available, all songs will be shuffled. Playback will start immediately. Be careful controlling this service, if you close it and then try to use it again, you will probably crash the app.")
|
||||
}
|
||||
}
|
||||
|
||||
class ActivityConfigStartAction : Activity(), TaskerPluginConfigNoInput {
|
||||
override val context
|
||||
get() = applicationContext
|
||||
|
||||
private val taskerHelper by lazy { StartActionHelper(this) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
taskerHelper.finishForTasker()
|
||||
}
|
||||
}
|
||||
|
||||
class StartActionRunner : TaskerPluginRunnerActionNoOutputOrInput() {
|
||||
override fun run(context: Context, input: TaskerInput<Unit>): TaskerPluginResult<Unit> {
|
||||
ContextCompat.startForegroundService(
|
||||
context,
|
||||
Intent(context, AuxioService::class.java)
|
||||
.putExtra(AuxioService.INTENT_KEY_START_ID, IntegerTable.START_ID_TASKER))
|
||||
while (!AuxioService.isForeground) {
|
||||
Thread.sleep(100)
|
||||
}
|
||||
return TaskerPluginResultSucess()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue