android: update download progress notification (ProgressStyle / Live Update on API 36+)
This commit is contained in:
1 parent
564b8aaa8d
commit
87c3d73fbc
5 files changed
+75
No files matched your search
@@ -30,6 +30,7 @@
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.POST_PROMOTED_NOTIFICATIONS"/>
|
||||
<!-- required to install downloaded updates of the app itself -->
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<!-- lets the app install its own updates in the background without the
|
||||
|
||||
+71
@@ -14,6 +14,7 @@
|
||||
|
||||
package org.strongswan.android.logic.updates
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
@@ -113,6 +114,7 @@ class UpdateManager private constructor(private val context: Context)
|
||||
private const val READ_TIMEOUT_MS = 10_000
|
||||
private const val UPDATES_CHANNEL = "org.strongswan.android.updates"
|
||||
private const val UPDATES_NOTIFICATION_ID = 1001
|
||||
private const val UPDATES_PROGRESS_NOTIFICATION_ID = 1002
|
||||
|
||||
private var mInstance: UpdateManager? = null
|
||||
|
||||
@@ -323,6 +325,73 @@ class UpdateManager private constructor(private val context: Context)
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && UpdateInstaller.canInstall(context)
|
||||
}
|
||||
|
||||
|
||||
private fun ensureUpdatesChannel(manager: NotificationManager)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
{
|
||||
manager.createNotificationChannel(
|
||||
NotificationChannel(UPDATES_CHANNEL, context.getString(R.string.updates_channel_name),
|
||||
NotificationManager.IMPORTANCE_DEFAULT))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the download progress. Android 16+ gets Notification.ProgressStyle, promoted
|
||||
* to a Live Update (POST_PROMOTED_NOTIFICATIONS is a normal permission, granted at
|
||||
* install, so there is no extra prompt); older versions get the classic progress bar.
|
||||
*/
|
||||
private fun postDownloadProgress(info: UpdateInfo, progress: Int)
|
||||
{
|
||||
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager ?: return
|
||||
ensureUpdatesChannel(manager)
|
||||
val title = context.getString(R.string.update_downloading_title, info.versionName)
|
||||
val intent = Intent(context, MainActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
val pending = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||
val notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA)
|
||||
{
|
||||
Notification.Builder(context, UPDATES_CHANNEL)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle(title)
|
||||
.setContentText("$progress%")
|
||||
.setShortCriticalText("$progress%")
|
||||
.setStyle(Notification.ProgressStyle()
|
||||
.setProgressSegments(listOf(Notification.ProgressStyle.Segment(100)))
|
||||
.setProgress(progress))
|
||||
.setRequestPromotedOngoing(true)
|
||||
.setOngoing(true)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setContentIntent(pending)
|
||||
.build()
|
||||
}
|
||||
else
|
||||
{
|
||||
NotificationCompat.Builder(context, UPDATES_CHANNEL)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle(title)
|
||||
.setContentText("$progress%")
|
||||
.setProgress(100, progress, false)
|
||||
.setOngoing(true)
|
||||
.setOnlyAlertOnce(true)
|
||||
.setContentIntent(pending)
|
||||
.build()
|
||||
}
|
||||
try
|
||||
{
|
||||
manager.notify(UPDATES_PROGRESS_NOTIFICATION_ID, notification)
|
||||
}
|
||||
catch (e: SecurityException)
|
||||
{ /* POST_NOTIFICATIONS denied - progress stays visible in the settings */
|
||||
Log.w(TAG, "Cannot post the update progress notification", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun cancelDownloadProgress()
|
||||
{
|
||||
(context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager)
|
||||
?.cancel(UPDATES_PROGRESS_NOTIFICATION_ID)
|
||||
}
|
||||
|
||||
/** Posts a notification that the downloaded update is ready to install */
|
||||
private fun notifyUpdateReady(info: UpdateInfo)
|
||||
{
|
||||
@@ -507,6 +576,7 @@ class UpdateManager private constructor(private val context: Context)
|
||||
{
|
||||
lastProgress = progress
|
||||
mState.value = UpdateState.Downloading(info, progress)
|
||||
postDownloadProgress(info, progress)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -527,6 +597,7 @@ class UpdateManager private constructor(private val context: Context)
|
||||
finally
|
||||
{
|
||||
conn.disconnect()
|
||||
cancelDownloadProgress()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -505,4 +505,5 @@
|
||||
<string name="widget_description">Schutzstatus und Verbinden mit einem Tipp</string>
|
||||
|
||||
<string name="profile_detail_placeholder">Profil auswählen oder hinzufügen</string>
|
||||
<string name="update_downloading_title">Update %1$s wird heruntergeladen</string>
|
||||
</resources>
|
||||
@@ -502,4 +502,5 @@
|
||||
<string name="widget_label">SHX VPN</string>
|
||||
<string name="widget_description">Статус защиты и подключение одним касанием</string>
|
||||
<string name="profile_detail_placeholder">Выберите или добавьте профиль</string>
|
||||
<string name="update_downloading_title">Загрузка обновления %1$s</string>
|
||||
</resources>
|
||||
@@ -507,4 +507,5 @@
|
||||
<string name="widget_label">SHX VPN</string>
|
||||
<string name="widget_description">Protection status and one-tap connect</string>
|
||||
<string name="profile_detail_placeholder">Select or add a profile</string>
|
||||
<string name="update_downloading_title">Downloading update %1$s</string>
|
||||
</resources>
|
||||
Reference in new issue
Block a user