EtchDroid/app/src/main/java/eu/depau/ddroid/abc/UsbWriteService.kt

99 lines
3.6 KiB
Kotlin

package eu.depau.ddroid.abc
import android.app.IntentService
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.net.Uri
import android.os.Build
import eu.depau.ddroid.R
import eu.depau.ddroid.utils.getFileName
import eu.depau.ddroid.utils.toHRSize
abstract class UsbWriteService(name: String) : IntentService(name) {
val TAG = name
val FOREGROUND_ID = 1931
val WRITE_PROGRESS_CHANNEL_ID = "eu.depau.ddroid.notifications.USB_WRITE_PROGRESS"
private var prevTime = System.currentTimeMillis()
private var prevBytes = 0L
private var notifyChanRegistered = false
fun getNotificationBuilder(): Notification.Builder {
if (!notifyChanRegistered) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channame = "USB write progress"
val description = "Displays the status of ongoing USB writes"
val importance = NotificationManager.IMPORTANCE_LOW
val channel = NotificationChannel(WRITE_PROGRESS_CHANNEL_ID, channame, importance)
channel.description = description
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager!!.createNotificationChannel(channel)
}
notifyChanRegistered = true
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
Notification.Builder(this, WRITE_PROGRESS_CHANNEL_ID)
else
Notification.Builder(this)
}
fun updateNotification(usbDevice: String, uri: Uri, bytes: Long, total: Long) {
// Notification rate limiting
val time = System.currentTimeMillis()
if (time <= prevTime + 1000)
return
val speed = ((bytes - prevBytes).toDouble() / (time - prevTime).toDouble()).toHRSize()
prevTime = time
prevBytes = bytes
val perc: Int = (bytes.toDouble() / total * 100.0).toInt()
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(FOREGROUND_ID, buildForegroundNotification(usbDevice, uri, bytes, total, "$perc% • $speed/s"))
}
fun errorNotification() {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val b = getNotificationBuilder()
.setContentTitle("Write failed")
.setContentText("The USB drive may have been unplugged while writing.")
.setOngoing(false)
.setSmallIcon(R.drawable.ic_usb_white_24dp)
notificationManager.notify(FOREGROUND_ID, b.build())
}
fun buildForegroundNotification(usbDevice: String, uri: Uri, bytes: Long, total: Long, subText: String? = null): Notification {
val progr: Int
val indet: Boolean
if (total < 0) {
progr = 0
indet = true
} else {
progr = (bytes.toFloat()/total * 100).toInt()
indet = false
}
val b = getNotificationBuilder()
b.setContentTitle("Writing image")
.setContentText("${uri.getFileName(this)} to $usbDevice")
.setOngoing(true)
.setSmallIcon(R.drawable.ic_usb_white_24dp)
.setProgress(100, progr, indet)
if (subText != null)
b.setSubText(subText)
return b.build()
}
}