diff --git a/updater/src/main/aidl/com/farsitel/bazaar/IAutoUpdateCheckService.aidl b/updater/src/main/aidl/com/farsitel/bazaar/IAutoUpdateCheckService.aidl new file mode 100644 index 0000000..62bb03b --- /dev/null +++ b/updater/src/main/aidl/com/farsitel/bazaar/IAutoUpdateCheckService.aidl @@ -0,0 +1,5 @@ +package com.farsitel.bazaar; +interface IAutoUpdateCheckService { + boolean isAutoUpdateEnable(String packageName); + boolean update(String packageName); // false mean you don't have permission +} diff --git a/updater/src/main/java/com/farsitel/bazaar/updater/AutoUpdateResult.kt b/updater/src/main/java/com/farsitel/bazaar/updater/AutoUpdateResult.kt new file mode 100644 index 0000000..df44a4e --- /dev/null +++ b/updater/src/main/java/com/farsitel/bazaar/updater/AutoUpdateResult.kt @@ -0,0 +1,16 @@ +package com.farsitel.bazaar.updater + +sealed class AutoUpdateResult { + data class Success(val isEnable: Boolean) : AutoUpdateResult() + data class Error(val throwable: Throwable) : AutoUpdateResult() +} + +inline fun AutoUpdateResult.doOnSuccess(call: (Boolean) -> Unit): AutoUpdateResult { + if (this is AutoUpdateResult.Success) call(isEnable) + return this +} + +inline fun AutoUpdateResult.doOnError(call: (Throwable) -> Unit): AutoUpdateResult { + if (this is AutoUpdateResult.Error) call(throwable) + return this +} \ No newline at end of file diff --git a/updater/src/main/java/com/farsitel/bazaar/updater/AutoUpdateServiceConnection.kt b/updater/src/main/java/com/farsitel/bazaar/updater/AutoUpdateServiceConnection.kt new file mode 100644 index 0000000..cc6338c --- /dev/null +++ b/updater/src/main/java/com/farsitel/bazaar/updater/AutoUpdateServiceConnection.kt @@ -0,0 +1,34 @@ +package com.farsitel.bazaar.updater + +import android.content.ComponentName +import android.content.ServiceConnection +import android.os.IBinder +import com.farsitel.bazaar.IAutoUpdateCheckService +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +internal class AutoUpdateServiceConnection( + private val packageName: String, + private val scope: CoroutineScope, + private val onResult: ((Boolean) -> Unit), + private val onError: ((Throwable) -> Unit), +) : ServiceConnection { + + private var service: IAutoUpdateCheckService? = null + + override fun onServiceConnected(name: ComponentName?, boundService: IBinder?) { + service = IAutoUpdateCheckService.Stub.asInterface(boundService) + try { + scope.launch(Dispatchers.IO) { + val isEnabled = service?.isAutoUpdateEnable(packageName) + onResult(isEnabled ?: false) + } + } catch (t: Throwable) { + onError(t) + } + } + + override fun onServiceDisconnected(p0: ComponentName?) { + } +} \ No newline at end of file diff --git a/updater/src/main/java/com/farsitel/bazaar/updater/BazaarUpdater.kt b/updater/src/main/java/com/farsitel/bazaar/updater/BazaarUpdater.kt index 06b9d71..6d48ef3 100644 --- a/updater/src/main/java/com/farsitel/bazaar/updater/BazaarUpdater.kt +++ b/updater/src/main/java/com/farsitel/bazaar/updater/BazaarUpdater.kt @@ -15,7 +15,8 @@ import java.lang.ref.WeakReference object BazaarUpdater { - private var connection: WeakReference? = null + private var updateConnection: WeakReference? = null + private var autoUpdateConnection: WeakReference? = null fun getLastUpdateState( context: Context, @@ -25,7 +26,7 @@ object BazaarUpdater { if (verifyBazaarIsInstalled(context).not()) { onResult(UpdateResult.Error(BazaarIsNotInstalledException())) } else { - initService( + initUpdateService( context = context, onResult = onResult, scope = scope @@ -33,6 +34,35 @@ object BazaarUpdater { } } + fun getAutoUpdateState( + context: Context, + scope: CoroutineScope = retrieveScope(context), + onResult: (AutoUpdateResult) -> Unit + ) { + if (verifyBazaarIsInstalled(context).not()) { + onResult(AutoUpdateResult.Error(BazaarIsNotInstalledException())) + } else { + initAutoUpdateService( + context = context, + onResult = onResult, + scope = scope + ) + } + } + + fun enableAutoUpdate(context: Context) { + if (verifyBazaarIsInstalled(context).not()) { + return + } else { + val intent = Intent( + Intent.ACTION_VIEW, "$BAZAAR_THIRD_PARTY_AUTO_UPDATE${context.packageName}".toUri() + ).apply { + setPackage(BAZAAR_PACKAGE_NAME) + } + context.startActivity(intent) + } + } + fun updateApplication(context: Context) { val intent = if (verifyBazaarIsInstalled(context).not()) { Intent(Intent.ACTION_VIEW, "$BAZAAR_WEB_APP_DETAIL${context.packageName}".toUri()) @@ -57,40 +87,75 @@ object BazaarUpdater { } } - private fun initService( + private fun initUpdateService( context: Context, scope: CoroutineScope, onResult: (UpdateResult) -> Unit ) { - connection = WeakReference( + updateConnection = WeakReference( UpdateServiceConnection( packageName = context.packageName, scope = scope, bazaarVersionCode = getBazaarVersionCode(context), onResult = { updateVersion -> onResult(parseUpdateResponse(version = updateVersion, context = context)) - releaseService(context) + releaseUpdateService(context) }, onError = { message -> onResult(UpdateResult.Error(message)) - releaseService(context) + releaseUpdateService(context) } )) val intent = Intent(BAZAAR_UPDATE_INTENT) intent.setPackage(BAZAAR_PACKAGE_NAME) try { - connection?.get()?.let { con -> + updateConnection?.get()?.let { con -> context.bindService(intent, con, Context.BIND_AUTO_CREATE) } } catch (e: Exception) { - releaseService(context) + releaseUpdateService(context) + } + } + + private fun initAutoUpdateService( + context: Context, + scope: CoroutineScope, + onResult: (AutoUpdateResult) -> Unit + ) { + autoUpdateConnection = WeakReference( + AutoUpdateServiceConnection( + packageName = context.packageName, + scope = scope, + onResult = { isEnable -> + onResult(AutoUpdateResult.Success(isEnable)) + releaseAutoUpdateService(context) + }, + onError = { message -> + onResult(AutoUpdateResult.Error(message)) + releaseUpdateService(context) + } + )) + + val intent = Intent(BAZAAR_AUTO_UPDATE_INTENT) + intent.setPackage(BAZAAR_PACKAGE_NAME) + try { + autoUpdateConnection?.get()?.let { con -> + context.bindService(intent, con, Context.BIND_AUTO_CREATE) + } + } catch (e: Exception) { + releaseAutoUpdateService(context) } } /** This is our function to un-binds this activity from our service. */ - private fun releaseService(context: Context) { - connection?.get()?.let { con -> context.unbindService(con) } - connection = null + private fun releaseUpdateService(context: Context) { + updateConnection?.get()?.let { con -> context.unbindService(con) } + updateConnection = null + } + + private fun releaseAutoUpdateService(context: Context) { + autoUpdateConnection?.get()?.let { con -> context.unbindService(con) } + autoUpdateConnection = null } } \ No newline at end of file diff --git a/updater/src/main/java/com/farsitel/bazaar/updater/Constants.kt b/updater/src/main/java/com/farsitel/bazaar/updater/Constants.kt index 71170eb..94f3fd0 100644 --- a/updater/src/main/java/com/farsitel/bazaar/updater/Constants.kt +++ b/updater/src/main/java/com/farsitel/bazaar/updater/Constants.kt @@ -1,8 +1,10 @@ package com.farsitel.bazaar.updater internal const val BAZAAR_UPDATE_INTENT = "com.farsitel.bazaar.service.UpdateCheckService.BIND" +internal const val BAZAAR_AUTO_UPDATE_INTENT = "com.farsitel.bazaar.service.AutoUpdateCheckService.BIND" internal const val BAZAAR_PACKAGE_NAME = "com.farsitel.bazaar" internal const val BAZAAR_THIRD_PARTY_APP_DETAIL = "bazaar://details/modal?id=" +internal const val BAZAAR_THIRD_PARTY_AUTO_UPDATE = "bazaar://autoupdate/modal?id=" internal const val BAZAAR_WEB_APP_DETAIL = "https://cafebazaar.ir/app/?id=" internal const val BAZAAR_ERROR_RESULT = -1L