diff --git a/CHANGELOG.md b/CHANGELOG.md index e0e8d58..0775cae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change Log +## 0.0.8 *(2025-01-21)* + +### THIS SDK IS NOT YET STABLE +Please feel free to try but note that this is a work in progress. Feel free to join Open Attribution for questions or contributing. + +### Changes +- Switch from simple coroutine to CoroutineWorker + + ## 0.0.7 *(2024-11-29)* ### THIS SDK IS NOT YET STABLE diff --git a/OpenAttribution/build.gradle.kts b/OpenAttribution/build.gradle.kts index a5d1ffe..9bac36c 100644 --- a/OpenAttribution/build.gradle.kts +++ b/OpenAttribution/build.gradle.kts @@ -43,6 +43,8 @@ dependencies { implementation(platform(libs.okhttp.bom)) implementation(libs.okhttp) + implementation(libs.androidx.work.runtime.ktx) + implementation(libs.play.services.ads.identifier) implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) diff --git a/OpenAttribution/src/main/java/dev/openattribution/sdk/OAWorker.kt b/OpenAttribution/src/main/java/dev/openattribution/sdk/OAWorker.kt new file mode 100644 index 0000000..5e80e49 --- /dev/null +++ b/OpenAttribution/src/main/java/dev/openattribution/sdk/OAWorker.kt @@ -0,0 +1,100 @@ +package dev.openattribution.sdk + +import android.content.Context +import android.provider.Settings +import android.util.Log +import androidx.work.CoroutineWorker +import androidx.work.WorkerParameters +import kotlinx.coroutines.Dispatchers +import com.google.android.gms.ads.identifier.AdvertisingIdClient +import kotlinx.coroutines.withContext +import okhttp3.OkHttpClient +import okhttp3.Request +import java.util.UUID +import java.util.concurrent.TimeUnit + +class TrackAppOpenWorker( + private val appContext: Context, + workerParams: WorkerParameters +) : CoroutineWorker(appContext, workerParams) { + + override suspend fun doWork(): Result { + Log.d("MyOA", "doWork start") + + val userIdManager = UserIdManager.getInstance(appContext) + val baseUrl = OpenAttribution.getBaseUrl() + + try { + val androidId = Settings.Secure.getString(appContext.contentResolver, Settings.Secure.ANDROID_ID) + val myTimestamp = System.currentTimeMillis() + val eventId = "app_open" + val myUid = UUID.randomUUID().toString() + val myOaUid = userIdManager.getUserId() + val basePackageName = appContext.packageName + val appendedPackageName = if (EmulatorDetector.isEmulator()) { + "${basePackageName}_test" + } else { + basePackageName + } + + val gaid = withContext(Dispatchers.IO) { + try { + val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(appContext) + adInfo.id + } catch (e: Exception) { + Log.e("OpenAttribution", "Error retrieving GAID: ${e.message}") + null + } + } + + val url = constructTrackingUrl( + baseUrl, + appendedPackageName, + myOaUid, + gaid, + androidId ?: "unknown", + eventId, + myUid, + myTimestamp + ) + + val client = OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + + withContext(Dispatchers.IO) { + client.newCall(Request.Builder().url(url).build()).execute() + }.use { response -> + return if (response.isSuccessful) { + Log.i("OpenAttribution", "Tracking request successful: ${response.code}") + Result.success() + } else { + Log.w("OpenAttribution", "Tracking request failed: ${response.code}") + Result.retry() + } + } + } catch (e: Exception) { + Log.e("OpenAttribution", "Error in TrackAppOpenWorker: ${e.message}") + return Result.retry() + } + + + } + + private fun constructTrackingUrl( + baseUrl: String, + packageName: String, + oauid: String, + gaid: String?, + androidId: String, + eventId: String, + eventUid: String, + eventTime: Long + ): String { + val url = "$baseUrl/collect/events/$packageName?oa_uid=$oauid&ifa=$gaid&android_id=$androidId&event_id=$eventId&event_uid=$eventUid&event_time=$eventTime&b=A" + Log.i("OpenAttribution", "Constructing tracking URL $url") + return url + } +} diff --git a/OpenAttribution/src/main/java/dev/openattribution/sdk/Track.kt b/OpenAttribution/src/main/java/dev/openattribution/sdk/Track.kt index 4cd930f..ec4863e 100644 --- a/OpenAttribution/src/main/java/dev/openattribution/sdk/Track.kt +++ b/OpenAttribution/src/main/java/dev/openattribution/sdk/Track.kt @@ -11,7 +11,8 @@ import okhttp3.OkHttpClient import okhttp3.Request import java.util.UUID import java.util.concurrent.TimeUnit - +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager @@ -87,11 +88,15 @@ class OpenAttribution private constructor(private val context: Context) { // Method to initialize the SDK fun initialize(context: Context, baseUrl: String): OpenAttribution { + Log.d("MyOA", "InitStart") + + val instance = OpenAttribution(context) - instance.trackAppOpenAsync() + instance.scheduleTrackAppOpen() myBaseUrl = baseUrl - return OpenAttribution(context) +// return OpenAttribution(context) + return instance } // Getter for the base URL to ensure it's set @@ -100,98 +105,11 @@ class OpenAttribution private constructor(private val context: Context) { } } - - private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) - private val userIdManager by lazy { UserIdManager.getInstance(context) } - - - private fun trackAppOpenAsync() { - appScope.launch { - try { - trackAppOpen() - } catch (e: Exception) { - Log.e("OpenAttribution", "Error in trackAppOpen: ${e.message}") - } - } - } - - - suspend fun trackAppOpen() { - val baseUrl = getBaseUrl() // Ensure the URL is retrieved dynamically - val androidId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) - val myTimestamp = System.currentTimeMillis() - val eventId = "app_open" - val myUid = UUID.randomUUID().toString() - val myOaUid = userIdManager.getUserId() - - val basePackageName = context.packageName - val appendedPackageName = if (EmulatorDetector.isEmulator()) { - "${basePackageName}_test" - } else { - basePackageName - } - - - Log.d("OpenAttribution", "Base Package Name: $basePackageName") - Log.d("OpenAttribution", "Appended Package Name: $appendedPackageName") - - val gaid = withContext(Dispatchers.IO) { - try { - val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context) - adInfo.id - } catch (e: Exception) { - Log.e("OpenAttribution", "Error retrieving GAID: ${e.message}") - null - } - } - - val url = constructTrackingUrl( - baseUrl, - appendedPackageName, - myOaUid, - gaid, - androidId ?: "unknown", - eventId, - myUid, - myTimestamp - ) - - try { - val client = OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() - - withContext(Dispatchers.IO) { - client.newCall(Request.Builder().url(url).build()).execute() - }.use { response -> - if (response.isSuccessful) { - Log.i("OpenAttribution", "Tracking request successful: ${response.code}") - } else { - val responseBody = response.body?.string() - Log.w("OpenAttribution", "Tracking request failed: ${response.code} $responseBody") - } - } - } catch (e: Exception) { - Log.e("OpenAttribution", "Error sending tracking request: ${e.message}") - } + private fun scheduleTrackAppOpen() { + val workRequest = OneTimeWorkRequestBuilder() + .build() + WorkManager.getInstance(context).enqueue(workRequest) } - private fun constructTrackingUrl( - baseUrl: String, - packageName: String, - oauid: String, - gaid: String?, - androidId: String, - eventId: String, - eventUid: String, - eventTime: Long - ): String { - val url= "$baseUrl/collect/events/$packageName?oa_uid=$oauid&ifa=$gaid&android_id=$androidId&event_id=$eventId&event_uid=$eventUid&event_time=$eventTime" - - Log.i("OpenAttribution", "Constructing tracking URL $url") - return url - } } \ No newline at end of file diff --git a/README.md b/README.md index 3a63438..8c3c186 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ You can get the latest version of OpenAttribution's (Android SDK from Maven Cent `build.gradle.kts` ```kotlin dependencies { - implementation("dev.openattribution:open-attribution-sdk:0.0.7") + implementation("dev.openattribution:open-attribution-sdk:{LATEST_VERSION}") // rest of your dependencies } ``` diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 52073b2..b9d412c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -oaReleaseVersion = "0.0.7" +oaReleaseVersion = "0.0.8" agp = "8.7.2" kotlin = "1.9.24" coreKtx = "1.15.0" @@ -10,9 +10,12 @@ appcompat = "1.7.0" material = "1.12.0" okhttpBom = "4.12.0" playServicesAdsIdentifier = "18.1.0" +workRuntimeKtx = "2.10.0" + [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtx" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } @@ -24,6 +27,7 @@ play-services-ads-identifier = { module = "com.google.android.gms:play-services- + [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }