diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a924e1b68..763ae11bf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -91,6 +91,11 @@ + + @@ -123,5 +128,8 @@ + diff --git a/app/src/main/java/com/aurora/Constants.kt b/app/src/main/java/com/aurora/Constants.kt index 5feb8db5c..e0d7a4383 100644 --- a/app/src/main/java/com/aurora/Constants.kt +++ b/app/src/main/java/com/aurora/Constants.kt @@ -23,6 +23,7 @@ object Constants { const val INT_EXTRA = "INT_EXTRA" const val FLOAT_EXTRA = "FLOAT_EXTRA" const val STRING_APP = "STRING_APP" + const val STRING_VERSION = "STRING_VERSION" const val STRING_EXTRA = "STRING_EXTRA" const val BROWSE_EXTRA = "BROWSE_EXTRA" diff --git a/app/src/main/java/com/aurora/store/data/activity/InstallActivity.kt b/app/src/main/java/com/aurora/store/data/activity/InstallActivity.kt new file mode 100644 index 000000000..0d2d84905 --- /dev/null +++ b/app/src/main/java/com/aurora/store/data/activity/InstallActivity.kt @@ -0,0 +1,42 @@ +package com.aurora.store.data.activity + +import android.app.Activity +import android.os.Bundle +import android.util.Log +import com.aurora.Constants +import com.aurora.store.data.installer.AppInstaller +import com.aurora.store.util.PathUtil +import java.io.File +import kotlin.io.path.pathString + +class InstallActivity : Activity() { + + private val TAG = InstallActivity::class.java.simpleName + + private lateinit var packageName: String + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + packageName = intent.extras?.getString(Constants.STRING_APP) ?: String() + val version = intent.extras?.getInt(Constants.STRING_VERSION) + if (packageName.isNotBlank() && version != null) { + try { + val downloadDir = + File(PathUtil.getAppDownloadDir(this, packageName, version).pathString) + AppInstaller.getInstance(this).getPreferredInstaller() + .install( + packageName, + downloadDir.listFiles()!!.filter { it.path.endsWith(".apk") } + ) + } catch (exception: Exception) { + Log.e(TAG, "Failed to install $packageName") + } + } + } + + override fun onResume() { + super.onResume() + finish() + } +} diff --git a/app/src/main/java/com/aurora/store/data/receiver/InstallReceiver.kt b/app/src/main/java/com/aurora/store/data/receiver/InstallReceiver.kt index 2ebba3d56..5638de693 100644 --- a/app/src/main/java/com/aurora/store/data/receiver/InstallReceiver.kt +++ b/app/src/main/java/com/aurora/store/data/receiver/InstallReceiver.kt @@ -21,16 +21,32 @@ package com.aurora.store.data.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.util.Log +import com.aurora.Constants +import com.aurora.store.data.installer.AppInstaller +import com.aurora.store.util.PathUtil +import java.io.File +import kotlin.io.path.pathString class InstallReceiver : BroadcastReceiver() { + + private val TAG = InstallReceiver::class.java.simpleName + override fun onReceive(context: Context, intent: Intent) { - val extras = intent.extras - if (extras != null) { - /*val packageName = extras.getString(Constants.INTENT_PACKAGE_NAME, "") - val versionString = extras.getString(Constants.DOWNLOAD_VERSION_CODE) - if (!packageName.isEmpty() && versionString != null) { - AuroraApplication.getInstaller().installSplit(packageName, versionString.toInt()) - }*/ + val packageName = intent.extras?.getString(Constants.STRING_APP) ?: String() + val version = intent.extras?.getInt(Constants.STRING_VERSION) + if (packageName.isNotBlank() && version != null) { + try { + val downloadDir = + File(PathUtil.getAppDownloadDir(context, packageName, version).pathString) + AppInstaller.getInstance(context).getPreferredInstaller() + .install( + packageName, + downloadDir.listFiles()!!.filter { it.path.endsWith(".apk") } + ) + } catch (exception: Exception) { + Log.e(TAG, "Failed to install $packageName") + } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt index d2b091feb..ce39be6dd 100644 --- a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt +++ b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt @@ -3,6 +3,7 @@ package com.aurora.store.data.work import android.app.NotificationManager import android.app.Service import android.content.Context +import android.content.Intent import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC import android.util.Log import androidx.work.CoroutineWorker @@ -13,6 +14,7 @@ import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OutOfQuotaPolicy import androidx.work.WorkManager import androidx.work.WorkerParameters +import com.aurora.Constants import com.aurora.extensions.copyTo import com.aurora.extensions.isQAndAbove import com.aurora.gplayapi.data.models.App @@ -21,6 +23,7 @@ import com.aurora.store.data.model.DownloadStatus import com.aurora.store.data.model.Request import com.aurora.store.data.network.HttpClient import com.aurora.store.data.providers.AuthProvider +import com.aurora.store.data.receiver.InstallReceiver import com.aurora.store.util.NotificationUtil import com.aurora.store.util.PathUtil import com.google.gson.Gson @@ -63,7 +66,6 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame } private lateinit var app: App - private lateinit var appDownloadDir: Path private var downloading = false private val TAG = DownloadWorker::class.java.simpleName @@ -81,7 +83,6 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame withContext(Dispatchers.Default) { try { app = gson.fromJson(inputData.getString(DOWNLOAD_DATA), App::class.java) - appDownloadDir = Path(PathUtil.getPackageDirectory(appContext, app.packageName)) } catch (exception: Exception) { Log.e(TAG, "Failed parsing requested app!", exception) notifyStatus(DownloadStatus.FAILED) @@ -101,7 +102,7 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame } // Download and verify all files exists - Path(appDownloadDir.absolutePathString(), app.versionCode.toString()).createDirectories() + PathUtil.getAppDownloadDir(appContext, app.packageName, app.versionCode).createDirectories() val requestList = getDownloadRequest(files) requestList.forEach { request -> @@ -115,6 +116,14 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame // Mark download as completed notifyStatus(DownloadStatus.COMPLETED) Log.i(TAG, "Finished downloading ${app.packageName}") + + // Notify for installation + Intent(appContext, InstallReceiver::class.java).also { + it.putExtra(Constants.STRING_APP, app.packageName) + it.putExtra(Constants.STRING_VERSION, app.versionCode) + appContext.sendBroadcast(it) + + } return Result.success() } diff --git a/app/src/main/java/com/aurora/store/util/NotificationUtil.kt b/app/src/main/java/com/aurora/store/util/NotificationUtil.kt index 253e3678d..75951f7b2 100644 --- a/app/src/main/java/com/aurora/store/util/NotificationUtil.kt +++ b/app/src/main/java/com/aurora/store/util/NotificationUtil.kt @@ -20,11 +20,11 @@ import com.aurora.extensions.isMAndAbove import com.aurora.gplayapi.data.models.App import com.aurora.store.MainActivity import com.aurora.store.R +import com.aurora.store.data.activity.InstallActivity import com.aurora.store.data.model.DownloadStatus import com.aurora.store.data.receiver.DownloadCancelReceiver import com.aurora.store.data.receiver.DownloadPauseReceiver import com.aurora.store.data.receiver.DownloadResumeReceiver -import com.aurora.store.data.receiver.InstallReceiver import com.tonyodev.fetch2.Download import com.tonyodev.fetch2.FetchGroup import com.tonyodev.fetch2.Status @@ -231,6 +231,13 @@ object NotificationUtil { builder.setAutoCancel(true) builder.setCategory(Notification.CATEGORY_STATUS) builder.setContentIntent(getContentIntentForDetails(context, app)) + builder.addAction( + NotificationCompat.Action.Builder( + R.drawable.ic_install, + context.getString(R.string.action_install), + getInstallIntent(context, app.packageName, app.versionCode) + ).build() + ) } DownloadStatus.DOWNLOADING, DownloadStatus.QUEUED -> { @@ -314,17 +321,22 @@ object NotificationUtil { .createPendingIntent() } - private fun getInstallIntent(context: Context, packageName: String): PendingIntent { - val intent = Intent(context, InstallReceiver::class.java) - intent.putExtra(Constants.STRING_EXTRA, packageName) - val flags = if (isMAndAbove()) + private fun getInstallIntent( + context: Context, + packageName: String, + version: Int + ): PendingIntent { + val intent = Intent(context, InstallActivity::class.java).apply { + putExtra(Constants.STRING_APP, packageName) + putExtra(Constants.STRING_VERSION, version) + } + val flags = if (isMAndAbove()) { PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE - else PendingIntent.FLAG_CANCEL_CURRENT - return PendingIntent.getBroadcast( - context, - packageName.hashCode(), - intent, - flags + } else { + PendingIntent.FLAG_CANCEL_CURRENT + } + return PendingIntent.getActivity( + context, packageName.hashCode(), intent, flags ) } } diff --git a/app/src/main/java/com/aurora/store/util/PathUtil.kt b/app/src/main/java/com/aurora/store/util/PathUtil.kt index 6b876e971..cb7e67544 100644 --- a/app/src/main/java/com/aurora/store/util/PathUtil.kt +++ b/app/src/main/java/com/aurora/store/util/PathUtil.kt @@ -24,7 +24,9 @@ import android.os.Environment import com.aurora.extensions.isRAndAbove import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.File +import java.nio.file.Path import java.util.UUID +import kotlin.io.path.Path fun Context.getInternalBaseDirectory(): String { return (getExternalFilesDir(null) ?: filesDir).path @@ -52,6 +54,10 @@ object PathUtil { return getPackageDirectory(context, packageName) + "/$versionCode" } + fun getAppDownloadDir(context: Context, packageName: String, versionCode: Int): Path { + return Path(getPackageDirectory(context, packageName), versionCode.toString()) + } + fun getApkDownloadFile(context: Context, app: App, file: File): String { return getVersionDirectory(context, app.packageName, app.versionCode) + "/${file.name}" }