Skip to content

Commit

Permalink
set up test env for DIA-1716-fix-stuck-pm
Browse files Browse the repository at this point in the history
  • Loading branch information
bohdan-go-wombat committed Jul 14, 2023
1 parent 618c3b6 commit fd52c71
Show file tree
Hide file tree
Showing 10 changed files with 355 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sourcepoint.cmplibrary

import android.content.Context
import android.util.Log
import android.view.View
import com.sourcepoint.cmplibrary.campaign.CampaignManager
import com.sourcepoint.cmplibrary.consent.ClientEventManager
Expand Down Expand Up @@ -419,6 +420,7 @@ internal class SpConsentLibImpl(
inner class JSReceiverDelegate : JSClientLib {

override fun onConsentUIReady(view: View, isFromPM: Boolean) {
Log.i("DIA-1716", "=== JSReceiverDelegate || onConsentUIReady ===")
executor.executeOnMain { spClient.onUIReady(view) }
}

Expand Down Expand Up @@ -447,6 +449,8 @@ internal class SpConsentLibImpl(
}

override fun onError(view: View, errorMessage: String) {
Log.e("DIA-1716", "=== JSReceiverDelegate || onError ===")
Log.e("DIA-1716", "error = $errorMessage")
val ex = RenderingAppException(description = errorMessage)
spClient.onError(ex)
pLogger.error(ex)
Expand All @@ -458,6 +462,7 @@ internal class SpConsentLibImpl(
}

override fun dismiss(view: View) {
Log.i("DIA-1716", "=== JSReceiverDelegate || dismiss ===")
viewManager.removeView(view)
}

Expand Down
5 changes: 5 additions & 0 deletions samples/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ dependencies {
implementation "org.koin:koin-android:$koin_version"
implementation "org.koin:koin-java:$koin_java_version"

implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
implementation "io.reactivex.rxjava2:rxjava:2.2.21"

implementation "com.jakewharton.rxrelay2:rxrelay:2.1.1"

// mockk
androidTestImplementation(Libs.mockkAndroid)

Expand Down
2 changes: 1 addition & 1 deletion samples/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
android:supportsRtl="true"
android:name=".App"
android:theme="@style/AppTheme">
<activity android:name=".MainActivityKotlin">
<activity android:name=".pm_test.PmTestMainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.sourcepoint.app.v6.pm_test

import android.view.View
import com.jakewharton.rxrelay2.BehaviorRelay
import io.reactivex.Observable

interface ConsentManagementPlatform {
fun openFirstLayer(consentGivenCallback: () -> Unit)
fun openPrivacyManager(consentGivenCallback: () -> Unit)
fun dispose()

fun onScreenShown()

val events: Observable<Event>

sealed class Event {

object Finished : Event()

sealed class UiEvent : Event() {

class ViewReady(val view: View) : UiEvent()
class ViewFinished(val view: View) : UiEvent()
}
}

companion object CmpEvents {

// TODO try make internal or protected after removing mock implementation
val consentReadyRelay = BehaviorRelay.create<ConsentType>()

fun consentReadyEvents(): Observable<ConsentType> = consentReadyRelay
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.sourcepoint.app.v6.pm_test

enum class ConsentType {
GDPR, CCPA, OTHER,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.sourcepoint.app.v6.pm_test

import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import com.sourcepoint.app.v6.R
import com.sourcepoint.cmplibrary.util.clearAllData
import io.reactivex.disposables.CompositeDisposable

class PmTestMainActivity : AppCompatActivity() {

private val disposables = CompositeDisposable()

private var counter = 0

private val root by lazy { findViewById<FrameLayout>(R.id.source_point_root) }
private val reloadButton by lazy { findViewById<Button>(R.id.button_reload) }

private var platform: ConsentManagementPlatform? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.pm_test_activity_main)

reloadButton.setOnClickListener {
counter++
Log.i("DIA-1716", "=== reload ===")
Log.d("DIA-1716", "counter = $counter")
loadFLM()
}

loadFLM()
}

private fun loadFLM() {
// for first layer to be loaded each time
clearAllData(applicationContext)

platform?.dispose()
root.removeAllViews()
val new =
SourcePointConsentManagementPlatformImpl(
sourcePointConfig = SourcePointConfig.hardcoded(),
activity = this
)

// only open first layer/load message
new.openFirstLayer({})
disposables.clear()

platform = new

disposables.add(
new.events.subscribe { event ->

when (event) {
is ConsentManagementPlatform.Event.UiEvent -> {
when (event) {
is ConsentManagementPlatform.Event.UiEvent.ViewReady ->
root.addView(event.view)
is ConsentManagementPlatform.Event.UiEvent.ViewFinished ->
root.removeView(event.view)
}

}
is ConsentManagementPlatform.Event.Finished -> {
platform?.dispose()
}
}
}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.sourcepoint.app.v6.pm_test

sealed class SourcePointConfig {

data class Loaded(
val accountId: Int,
val propertyName: String,
val propertyId: Int,
val gdprId: String,
val ccpaId: String
) : SourcePointConfig()

object Empty : SourcePointConfig()


companion object {

fun hardcoded() = Loaded(
accountId = 1789,
propertyName = "badoo.android",
propertyId = 27195,
gdprId = "759246",
ccpaId = "759254"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package com.sourcepoint.app.v6.pm_test

import android.app.Activity
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.View
import androidx.core.os.ConfigurationCompat
import com.jakewharton.rxrelay2.BehaviorRelay
import com.sourcepoint.cmplibrary.NativeMessageController
import com.sourcepoint.cmplibrary.SpClient
import com.sourcepoint.cmplibrary.core.nativemessage.MessageStructure
import com.sourcepoint.cmplibrary.creation.config
import com.sourcepoint.cmplibrary.creation.delegate.spConsentLibLazy
import com.sourcepoint.cmplibrary.exception.CampaignType
import com.sourcepoint.cmplibrary.model.ConsentAction
import com.sourcepoint.cmplibrary.model.MessageLanguage
import com.sourcepoint.cmplibrary.model.PMTab
import com.sourcepoint.cmplibrary.model.exposed.SPConsents
import com.sourcepoint.cmplibrary.model.exposed.SpConfig
import io.reactivex.Observable
import org.json.JSONObject

class SourcePointConsentManagementPlatformImpl(
private val sourcePointConfig: SourcePointConfig.Loaded,
private val activity: Activity,
) : ConsentManagementPlatform {

private var consentCallback: (() -> Unit)? = null

private val handler = Handler(Looper.getMainLooper())

private val eventsRelay = BehaviorRelay.create<ConsentManagementPlatform.Event>()

override val events: Observable<ConsentManagementPlatform.Event> = eventsRelay

private val cmpConfig: SpConfig = config {
accountId = sourcePointConfig.accountId
propertyName = sourcePointConfig.propertyName
messLanguage = getMessageLanguage()
messageTimeout = MESSAGE_TIMEOUT_MS
propertyId = sourcePointConfig.propertyId
+CampaignType.GDPR
+CampaignType.CCPA
}

private val spConsentLib by spConsentLibLazy {
activity = this@SourcePointConsentManagementPlatformImpl.activity
spClient = LocalClient()
spConfig = cmpConfig
}

override fun openFirstLayer(consentGivenCallback: () -> Unit) {
consentCallback = consentGivenCallback
spConsentLib.loadMessage()
}

override fun dispose() {
spConsentLib.dispose()
}

// this 100% of the cases will be called after we initialized the platform by
// spConsentLib.loadMessage()
override fun openPrivacyManager(consentGivenCallback: () -> Unit) {
consentCallback = consentGivenCallback
return when (getConsentType()) {
ConsentType.GDPR -> launchGDPRSettings()
ConsentType.CCPA -> launchCCPASettings()
else -> consentCallback = null
}
}

private fun getMessageLanguage(): MessageLanguage =
ConfigurationCompat.getLocales(activity.resources.configuration).let { localeList ->
if (!localeList.isEmpty) {
localeList[0]
} else null
}.asMessageLanguage()

private fun getConsentType() = getCmpConsentType(activity.applicationContext)

private fun launchGDPRSettings() {
spConsentLib.loadPrivacyManager(
pmId = sourcePointConfig.gdprId,
pmTab = PMTab.PURPOSES,
campaignType = CampaignType.GDPR
)
}

private fun launchCCPASettings() {
spConsentLib.loadPrivacyManager(
pmId = sourcePointConfig.ccpaId,
pmTab = PMTab.PURPOSES,
campaignType = CampaignType.CCPA
)
}

inner class LocalClient : SpClient {
override fun onAction(view: View, consentAction: ConsentAction): ConsentAction {
return consentAction
}

override fun onConsentReady(consent: SPConsents) {
}

override fun onError(error: Throwable) {
Log.e("DIA-1716", "=== onError ===")
Log.e("DIA-1716", "error = ${error.message}")
handler.post {
consentCallback?.invoke()
eventsRelay.accept(ConsentManagementPlatform.Event.Finished)
}
}

override fun onMessageReady(message: JSONObject) {
Log.d("DIA-1716", "=== onMessageReady ===")
}

override fun onNativeMessageReady(
message: MessageStructure,
messageController: NativeMessageController
) {
Log.d("DIA-1716", "=== onNativeMessageReady ===")
}

override fun onNoIntentActivitiesFound(url: String) {
}

override fun onSpFinished(sPConsents: SPConsents) {
handler.post {
consentCallback?.invoke()
eventsRelay.accept(ConsentManagementPlatform.Event.Finished)
}
val consentType = getConsentType()
ConsentManagementPlatform.consentReadyRelay.accept(consentType)
}

override fun onUIFinished(view: View) {
Log.d("DIA-1716", "=== onUIFinished ===")
eventsRelay.accept(ConsentManagementPlatform.Event.UiEvent.ViewFinished(view))
}

override fun onUIReady(view: View) {
eventsRelay.accept(ConsentManagementPlatform.Event.UiEvent.ViewReady(view))
}
}

override fun onScreenShown() {
}

companion object {
private const val MESSAGE_TIMEOUT_MS = 10_000L
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.sourcepoint.app.v6.pm_test

import android.content.Context
import com.sourcepoint.cmplibrary.exception.CampaignType
import com.sourcepoint.cmplibrary.model.MessageLanguage
import com.sourcepoint.cmplibrary.util.campaignApplies
import java.util.*

internal fun getCmpConsentType(context: Context): ConsentType = when {
campaignApplies(context, CampaignType.GDPR) -> ConsentType.GDPR
campaignApplies(context, CampaignType.CCPA) -> ConsentType.CCPA
else -> ConsentType.OTHER
}

internal fun Locale?.asMessageLanguage(): MessageLanguage = this?.language.let { code ->
MessageLanguage.values().find { it.value.equals(other = code, ignoreCase = true) }
} ?: MessageLanguage.ENGLISH
Loading

0 comments on commit fd52c71

Please sign in to comment.