├── .gitignore
├── .idea
├── assetWizardSettings.xml
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── misc.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── smartlook
│ │ └── consentsdksample
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── smartlook
│ │ │ └── consentsdksample
│ │ │ ├── App.kt
│ │ │ └── ui
│ │ │ └── main
│ │ │ ├── ConsentResultsAdapter.kt
│ │ │ └── MainActivity.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ └── consent_result.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── smartlook
│ └── consentsdksample
│ └── ExampleUnitTest.kt
├── build.gradle
├── consentsdk
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── smartlook
│ │ └── consentsdk
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── smartlook
│ │ │ └── consentsdk
│ │ │ ├── ConsentSDK.kt
│ │ │ ├── data
│ │ │ ├── ConsentFormData.kt
│ │ │ └── ConsentFormItem.kt
│ │ │ ├── helpers
│ │ │ ├── ConsentHelper.kt
│ │ │ ├── SharedPreferencesHelper.kt
│ │ │ └── UtilsHelper.kt
│ │ │ ├── listeners
│ │ │ ├── ConsentItemListener.kt
│ │ │ └── ConsentResultsListener.kt
│ │ │ └── ui
│ │ │ ├── consent
│ │ │ ├── ConsentFormBase.kt
│ │ │ ├── ConsentFormItemView.kt
│ │ │ ├── activity
│ │ │ │ └── ConsentFormActivity.kt
│ │ │ ├── dialog
│ │ │ │ ├── ConsentFormDialog.kt
│ │ │ │ └── ConsentFormDialogFragment.kt
│ │ │ └── fragment
│ │ │ │ └── ConsentFormFragment.kt
│ │ │ └── customViews
│ │ │ └── LeftSideSwitch.kt
│ └── res
│ │ ├── drawable
│ │ └── ic_info_link.xml
│ │ ├── layout
│ │ ├── consent_activity.xml
│ │ ├── consent_dialog.xml
│ │ ├── consent_item.xml
│ │ └── left_side_switch.xml
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ └── dimens.xml
│ └── test
│ └── java
│ └── com
│ └── smartlook
│ └── consentsdk
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots
├── consent_form_activity.png
├── consent_form_activity_styled.png
├── consent_form_dialog.png
└── consent_form_dialog_styled.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 | *.aab
5 |
6 | # Files for the ART/Dalvik VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Generated files
13 | bin/
14 | gen/
15 | out/
16 |
17 | # Gradle files
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | # Android Studio captures folder
34 | captures/
35 |
36 | # User-specific stuff
37 | .idea/**/workspace.xml
38 | .idea/**/tasks.xml
39 | .idea/**/usage.statistics.xml
40 | .idea/**/dictionaries
41 | .idea/**/shelf
42 | *.iml
43 |
44 | # Generated files
45 | .idea/**/contentModel.xml
46 |
47 | # Sensitive or high-churn files
48 | .idea/**/dataSources/
49 | .idea/**/dataSources.ids
50 | .idea/**/dataSources.local.xml
51 | .idea/**/sqlDataSources.xml
52 | .idea/**/dynamic.xml
53 | .idea/**/uiDesigner.xml
54 | .idea/**/dbnavigator.xml
55 |
56 | # Gradle
57 | .idea/**/gradle.xml
58 | .idea/**/libraries
59 |
60 | # Gradle and Maven with auto-import
61 | .idea/modules.xml
62 | .idea/*.iml
63 | .idea/modules
64 |
65 | # CMake
66 | cmake-build-*/
67 |
68 | # Mongo Explorer plugin
69 | .idea/**/mongoSettings.xml
70 |
71 | # File-based project format
72 | *.iws
73 |
74 | # IntelliJ
75 | out/
76 |
77 | # mpeltonen/sbt-idea plugin
78 | .idea_modules/
79 |
80 | # JIRA plugin
81 | atlassian-ide-plugin.xml
82 |
83 | # Cursive Clojure plugin
84 | .idea/replstate.xml
85 |
86 | # Crashlytics plugin (for Android Studio and IntelliJ)
87 | com_crashlytics_export_strings.xml
88 | crashlytics.properties
89 | crashlytics-build.properties
90 | fabric.properties
91 |
92 | # Editor-based Rest Client
93 | .idea/httpRequests
94 |
95 | # Android studio 3.1+ serialized cache file
96 | .idea/caches/build_file_checksums.ser
97 |
98 | # Sonarlint plugin
99 | .idea/sonarlint
100 |
101 | # Keystore files
102 | *.jks
103 | *.keystore
104 |
105 | # External native build folder generated in Android Studio 2.2 and later
106 | .externalNativeBuild
107 |
108 | # Google Services (e.g. APIs or Firebase)
109 | google-services.json
110 |
111 | # Freeline
112 | freeline.py
113 | freeline/
114 | freeline_project_description.json
115 |
116 | # fastlane
117 | fastlane/report.xml
118 | fastlane/Preview.html
119 | fastlane/screenshots
120 | fastlane/test_output
121 | fastlane/readme.md
122 |
--------------------------------------------------------------------------------
/.idea/assetWizardSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Smartlook
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Consent SDK for Android
2 |
3 | Obtaining explicit user consent regarding the gathering analytics data in an app, or with processing user’s personal data is an important part of establishing user trust and seamless user experience.
4 |
5 | Although implementing some form to obtain user consents and store them for further reference seems pretty straightforward, digging into it reveals (as usual with “simple tasks”) many programming and design details that must be implemented, which are not the core functionality of your app.
6 |
7 |
8 |
9 | ## Consent SDK main functionality
10 |
11 | - Provides configurable __consent form__ that can be displayed as:
12 | - __Dialog__
13 | - __FragmentDialog__(persists orientation changes)
14 | - __Activity__
15 | - __Fragment__
16 | - Stores consent results and provides access methods.
17 |
18 | ## Installation
19 | Add the following dependency in your app's build.gradle:
20 |
21 | ```
22 | implementation 'com.smartlook:consent:1.0'
23 | ```
24 |
25 | And add the following in your project's build.gradle:
26 |
27 | ```
28 | allprojects {
29 | repositories {
30 | maven {
31 | url "https://sdk.smartlook.com/android/release"
32 | }
33 | }
34 | }
35 | ```
36 |
37 | ## How to use
38 |
39 | Firstly you need to instantiate `ConsentSDK` with `applicationContext`.
40 |
41 | ```
42 | val consentSDK = ConsentSDK(applicationContext)
43 | ```
44 |
45 | This object is going to be used for all interactions with ConsentSDK.
46 |
47 | ### Consent form data
48 |
49 | Before you can display consent form you need to prepare consent form data.
50 |
51 | ```
52 | companion object {
53 | const val CONSENT_1_KEY = "consent_1_key"
54 | const val CONSENT_2_KEY = "consent_2_key"
55 | }
56 |
57 | ...
58 |
59 | val consentFormItems = arrayOf(
60 | ConsentFormItem(
61 | consentKey = CONSENT_1_KEY,
62 | required = true,
63 | description = getString(R.string.consent_1_description),
64 | link = null
65 | ),
66 | ConsentFormItem(
67 | consentKey = CONSENT_2_KEY,
68 | required = false,
69 | description = getString(R.string.consent_2_description),
70 | link = getString(R.string.consent_2_link)
71 | )
72 | )
73 |
74 | val consentFormData = ConsentFormData(
75 | titleText = getString(R.string.consent_form_title),
76 | descriptionText = getString(R.string.consent_form_description),
77 | confirmButtonText = getString(R.string.consent_form_confirm_button_text),
78 | consentFormItems = consentFormItems)
79 |
80 | ```
81 |
82 | Array `consentFormItems` represents consents we want the user to grant us. Every item needs to have:
83 | - unique `consentKey` that represents it and can be used to obtain grant result for this consent.
84 | - `required` flag. If this flag is set to `true` user cannot successfully finish the consent form without granting this consent.
85 | - `descriptionText` informing the user about the consent.
86 | - `link` (optional) that lets the user open a web page (URL) with more info.
87 |
88 | Object `consentFormData` provides all needed data for displaying consent form.
89 |
90 | ### Showing consent form on `Dialog`
91 | A most simple and straight-forward way of displaying consent form is on `Dialog`. It has one __drawback__, this way we __cannot__ properly persist user data on orientation change. Use this if you have locked screen orientation.
92 |
93 | ```
94 | consentSDK.showConsentFormDialog(consentFormData, object : ConsentResultsListener {
95 | override fun onConsentResults(consentResults: HashMap) {
96 | // consent form result here
97 | }
98 | })
99 | ```
100 |
101 | ### Showing consent form on `DialogFragment`
102 | By using `DialogFragment` SDK can properly handle orientation changes.
103 |
104 | ```
105 | consentSDK.showConsentFormDialogFragment(/, consentFormData)
106 | ```
107 |
108 | The first parameter of `showConsentFormDialogFragment` accepts `Activity` or `Fragment` reference so you can call it from both.
109 | Your calling `Activity` or `Fragment` __must__ implement ConsentResultsListener.
110 |
111 | ```
112 | class SampleActivity : AppCompatActivity(), ConsentResultsListener {
113 |
114 | ...
115 |
116 | override fun onConsentResults(consentResults: HashMap) {
117 | // consent form result here
118 | }
119 | }
120 | ```
121 |
122 | ### Starting consent form `Activity`
123 |
124 | ```
125 | class SampleActivity : AppCompatActivity() {
126 |
127 | companion object {
128 | const val CONSENT_REQUEST_CODE = 10001
129 | }
130 |
131 | ...
132 |
133 | consentSDK.startConsentFormActivity(this, consentFormData, CONSENT_REQUEST_CODE)
134 |
135 | ...
136 |
137 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
138 | if (requestCode == CONSENT_REQUEST_CODE) {
139 | if (resultCode == Activity.RESULT_OK) {
140 | val consentResults = consentSDK.parseOutConsentResults(data)
141 | } else {
142 | // user didnt confirm the form (back press)
143 | }
144 | }
145 | }
146 | }
147 | ```
148 |
149 | Consent form `Activity` is started "for a result" so to get a result you need to implement `onActivityResult` method in your `Activity`.
150 |
151 | ### Creating conset form `Fragment`
152 | Method `createConsentFormFragment` lets you create `Fragment` with consent form. Example usage might look something like this:
153 |
154 | ```
155 | const val TAG = "unique_fragment_tag"
156 |
157 | ...
158 |
159 | with(supportFragmentManager) {
160 | beginTransaction()
161 | .replace(R.id.fragment_placeholder, consentSDK.createConsentFormFragment(consentFormData), TAG)
162 | .commit()
163 | executePendingTransactions()
164 | }
165 | ```
166 |
167 | `ConsentResultsListener` can be registered like this:
168 |
169 | ```
170 | val consentFormFragment = supportFragmentManager.findFragmentByTag(TAG) as ConsentFormFragment
171 | consentFormFragment.registerConsentResultsListener(object : ConsentResultsListener {
172 | override fun onConsentResults(consentResults: HashMap) {
173 | // Consent form result here
174 | }
175 | })
176 | ```
177 |
178 | ### Consent results
179 | When user sucessfully finishes consent form you gonna get `consentResult`. It is a `HashMap` in which:
180 | - `key` == `consentKey`
181 | - `value` represents `consentResult`:
182 | - `true` consent was granted.
183 | - `false` consent was rejected.
184 |
185 | ### Are consent results stored?
186 | SDK method `areConsentResultsStored()` can be used to determine if the user has already successfully filled consent form and results were stored.
187 |
188 | ### Obtaining consent
189 |
190 | If you want to obtain a grant result for given conset (identified by unique `consentKey`) you can do it like this:
191 |
192 | ```
193 | val consentResult = consentSDK.loadConsetResult(consentKey)
194 | ```
195 |
196 | If `consentResult` is:
197 | - `true` consent was granted.
198 | - `false` consent was rejected.
199 | - `null` not defined.
200 |
201 | ## Styling
202 |
203 |
204 |
205 | You can define custom `style` for the consent form. All configurable attributes are listed in the table below.
206 |
207 | | Attribute | Description |
208 | |:-------------------------:|:------------------------------------------------:|
209 | | colorAccent | Confirm button, link icons and `Switches` color. |
210 | | cf_textColor | Description text and form item texts color. |
211 | | cf_titleTextColor | Title text color. |
212 | | cf_confirmButtonTextColor | Confirm button text color. |
213 | | cf_backgroundColor | Form background color. |
214 | | cf_dividerColor | Form item list divider color. |
215 |
216 | ### `Dialog`/`FragmentDialog`
217 |
218 | In `styles.xml` define custom Dialog style:
219 |
220 | ```
221 |
229 | ```
230 |
231 | Then add the style reference to `showConsentFormDialog`/`showConsentFormDialogFragment` method like this:
232 |
233 | ```
234 | // Dialog
235 | consentSDK.showConsentFormDialog(this, consentFormData, R.style.DialogStyle, listener)
236 |
237 | // DialogFragment
238 | consentSDK.showConsentFormDialogFragment(this, consentFormData, R.style.DialogStyle)
239 | ```
240 |
241 | ### `Activity`
242 |
243 | In `styles.xml` define custom Activity style:
244 |
245 | ```
246 |
254 | ```
255 |
256 | Then add the style reference to `startConsentFormActivity` method like this:
257 |
258 | ```
259 | consentSDK.startConsentFormActivity(this, consentFormData, CONSENT_REQUEST_CODE, R.style.ActivityStyle)
260 | ```
261 |
262 | ### Fragment
263 |
264 | In `styles.xml` define custom Fragment style:
265 |
266 | ```
267 |
275 | ```
276 |
277 | Then add the style reference to `startConsentFormActivity` method like this:
278 |
279 | ```
280 | consentSDK.createConsentFormFragment(consentFormData, R.style.FragmentStyle)
281 | ```
282 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | androidExtensions {
6 | experimental = true
7 | }
8 |
9 | android {
10 | compileSdkVersion 28
11 | defaultConfig {
12 | applicationId "com.smartlook.consentsdksample"
13 | minSdkVersion 16
14 | targetSdkVersion 28
15 | versionCode 1
16 | versionName "1.0"
17 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
18 | }
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(dir: 'libs', include: ['*.jar'])
29 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
30 | implementation 'com.android.support:appcompat-v7:28.0.0'
31 | implementation "com.android.support:design:28.0.0"
32 | testImplementation 'junit:junit:4.12'
33 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
34 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
35 |
36 | compile project(':consentsdk')
37 | }
38 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/smartlook/consentsdksample/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdksample
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.smartlook.consentsdksample", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smartlook/consentsdksample/App.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdksample
2 |
3 | import android.app.Application
4 | import com.smartlook.consentsdk.ConsentSDK
5 |
6 | class App: Application() {
7 |
8 | companion object {
9 | lateinit var consentSDK: ConsentSDK
10 | }
11 |
12 | override fun onCreate() {
13 | super.onCreate()
14 |
15 | consentSDK = ConsentSDK(applicationContext)
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/smartlook/consentsdksample/ui/main/ConsentResultsAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdksample.ui.main
2 |
3 | import android.content.Context
4 | import android.graphics.Color
5 | import android.support.v7.widget.RecyclerView
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import com.smartlook.consentsdksample.R
10 | import kotlinx.android.extensions.LayoutContainer
11 | import kotlinx.android.synthetic.main.consent_result.view.*
12 |
13 | class ConsentResultsAdapter(val context: Context,
14 | private var consentResults: HashMap) : RecyclerView.Adapter() {
15 |
16 | private var consentKeys = consentResults.keys.toList()
17 |
18 | /* Public methods *****************************************************************************/
19 |
20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ConsentResultVH {
21 | return ConsentResultVH(LayoutInflater.from(context).inflate(R.layout.consent_result, parent, false))
22 | }
23 |
24 | override fun onBindViewHolder(holder: ConsentResultVH, position: Int) {
25 | holder.bindConsentResult(consentKeys[position], consentResults[consentKeys[position]])
26 | }
27 |
28 | override fun getItemCount() = consentResults.size
29 |
30 |
31 | /* View holders *******************************************************************************/
32 |
33 | inner class ConsentResultVH(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer {
34 | fun bindConsentResult(consentKey: String, grantResult: Boolean?) {
35 |
36 | containerView.consent_key.text = consentKey
37 | containerView.grand_result.text = grantResultText(grantResult)
38 | containerView.grand_result.setTextColor(grantResultColor(grantResult))
39 | }
40 |
41 | private fun grantResultText(grantResult: Boolean?): String {
42 | return when(grantResult) {
43 | true -> "GRANTED"
44 | false -> "REJECTED"
45 | null -> "UNDEFINED"
46 | }
47 | }
48 |
49 | private fun grantResultColor(grantResult: Boolean?): Int {
50 | return when(grantResult) {
51 | true -> Color.GREEN
52 | false -> Color.RED
53 | null -> Color.GRAY
54 | }
55 | }
56 | }
57 |
58 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/smartlook/consentsdksample/ui/main/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdksample.ui.main
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import android.support.v7.app.AppCompatActivity
7 | import android.support.v7.widget.LinearLayoutManager
8 | import com.smartlook.consentsdk.data.ConsentFormData
9 | import com.smartlook.consentsdk.data.ConsentFormItem
10 | import com.smartlook.consentsdk.listeners.ConsentResultsListener
11 | import com.smartlook.consentsdk.ui.consent.fragment.ConsentFormFragment
12 | import com.smartlook.consentsdksample.App
13 | import com.smartlook.consentsdksample.R
14 | import kotlinx.android.synthetic.main.activity_main.*
15 |
16 | class MainActivity : AppCompatActivity(), ConsentResultsListener {
17 |
18 | companion object {
19 | const val CONSENT_1_KEY = "consent_1_key"
20 | const val CONSENT_2_KEY = "consent_2_key"
21 |
22 | const val CONSENT_REQUEST_CODE = 10001
23 |
24 | const val CONSENT_FORM_FRAGMENT_TAG = "consent_form_fragment"
25 | }
26 |
27 | override fun onCreate(savedInstanceState: Bundle?) {
28 | super.onCreate(savedInstanceState)
29 | setContentView(R.layout.activity_main)
30 |
31 | prepareConsentFormData().let {
32 | displayConsentResults(loadConsentResults(it.consentFormItems))
33 | handleShowDialog(it)
34 | handleShowFragmentDialog(it)
35 | handleStartConsentActivity(it)
36 | handleShowFragment(it)
37 | }
38 | }
39 |
40 | private fun loadConsentResults(consentFormItems: Array): HashMap {
41 | return hashMapOf().apply {
42 | consentFormItems.forEach {
43 | put(it.consentKey, App.consentSDK.loadConsentResult(it.consentKey))
44 | }
45 | }
46 | }
47 |
48 | // Getting result from DialogFragment
49 | override fun onConsentResults(consentResults: HashMap) {
50 | displayConsentResults(consentResults as HashMap)
51 | }
52 |
53 | // Getting result from activity
54 | override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
55 | if (requestCode == CONSENT_REQUEST_CODE) {
56 | if (resultCode == Activity.RESULT_OK) {
57 | displayConsentResults(App.consentSDK.parseOutConsentResults(data) as HashMap)
58 | } else {
59 | // consent form not filled successfully
60 | }
61 | }
62 | }
63 |
64 | private fun prepareConsentFormData(): ConsentFormData {
65 | return ConsentFormData(
66 | titleText = getString(R.string.consent_form_title),
67 | descriptionText = getString(R.string.consent_form_description),
68 | confirmButtonText = getString(R.string.consent_form_confirm_button_text),
69 | consentFormItems = prepareConsentFormItems()
70 | )
71 | }
72 |
73 | private fun prepareConsentFormItems(): Array {
74 | return arrayOf(
75 | ConsentFormItem(
76 | consentKey = CONSENT_1_KEY,
77 | required = true,
78 | description = getString(R.string.consent_1_description),
79 | link = null
80 | ),
81 | ConsentFormItem(
82 | consentKey = CONSENT_2_KEY,
83 | required = false,
84 | description = getString(R.string.consent_2_description),
85 | link = getString(R.string.consent_2_link)
86 | )
87 | )
88 | }
89 |
90 | private fun handleStartConsentActivity(consentFormData: ConsentFormData) {
91 | start_activity.setOnClickListener {
92 | App.consentSDK.startConsentFormActivity(this, consentFormData, CONSENT_REQUEST_CODE, R.style.ActivityStyle)
93 | }
94 | }
95 |
96 | private fun handleShowFragmentDialog(consentFormData: ConsentFormData) {
97 | show_dialog_fragment.setOnClickListener {
98 | App.consentSDK.showConsentFormDialogFragment(this, consentFormData, R.style.DialogStyle)
99 | }
100 | }
101 |
102 | private fun handleShowDialog(consentFormData: ConsentFormData) {
103 | show_dialog.setOnClickListener {
104 | App.consentSDK.showConsentFormDialog(this, consentFormData, object : ConsentResultsListener {
105 | override fun onConsentResults(consentResults: HashMap) {
106 | displayConsentResults(consentResults as HashMap)
107 | }
108 | })
109 | }
110 | }
111 |
112 | private fun handleShowFragment(consentFormData: ConsentFormData) {
113 | show_fragment.setOnClickListener {
114 | with(supportFragmentManager) {
115 | beginTransaction()
116 | .replace(R.id.fragment_placeholder, App.consentSDK.createConsentFormFragment(consentFormData, R.style.ActivityStyle), CONSENT_FORM_FRAGMENT_TAG)
117 | .commit()
118 | executePendingTransactions()
119 | }
120 |
121 | show_fragment.isEnabled = false
122 |
123 | with(supportFragmentManager.findFragmentByTag(CONSENT_FORM_FRAGMENT_TAG) as ConsentFormFragment) {
124 | registerConsentResultsListener(createConsentFormFragmentResultsListener())
125 | }
126 | }
127 |
128 | }
129 |
130 | private fun createConsentFormFragmentResultsListener(): ConsentResultsListener {
131 | return object : ConsentResultsListener {
132 | override fun onConsentResults(consentResults: HashMap) {
133 | displayConsentResults(consentResults as HashMap)
134 |
135 | with(supportFragmentManager.beginTransaction()) {
136 | remove(supportFragmentManager.findFragmentByTag(CONSENT_FORM_FRAGMENT_TAG) as ConsentFormFragment)
137 | commit()
138 | }
139 |
140 | show_fragment.isEnabled = true
141 | }
142 | }
143 | }
144 |
145 | private fun displayConsentResults(consentResults: HashMap) {
146 | with(consent_results) {
147 | hasFixedSize()
148 | layoutManager = LinearLayoutManager(this@MainActivity)
149 | adapter = ConsentResultsAdapter(context!!, consentResults)
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
20 |
21 |
27 |
28 |
34 |
35 |
41 |
42 |
48 |
49 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/consent_result.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smartlook/android-consent-sdk/04da38353f02b1566d358dd517dc7967bc9bc665/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #1179F4
4 | #1179F4
5 | #1179F4
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Consent SDK sample
3 |
4 |
5 | Show Dialog
6 | Show DialogFragment
7 | Start activity
8 | Show fragment
9 |
10 |
11 | Consent form
12 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam feugiat,turpis at pulvinar vulputate, erat libero tristique tellus.\n\nFusce nibh. Duis viverra diam non justo. Proin in tellus sit amet nibh dignissim sagittis. Integer tempor. Pellentesque arcu.\n\nNam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime.
13 | This is my will
14 |
15 |
16 | Quisque tincidunt scelerisque libero. Praesent id justo in neque elementum ultrices.
17 |
18 |
19 | Curabitur vitae diam non enim vestibulum interdum. Fusce tellus. Cras pede libero, dapibus nec, pretium sit amet, tempor quis.
20 | https://www.smartlook.com/
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
19 |
20 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/test/java/com/smartlook/consentsdksample/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdksample
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.21'
5 | repositories {
6 | google()
7 | jcenter()
8 |
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.3.1'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 |
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
--------------------------------------------------------------------------------
/consentsdk/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/consentsdk/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android-extensions'
3 | apply plugin: 'kotlin-android'
4 |
5 | android {
6 | compileSdkVersion 28
7 |
8 |
9 |
10 | defaultConfig {
11 | minSdkVersion 16
12 | targetSdkVersion 28
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
17 |
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 |
27 | }
28 |
29 | dependencies {
30 | implementation fileTree(dir: 'libs', include: ['*.jar'])
31 |
32 | implementation 'com.android.support:appcompat-v7:28.0.0'
33 | testImplementation 'junit:junit:4.12'
34 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
35 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
36 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
37 | implementation "com.android.support:recyclerview-v7:28.0.0"
38 | }
39 | repositories {
40 | mavenCentral()
41 | }
42 |
--------------------------------------------------------------------------------
/consentsdk/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/consentsdk/src/androidTest/java/com/smartlook/consentsdk/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.assertEquals;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.smartlook.consentsdk.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/consentsdk/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/ConsentSDK.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk
2 |
3 | import android.app.Activity
4 | import android.content.Context
5 | import android.content.ContextWrapper
6 | import android.content.Intent
7 | import android.support.annotation.StyleRes
8 | import android.support.v4.app.Fragment
9 | import android.support.v4.app.FragmentActivity
10 | import com.smartlook.consentsdk.data.ConsentFormData
11 | import com.smartlook.consentsdk.helpers.ConsentHelper
12 | import com.smartlook.consentsdk.helpers.SharedPreferencesHelper
13 | import com.smartlook.consentsdk.listeners.ConsentResultsListener
14 | import com.smartlook.consentsdk.ui.consent.activity.ConsentFormActivity
15 | import com.smartlook.consentsdk.ui.consent.dialog.ConsentFormDialog
16 | import com.smartlook.consentsdk.ui.consent.dialog.ConsentFormDialogFragment
17 | import com.smartlook.consentsdk.ui.consent.fragment.ConsentFormFragment
18 |
19 | class ConsentSDK(applicationContext: Context) : ContextWrapper(applicationContext) {
20 |
21 | companion object {
22 | private const val CONSENT_RESULT_STORED = "consent_result_stored"
23 | }
24 |
25 | private val sharedPreferences = SharedPreferencesHelper(this)
26 |
27 | /**
28 | * Load consent granting result from preferences.
29 | *
30 | * @param consentKey Unique key identifying consent.
31 | * @return TRUE if consent was granted, FALSE if it was refused and null if not defined.
32 | */
33 | fun loadConsentResult(consentKey: String): Boolean? {
34 | return if (areConsentResultsStored()) {
35 | sharedPreferences.loadBoolean(consentKey)
36 | } else {
37 | null
38 | }
39 | }
40 |
41 | /**
42 | * Save consent granting result to preferences.
43 | *
44 | * @param consentKey Unique key identifying consent.
45 | * @param grantResult TRUE if consent was granted, FALSE if it was refused.
46 | */
47 | fun saveConsentResult(consentKey: String,
48 | grantResult: Boolean) =
49 | sharedPreferences.saveBoolean(consentKey, grantResult)
50 |
51 | /**
52 | * Check if user has seen and successfully filled consent form.
53 | *
54 | * @return TRUE if user has seen and successfully filled consent form.
55 | */
56 | fun areConsentResultsStored() = sharedPreferences.loadBoolean(CONSENT_RESULT_STORED)
57 |
58 | /**
59 | * Store information that user filled consent form successfully.
60 | */
61 | fun setConsentResultsStored() = sharedPreferences.saveBoolean(CONSENT_RESULT_STORED, true)
62 |
63 | /**
64 | * Display consent form on Dialog. If you want to correctly persist on orientation change use
65 | * showConsentFormDialogFragment().
66 | *
67 | * @param activity Calling Activity reference.
68 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
69 | * @param consentResultsListener Callback called on successful fill of consent form (@see ConsentResultsListener).
70 | */
71 | fun showConsentFormDialog(activity: Activity,
72 | consentFormData: ConsentFormData,
73 | consentResultsListener: ConsentResultsListener) =
74 | ConsentFormDialog(activity, consentFormData, consentResultsListener).show()
75 |
76 | /**
77 | * Display consent form on Dialog. If you want to correctly persist on orientation change use
78 | * showConsentFormDialogFragment().
79 | *
80 | * @param activity Calling Activity reference.
81 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
82 | * @param consentResultsListener Callback called on successful fill of consent form (@see ConsentResultsListener).
83 | * @param styleId Reference to style resource. Can be used to style Dialog.
84 | */
85 | fun showConsentFormDialog(activity: Activity,
86 | consentFormData: ConsentFormData,
87 | @StyleRes styleId: Int,
88 | consentResultsListener: ConsentResultsListener) =
89 | ConsentFormDialog(activity, consentFormData, styleId, consentResultsListener).show()
90 |
91 | /**
92 | * Display consent form on DialogFragment.
93 | *
94 | * @param activity Calling Activity reference. This Activity needs to implement ConsentResultsListener.
95 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
96 | */
97 | fun showConsentFormDialogFragment(activity: FragmentActivity,
98 | consentFormData: ConsentFormData) {
99 | ConsentFormDialogFragment.show(activity, consentFormData)
100 | }
101 |
102 | /**
103 | * Display consent form on DialogFragment.
104 | *
105 | * @param activity Calling Activity reference. This Activity needs to implement ConsentResultsListener.
106 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
107 | * @param styleId Reference to style resource. Can be used to style DialogFragment.
108 | */
109 | fun showConsentFormDialogFragment(activity: FragmentActivity,
110 | consentFormData: ConsentFormData,
111 | @StyleRes styleId: Int) {
112 | ConsentFormDialogFragment.show(activity, consentFormData, styleId)
113 | }
114 |
115 | /**
116 | * Display consent form on DialogFragment.
117 | *
118 | * @param fragment Calling Fragment reference. This Fragment needs to implement ConsentResultsListener.
119 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
120 | */
121 | fun showConsentFormDialogFragment(fragment: Fragment,
122 | consentFormData: ConsentFormData) {
123 | ConsentFormDialogFragment.show(fragment, consentFormData)
124 | }
125 |
126 | /**
127 | * Display consent form on DialogFragment.
128 | *
129 | * @param fragment Calling Fragment reference. This Fragment needs to implement ConsentResultsListener.
130 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
131 | * @param styleId Reference to style resource. Can be used to style DialogFragment.
132 | */
133 | fun showConsentFormDialogFragment(fragment: Fragment,
134 | consentFormData: ConsentFormData,
135 | @StyleRes styleId: Int) {
136 | ConsentFormDialogFragment.show(fragment, consentFormData, styleId)
137 | }
138 |
139 | /**
140 | * Display consent form Activity.
141 | *
142 | * @param activity Calling Activity reference. This Activity needs to implement onActivityResult to get result.
143 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
144 | * @param requestCode Unique request code used in onActivityResult to determine corresponding result.
145 | */
146 | fun startConsentFormActivity(activity: Activity,
147 | consentFormData: ConsentFormData,
148 | requestCode: Int) =
149 | ConsentFormActivity.start(activity, consentFormData, requestCode)
150 |
151 | /**
152 | * Display consent form Activity.
153 | *
154 | * @param activity Calling Activity reference. This Activity needs to implement onActivityResult to get result.
155 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
156 | * @param requestCode Unique request code used in onActivityResult to determine corresponding result.
157 | * @param styleId Reference to style resource. Can be used to style Activity.
158 | */
159 | fun startConsentFormActivity(activity: Activity,
160 | consentFormData: ConsentFormData,
161 | requestCode: Int,
162 | @StyleRes styleId: Int) =
163 | ConsentFormActivity.start(activity, consentFormData, requestCode, styleId)
164 |
165 | /**
166 | * Parse out consentResults HashMap from activity result.
167 | *
168 | * @param data Intent containing consentResults.
169 | */
170 | fun parseOutConsentResults(data: Intent?): HashMap {
171 | ConsentHelper.restoreConsentResults(data?.extras).let {
172 | return it ?: throw UnknownError()
173 | }
174 | }
175 |
176 | /**
177 | * Create instance of consent form Fragment. To register ConsentResultsListener you need to call
178 | * registerConsentResultsListener().
179 | *
180 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
181 | */
182 | fun createConsentFormFragment(consentFormData: ConsentFormData) = ConsentFormFragment.newInstance(consentFormData)
183 |
184 | /**
185 | * Create instance of consent form Fragment. To register ConsentResultsListener you need to call
186 | * registerConsentResultsListener().
187 | *
188 | * @param consentFormData Data object containing all needed info display the form (@see ConsentFormData).
189 | * @param styleId Reference to style resource. Can be used to style Fragment.
190 | */
191 | fun createConsentFormFragment(consentFormData: ConsentFormData,
192 | @StyleRes styleId: Int) = ConsentFormFragment.newInstance(consentFormData, styleId)
193 |
194 | }
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/data/ConsentFormData.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.data
2 |
3 | import android.os.Bundle
4 | import java.io.Serializable
5 |
6 | data class ConsentFormData(val titleText: String,
7 | val descriptionText: String,
8 | val confirmButtonText: String,
9 | val consentFormItems: Array) : Serializable {
10 |
11 | companion object {
12 | private const val CONSENT_EXTRA = "CONSENT_EXTRA"
13 |
14 | fun constructFromBundle(bundle: Bundle?): ConsentFormData? {
15 | return if (bundle != null && bundle.containsKey(CONSENT_EXTRA)) {
16 | bundle.getSerializable(CONSENT_EXTRA) as ConsentFormData
17 | } else {
18 | null
19 | }
20 | }
21 | }
22 |
23 | fun createBundle() = Bundle().apply { putSerializable(CONSENT_EXTRA, this@ConsentFormData) }
24 | }
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/data/ConsentFormItem.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.data
2 |
3 | import java.io.Serializable
4 |
5 | data class ConsentFormItem(val consentKey: String,
6 | val required: Boolean,
7 | val description: String,
8 | val link: String?) : Serializable
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/helpers/ConsentHelper.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.helpers
2 |
3 | import android.os.Bundle
4 |
5 | object ConsentHelper {
6 |
7 | const val CONSENT_RESULTS_EXTRA = "CONSENT_RESULTS_EXTRA"
8 |
9 | fun storeConsentResults(outState: Bundle, consentResults: HashMap) {
10 | outState.putSerializable(CONSENT_RESULTS_EXTRA, consentResults)
11 | }
12 |
13 | fun restoreConsentResults(inState: Bundle?): HashMap? {
14 | return if (inState == null || !inState.containsKey(CONSENT_RESULTS_EXTRA)) {
15 | null
16 | } else {
17 | inState.getSerializable(CONSENT_RESULTS_EXTRA) as HashMap
18 | }
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/helpers/SharedPreferencesHelper.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.helpers
2 |
3 | import android.content.Context
4 | import android.content.ContextWrapper
5 | import android.content.SharedPreferences
6 |
7 | class SharedPreferencesHelper(context: Context) : ContextWrapper(context.applicationContext) {
8 |
9 | companion object {
10 | private const val CONSENT_SDI_SHARED_PREFERENCES = "com.smartlook.consentsdk.sharedpreferences"
11 | }
12 |
13 | private val sharedPreferences: SharedPreferences = getSharedPreferences(CONSENT_SDI_SHARED_PREFERENCES, Context.MODE_PRIVATE)
14 |
15 | fun saveBoolean(key: String, state: Boolean) {
16 | sharedPreferences.edit().putBoolean(key, state).apply()
17 | }
18 |
19 | fun loadBoolean(key: String) = sharedPreferences.getBoolean(key, false)
20 |
21 | }
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/helpers/UtilsHelper.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.helpers
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.net.Uri
6 | import android.os.Bundle
7 | import android.support.annotation.StyleRes
8 | import android.util.DisplayMetrics
9 | import android.view.View
10 |
11 |
12 | object UtilsHelper {
13 |
14 | const val STYLE_ID_EXTRA = "style_id_extra"
15 |
16 | fun hideViewIfNull(nullableObject: Any?, view: View) {
17 | view.visibility = if (nullableObject == null) {
18 | View.GONE
19 | } else {
20 | View.VISIBLE
21 | }
22 | }
23 |
24 | fun openLink(context: Context, link: String) {
25 | context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(link)))
26 | }
27 |
28 | fun convertDpToPixel(context: Context, dp: Float): Float {
29 | return dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
30 | }
31 |
32 | fun convertPixelsToDp(context: Context, px: Float): Float {
33 | return px / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
34 | }
35 |
36 | @StyleRes
37 | fun getStyleId(arguments: Bundle?): Int? {
38 | @StyleRes val styleId = arguments?.getInt(STYLE_ID_EXTRA)
39 | return if (styleId == View.NO_ID) {
40 | null
41 | } else {
42 | styleId
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/listeners/ConsentItemListener.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.listeners
2 |
3 | interface ConsentItemListener {
4 | fun onConsentChange(itemIndex: Int, consent: Boolean)
5 | }
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/listeners/ConsentResultsListener.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.listeners
2 |
3 | interface ConsentResultsListener {
4 | fun onConsentResults(consentResults: HashMap)
5 | }
--------------------------------------------------------------------------------
/consentsdk/src/main/java/com/smartlook/consentsdk/ui/consent/ConsentFormBase.kt:
--------------------------------------------------------------------------------
1 | package com.smartlook.consentsdk.ui.consent
2 |
3 | import android.content.ContextWrapper
4 | import android.support.annotation.ColorInt
5 | import android.support.annotation.StyleRes
6 | import android.support.v4.content.ContextCompat
7 | import android.view.View
8 | import android.widget.Button
9 | import android.widget.FrameLayout
10 | import android.widget.LinearLayout
11 | import android.widget.TextView
12 | import com.smartlook.consentsdk.ConsentSDK
13 | import com.smartlook.consentsdk.R
14 | import com.smartlook.consentsdk.data.ConsentFormData
15 | import com.smartlook.consentsdk.data.ConsentFormItem
16 | import com.smartlook.consentsdk.helpers.UtilsHelper
17 | import com.smartlook.consentsdk.listeners.ConsentItemListener
18 |
19 | class ConsentFormBase(
20 | private val consentFormData: ConsentFormData,
21 | private val rootView: View,
22 | private val resultListener: ResultListener,
23 | consentResults: HashMap? = null,
24 | @StyleRes private val styleId: Int? = null) : ContextWrapper(rootView.context) {
25 |
26 | private val consentApi = ConsentSDK(this)
27 | var consentResults: HashMap
28 |
29 | // We are doing it oldschool because it works for both dialog and activity
30 | private val tvTitle = rootView.findViewById(R.id.consent_title)
31 | private val tvDescription = rootView.findViewById(R.id.consent_description)
32 | private val lvConsentItemsRoot = rootView.findViewById(R.id.consent_items_root)
33 | private val bConfirm = rootView.findViewById