Support unarchiving apps on Android 15+ devices
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -173,5 +173,14 @@
|
|||||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</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>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ object Constants {
|
|||||||
const val NOTIFICATION_CHANNEL_INSTALL = "NOTIFICATION_CHANNEL_INSTALL"
|
const val NOTIFICATION_CHANNEL_INSTALL = "NOTIFICATION_CHANNEL_INSTALL"
|
||||||
const val NOTIFICATION_CHANNEL_DOWNLOADS = "NOTIFICATION_CHANNEL_DOWNLOADS"
|
const val NOTIFICATION_CHANNEL_DOWNLOADS = "NOTIFICATION_CHANNEL_DOWNLOADS"
|
||||||
const val NOTIFICATION_CHANNEL_UPDATES = "NOTIFICATION_CHANNEL_UPDATES"
|
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 GITLAB_URL = "https://gitlab.com/AuroraOSS/AuroraStore"
|
||||||
const val URL_DISPENSER = "https://auroraoss.com/api/auth"
|
const val URL_DISPENSER = "https://auroraoss.com/api/auth"
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,6 +49,13 @@ object NotificationUtil {
|
|||||||
NotificationManager.IMPORTANCE_HIGH
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
channels.add(
|
||||||
|
NotificationChannel(
|
||||||
|
Constants.NOTIFICATION_CHANNEL_ACCOUNT,
|
||||||
|
context.getString(R.string.notification_channel_account),
|
||||||
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
|
)
|
||||||
|
)
|
||||||
channels.add(
|
channels.add(
|
||||||
NotificationChannel(
|
NotificationChannel(
|
||||||
Constants.NOTIFICATION_CHANNEL_DOWNLOADS,
|
Constants.NOTIFICATION_CHANNEL_DOWNLOADS,
|
||||||
@@ -254,7 +261,18 @@ object NotificationUtil {
|
|||||||
.setSmallIcon(R.drawable.ic_file_copy)
|
.setSmallIcon(R.drawable.ic_file_copy)
|
||||||
.setContentTitle(context.getString(R.string.export_app_title))
|
.setContentTitle(context.getString(R.string.export_app_title))
|
||||||
.setContentText(context.getString(R.string.export_app_summary))
|
.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()
|
.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 {
|
private fun getContentIntentForDetails(context: Context, packageName: String): PendingIntent {
|
||||||
return NavDeepLinkBuilder(context)
|
return NavDeepLinkBuilder(context)
|
||||||
.setGraph(R.navigation.mobile_navigation)
|
.setGraph(R.navigation.mobile_navigation)
|
||||||
|
|||||||
@@ -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="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_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="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_export">App export notification</string>
|
||||||
<string name="notification_channel_install">Install notification</string>
|
<string name="notification_channel_install">Install notification</string>
|
||||||
<string name="notification_channel_downloads">Downloads notification</string>
|
<string name="notification_channel_downloads">Downloads notification</string>
|
||||||
@@ -465,4 +466,8 @@
|
|||||||
<string name="status_completed">Completed</string>
|
<string name="status_completed">Completed</string>
|
||||||
<string name="status_queued">Queued</string>
|
<string name="status_queued">Queued</string>
|
||||||
<string name="status_unavailable">Unavailable</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>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user