Loading presentation/src/main/AndroidManifest.xml +0 −1 Original line number Diff line number Diff line Loading @@ -93,7 +93,6 @@ android:value=".common.util.QkChooserTargetService" /> </activity> <activity android:name=".feature.settings.SettingsActivity" /> <activity android:name=".feature.plus.PlusActivity" /> <activity android:name=".feature.gallery.GalleryActivity" android:theme="@style/AppThemeBlack" /> Loading presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt +0 −3 Original line number Diff line number Diff line Loading @@ -26,8 +26,6 @@ import android.os.Build import android.provider.ContactsContract import android.provider.Settings import android.provider.Telephony import com.moez.QKSMS.BuildConfig import com.moez.QKSMS.common.util.BillingManager import com.moez.QKSMS.feature.backup.BackupActivity import com.moez.QKSMS.feature.blocked.BlockedActivity import com.moez.QKSMS.feature.compose.ComposeActivity Loading @@ -47,7 +45,6 @@ import javax.inject.Singleton class Navigator @Inject constructor( private val context: Context, private val analyticsManager: AnalyticsManager, private val billingManager: BillingManager, private val notificationManager: NotificationManager, private val permissions: PermissionManager ) { Loading presentation/src/main/java/com/moez/QKSMS/common/util/BillingManager.ktdeleted 100644 → 0 +0 −144 Original line number Diff line number Diff line /* * Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com> * * This file is part of QKSMS. * * QKSMS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * QKSMS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with QKSMS. If not, see <http://www.gnu.org/licenses/>. */ package com.moez.QKSMS.common.util import android.app.Activity import android.content.Context import com.android.billingclient.api.BillingClient import com.android.billingclient.api.BillingClient.BillingResponse import com.android.billingclient.api.BillingClient.SkuType import com.android.billingclient.api.BillingClientStateListener import com.android.billingclient.api.BillingFlowParams import com.android.billingclient.api.Purchase import com.android.billingclient.api.PurchasesUpdatedListener import com.android.billingclient.api.SkuDetails import com.android.billingclient.api.SkuDetailsParams import com.moez.QKSMS.BuildConfig import com.moez.QKSMS.manager.AnalyticsManager import io.reactivex.Flowable import io.reactivex.Observable import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @Singleton class BillingManager @Inject constructor( context: Context, private val analyticsManager: AnalyticsManager ) : PurchasesUpdatedListener { companion object { const val SKU_PLUS = "remove_ads" const val SKU_PLUS_DONATE = "qksms_plus_donate" } val products: Observable<List<SkuDetails>> = BehaviorSubject.create() val upgradeStatus: Observable<Boolean> private val skus = listOf(SKU_PLUS, SKU_PLUS_DONATE) private val purchaseListObservable = BehaviorSubject.create<List<Purchase>>() private val billingClient: BillingClient = BillingClient.newBuilder(context).setListener(this).build() private var isServiceConnected = false init { startServiceConnection { queryPurchases() querySkuDetailsAsync() } upgradeStatus = when (BuildConfig.FLAVOR) { "noAnalytics" -> BehaviorSubject.createDefault(true) else -> purchaseListObservable .map { purchases -> purchases.any { it.sku == SKU_PLUS } || purchases.any { it.sku == SKU_PLUS_DONATE } } .doOnNext { upgraded -> analyticsManager.setUserProperty("Upgraded", upgraded) } } } private fun queryPurchases() { executeServiceRequest { // Load the cached data purchaseListObservable.onNext(billingClient.queryPurchases(SkuType.INAPP).purchasesList.orEmpty()) // On a fresh device, the purchase might not be cached, and so we'll need to force a refresh billingClient.queryPurchaseHistoryAsync(SkuType.INAPP) { _, _ -> purchaseListObservable.onNext(billingClient.queryPurchases(SkuType.INAPP).purchasesList.orEmpty()) } } } private fun startServiceConnection(onSuccess: () -> Unit) { val listener = object : BillingClientStateListener { override fun onBillingSetupFinished(@BillingResponse billingResponseCode: Int) { if (billingResponseCode == BillingResponse.OK) { isServiceConnected = true onSuccess() } else { Timber.w("Billing response: $billingResponseCode") purchaseListObservable.onNext(listOf()) } } override fun onBillingServiceDisconnected() { isServiceConnected = false } } Flowable.fromCallable { billingClient.startConnection(listener) } .subscribeOn(Schedulers.io()) .subscribe() } private fun querySkuDetailsAsync() { executeServiceRequest { val subParams = SkuDetailsParams.newBuilder().setSkusList(skus).setType(BillingClient.SkuType.INAPP) billingClient.querySkuDetailsAsync(subParams.build()) { responseCode, skuDetailsList -> if (responseCode == BillingResponse.OK) { (products as Subject).onNext(skuDetailsList) } } } } fun initiatePurchaseFlow(activity: Activity, sku: String) { executeServiceRequest { val params = BillingFlowParams.newBuilder().setSku(sku).setType(SkuType.INAPP) billingClient.launchBillingFlow(activity, params.build()) } } private fun executeServiceRequest(runnable: () -> Unit) { when (isServiceConnected) { true -> runnable() false -> startServiceConnection(runnable) } } override fun onPurchasesUpdated(resultCode: Int, purchases: List<Purchase>?) { if (resultCode == BillingResponse.OK) { purchaseListObservable.onNext(purchases.orEmpty()) } } } No newline at end of file presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt +0 −10 Original line number Diff line number Diff line Loading @@ -161,16 +161,6 @@ class BackupController : QkController<BackupView, BackupState, BackupPresenter>( backup.summary = state.lastBackup adapter.data = state.backups fabIcon.setImageResource(when (state.upgraded) { true -> R.drawable.ic_file_upload_black_24dp false -> R.drawable.ic_star_black_24dp }) fabLabel.setText(when (state.upgraded) { true -> R.string.backup_now false -> R.string.title_qksms_plus }) } override fun activityVisible(): Observable<*> = activityVisibleSubject Loading presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupPresenter.kt +2 −9 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.content.Context import com.moez.QKSMS.R import com.moez.QKSMS.common.Navigator import com.moez.QKSMS.common.base.QkPresenter import com.moez.QKSMS.common.util.BillingManager import com.moez.QKSMS.common.util.DateFormatter import com.moez.QKSMS.common.util.extensions.makeToast import com.moez.QKSMS.interactor.PerformBackup Loading @@ -38,7 +37,6 @@ import javax.inject.Inject class BackupPresenter @Inject constructor( private val backupRepo: BackupRepository, private val billingManager: BillingManager, private val context: Context, private val dateFormatter: DateFormatter, private val navigator: Navigator, Loading Loading @@ -72,9 +70,6 @@ class BackupPresenter @Inject constructor( } .startWith(context.getString(R.string.backup_loading)) .subscribe { lastBackup -> newState { copy(lastBackup = lastBackup) } } disposables += billingManager.upgradeStatus .subscribe { upgraded -> newState { copy(upgraded = upgraded) } } } override fun bindIntents(view: BackupView) { Loading @@ -88,11 +83,9 @@ class BackupPresenter @Inject constructor( view.restoreClicks() .withLatestFrom( backupRepo.getBackupProgress(), backupRepo.getRestoreProgress(), billingManager.upgradeStatus) { _, backupProgress, restoreProgress, upgraded -> backupRepo.getRestoreProgress()) { _, backupProgress, restoreProgress -> when { !upgraded -> context.makeToast(R.string.backup_restore_error_plus) backupProgress.running -> context.makeToast(R.string.backup_restore_error_backup) restoreProgress.running -> context.makeToast(R.string.backup_restore_error_restore) !permissionManager.hasStorage() -> view.requestStoragePermission() Loading Loading
presentation/src/main/AndroidManifest.xml +0 −1 Original line number Diff line number Diff line Loading @@ -93,7 +93,6 @@ android:value=".common.util.QkChooserTargetService" /> </activity> <activity android:name=".feature.settings.SettingsActivity" /> <activity android:name=".feature.plus.PlusActivity" /> <activity android:name=".feature.gallery.GalleryActivity" android:theme="@style/AppThemeBlack" /> Loading
presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt +0 −3 Original line number Diff line number Diff line Loading @@ -26,8 +26,6 @@ import android.os.Build import android.provider.ContactsContract import android.provider.Settings import android.provider.Telephony import com.moez.QKSMS.BuildConfig import com.moez.QKSMS.common.util.BillingManager import com.moez.QKSMS.feature.backup.BackupActivity import com.moez.QKSMS.feature.blocked.BlockedActivity import com.moez.QKSMS.feature.compose.ComposeActivity Loading @@ -47,7 +45,6 @@ import javax.inject.Singleton class Navigator @Inject constructor( private val context: Context, private val analyticsManager: AnalyticsManager, private val billingManager: BillingManager, private val notificationManager: NotificationManager, private val permissions: PermissionManager ) { Loading
presentation/src/main/java/com/moez/QKSMS/common/util/BillingManager.ktdeleted 100644 → 0 +0 −144 Original line number Diff line number Diff line /* * Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com> * * This file is part of QKSMS. * * QKSMS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * QKSMS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with QKSMS. If not, see <http://www.gnu.org/licenses/>. */ package com.moez.QKSMS.common.util import android.app.Activity import android.content.Context import com.android.billingclient.api.BillingClient import com.android.billingclient.api.BillingClient.BillingResponse import com.android.billingclient.api.BillingClient.SkuType import com.android.billingclient.api.BillingClientStateListener import com.android.billingclient.api.BillingFlowParams import com.android.billingclient.api.Purchase import com.android.billingclient.api.PurchasesUpdatedListener import com.android.billingclient.api.SkuDetails import com.android.billingclient.api.SkuDetailsParams import com.moez.QKSMS.BuildConfig import com.moez.QKSMS.manager.AnalyticsManager import io.reactivex.Flowable import io.reactivex.Observable import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @Singleton class BillingManager @Inject constructor( context: Context, private val analyticsManager: AnalyticsManager ) : PurchasesUpdatedListener { companion object { const val SKU_PLUS = "remove_ads" const val SKU_PLUS_DONATE = "qksms_plus_donate" } val products: Observable<List<SkuDetails>> = BehaviorSubject.create() val upgradeStatus: Observable<Boolean> private val skus = listOf(SKU_PLUS, SKU_PLUS_DONATE) private val purchaseListObservable = BehaviorSubject.create<List<Purchase>>() private val billingClient: BillingClient = BillingClient.newBuilder(context).setListener(this).build() private var isServiceConnected = false init { startServiceConnection { queryPurchases() querySkuDetailsAsync() } upgradeStatus = when (BuildConfig.FLAVOR) { "noAnalytics" -> BehaviorSubject.createDefault(true) else -> purchaseListObservable .map { purchases -> purchases.any { it.sku == SKU_PLUS } || purchases.any { it.sku == SKU_PLUS_DONATE } } .doOnNext { upgraded -> analyticsManager.setUserProperty("Upgraded", upgraded) } } } private fun queryPurchases() { executeServiceRequest { // Load the cached data purchaseListObservable.onNext(billingClient.queryPurchases(SkuType.INAPP).purchasesList.orEmpty()) // On a fresh device, the purchase might not be cached, and so we'll need to force a refresh billingClient.queryPurchaseHistoryAsync(SkuType.INAPP) { _, _ -> purchaseListObservable.onNext(billingClient.queryPurchases(SkuType.INAPP).purchasesList.orEmpty()) } } } private fun startServiceConnection(onSuccess: () -> Unit) { val listener = object : BillingClientStateListener { override fun onBillingSetupFinished(@BillingResponse billingResponseCode: Int) { if (billingResponseCode == BillingResponse.OK) { isServiceConnected = true onSuccess() } else { Timber.w("Billing response: $billingResponseCode") purchaseListObservable.onNext(listOf()) } } override fun onBillingServiceDisconnected() { isServiceConnected = false } } Flowable.fromCallable { billingClient.startConnection(listener) } .subscribeOn(Schedulers.io()) .subscribe() } private fun querySkuDetailsAsync() { executeServiceRequest { val subParams = SkuDetailsParams.newBuilder().setSkusList(skus).setType(BillingClient.SkuType.INAPP) billingClient.querySkuDetailsAsync(subParams.build()) { responseCode, skuDetailsList -> if (responseCode == BillingResponse.OK) { (products as Subject).onNext(skuDetailsList) } } } } fun initiatePurchaseFlow(activity: Activity, sku: String) { executeServiceRequest { val params = BillingFlowParams.newBuilder().setSku(sku).setType(SkuType.INAPP) billingClient.launchBillingFlow(activity, params.build()) } } private fun executeServiceRequest(runnable: () -> Unit) { when (isServiceConnected) { true -> runnable() false -> startServiceConnection(runnable) } } override fun onPurchasesUpdated(resultCode: Int, purchases: List<Purchase>?) { if (resultCode == BillingResponse.OK) { purchaseListObservable.onNext(purchases.orEmpty()) } } } No newline at end of file
presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt +0 −10 Original line number Diff line number Diff line Loading @@ -161,16 +161,6 @@ class BackupController : QkController<BackupView, BackupState, BackupPresenter>( backup.summary = state.lastBackup adapter.data = state.backups fabIcon.setImageResource(when (state.upgraded) { true -> R.drawable.ic_file_upload_black_24dp false -> R.drawable.ic_star_black_24dp }) fabLabel.setText(when (state.upgraded) { true -> R.string.backup_now false -> R.string.title_qksms_plus }) } override fun activityVisible(): Observable<*> = activityVisibleSubject Loading
presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupPresenter.kt +2 −9 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.content.Context import com.moez.QKSMS.R import com.moez.QKSMS.common.Navigator import com.moez.QKSMS.common.base.QkPresenter import com.moez.QKSMS.common.util.BillingManager import com.moez.QKSMS.common.util.DateFormatter import com.moez.QKSMS.common.util.extensions.makeToast import com.moez.QKSMS.interactor.PerformBackup Loading @@ -38,7 +37,6 @@ import javax.inject.Inject class BackupPresenter @Inject constructor( private val backupRepo: BackupRepository, private val billingManager: BillingManager, private val context: Context, private val dateFormatter: DateFormatter, private val navigator: Navigator, Loading Loading @@ -72,9 +70,6 @@ class BackupPresenter @Inject constructor( } .startWith(context.getString(R.string.backup_loading)) .subscribe { lastBackup -> newState { copy(lastBackup = lastBackup) } } disposables += billingManager.upgradeStatus .subscribe { upgraded -> newState { copy(upgraded = upgraded) } } } override fun bindIntents(view: BackupView) { Loading @@ -88,11 +83,9 @@ class BackupPresenter @Inject constructor( view.restoreClicks() .withLatestFrom( backupRepo.getBackupProgress(), backupRepo.getRestoreProgress(), billingManager.upgradeStatus) { _, backupProgress, restoreProgress, upgraded -> backupRepo.getRestoreProgress()) { _, backupProgress, restoreProgress -> when { !upgraded -> context.makeToast(R.string.backup_restore_error_plus) backupProgress.running -> context.makeToast(R.string.backup_restore_error_backup) restoreProgress.running -> context.makeToast(R.string.backup_restore_error_restore) !permissionManager.hasStorage() -> view.requestStoragePermission() Loading