Fix AppInstaller spawning useless instances by preserving the original instance of every instantiated installer type (fixes wrongly started or concurrent installs/uninstalls), implement service based install for new downloads (integrated in the UpdateService.kt and the AppDetailsActivity.kt), prevent multiple calls for install by using ThreadPoolExecutor (applied only to ServiceInstaller.kt for now), fix timer issues in the UpdateService.kt
This commit is contained in:
@@ -26,9 +26,10 @@ import com.aurora.store.R
|
|||||||
import com.aurora.store.util.Preferences
|
import com.aurora.store.util.Preferences
|
||||||
import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID
|
import com.aurora.store.util.Preferences.PREFERENCE_INSTALLER_ID
|
||||||
|
|
||||||
open class AppInstaller constructor(var context: Context) {
|
open class AppInstaller private constructor(var context: Context) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private var instance: AppInstaller? = null
|
||||||
fun getErrorString(context: Context, status: Int): String {
|
fun getErrorString(context: Context, status: Int): String {
|
||||||
return when (status) {
|
return when (status) {
|
||||||
PackageInstaller.STATUS_FAILURE_ABORTED -> context.getString(R.string.installer_status_user_action)
|
PackageInstaller.STATUS_FAILURE_ABORTED -> context.getString(R.string.installer_status_user_action)
|
||||||
@@ -40,22 +41,50 @@ open class AppInstaller constructor(var context: Context) {
|
|||||||
else -> context.getString(R.string.installer_status_failure)
|
else -> context.getString(R.string.installer_status_failure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun getInstance(context: Context): AppInstaller {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = AppInstaller(context.applicationContext)
|
||||||
|
}
|
||||||
|
return instance!!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val choiceAndInstaller = HashMap<Int, IInstaller>()
|
||||||
|
|
||||||
fun getPreferredInstaller(): IInstaller {
|
fun getPreferredInstaller(): IInstaller {
|
||||||
val prefValue = Preferences.getInteger(
|
val prefValue = Preferences.getInteger(
|
||||||
context,
|
context,
|
||||||
PREFERENCE_INSTALLER_ID
|
PREFERENCE_INSTALLER_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (choiceAndInstaller.containsKey(prefValue)) {
|
||||||
|
return choiceAndInstaller[prefValue]!!
|
||||||
|
}
|
||||||
|
|
||||||
return when (prefValue) {
|
return when (prefValue) {
|
||||||
1 -> NativeInstaller(context)
|
1 -> {
|
||||||
2 -> RootInstaller(context)
|
val installer = NativeInstaller(context)
|
||||||
3 -> ServiceInstaller(context)
|
choiceAndInstaller[prefValue] = installer
|
||||||
|
installer
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
val installer = RootInstaller(context)
|
||||||
|
choiceAndInstaller[prefValue] = installer
|
||||||
|
installer
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
val installer = ServiceInstaller(context)
|
||||||
|
choiceAndInstaller[prefValue] = installer
|
||||||
|
installer
|
||||||
|
}
|
||||||
else -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
else -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
SessionInstaller(context)
|
val installer = SessionInstaller(context)
|
||||||
|
choiceAndInstaller[prefValue] = installer
|
||||||
|
installer
|
||||||
} else {
|
} else {
|
||||||
NativeInstaller(context)
|
val installer = NativeInstaller(context)
|
||||||
|
choiceAndInstaller[prefValue] = installer
|
||||||
|
installer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ import android.content.Intent
|
|||||||
import android.content.ServiceConnection
|
import android.content.ServiceConnection
|
||||||
import android.content.pm.PackageInstaller
|
import android.content.pm.PackageInstaller
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.*
|
||||||
import android.os.IBinder
|
|
||||||
import android.os.RemoteException
|
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import com.aurora.services.IPrivilegedCallback
|
import com.aurora.services.IPrivilegedCallback
|
||||||
@@ -41,10 +39,14 @@ import com.aurora.store.util.Log
|
|||||||
import com.aurora.store.util.PackageUtil
|
import com.aurora.store.util.PackageUtil
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class ServiceInstaller(context: Context) : InstallerBase(context) {
|
class ServiceInstaller(context: Context) : InstallerBase(context) {
|
||||||
|
|
||||||
private lateinit var serviceConnection: ServiceConnection
|
private lateinit var serviceConnection: ServiceConnection
|
||||||
|
private val executor = ThreadPoolExecutor(0, 1, 30L, TimeUnit.SECONDS, LinkedBlockingQueue())
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val ACTION_INSTALL_REPLACE_EXISTING = 2
|
const val ACTION_INSTALL_REPLACE_EXISTING = 2
|
||||||
@@ -85,134 +87,168 @@ class ServiceInstaller(context: Context) : InstallerBase(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun uninstall(packageName: String) {
|
override fun uninstall(packageName: String) {
|
||||||
val serviceConnection = object : ServiceConnection {
|
executor.execute {
|
||||||
override fun onServiceConnected(name: ComponentName, binder: IBinder) {
|
var readyWithAction = false
|
||||||
AuroraApplication.enqueuedInstalls.add(packageName)
|
Handler(Looper.getMainLooper()).post {
|
||||||
val service = IPrivilegedService.Stub.asInterface(binder)
|
serviceConnection = object : ServiceConnection {
|
||||||
|
override fun onServiceConnected(name: ComponentName, binder: IBinder) {
|
||||||
if (service.hasPrivilegedPermissions()) {
|
if (isAlreadyQueued(packageName)) {
|
||||||
Log.i(context.getString(R.string.installer_service_available))
|
if (::serviceConnection.isInitialized) {
|
||||||
|
context.unbindService(serviceConnection)
|
||||||
val callback = object : IPrivilegedCallback.Stub() {
|
}
|
||||||
|
readyWithAction = true
|
||||||
override fun handleResult(packageName: String, returnCode: Int) {
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
AuroraApplication.enqueuedInstalls.add(packageName)
|
||||||
|
val service = IPrivilegedService.Stub.asInterface(binder)
|
||||||
|
|
||||||
override fun handleResultX(
|
if (service.hasPrivilegedPermissions()) {
|
||||||
packageName: String,
|
Log.i(context.getString(R.string.installer_service_available))
|
||||||
returnCode: Int,
|
|
||||||
extra: String?
|
val callback = object : IPrivilegedCallback.Stub() {
|
||||||
) {
|
|
||||||
|
override fun handleResult(packageName: String, returnCode: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleResultX(
|
||||||
|
packageName: String,
|
||||||
|
returnCode: Int,
|
||||||
|
extra: String?
|
||||||
|
) {
|
||||||
|
removeFromInstallQueue(packageName)
|
||||||
|
readyWithAction = true
|
||||||
|
handleCallbackUninstall(packageName, returnCode, extra)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
service.deletePackageX(
|
||||||
|
packageName,
|
||||||
|
2,
|
||||||
|
BuildConfig.APPLICATION_ID,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
Log.e("Failed to connect Aurora Services")
|
||||||
|
removeFromInstallQueue(packageName)
|
||||||
|
readyWithAction = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
removeFromInstallQueue(packageName)
|
removeFromInstallQueue(packageName)
|
||||||
handleCallbackUninstall(packageName, returnCode, extra)
|
readyWithAction = true
|
||||||
|
postError(
|
||||||
|
packageName,
|
||||||
|
context.getString(R.string.installer_status_failure),
|
||||||
|
context.getString(R.string.installer_service_misconfigured)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
service.deletePackageX(
|
removeFromInstallQueue(packageName)
|
||||||
packageName,
|
Log.e("Disconnected from Aurora Services")
|
||||||
2,
|
readyWithAction = true
|
||||||
BuildConfig.APPLICATION_ID,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
} catch (e: RemoteException) {
|
|
||||||
Log.e("Failed to connect Aurora Services")
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
postError(
|
|
||||||
packageName,
|
|
||||||
context.getString(R.string.installer_status_failure),
|
|
||||||
context.getString(R.string.installer_service_misconfigured)
|
|
||||||
)
|
|
||||||
removeFromInstallQueue(packageName)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName) {
|
val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT)
|
||||||
removeFromInstallQueue(packageName)
|
intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME)
|
||||||
Log.e("Disconnected from Aurora Services")
|
|
||||||
|
context.bindService(
|
||||||
|
intent,
|
||||||
|
serviceConnection,
|
||||||
|
Context.BIND_AUTO_CREATE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
while (!readyWithAction) {
|
||||||
|
Thread.sleep(1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT)
|
|
||||||
intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME)
|
|
||||||
|
|
||||||
context.bindService(
|
|
||||||
intent,
|
|
||||||
serviceConnection,
|
|
||||||
Context.BIND_AUTO_CREATE
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
private fun xInstall(packageName: String, uriList: List<Uri>) {
|
private fun xInstall(packageName: String, uriList: List<Uri>) {
|
||||||
serviceConnection = object : ServiceConnection {
|
executor.execute {
|
||||||
override fun onServiceConnected(name: ComponentName, binder: IBinder) {
|
var readyWithAction = false
|
||||||
if (isAlreadyQueued(packageName)) {
|
Handler(Looper.getMainLooper()).post {
|
||||||
if (::serviceConnection.isInitialized) {
|
serviceConnection = object : ServiceConnection {
|
||||||
context.unbindService(serviceConnection)
|
override fun onServiceConnected(name: ComponentName, binder: IBinder) {
|
||||||
}
|
if (isAlreadyQueued(packageName)) {
|
||||||
return
|
if (::serviceConnection.isInitialized) {
|
||||||
}
|
context.unbindService(serviceConnection)
|
||||||
AuroraApplication.enqueuedInstalls.add(packageName)
|
}
|
||||||
val service = IPrivilegedService.Stub.asInterface(binder)
|
readyWithAction = true
|
||||||
|
return
|
||||||
if (service.hasPrivilegedPermissions()) {
|
|
||||||
Log.i(context.getString(R.string.installer_service_available))
|
|
||||||
|
|
||||||
val callback = object : IPrivilegedCallback.Stub() {
|
|
||||||
|
|
||||||
override fun handleResult(packageName: String, returnCode: Int) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
AuroraApplication.enqueuedInstalls.add(packageName)
|
||||||
|
val service = IPrivilegedService.Stub.asInterface(binder)
|
||||||
|
|
||||||
override fun handleResultX(
|
if (service.hasPrivilegedPermissions()) {
|
||||||
packageName: String,
|
Log.i(context.getString(R.string.installer_service_available))
|
||||||
returnCode: Int,
|
|
||||||
extra: String?
|
val callback = object : IPrivilegedCallback.Stub() {
|
||||||
) {
|
|
||||||
|
override fun handleResult(packageName: String, returnCode: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleResultX(
|
||||||
|
packageName: String,
|
||||||
|
returnCode: Int,
|
||||||
|
extra: String?
|
||||||
|
) {
|
||||||
|
removeFromInstallQueue(packageName)
|
||||||
|
readyWithAction = true
|
||||||
|
handleCallback(packageName, returnCode, extra)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
service.installSplitPackageX(
|
||||||
|
packageName,
|
||||||
|
uriList,
|
||||||
|
ACTION_INSTALL_REPLACE_EXISTING,
|
||||||
|
BuildConfig.APPLICATION_ID,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
} catch (e: RemoteException) {
|
||||||
|
removeFromInstallQueue(packageName)
|
||||||
|
readyWithAction = true
|
||||||
|
postError(packageName, e.localizedMessage, e.stackTraceToString())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
removeFromInstallQueue(packageName)
|
removeFromInstallQueue(packageName)
|
||||||
handleCallback(packageName, returnCode, extra)
|
readyWithAction = true
|
||||||
|
postError(
|
||||||
|
packageName,
|
||||||
|
context.getString(R.string.installer_status_failure),
|
||||||
|
context.getString(R.string.installer_service_misconfigured)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
service.installSplitPackageX(
|
|
||||||
packageName,
|
|
||||||
uriList,
|
|
||||||
ACTION_INSTALL_REPLACE_EXISTING,
|
|
||||||
BuildConfig.APPLICATION_ID,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
} catch (e: RemoteException) {
|
|
||||||
removeFromInstallQueue(packageName)
|
removeFromInstallQueue(packageName)
|
||||||
postError(packageName, e.localizedMessage, e.stackTraceToString())
|
readyWithAction = true
|
||||||
|
Log.e("Disconnected from Aurora Services")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
postError(
|
|
||||||
packageName,
|
|
||||||
context.getString(R.string.installer_status_failure),
|
|
||||||
context.getString(R.string.installer_service_misconfigured)
|
|
||||||
)
|
|
||||||
removeFromInstallQueue(packageName)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName) {
|
val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT)
|
||||||
removeFromInstallQueue(packageName)
|
intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME)
|
||||||
Log.e("Disconnected from Aurora Services")
|
|
||||||
|
context.bindService(
|
||||||
|
intent,
|
||||||
|
serviceConnection,
|
||||||
|
Context.BIND_AUTO_CREATE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
while (!readyWithAction) {
|
||||||
|
Thread.sleep(1000)
|
||||||
|
}
|
||||||
|
Log.i("Services Callback : install wait done")
|
||||||
}
|
}
|
||||||
|
|
||||||
val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT)
|
|
||||||
intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME)
|
|
||||||
|
|
||||||
context.bindService(
|
|
||||||
intent,
|
|
||||||
serviceConnection,
|
|
||||||
Context.BIND_AUTO_CREATE
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCallbackUninstall(packageName: String, returnCode: Int, extra: String?) {
|
private fun handleCallbackUninstall(packageName: String, returnCode: Int, extra: String?) {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ open class PackageManagerReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Clear installation queue
|
//Clear installation queue
|
||||||
AppInstaller(context)
|
AppInstaller.getInstance(context)
|
||||||
.getPreferredInstaller()
|
.getPreferredInstaller()
|
||||||
.removeFromInstallQueue(packageName)
|
.removeFromInstallQueue(packageName)
|
||||||
|
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ class NotificationService : Service() {
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun install(packageName: String, files: List<Download>) {
|
private fun install(packageName: String, files: List<Download>) {
|
||||||
AppInstaller(this)
|
AppInstaller.getInstance(this)
|
||||||
.getPreferredInstaller()
|
.getPreferredInstaller()
|
||||||
.install(
|
.install(
|
||||||
packageName,
|
packageName,
|
||||||
|
|||||||
@@ -17,32 +17,31 @@ import com.aurora.gplayapi.helpers.PurchaseHelper
|
|||||||
import com.aurora.store.R
|
import com.aurora.store.R
|
||||||
import com.aurora.store.data.downloader.DownloadManager
|
import com.aurora.store.data.downloader.DownloadManager
|
||||||
import com.aurora.store.data.downloader.RequestBuilder
|
import com.aurora.store.data.downloader.RequestBuilder
|
||||||
import com.aurora.store.data.downloader.RequestGroupIdBuilder
|
|
||||||
import com.aurora.store.data.downloader.getGroupId
|
|
||||||
import com.aurora.store.data.event.InstallerEvent
|
import com.aurora.store.data.event.InstallerEvent
|
||||||
import com.aurora.store.data.installer.AppInstaller
|
import com.aurora.store.data.installer.AppInstaller
|
||||||
import com.aurora.store.data.model.UpdateFile
|
import com.aurora.store.data.model.UpdateFile
|
||||||
import com.aurora.store.data.providers.AuthProvider
|
import com.aurora.store.data.providers.AuthProvider
|
||||||
import com.aurora.store.util.Log
|
import com.aurora.store.util.Log
|
||||||
import com.tonyodev.fetch2.*
|
import com.tonyodev.fetch2.*
|
||||||
|
import com.tonyodev.fetch2core.DownloadBlock
|
||||||
import com.tonyodev.fetch2core.FetchObserver
|
import com.tonyodev.fetch2core.FetchObserver
|
||||||
import com.tonyodev.fetch2core.Reason
|
import com.tonyodev.fetch2core.Reason
|
||||||
import nl.komponents.kovenant.task
|
import nl.komponents.kovenant.task
|
||||||
import nl.komponents.kovenant.then
|
|
||||||
import nl.komponents.kovenant.ui.failUi
|
import nl.komponents.kovenant.ui.failUi
|
||||||
import nl.komponents.kovenant.ui.successUi
|
import nl.komponents.kovenant.ui.successUi
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.concurrent.timerTask
|
import kotlin.concurrent.timerTask
|
||||||
|
|
||||||
class UpdateService: LifecycleService() {
|
class UpdateService: LifecycleService() {
|
||||||
|
|
||||||
lateinit var fetch: Fetch
|
lateinit var fetch: Fetch
|
||||||
private lateinit var fetchListener: AbstractFetchGroupListener
|
lateinit var downloadManager: DownloadManager
|
||||||
|
private lateinit var fetchListener: FetchGroupListener
|
||||||
private var fetchActiveDownloadObserver = object : FetchObserver<Boolean> {
|
private var fetchActiveDownloadObserver = object : FetchObserver<Boolean> {
|
||||||
override fun onChanged(data: Boolean, reason: Reason) {
|
override fun onChanged(data: Boolean, reason: Reason) {
|
||||||
if (!data && !installing.get() && listeners.isEmpty()) {
|
if (!data && !installing.get() && listeners.isEmpty()) {
|
||||||
@@ -56,7 +55,7 @@ class UpdateService: LifecycleService() {
|
|||||||
}
|
}
|
||||||
private var hasActiveDownloadObserver = false
|
private var hasActiveDownloadObserver = false
|
||||||
|
|
||||||
private val listeners: ArrayList<AbstractFetchGroupListener> = ArrayList()
|
private val listeners: ArrayList<FetchGroupListener> = ArrayList()
|
||||||
|
|
||||||
private val pendingEvents: MutableMap</*groupId: */Int, AppDownloadStatus> = mutableMapOf()
|
private val pendingEvents: MutableMap</*groupId: */Int, AppDownloadStatus> = mutableMapOf()
|
||||||
|
|
||||||
@@ -114,8 +113,9 @@ class UpdateService: LifecycleService() {
|
|||||||
EventBus.getDefault().register(this)
|
EventBus.getDefault().register(this)
|
||||||
authData = AuthProvider.with(this).getAuthData()
|
authData = AuthProvider.with(this).getAuthData()
|
||||||
purchaseHelper = PurchaseHelper(authData)
|
purchaseHelper = PurchaseHelper(authData)
|
||||||
fetch = DownloadManager.with(this).fetch
|
downloadManager = DownloadManager.with(this)
|
||||||
fetchListener = object : AbstractFetchGroupListener() {
|
fetch = downloadManager.fetch
|
||||||
|
fetchListener = object : FetchGroupListener {
|
||||||
|
|
||||||
override fun onAdded(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
override fun onAdded(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
@@ -127,6 +127,12 @@ class UpdateService: LifecycleService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAdded(download: Download) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onAdded(download)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onProgress(
|
override fun onProgress(
|
||||||
groupId: Int,
|
groupId: Int,
|
||||||
download: Download,
|
download: Download,
|
||||||
@@ -139,6 +145,86 @@ class UpdateService: LifecycleService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onProgress(download: Download, etaInMilliSeconds: Long, downloadedBytesPerSecond: Long) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onProgress(download, etaInMilliSeconds, downloadedBytesPerSecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onQueued(groupId: Int, download: Download, waitingNetwork: Boolean, fetchGroup: FetchGroup) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onQueued(groupId, download, waitingNetwork, fetchGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onQueued(download: Download, waitingOnNetwork: Boolean) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onQueued(download, waitingOnNetwork)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRemoved(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onRemoved(groupId, download, fetchGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRemoved(download: Download) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onRemoved(download)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResumed(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onResumed(groupId, download, fetchGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResumed(download: Download) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onResumed(download)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStarted(
|
||||||
|
groupId: Int,
|
||||||
|
download: Download,
|
||||||
|
downloadBlocks: List<DownloadBlock>,
|
||||||
|
totalBlocks: Int,
|
||||||
|
fetchGroup: FetchGroup
|
||||||
|
) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onStarted(
|
||||||
|
groupId,
|
||||||
|
download,
|
||||||
|
downloadBlocks,
|
||||||
|
totalBlocks,
|
||||||
|
fetchGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStarted(download: Download, downloadBlocks: List<DownloadBlock>, totalBlocks: Int) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onStarted(
|
||||||
|
download,
|
||||||
|
downloadBlocks,
|
||||||
|
totalBlocks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWaitingNetwork(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onWaitingNetwork(groupId, download, fetchGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWaitingNetwork(download: Download) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onWaitingNetwork(download)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCompleted(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
override fun onCompleted(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onCompleted(groupId, download, fetchGroup)
|
it.onCompleted(groupId, download, fetchGroup)
|
||||||
@@ -146,7 +232,7 @@ class UpdateService: LifecycleService() {
|
|||||||
if (listeners.isEmpty()) {
|
if (listeners.isEmpty()) {
|
||||||
pendingEvents[groupId] = AppDownloadStatus(download, fetchGroup, isComplete = true)
|
pendingEvents[groupId] = AppDownloadStatus(download, fetchGroup, isComplete = true)
|
||||||
}
|
}
|
||||||
if (fetchGroup.groupDownloadProgress == 100 || fetchGroup.groupDownloadProgress == -1) {
|
if (fetchGroup.groupDownloadProgress == 100) {
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
try {
|
try {
|
||||||
install(download.tag!!, fetchGroup.downloads)
|
install(download.tag!!, fetchGroup.downloads)
|
||||||
@@ -159,6 +245,12 @@ class UpdateService: LifecycleService() {
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCompleted(download: Download) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onCompleted(download)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCancelled(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
override fun onCancelled(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onCancelled(groupId, download, fetchGroup)
|
it.onCancelled(groupId, download, fetchGroup)
|
||||||
@@ -168,6 +260,10 @@ class UpdateService: LifecycleService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCancelled(download: Download) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDeleted(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
override fun onDeleted(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
it.onDeleted(groupId, download, fetchGroup)
|
it.onDeleted(groupId, download, fetchGroup)
|
||||||
@@ -176,6 +272,80 @@ class UpdateService: LifecycleService() {
|
|||||||
pendingEvents[groupId] = AppDownloadStatus(download, fetchGroup, isCancelled = true)
|
pendingEvents[groupId] = AppDownloadStatus(download, fetchGroup, isCancelled = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDeleted(download: Download) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onDeleted(download)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDownloadBlockUpdated(
|
||||||
|
groupId: Int,
|
||||||
|
download: Download,
|
||||||
|
downloadBlock: DownloadBlock,
|
||||||
|
totalBlocks: Int,
|
||||||
|
fetchGroup: FetchGroup
|
||||||
|
) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onDownloadBlockUpdated(
|
||||||
|
groupId,
|
||||||
|
download,
|
||||||
|
downloadBlock,
|
||||||
|
totalBlocks,
|
||||||
|
fetchGroup
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDownloadBlockUpdated(download: Download, downloadBlock: DownloadBlock, totalBlocks: Int) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onDownloadBlockUpdated(
|
||||||
|
download,
|
||||||
|
downloadBlock,
|
||||||
|
totalBlocks
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(
|
||||||
|
groupId: Int,
|
||||||
|
download: Download,
|
||||||
|
error: Error,
|
||||||
|
throwable: Throwable?,
|
||||||
|
fetchGroup: FetchGroup
|
||||||
|
) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onError(
|
||||||
|
groupId,
|
||||||
|
download,
|
||||||
|
error,
|
||||||
|
throwable,
|
||||||
|
fetchGroup
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(download: Download, error: Error, throwable: Throwable?) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onError(
|
||||||
|
download,
|
||||||
|
error,
|
||||||
|
throwable
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPaused(groupId: Int, download: Download, fetchGroup: FetchGroup) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onPaused(groupId, download, fetchGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPaused(download: Download) {
|
||||||
|
listeners.forEach {
|
||||||
|
it.onPaused(download)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*liveUpdateData.observe(this) { updateData ->
|
/*liveUpdateData.observe(this) { updateData ->
|
||||||
|
|
||||||
@@ -210,16 +380,16 @@ class UpdateService: LifecycleService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var timer: Timer? = null
|
var timer: Timer? = null
|
||||||
val timerTask: TimerTask = timerTask {
|
val timerTaskRun: Runnable = Runnable {
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
if (!installing.get() && listeners.isEmpty()) {
|
if (!installing.get() && listeners.isEmpty()) {
|
||||||
fetch.hasActiveDownloads(true, { hasActiveDownloads ->
|
fetch.hasActiveDownloads(true) { hasActiveDownloads ->
|
||||||
if (!hasActiveDownloads && !installing.get() && listeners.isEmpty()) {
|
if (!hasActiveDownloads && !installing.get() && listeners.isEmpty()) {
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +407,7 @@ class UpdateService: LifecycleService() {
|
|||||||
if (filesExist) {
|
if (filesExist) {
|
||||||
task {
|
task {
|
||||||
try {
|
try {
|
||||||
val installer = AppInstaller(this)
|
val installer = AppInstaller.getInstance(this)
|
||||||
.getPreferredInstaller()
|
.getPreferredInstaller()
|
||||||
installer.install(
|
installer.install(
|
||||||
packageName,
|
packageName,
|
||||||
@@ -255,30 +425,24 @@ class UpdateService: LifecycleService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe()
|
var timerLock = Object()
|
||||||
fun onEventMainThreadExec(event: Any) {
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||||
|
fun onEventBackgroundThreadExec(event: Any) {
|
||||||
when (event) {
|
when (event) {
|
||||||
is InstallerEvent.Success -> {
|
is InstallerEvent.Success,
|
||||||
if (timer != null) {
|
|
||||||
timer!!.cancel()
|
|
||||||
timer = null
|
|
||||||
}
|
|
||||||
if (timer == null) {
|
|
||||||
timer = Timer()
|
|
||||||
}
|
|
||||||
installing.set(false)
|
|
||||||
timer!!.schedule(timerTask, 10 * 1000)
|
|
||||||
}
|
|
||||||
is InstallerEvent.Failed -> {
|
is InstallerEvent.Failed -> {
|
||||||
if (timer != null) {
|
synchronized(timerLock) {
|
||||||
timer!!.cancel()
|
if (timer != null) {
|
||||||
timer = null
|
timer!!.cancel()
|
||||||
|
timer = null
|
||||||
|
}
|
||||||
|
if (timer == null) {
|
||||||
|
timer = Timer()
|
||||||
|
}
|
||||||
|
installing.set(false)
|
||||||
|
timer!!.schedule(timerTask { timerTaskRun.run() }, 10 * 1000)
|
||||||
}
|
}
|
||||||
if (timer == null) {
|
|
||||||
timer = Timer()
|
|
||||||
}
|
|
||||||
installing.set(false)
|
|
||||||
timer!!.schedule(timerTask, 10 * 1000)
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
||||||
@@ -286,7 +450,7 @@ class UpdateService: LifecycleService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerListener(listener: AbstractFetchGroupListener) {
|
fun registerListener(listener: FetchGroupListener) {
|
||||||
listeners.add(listener)
|
listeners.add(listener)
|
||||||
val iterator = pendingEvents.iterator()
|
val iterator = pendingEvents.iterator()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
|
|||||||
@@ -21,9 +21,12 @@ package com.aurora.store.view.ui.details
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.ServiceConnection
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.IBinder
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -47,6 +50,7 @@ import com.aurora.store.data.event.InstallerEvent
|
|||||||
import com.aurora.store.data.installer.AppInstaller
|
import com.aurora.store.data.installer.AppInstaller
|
||||||
import com.aurora.store.data.network.HttpClient
|
import com.aurora.store.data.network.HttpClient
|
||||||
import com.aurora.store.data.providers.AuthProvider
|
import com.aurora.store.data.providers.AuthProvider
|
||||||
|
import com.aurora.store.data.service.UpdateService
|
||||||
import com.aurora.store.databinding.ActivityDetailsBinding
|
import com.aurora.store.databinding.ActivityDetailsBinding
|
||||||
import com.aurora.store.util.*
|
import com.aurora.store.util.*
|
||||||
import com.aurora.store.view.ui.downloads.DownloadActivity
|
import com.aurora.store.view.ui.downloads.DownloadActivity
|
||||||
@@ -74,8 +78,22 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
|
|
||||||
private lateinit var authData: AuthData
|
private lateinit var authData: AuthData
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
private lateinit var downloadManager: DownloadManager
|
|
||||||
private lateinit var fetch: Fetch
|
private var updateService: UpdateService? = null
|
||||||
|
private var pendingAddListener = true
|
||||||
|
private var serviceConnection = object : ServiceConnection {
|
||||||
|
override fun onServiceConnected(name: ComponentName, binder: IBinder) {
|
||||||
|
updateService = (binder as UpdateService.UpdateServiceBinder).getUpdateService()
|
||||||
|
if (::fetchGroupListener.isInitialized) {
|
||||||
|
updateService!!.registerListener(fetchGroupListener)
|
||||||
|
pendingAddListener = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
|
updateService = null
|
||||||
|
}
|
||||||
|
}
|
||||||
private lateinit var fetchGroupListener: FetchGroupListener
|
private lateinit var fetchGroupListener: FetchGroupListener
|
||||||
private lateinit var completionMarker: java.io.File
|
private lateinit var completionMarker: java.io.File
|
||||||
private lateinit var inProgressMarker: java.io.File
|
private lateinit var inProgressMarker: java.io.File
|
||||||
@@ -166,9 +184,8 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
if (!isLAndAbove()) {
|
getUpdateServiceInstance()
|
||||||
checkAndSetupInstall()
|
checkAndSetupInstall()
|
||||||
}
|
|
||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,11 +224,14 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var uninstallActionEnabled = false
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_details, menu)
|
menuInflater.inflate(R.menu.menu_details, menu)
|
||||||
if (::app.isInitialized) {
|
if (::app.isInitialized) {
|
||||||
val installed = PackageUtil.isInstalled(this, app.packageName)
|
val installed = PackageUtil.isInstalled(this, app.packageName)
|
||||||
menu?.findItem(R.id.action_uninstall)?.isVisible = installed
|
menu?.findItem(R.id.action_uninstall)?.isVisible = installed
|
||||||
|
uninstallActionEnabled = installed
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -306,7 +326,7 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
showDialog(R.string.title_installer, R.string.dialog_desc_native_split)
|
showDialog(R.string.title_installer, R.string.dialog_desc_native_split)
|
||||||
} else {
|
} else {
|
||||||
task {
|
task {
|
||||||
AppInstaller(this)
|
AppInstaller.getInstance(this)
|
||||||
.getPreferredInstaller()
|
.getPreferredInstaller()
|
||||||
.install(
|
.install(
|
||||||
app.packageName,
|
app.packageName,
|
||||||
@@ -325,7 +345,7 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
private fun uninstallApp() {
|
private fun uninstallApp() {
|
||||||
task {
|
task {
|
||||||
AppInstaller(this)
|
AppInstaller.getInstance(this)
|
||||||
.getPreferredInstaller()
|
.getPreferredInstaller()
|
||||||
.uninstall(app.packageName)
|
.uninstall(app.packageName)
|
||||||
}
|
}
|
||||||
@@ -428,14 +448,14 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
private fun startDownload() {
|
private fun startDownload() {
|
||||||
when (status) {
|
when (status) {
|
||||||
Status.PAUSED -> {
|
Status.PAUSED -> {
|
||||||
fetch.resumeGroup(app.getGroupId(this@AppDetailsActivity))
|
updateService?.fetch?.resumeGroup(app.getGroupId(this@AppDetailsActivity))
|
||||||
}
|
}
|
||||||
Status.DOWNLOADING -> {
|
Status.DOWNLOADING -> {
|
||||||
flip(1)
|
flip(1)
|
||||||
toast("Already downloading")
|
toast("Already downloading")
|
||||||
}
|
}
|
||||||
Status.COMPLETED -> {
|
Status.COMPLETED -> {
|
||||||
fetch.getFetchGroup(app.getGroupId(this@AppDetailsActivity)) {
|
updateService?.fetch?.getFetchGroup(app.getGroupId(this@AppDetailsActivity)) {
|
||||||
verifyAndInstall(it.downloads)
|
verifyAndInstall(it.downloads)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -519,10 +539,10 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
|
|
||||||
if (requestList.isNotEmpty()) {
|
if (requestList.isNotEmpty()) {
|
||||||
/*Remove old fetch group if downloaded earlier, mostly in case of updates*/
|
/*Remove old fetch group if downloaded earlier, mostly in case of updates*/
|
||||||
fetch.deleteGroup(app.getGroupId(this@AppDetailsActivity))
|
updateService?.fetch?.deleteGroup(app.getGroupId(this@AppDetailsActivity))
|
||||||
|
|
||||||
/*Enqueue new fetch group*/
|
/*Enqueue new fetch group*/
|
||||||
fetch.enqueue(
|
updateService?.fetch?.enqueue(
|
||||||
requestList
|
requestList
|
||||||
) {
|
) {
|
||||||
status = Status.ADDED
|
status = Status.ADDED
|
||||||
@@ -604,6 +624,9 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
btn.setText(R.string.action_open)
|
btn.setText(R.string.action_open)
|
||||||
btn.addOnClickListener { openApp() }
|
btn.addOnClickListener { openApp() }
|
||||||
}
|
}
|
||||||
|
if (!uninstallActionEnabled) {
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (app.isFree) {
|
if (app.isFree) {
|
||||||
btn.setText(R.string.action_install)
|
btn.setText(R.string.action_install)
|
||||||
@@ -619,6 +642,9 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
startDownload()
|
startDownload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (uninstallActionEnabled) {
|
||||||
|
invalidateOptionsMenu()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -636,16 +662,13 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun attachFetch() {
|
private fun attachFetch() {
|
||||||
downloadManager = DownloadManager.with(this)
|
updateService?.fetch?.getFetchGroup(app.getGroupId(this@AppDetailsActivity)) { fetchGroup: FetchGroup ->
|
||||||
fetch = downloadManager.fetch
|
|
||||||
|
|
||||||
fetch.getFetchGroup(app.getGroupId(this@AppDetailsActivity)) { fetchGroup: FetchGroup ->
|
|
||||||
if (fetchGroup.groupDownloadProgress == 100 && fetchGroup.completedDownloads.isNotEmpty()) {
|
if (fetchGroup.groupDownloadProgress == 100 && fetchGroup.completedDownloads.isNotEmpty()) {
|
||||||
status = Status.COMPLETED
|
status = Status.COMPLETED
|
||||||
} else if (downloadManager.isDownloading(fetchGroup)) {
|
} else if (updateService?.downloadManager?.isDownloading(fetchGroup) == true) {
|
||||||
status = Status.DOWNLOADING
|
status = Status.DOWNLOADING
|
||||||
flip(1)
|
flip(1)
|
||||||
} else if (downloadManager.isCanceled(fetchGroup)) {
|
} else if (updateService?.downloadManager?.isCanceled(fetchGroup) == true) {
|
||||||
status = Status.CANCELLED
|
status = Status.CANCELLED
|
||||||
} else if (fetchGroup.pausedDownloads.isNotEmpty()) {
|
} else if (fetchGroup.pausedDownloads.isNotEmpty()) {
|
||||||
status = Status.PAUSED
|
status = Status.PAUSED
|
||||||
@@ -716,12 +739,14 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
status = download.status
|
status = download.status
|
||||||
flip(0)
|
flip(0)
|
||||||
updateProgress(fetchGroup, -1, -1)
|
updateProgress(fetchGroup, -1, -1)
|
||||||
inProgressMarker.delete()
|
|
||||||
completionMarker.createNewFile()
|
|
||||||
try {
|
try {
|
||||||
verifyAndInstall(fetchGroup.downloads)
|
inProgressMarker.delete()
|
||||||
} catch (e: Exception) {
|
completionMarker.createNewFile()
|
||||||
Log.e(e.stackTraceToString())
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
|
runOnUiThread {
|
||||||
|
B.layoutDetailsInstall.btnDownload.setText(getString(R.string.action_installing))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -749,13 +774,45 @@ class AppDetailsActivity : BaseDetailsActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch.addListener(fetchGroupListener)
|
getUpdateServiceInstance()
|
||||||
|
|
||||||
B.layoutDetailsInstall.imgCancel.setOnClickListener {
|
B.layoutDetailsInstall.imgCancel.setOnClickListener {
|
||||||
fetch.cancelGroup(
|
updateService?.fetch?.cancelGroup(
|
||||||
app.getGroupId(this@AppDetailsActivity)
|
app.getGroupId(this@AppDetailsActivity)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (pendingAddListener && updateService != null) {
|
||||||
|
pendingAddListener = false
|
||||||
|
updateService!!.registerListener(fetchGroupListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUpdateServiceInstance() {
|
||||||
|
if (updateService == null) {
|
||||||
|
val intent = Intent(this, UpdateService::class.java)
|
||||||
|
startService(intent)
|
||||||
|
bindService(
|
||||||
|
intent,
|
||||||
|
serviceConnection,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
if (updateService != null) {
|
||||||
|
updateService = null
|
||||||
|
unbindService(serviceConnection)
|
||||||
|
}
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
if (updateService != null) {
|
||||||
|
updateService = null
|
||||||
|
unbindService(serviceConnection)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun attachBottomSheet() {
|
private fun attachBottomSheet() {
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class AppMenuSheet : BaseBottomSheet() {
|
|||||||
|
|
||||||
R.id.action_uninstall -> {
|
R.id.action_uninstall -> {
|
||||||
task {
|
task {
|
||||||
AppInstaller(requireContext())
|
AppInstaller.getInstance(requireContext())
|
||||||
.getPreferredInstaller().uninstall(app.packageName)
|
.getPreferredInstaller().uninstall(app.packageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ class UpdatesFragment : BaseFragment() {
|
|||||||
|
|
||||||
if (filesExist) {
|
if (filesExist) {
|
||||||
task {
|
task {
|
||||||
AppInstaller(requireContext())
|
AppInstaller.getInstance(requireContext())
|
||||||
.getPreferredInstaller()
|
.getPreferredInstaller()
|
||||||
.install(
|
.install(
|
||||||
packageName,
|
packageName,
|
||||||
|
|||||||
Reference in New Issue
Block a user