Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion Branch-SDK/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ jacoco {
toolVersion = "0.8.10"
}

//configurations.all {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted

// resolutionStrategy {
// force("com.android.billingclient:billing:8.0.0")
// }
//}

dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to "*.jar")))
implementation(kotlin("stdlib"))
Expand Down Expand Up @@ -41,7 +47,6 @@ dependencies {

// Google Play Billing library
compileOnly("com.android.billingclient:billing:6.0.1")

// In app browser experience
compileOnly("androidx.browser:browser:1.8.0")

Expand Down Expand Up @@ -136,6 +141,18 @@ android {
signing {
isRequired = isReleaseBuild()
}

flavorDimensions.add("billing")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep things simple and just check the buildconfig version string and conditionally execute the right library implementation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Removing flavor dimensions


productFlavors {
create("billing_v6v7") {
dimension = "billing"
}
create("billing_v8") {
dimension = "billing"
}
}

}

fun getRepositoryUsername(): String {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package io.branch.referral

import android.content.Context
import com.android.billingclient.api.*
import io.branch.indexing.BranchUniversalObject
import io.branch.referral.util.*
import java.math.BigDecimal

class BillingGooglePlayV6V7 : BillingGooglePlayInterface {
lateinit var billingClient: BillingClient

companion object {
@Volatile
private lateinit var instance: BillingGooglePlay

fun getInstance(): BillingGooglePlay {
synchronized(this) {
if (!::instance.isInitialized) {
instance = BillingGooglePlay()

instance.billingClient =
BillingClient.newBuilder(Branch.getInstance().applicationContext)
.setListener(instance.purchasesUpdatedListener)
.enablePendingPurchases()
.build()
}
return instance
}
}
}


override fun startBillingClient(callback: (Boolean) -> Unit) {
if (billingClient.isReady) {
BranchLogger.v("Billing Client has already been started..")
callback(true)
} else {
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
BranchLogger.v("Billing Client setup finished.")
callback(true)
} else {
val errorMessage =
"Billing Client setup failed with error: ${billingResult.debugMessage}"
BranchLogger.e(errorMessage)
callback(false)
}
}

override fun onBillingServiceDisconnected() {
BranchLogger.w("Billing Client disconnected")
callback(false)
}
})
}
}

override fun logEventWithPurchase(
context: Context,
purchase: Purchase
) {
val productIds = purchase.products
val productList: MutableList<QueryProductDetailsParams.Product> = ArrayList()
val subsList: MutableList<QueryProductDetailsParams.Product> = ArrayList()

for (productId: String? in productIds) {
val inAppProduct = QueryProductDetailsParams.Product.newBuilder()
.setProductId(productId!!)
.setProductType(BillingClient.ProductType.INAPP)
.build()
productList.add(inAppProduct)

val subsProduct = QueryProductDetailsParams.Product.newBuilder()
.setProductId(productId)
.setProductType(BillingClient.ProductType.SUBS)
.build()
subsList.add(subsProduct)
}

val queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
.setProductList(productList)
.build()

val querySubsProductDetailsParams = QueryProductDetailsParams.newBuilder()
.setProductList(subsList)
.build()

billingClient.queryProductDetailsAsync(
querySubsProductDetailsParams
) { billingResult: BillingResult, subsProductDetailsList: List<ProductDetails?> ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val contentItemBUOs: MutableList<BranchUniversalObject> =
ArrayList()
var currency: CurrencyType = CurrencyType.USD
var revenue = 0.00

for (product: ProductDetails? in subsProductDetailsList) {
val buo: BranchUniversalObject = createBUOWithSubsProductDetails(product)
contentItemBUOs.add(buo)

revenue += buo.contentMetadata.price
currency = buo.contentMetadata.currencyType
}

if (contentItemBUOs.isNotEmpty()) {
createAndLogEventForPurchase(
context,
purchase,
contentItemBUOs,
currency,
revenue,
BillingClient.ProductType.SUBS
)
}
}
else {
BranchLogger.e("Failed to query subscriptions. Error: " + billingResult.debugMessage)
}
}

billingClient.queryProductDetailsAsync(
queryProductDetailsParams
) { billingResult: BillingResult, productDetailsList: List<ProductDetails?> ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {

val contentItemBUOs: MutableList<BranchUniversalObject> =
ArrayList()
var currency: CurrencyType = CurrencyType.USD
var revenue = 0.00
val quantity: Int = purchase.quantity

for (product: ProductDetails? in productDetailsList) {
val buo: BranchUniversalObject =
createBUOWithInAppProductDetails(product, quantity)
contentItemBUOs.add(buo)

revenue += (BigDecimal(buo.contentMetadata.price.toString()) * BigDecimal(
quantity.toString()
)).toDouble()
currency = buo.contentMetadata.currencyType
}

if (contentItemBUOs.isNotEmpty()) {
createAndLogEventForPurchase(
context,
purchase,
contentItemBUOs,
currency,
revenue,
BillingClient.ProductType.INAPP
)
}
}
else {
BranchLogger.e("Failed to query subscriptions. Error: " + billingResult.debugMessage)
}
}
}



}
40 changes: 40 additions & 0 deletions Branch-SDK/src/BillingGooglePlayModules/BillingV6/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
plugins {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these gradle files necessary to get the library version?

Copy link
Contributor

@gdeluna-branch gdeluna-branch Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to do this with
String billingClientVersion = com.android.billingclient.BuildConfig.VERSION_NAME;
in Java (or Kotlin) instead

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean having that line in the main gradle file instead? So I'll remove the product flavors.

Doe that replace this? :compileOnly("com.android.billingclient:billing:6.0.1")

id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}

