Skip to content

Commit

Permalink
Merge pull request #22 from shortcut/master
Browse files Browse the repository at this point in the history
Fix memory leak, activity was retained during initialization
  • Loading branch information
ardian4 committed Feb 19, 2024
2 parents 2aff033 + 1014f37 commit 32d78d9
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 101 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

version = "4.0.2"
version = "4.0.3"

android {
compileSdkVersion 33
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package se.kantarsifo.mobileanalytics.sampleapp

import android.content.Context
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import androidx.activity.result.ActivityResultLauncher
import androidx.browser.trusted.TrustedWebActivityIntentBuilder
import com.google.androidbrowserhelper.trusted.TwaLauncher
import kotlinx.android.synthetic.main.activity_initialization.*
import se.kantarsifo.mobileanalytics.framework.TSMobileAnalytics
import se.kantarsifo.mobileanalytics.framework.TWAModel
Expand Down Expand Up @@ -131,17 +127,10 @@ class InitializationActivity : BaseActivity() {

private fun onTWAClicked() {
if (isFrameworkInitialized()) {
start(this)
TSMobileAnalytics.instance?.openTwa(activity = this)
}
}

fun start(context: Context) {

TSMobileAnalytics.instance?.openTwa()

}


private fun onNativeClicked() {
if (isFrameworkInitialized()) {
NativeActivity.start(this)
Expand Down
2 changes: 1 addition & 1 deletion libmobiletagging/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apply plugin: 'com.github.dcendents.android-maven'

group='myGroups'

version = "4.2.0"
version = "4.2.1"


android {
Expand Down
4 changes: 4 additions & 0 deletions libmobiletagging/release-notes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ using Kantar Sifo’s services. The SDK zip file contains three folders:

RELEASE NOTES:

v4.2.1 2024-02-19

- Bug fix memory leak where activity was retained during library initialization

v4.2.0 2023-06-14

- Bug fix Android 12 for secure cookies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ internal object PanelistHandler {
}
}

fun getCookies(context: Context, activity: ComponentActivity): List<HttpCookie>? {
val sharedPref = activity.getSharedPreferences(TagStringsAndValues.SIFO_PREFERENCE_KEY, Context.MODE_PRIVATE)
fun getCookies(context: Context): List<HttpCookie>? {
val sharedPref = context.getSharedPreferences(TagStringsAndValues.SIFO_PREFERENCE_KEY, Context.MODE_PRIVATE)
if (sharedPref.contains(TagStringsAndValues.SIFO_PREFERENCE_COOKIES)) {
return readCookiesFromJson(sharedPref.getString(TagStringsAndValues.SIFO_PREFERENCE_COOKIES, "") ?: "")
} else { // Fallback to old version of reading cookies from sifo panel app shared preference
Expand Down Expand Up @@ -159,8 +159,8 @@ internal object PanelistHandler {
return ""
}

private fun shouldUpdateCookieValues(activity: ComponentActivity): Boolean {
val sharedPref = activity.getSharedPreferences(TagStringsAndValues.SIFO_PREFERENCE_KEY, Context.MODE_PRIVATE)
private fun shouldUpdateCookieValues(context: Context): Boolean {
val sharedPref = context.getSharedPreferences(TagStringsAndValues.SIFO_PREFERENCE_KEY, Context.MODE_PRIVATE)
if (sharedPref.contains(TagStringsAndValues.SIFO_PREFERENCE_COOKIES_SYNC_TIME).not()) {
return true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package se.kantarsifo.mobileanalytics.framework

import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.activity.ComponentActivity
import org.json.JSONObject
import org.json.JSONTokener
import java.io.*
Expand All @@ -14,12 +12,12 @@ import java.security.MessageDigest

class TSMConfigUtil {
companion object {
fun syncConfig(activity: ComponentActivity, appName: String) {
val packageMngr = activity.packageManager
val packageName = activity.packageName
fun syncConfig(context: Context, appName: String) {
val packageMngr = context.packageManager
val packageName = context.packageName
val packageInfo = packageMngr.getPackageInfo(packageName, 0)
var version = ""
val sharedPref = activity.getSharedPreferences(TagStringsAndValues.SIFO_PREFERENCE_KEY, Context.MODE_PRIVATE)
val sharedPref = context.getSharedPreferences(TagStringsAndValues.SIFO_PREFERENCE_KEY, Context.MODE_PRIVATE)
val config = sharedPref.getString(TagStringsAndValues.SIFO_PREFERENCE_CONFIG, "")
var md5 = "nohash"
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package se.kantarsifo.mobileanalytics.framework

import android.webkit.WebView
import androidx.activity.ComponentActivity
import java.lang.ref.WeakReference

/**
* Kantar Sifo Mobile Analytics Framework for Android:
Expand Down Expand Up @@ -93,8 +94,8 @@ open class TSMobileAnalytics protected constructor() {
return dataRequestHandler.performMetricsRequest(category)
}

fun openTwa() {
dataRequestHandler.openTwa()
fun openTwa(activity: ComponentActivity) {
dataRequestHandler.openTwa(activity)
}


Expand Down Expand Up @@ -155,7 +156,7 @@ open class TSMobileAnalytics protected constructor() {
* @param callbackListener The callback-listener implementing the TagDataRequestCallbackListener interface.
*/
fun setCallbackListener(callbackListener: TagDataRequestCallbackListener?) {
dataRequestHandler.userCallbackListener = callbackListener
dataRequestHandler.userCallbackListener = WeakReference(callbackListener)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,49 +21,74 @@ import java.net.HttpCookie
* Extension of the framework class containing some extended functions used
* internally by the framework.
*/
internal class TSMobileAnalyticsBackend : TSMobileAnalytics {

/**
* Constructor used internally only.
* Use createInstance() and getInstance() instead.
*/
private constructor(context: Context, activity: ComponentActivity, cpId: String, applicationName: String, panelistId: String, trackPanelistOnly: Boolean) : super() {
dataRequestHandler = TagDataRequestHandler(context, activity, cpId, applicationName, panelistId, trackPanelistOnly)
}


/**
* Constructor used internally only.
* Use createInstance() and getInstance() instead.
*/
private constructor(context: Context, activity: ComponentActivity, cpId: String, applicationName: String, cookies: List<HttpCookie>?, trackPanelistOnly: Boolean,twaInfo: TWAModel,isWebViewBased: Boolean) : super() {
dataRequestHandler = TagDataRequestHandler(context, activity, cpId, applicationName, cookies, trackPanelistOnly,twaInfo,isWebViewBased)
internal class TSMobileAnalyticsBackend
/**
* Constructor used internally only.
* Use createInstance() and getInstance() instead.
*/ private constructor(
context: Context,
cpId: String,
applicationName: String,
cookies: List<HttpCookie>?,
trackPanelistOnly: Boolean,
twaInfo: TWAModel,
isWebViewBased: Boolean
) : TSMobileAnalytics() {

init {
dataRequestHandler = TagDataRequestHandler(
context,
cpId,
applicationName,
cookies,
trackPanelistOnly,
twaInfo,
isWebViewBased
)
}

companion object {

fun createInstance(activity: ComponentActivity, cpID: String?, applicationName: String?, onlyPanelist: Boolean, isWebBased: Boolean = false,twaInfo: TWAModel = TWAModel()): TSMobileAnalyticsBackend? {
fun createInstance(
activity: ComponentActivity,
cpID: String?,
applicationName: String?,
onlyPanelist: Boolean,
isWebBased: Boolean = false,
twaInfo: TWAModel = TWAModel()
): TSMobileAnalyticsBackend? {
if (activity == null) {
fatalError("Mobile Application Tagging Framework Failed to initiate - context must not be null")
return frameworkInstance
}
val sdkVersion = BuildConfig.VERSION_NAME
val appVersion = activity.getApplicationVersion()
val cookieValue = "trackPanelistOnly=$onlyPanelist&isWebViewBased=$isWebBased&sdkVersion=$sdkVersion&appVersion=$appVersion; SameSite=None; secure; Httponly"
val metaCookie = CookieHandler.createHttpCookie(TagStringsAndValues.SIFO_META_COOKIE_NAME, cookieValue)
val cookieValue =
"trackPanelistOnly=$onlyPanelist&isWebViewBased=$isWebBased&sdkVersion=$sdkVersion&appVersion=$appVersion; SameSite=None; secure; Httponly"
val metaCookie = CookieHandler.createHttpCookie(
TagStringsAndValues.SIFO_META_COOKIE_NAME,
cookieValue
)
CookieHandler.setupPanelistCookies(listOf(metaCookie))
if (paramsAreValid(cpID, applicationName)) {
if (frameworkInstance == null) {
CoroutineScope(Dispatchers.IO).launch {
TSMConfigUtil.syncConfig(activity, applicationName ?: "")
}

initTags(activity, cpID!!, applicationName!!, onlyPanelist, isWebBased,twaInfo)
initTags(
activity.applicationContext,
cpID!!,
applicationName!!,
onlyPanelist,
isWebBased,
twaInfo
)

sendAppStartEvent()

PanelistHandler.syncCookies(activity, activity) {
refreshCookiesAndKeys(activity,onlyPanelist)
PanelistHandler.syncCookies(activity.baseContext, activity) {
refreshCookiesAndKeys(activity, onlyPanelist)
frameworkInstance?.dataRequestHandler?.setStateReady()
}
} else {
Expand All @@ -75,8 +100,9 @@ internal class TSMobileAnalyticsBackend : TSMobileAnalytics {
}


private fun refreshCookiesAndKeys(activity: ComponentActivity, onlyPanelist: Boolean) {
val isInstalled = activity.isPackageInstalled(TagStringsAndValues.SIFO_PANELIST_PACKAGE_NAME_V2)
private fun refreshCookiesAndKeys(context: Context, onlyPanelist: Boolean) {
val isInstalled =
context.isPackageInstalled(TagStringsAndValues.SIFO_PANELIST_PACKAGE_NAME_V2)
if (!isInstalled) {
if (onlyPanelist && !isInstalled) {
frameworkInstance = null
Expand All @@ -86,15 +112,17 @@ internal class TSMobileAnalyticsBackend : TSMobileAnalytics {
return
}
log("Refreshing panelist keys(Cookies)")
val cookies = PanelistHandler.getCookies(activity, activity)
val cookies = PanelistHandler.getCookies(context)
frameworkInstance?.dataRequestHandler?.apply {
if (cookies != null) {
refreshCookies(cookies)
} else {
val panelistKey = PanelistHandler.getPanelistKey(activity)
val panelistKey = PanelistHandler.getPanelistKey(context)
if (onlyPanelist && panelistKey == TagStringsAndValues.NO_PANELIST_ID) {
fatalError("Mobile Application Tagging Framework Failed to initiate - " +
"Panelist Id was not found, it must exist if only panelist tracking is active")
fatalError(
"Mobile Application Tagging Framework Failed to initiate - " +
"Panelist Id was not found, it must exist if only panelist tracking is active"
)
return
}
refreshCookies(panelistKey)
Expand Down Expand Up @@ -128,14 +156,22 @@ internal class TSMobileAnalyticsBackend : TSMobileAnalytics {


private fun initTags(
activity: ComponentActivity,
context: Context,
cpID: String,
applicationName: String,
onlyPanelist: Boolean,
isWebViewBased: Boolean,
twaInfo: TWAModel
): Boolean {
frameworkInstance = TSMobileAnalyticsBackend(activity, activity, cpID, applicationName, null, onlyPanelist,twaInfo,isWebViewBased)
frameworkInstance = TSMobileAnalyticsBackend(
context,
cpID,
applicationName,
null,
onlyPanelist,
twaInfo,
isWebViewBased
)
log("Mobile Application Tagging Framework initiated with the following values " +
"\nCPID: $cpID\nApplication name: $applicationName\nOnly panelist tracking : $onlyPanelist")
return true
Expand All @@ -145,7 +181,7 @@ internal class TSMobileAnalyticsBackend : TSMobileAnalytics {
* Sends the app start event
*/
private fun sendAppStartEvent() {
if (frameworkInstance ==null) {
if (frameworkInstance == null) {
log("Cannot create app start event")
return
}
Expand Down
Loading

0 comments on commit 32d78d9

Please sign in to comment.