diff --git a/pretixprint/app/src/main/AndroidManifest.xml b/pretixprint/app/src/main/AndroidManifest.xml index f0975ac1..cf2b2708 100644 --- a/pretixprint/app/src/main/AndroidManifest.xml +++ b/pretixprint/app/src/main/AndroidManifest.xml @@ -124,6 +124,12 @@ + + diff --git a/pretixprint/app/src/main/java/eu/pretix/pretixprint/print/KeepaliveService.kt b/pretixprint/app/src/main/java/eu/pretix/pretixprint/print/KeepaliveService.kt new file mode 100644 index 00000000..313b2253 --- /dev/null +++ b/pretixprint/app/src/main/java/eu/pretix/pretixprint/print/KeepaliveService.kt @@ -0,0 +1,83 @@ +package eu.pretix.pretixprint.print + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.app.Service +import android.content.Context +import android.content.Intent +import android.os.Build +import android.os.IBinder +import androidx.core.app.NotificationCompat +import eu.pretix.pretixprint.R +import eu.pretix.pretixprint.ui.SettingsActivity + +class KeepaliveService : Service() { + + companion object { + val CHANNEL_ID = "pretixprint_keepalive_channel" + val ONGOING_NOTIFICATION_ID = 43 + + fun start(context: Context) { + val intent = Intent(context, KeepaliveService::class.java) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(intent) + } else { + context.startService(intent) + } + } + } + + private fun _startForeground() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + CHANNEL_ID, + getString(R.string.notification_channel_keepalive), + NotificationManager.IMPORTANCE_LOW + ) + channel.description = getString(R.string.notification_channel_keepalive_description) + channel.setSound(null, null) + channel.enableVibration(false) + getSystemService(NotificationManager::class.java).createNotificationChannel(channel) + } + + val startBaseActivity = Intent(this, SettingsActivity::class.java) + startBaseActivity.action = Intent.ACTION_MAIN + startBaseActivity.addCategory(Intent.CATEGORY_LAUNCHER) + startBaseActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + val keepAliveNotification: Notification = + NotificationCompat.Builder(this, CHANNEL_ID) + .setContentTitle(getString(R.string.keepalive_notification)) + .setSmallIcon(R.drawable.ic_stat_print) + .setContentIntent( + PendingIntent.getActivity( + this, + 0, + startBaseActivity, + if (Build.VERSION.SDK_INT >= 23) { + PendingIntent.FLAG_IMMUTABLE + } else { + 0 + } + ) + ) + .build() + this.startForeground(ONGOING_NOTIFICATION_ID, keepAliveNotification) + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + _startForeground() + return START_NOT_STICKY + } + + override fun onBind(p0: Intent?): IBinder? { + TODO("Not yet implemented") + } + + override fun onCreate() { + super.onCreate() + _startForeground() + } +} \ No newline at end of file diff --git a/pretixprint/app/src/main/java/eu/pretix/pretixprint/print/PrintService.kt b/pretixprint/app/src/main/java/eu/pretix/pretixprint/print/PrintService.kt index 86c96aa7..c8d1231f 100644 --- a/pretixprint/app/src/main/java/eu/pretix/pretixprint/print/PrintService.kt +++ b/pretixprint/app/src/main/java/eu/pretix/pretixprint/print/PrintService.kt @@ -10,6 +10,7 @@ import android.os.Build.VERSION.SDK_INT import android.os.Bundle import android.os.ResultReceiver import android.util.Log +import androidx.annotation.Keep import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.preference.PreferenceManager @@ -38,6 +39,7 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { } private fun createNotificationChannel() { + Log.i("PrintService", "createNotificationChannel()") // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { @@ -52,6 +54,7 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { } private fun startForegroundNotification() { + Log.i("PrintService", "startForegroundNotification()") createNotificationChannel() val notificationIntent = Intent(this, SettingsActivity::class.java) val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, @@ -61,10 +64,12 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { .setContentIntent(pendingIntent) .setSmallIcon(R.drawable.ic_stat_print) .build() + Log.i("PrintService", "startForeground()") startForeground(ONGOING_NOTIFICATION_ID, notification) } private fun logException(e: Throwable) { + Log.i("PrintService", "logException()") try { val log = File.createTempFile("error_", ".log", this.cacheDir) val fw = FileWriter(log) @@ -79,6 +84,7 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { } private fun print(intent: Intent, rr: ResultReceiver?) { + Log.i("PrintService", "print()") val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) val type = getType(intent.action!!) @@ -296,7 +302,12 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { } } + override fun onCreate() { + super.onCreate() + } + override fun onHandleIntent(intent: Intent?) { + Log.i("PrintService", "onHandleIntent()") var rr: ResultReceiver? = null if (intent!!.hasExtra("resultreceiver")) { rr = intent.getParcelableExtra("resultreceiver")!! as ResultReceiver @@ -305,6 +316,7 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { startForegroundNotification() if (intent.action == ACTION_STOP_SERVICE) { + Log.i("PrintService", "stopForeground()") stopForeground(true) stopSelf() return @@ -336,6 +348,11 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) val type = getType(intent.action!!) val connection = prefs.getString("hardware_${type}printer_connection", "network_printer") + + if (prefs.getBoolean("keepalive_service", false)) { + KeepaliveService.start(this) + } + if (connection == "system") { // stop the foreground service, but keep the notification if (SDK_INT >= Build.VERSION_CODES.N) { @@ -344,6 +361,7 @@ abstract class AbstractPrintService(name: String) : IntentService(name) { stopForeground(false) } } else { + Log.i("PrintService", "stopForeground()") stopForeground(true) } } diff --git a/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt index fe664eae..2fcebc81 100644 --- a/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt +++ b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt @@ -35,6 +35,7 @@ import eu.pretix.pretixprint.R import eu.pretix.pretixprint.connections.IMinInternalConnection import eu.pretix.pretixprint.connections.SunmiInternalConnection import eu.pretix.pretixprint.connections.SystemConnection +import eu.pretix.pretixprint.print.KeepaliveService import eu.pretix.pretixprint.print.testPrint import io.sentry.Sentry import kotlinx.coroutines.CoroutineScope @@ -371,6 +372,14 @@ class SettingsActivity : AppCompatActivity() { .beginTransaction() .replace(R.id.content, SettingsFragment()) .commit() + + if (prefs.getBoolean("keepalive_service", false)) { + try { + KeepaliveService.start(this) + } catch (e: IllegalStateException) { + e.printStackTrace() + } + } } override fun onRequestPermissionsResult( diff --git a/pretixprint/app/src/main/res/values/strings.xml b/pretixprint/app/src/main/res/values/strings.xml index 9731d2ea..2fd2d9b2 100644 --- a/pretixprint/app/src/main/res/values/strings.xml +++ b/pretixprint/app/src/main/res/values/strings.xml @@ -19,6 +19,11 @@ Driver Security Close + Service is running + Shows a notification when the service is running + pretixPRINT is running + Run keepalive service + Workaround to avoid the app being killed on low-powered devices. Print jobs Shows a notification during a print job Print prepared. Touch to open print dialog diff --git a/pretixprint/app/src/main/res/xml/preferences.xml b/pretixprint/app/src/main/res/xml/preferences.xml index 27a89482..c1b31059 100644 --- a/pretixprint/app/src/main/res/xml/preferences.xml +++ b/pretixprint/app/src/main/res/xml/preferences.xml @@ -52,6 +52,11 @@ android:key="pref_pin" android:title="@string/pin_protection_pin" android:summary="@string/pin_protection_description" /> +