android {
compileSdk ANDROID_BUILD_SDK_VERSION_COMPILE.toInt() // Or your project's compile SDK version

defaultConfig {
minSdk = ANDROID_BUILD_SDK_VERSION_MINIMUM.toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("proguard-consumer.txt")
}

// This section is for library-specific configurations
buildTypes {
fun String.wrapInQuotes(): String {
return "\"$this\""
}

debug {
enableUnitTestCoverage = true
enableAndroidTestCoverage = true
buildConfigField("long", "VERSION_CODE", VERSION_CODE)
buildConfigField("String", "VERSION_NAME", VERSION_NAME.wrapInQuotes())
}
release {
buildConfigField("long", "VERSION_CODE", VERSION_CODE)
buildConfigField("String", "VERSION_NAME", VERSION_NAME.wrapInQuotes())
}
}
}

dependencies {
// This is the older V6 version of the billing library
implementation 'com.android.billingclient:billing:6.0.1'

// Add any other dependencies specific to this module
implementation 'androidx.core:core-ktx:1.9.0'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.branch.referral

import android.content.Context
import com.android.billingclient.api.*

class BillingGooglePlayV8 : BillingGooglePlayInterface{
override fun startBillingClient(context: Context?) {
TODO("Not yet implemented")
}

override fun logEventWithPurchase(
context: Context?,
purchase: Purchase?
) {
TODO("Not yet implemented")
}
}
40 changes: 40 additions & 0 deletions Branch-SDK/src/BillingGooglePlayModules/BillingV7V8/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}

android {
compileSdk ANDROID_BUILD_SDK_VERSION_COMPILE.toInt() // Or your project's compile SDK version

defaultConfig {
minSdk = ANDROID_BUILD_SDK_VERSION_MINIMUM.toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("proguard-consumer.txt")
}

// This section is for library-specific configurations
buildTypes {
fun String.wrapInQuotes(): String {
return "\"$this\""
}

debug {
enableUnitTestCoverage = true
enableAndroidTestCoverage = true
buildConfigField("long", "VERSION_CODE", VERSION_CODE)
buildConfigField("String", "VERSION_NAME", VERSION_NAME.wrapInQuotes())
}
release {
buildConfigField("long", "VERSION_CODE", VERSION_CODE)
buildConfigField("String", "VERSION_NAME", VERSION_NAME.wrapInQuotes())
}
}
}

dependencies {
// This is the older V6 version of the billing library
implementation 'com.android.billingclient:billing:8.0.0'

// Add any other dependencies specific to this module
implementation 'androidx.core:core-ktx:1.9.0'
}
4 changes: 2 additions & 2 deletions Branch-SDK/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />-->
<!-- <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />-->
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

<application>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io.branch.referral

import android.Manifest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.GrantPermissionRule
import com.android.billingclient.api.Purchase
import io.branch.referral.util.CurrencyType

import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

Expand Down Expand Up @@ -46,4 +48,14 @@ class BillingGooglePlayTests : BranchTest() {
)
Assert.assertTrue(eventRequest.isWaitingOnProcessToFinish)
}

@Test
fun getBillingLibraryVersionReturnsCorrectVersion() {
// Act
val version = BillingGooglePlayReflection.getBillingLibraryVersion()

// Assert
//Change the assertion to match the version you have in your build.gradle file
Assert.assertEquals("Version 6.0 or higher", version)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.branch.referral;

import io.branch.referral.BillingGooglePlayV6V7;
import java.lang.ClassNotFoundException;

public class BillingGooglePlayReflection {
public static BillingGooglePlayInterface getBillingLibraryVersion() {
return new BillingGooglePlayV6V7();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.branch.referral;

import io.branch.referral.BillingGooglePlayV8;
import java.lang.ClassNotFoundException;

public class BillingGooglePlayReflection {
public static BillingGooglePlayInterface getBillingLibraryVersion() {
return new BillingGooglePlayV8();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.branch.referral;

import android.content.Context;
import io.branch.referral.util.*;

import com.android.billingclient.api.Purchase;

public interface BillingGooglePlayInterface {
fun logEventWithPurchase(context: Context, purchase: Purchase);
fun startBillingClient(callback: (Boolean) -> Unit);
}
Loading