Support unarchiving apps on Android 15+ devices

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-10-09 21:52:14 +05:30
parent dfc223d8cb
commit 98322b3358
5 changed files with 108 additions and 1 deletions

View File

@@ -173,5 +173,14 @@
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
<!-- Android15+ package unarchive feature -->
<receiver
android:name=".data.receiver.UnarchivePackageReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.UNARCHIVE_PACKAGE" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -41,6 +41,7 @@ object Constants {
const val NOTIFICATION_CHANNEL_INSTALL = "NOTIFICATION_CHANNEL_INSTALL"
const val NOTIFICATION_CHANNEL_DOWNLOADS = "NOTIFICATION_CHANNEL_DOWNLOADS"
const val NOTIFICATION_CHANNEL_UPDATES = "NOTIFICATION_CHANNEL_UPDATES"
const val NOTIFICATION_CHANNEL_ACCOUNT = "NOTIFICATION_CHANNEL_ACCOUNT"
const val GITLAB_URL = "https://gitlab.com/AuroraOSS/AuroraStore"
const val URL_DISPENSER = "https://auroraoss.com/api/auth"

View File

@@ -0,0 +1,65 @@
package com.aurora.store.data.receiver
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller.EXTRA_UNARCHIVE_PACKAGE_NAME
import android.util.Log
import androidx.core.content.getSystemService
import com.aurora.extensions.isVAndAbove
import com.aurora.gplayapi.helpers.AppDetailsHelper
import com.aurora.gplayapi.network.IHttpClient
import com.aurora.store.AuroraApp
import com.aurora.store.data.helper.DownloadHelper
import com.aurora.store.data.providers.AccountProvider
import com.aurora.store.data.providers.AuthProvider
import com.aurora.store.util.NotificationUtil
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
/**
* Triggers re-install/unarchive of a previously archived app on Android 15+ devices.
*/
@AndroidEntryPoint
class UnarchivePackageReceiver: BroadcastReceiver() {
private val TAG = UnarchivePackageReceiver::class.java.simpleName
@Inject
lateinit var httpClient: IHttpClient
@Inject
lateinit var authProvider: AuthProvider
@Inject
lateinit var downloadHelper: DownloadHelper
override fun onReceive(context: Context?, intent: Intent?) {
if (isVAndAbove() && context != null && intent?.action == Intent.ACTION_UNARCHIVE_PACKAGE) {
val packageName = intent.getStringExtra(EXTRA_UNARCHIVE_PACKAGE_NAME)!!
Log.i(TAG, "Received request to unarchive $packageName")
AuroraApp.scope.launch(Dispatchers.IO) {
if (!authProvider.isSavedAuthDataValid() || !AccountProvider.isLoggedIn(context)) {
Log.e(TAG, "Failed to authenticate user!")
with(context.getSystemService<NotificationManager>()!!) {
notify(
packageName.hashCode(),
NotificationUtil.getAuthDataExpiredNotification(context, packageName)
)
}
return@launch
}
val app = AppDetailsHelper(authProvider.authData!!)
.using(httpClient)
.getAppByPackageName(packageName)
downloadHelper.enqueueApp(app)
}
}
}
}

View File

@@ -49,6 +49,13 @@ object NotificationUtil {
NotificationManager.IMPORTANCE_HIGH
)
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_ACCOUNT,
context.getString(R.string.notification_channel_account),
NotificationManager.IMPORTANCE_HIGH
)
)
channels.add(
NotificationChannel(
Constants.NOTIFICATION_CHANNEL_DOWNLOADS,
@@ -254,7 +261,18 @@ object NotificationUtil {
.setSmallIcon(R.drawable.ic_file_copy)
.setContentTitle(context.getString(R.string.export_app_title))
.setContentText(context.getString(R.string.export_app_summary))
.setOngoing(false)
.build()
}
fun getAuthDataExpiredNotification(context: Context, packageName: String): Notification {
return NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ACCOUNT)
.setSmallIcon(R.drawable.ic_account)
.setContentTitle(context.getString(R.string.authentication_required_title))
.setContentText(context.getString(R.string.authentication_required_unarchive))
.setAutoCancel(true)
.setContentIntent(getContentIntentForSplash(context, packageName))
.setCategory(NotificationCompat.CATEGORY_ERROR)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.build()
}
@@ -315,6 +333,15 @@ object NotificationUtil {
)
}
private fun getContentIntentForSplash(context: Context, packageName: String): PendingIntent {
return NavDeepLinkBuilder(context)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.splashFragment)
.setComponentName(MainActivity::class.java)
.setArguments(bundleOf("packageName" to packageName))
.createPendingIntent()
}
private fun getContentIntentForDetails(context: Context, packageName: String): PendingIntent {
return NavDeepLinkBuilder(context)
.setGraph(R.navigation.mobile_navigation)

View File

@@ -188,6 +188,7 @@
<string name="device_miui_extra">"Optionally you can choose Native installer, but then you can not install bundled (split) APKs, so choice is yours."</string>
<string name="dialog_title_self_update">"New update available"</string>
<string name="dialog_desc_native_split">"You can not install bundled(split) apps via Native Installer. Change your installer to Session, Services or Root."</string>
<string name="notification_channel_account">Account-related notification</string>
<string name="notification_channel_export">App export notification</string>
<string name="notification_channel_install">Install notification</string>
<string name="notification_channel_downloads">Downloads notification</string>
@@ -465,4 +466,8 @@
<string name="status_completed">Completed</string>
<string name="status_queued">Queued</string>
<string name="status_unavailable">Unavailable</string>
<!-- UnarchivePackageReceiver -->
<string name="authentication_required_title">Authentication required</string>
<string name="authentication_required_unarchive">Please log in to your Google Play account to unarchive the app!</string>
</resources>