From ec6f6d00b730aa01aff954ccceed4f6ec775075d Mon Sep 17 00:00:00 2001 From: David Medenjak Date: Fri, 29 Jun 2018 15:30:32 +0200 Subject: [PATCH] Initial commit --- .gitignore | 45 ++++ .travis.yml | 30 +++ README.md | 62 +++++ app/.gitignore | 1 + app/build.gradle | 34 +++ app/proguard-rules.pro | 21 ++ app/src/main/AndroidManifest.xml | 29 +++ app/src/main/assets/bacon_policy.html | 48 ++++ .../gdprpolicysdk/MainActivity.kt | 44 ++++ .../ServicesBroadcastReceiver.kt | 25 ++ .../drawable-v24/ic_launcher_foreground.xml | 34 +++ .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++++ app/src/main/res/layout/activity_main.xml | 14 ++ app/src/main/res/layout/error.xml | 18 ++ app/src/main/res/layout/gdpr_item_service.xml | 27 +++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3056 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5024 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2096 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2858 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4569 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7098 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6464 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10676 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9250 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15523 bytes app/src/main/res/values/colors.xml | 6 + app/src/main/res/values/strings.xml | 7 + app/src/main/res/values/styles.xml | 21 ++ app/src/main/res/xml/gdpr_services.xml | 9 + build.gradle | 30 +++ gradle.properties | 13 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++++++ gradlew.bat | 84 +++++++ library/.gitignore | 1 + library/build.gradle | 119 ++++++++++ library/proguard-rules.pro | 21 ++ library/src/main/AndroidManifest.xml | 14 ++ .../allaboutapps/gdpr/BasePolicyFragment.kt | 16 ++ .../at/allaboutapps/gdpr/GDPRPolicyManager.kt | 201 ++++++++++++++++ .../at/allaboutapps/gdpr/GdprServiceIntent.kt | 25 ++ .../allaboutapps/gdpr/GdprSettingsProvider.kt | 220 ++++++++++++++++++ .../allaboutapps/gdpr/InformationFragment.kt | 42 ++++ .../gdpr/NavigationIconTintHelper.kt | 44 ++++ .../at/allaboutapps/gdpr/OptInFragment.kt | 41 ++++ .../gdpr/OptOutWarningFragment.kt | 43 ++++ .../at/allaboutapps/gdpr/PolicyActivity.kt | 196 ++++++++++++++++ .../allaboutapps/gdpr/PolicyStatusHolder.kt | 17 ++ .../gdpr/PolicyUpdateDialogFragment.kt | 71 ++++++ .../at/allaboutapps/gdpr/TypedValueUtils.kt | 10 + .../allaboutapps/gdpr/UpdateTitleCallback.kt | 12 + .../gdpr/policy/DataPolicyLoadingMethod.kt | 60 +++++ .../gdpr/policy/PolicyFragment.kt | 126 ++++++++++ .../gdpr/policy/PolicyLoadingMethod.kt | 19 ++ .../gdpr/policy/PolicyWebViewClient.kt | 97 ++++++++ .../gdpr/policy/UrlPolicyLoadingMethod.kt | 43 ++++ .../gdpr/services/ServicesPullParser.kt | 117 ++++++++++ .../gdpr/widget/PrivacyPolicySwitch.kt | 125 ++++++++++ .../allaboutapps/gdpr/widget/ServicesView.kt | 62 +++++ .../res/drawable/ic_arrow_back_black_24dp.xml | 9 + .../main/res/drawable/ic_close_black_24dp.xml | 9 + .../res/layout/gdpr_policy_error_loading.xml | 21 ++ .../gdpr_policy_fragment_information.xml | 67 ++++++ .../layout/gdpr_policy_fragment_opt_in.xml | 68 ++++++ .../layout/gdpr_policy_fragment_policy.xml | 27 +++ .../gdpr_policy_fragment_warning_opt_out.xml | 75 ++++++ .../res/layout/gdpr_policy_item_service.xml | 12 + .../layout/widget_privacy_policy_switch.xml | 26 +++ library/src/main/res/values/attrs.xml | 26 +++ .../src/main/res/values/donottranslate.xml | 6 + library/src/main/res/values/strings.xml | 28 +++ library/src/main/res/values/styles.xml | 54 +++++ settings.gradle | 1 + 76 files changed, 3131 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 README.md create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/assets/bacon_policy.html create mode 100644 app/src/main/java/at/allaboutapps/gdprpolicysdk/MainActivity.kt create mode 100644 app/src/main/java/at/allaboutapps/gdprpolicysdk/ServicesBroadcastReceiver.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/error.xml create mode 100644 app/src/main/res/layout/gdpr_item_service.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/main/res/xml/gdpr_services.xml create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 library/.gitignore create mode 100644 library/build.gradle create mode 100644 library/proguard-rules.pro create mode 100644 library/src/main/AndroidManifest.xml create mode 100644 library/src/main/java/at/allaboutapps/gdpr/BasePolicyFragment.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/GDPRPolicyManager.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/GdprServiceIntent.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/GdprSettingsProvider.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/InformationFragment.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/NavigationIconTintHelper.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/OptInFragment.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/OptOutWarningFragment.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/PolicyActivity.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/PolicyStatusHolder.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/PolicyUpdateDialogFragment.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/TypedValueUtils.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/UpdateTitleCallback.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/policy/DataPolicyLoadingMethod.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/policy/PolicyFragment.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/policy/PolicyLoadingMethod.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/policy/PolicyWebViewClient.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/policy/UrlPolicyLoadingMethod.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/services/ServicesPullParser.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/widget/PrivacyPolicySwitch.kt create mode 100644 library/src/main/java/at/allaboutapps/gdpr/widget/ServicesView.kt create mode 100644 library/src/main/res/drawable/ic_arrow_back_black_24dp.xml create mode 100644 library/src/main/res/drawable/ic_close_black_24dp.xml create mode 100644 library/src/main/res/layout/gdpr_policy_error_loading.xml create mode 100644 library/src/main/res/layout/gdpr_policy_fragment_information.xml create mode 100644 library/src/main/res/layout/gdpr_policy_fragment_opt_in.xml create mode 100644 library/src/main/res/layout/gdpr_policy_fragment_policy.xml create mode 100644 library/src/main/res/layout/gdpr_policy_fragment_warning_opt_out.xml create mode 100644 library/src/main/res/layout/gdpr_policy_item_service.xml create mode 100644 library/src/main/res/layout/widget_privacy_policy_switch.xml create mode 100644 library/src/main/res/values/attrs.xml create mode 100644 library/src/main/res/values/donottranslate.xml create mode 100644 library/src/main/res/values/strings.xml create mode 100644 library/src/main/res/values/styles.xml create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0452ea3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Built application files +*.apk +*.ap_ + +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties +release.properties +*.keystore + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Intellij project files +*.iml +*.ipr +*.iws +.idea/ + +# Realm +*.timestamp + +# Windows Image Previews +Thumbs.db + +# OSX +.DS_Store +*.swp +*.lock diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d1c0cf3 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,30 @@ +language: android +jdk: oraclejdk8 +android: + components: + - build-tools-27.0.3 + - android-27 + - extra-google-google_play_services + - extra-google-m2repository + - extra-android-m2repository +install: true +before_script: +- touch local.properties +script: "./gradlew build" +before_cache: +- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock +- rm -fr $HOME/.gradle/caches/*/plugin-resolution/ +cache: + directories: + - "$HOME/.gradle/caches/" + - "$HOME/.gradle/wrapper/" + - "$HOME/.android/build-cache" +deploy: + skip_cleanup: true + provider: script + script: "./gradlew bintrayUpload" + on: + tags: true +env: + global: + secure: fBJ6f9l32u/dIodgYysCsKAqmmV/ZN0WQ8c4Fo/dSaJhx2yZkmg5CgIzKdRjNi+obpWavscoi2TCEzdUhBcb1tmiODTA8K3WL/vfFeFwh90fOiZoaQMFwTMkq1u1AIdv8JwAusGO42A9MYIurDd1zOCdLlQPGG56p+7+vTxbYpR1EkSgSq68XV+Zpb7+zZo3Ejlt2WEzd4ujWDfrLVV0ybfnHB6yPjrp6DjYmfexwv5mrAkuTZnZuA7a7j7TKCArAE/H6bFvn9Y810Iv/WWZbyyP0eCCexEMYm4nIhyTVyjuUEMqnl8U1Mt1A1P+JYT7SlpyyYG6iiHZRPUNvpm9KAfoiuWPl9CxW7Qf5/xvFOUcVhmQ7CeB4vDxM3jRmcYHYGIh3akSAfs+bmhGXLk2Py3sIT2UeUXmYeepS1JB8YwzItg2/qkelS/OJlPmIeYCXcfHueP3OK/p7oXtvm/F/SgYWAikYRNWHp3ZoJ5dtTkm6jQ7m7MrOSnQOhCGR6kyF7TjjlI0VZiozvKFycZhlnW2rS+jvMlIuRZtso6Vmvuz/ZRmIQryY0DLrNIznilb9fSCD4tpgOJAAekB3lbt38Kx9+sofuoOQ8yMYXDiRVlp2pTxLXUShZZjLGyLQM60tam7fE2LoT4AUyjq1Vgy1Xdcu4tZk5oLEznJbbFz1Xg= diff --git a/README.md b/README.md new file mode 100644 index 0000000..dda8df5 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +## Policy Manager Library + +To support some GDPR requirements this library includes a WebView wrapper to show your terms and supplies an interface to update the timestamp when they were last accepted. + +To comply with [Art. 21 GDPR - Right to object](https://gdpr-info.eu/art-21-gdpr/) links in the policy that end with the fragment `#app-opt-out` provide an option to opt-out from tracking done under [Art. 6 (e) or (f)](https://gdpr-info.eu/art-6-gdpr/). + +## Setup + +Start by adding some meta data to your `` tag in the manifest. If your policy is not static you can also supply it later at runtime. + + + + + +Next create a `services.xml` in your `values/xml` directory. + + + + + + + + Description + + + +## Usage + +### Registration + +On your registration you should link to the terms of service that the user has to accept. You can use `PrivacyPolicySwitch` which provides a link next to a switch, or you can implement your own. +You can call `GDPRPolicyManager.instance().getPolicyIntent()` to get an intent to start the Activity. + + + +### Login + +After the login or acceptance it is _your responsibility_ to update the latest saved timestamp. + + GDPRPolicyManager.instance().setPolicyAccepted(true) // if local, uses current timestamp + GDPRPolicyManager.instance().setPolicyAccepted(timestamp) // queried from server + +### Policy Changes + +You should query your server about changes to the policy. Call `manager.updateLatestPolicyTimestamp(timestamp)` to update the cached data. You could do this at every app start, or from a background job. + +In your Activity you can use `manager.shouldShowPolicy()` to check the current status and display a dialog. +You can extend `PolicyUpdateDialogFragment` if you need some further customizations on the dialog design. + + if (manager.shouldShowPolicy()) { + // show dialog to accept / read + PolicyUpdateDialogFragment.newInstance() + .show(supportFragmentManager) + } \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..0c339e3 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "at.allaboutapps.gdprpolicysdk" + minSdkVersion 19 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation project(':library') + + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:27.1.1' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} +repositories { + mavenCentral() +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..cebee0e --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/assets/bacon_policy.html b/app/src/main/assets/bacon_policy.html new file mode 100644 index 0000000..b8579c7 --- /dev/null +++ b/app/src/main/assets/bacon_policy.html @@ -0,0 +1,48 @@ + + +

Bacon Policy

+

+ Bacon ipsum dolor amet bacon meatball shank tenderloin ham. Ham hock landjaeger ham buffalo, + kevin venison tail. Pork loin ball tip filet mignon landjaeger cupim. Venison boudin porchetta, + frankfurter chicken doner ball tip ribeye pork bresaola pork loin. Swine shank filet mignon + bresaola pork chop andouille, pig brisket shankle ham hock capicola picanha biltong shoulder. + Shank alcatra filet mignon, corned beef ribeye turducken burgdoggen ham hock doner fatback + tongue ground round kielbasa tenderloin strip steak. +

+

+ Venison bacon andouille jerky ham spare ribs pork tail cupim. Frankfurter pork chop chicken, + short loin pork spare ribs ham hock ham burgdoggen tri-tip buffalo. Pancetta buffalo boudin ham + hock. Tail tri-tip leberkas tenderloin corned beef pastrami. Pastrami tail jerky, ham flank + brisket pancetta frankfurter turducken. Bresaola bacon pastrami landjaeger capicola buffalo pig + chicken cow ball tip chuck burgdoggen filet mignon frankfurter. +

+

Opt out of bacon

+

+ Bresaola tri-tip leberkas fatback, pork belly pork chop beef ribs brisket alcatra ball tip + andouille bacon shoulder pork t-bone. Pork belly short ribs turkey rump. Pastrami tri-tip pork + chop, chuck boudin short ribs kevin tongue ham doner capicola cupim. Pancetta venison biltong + picanha ground round filet mignon doner shank ribeye prosciutto sirloin. Tri-tip kevin ball tip, + shoulder short ribs ham pork belly chuck ribeye. Kielbasa tenderloin sausage pig chuck venison + jowl biltong frankfurter sirloin. +

+

+ Ham hock biltong shank frankfurter salami. Burgdoggen jowl bacon venison shoulder. Shank salami + brisket drumstick meatball leberkas. Biltong ball tip t-bone, bacon chuck tail ham frankfurter + salami. Tail alcatra frankfurter pork meatball chuck ball tip shank pork loin boudin. Bacon + fatback chicken, ribeye capicola prosciutto cow jerky pancetta. +

+

Become Vegan

+

+ Leberkas andouille ground round tongue. Hamburger bacon picanha tri-tip pork pancetta ham hock + rump andouille, pig flank tail prosciutto landjaeger. Rump salami chicken, pancetta porchetta + pork loin pork chop drumstick meatloaf chuck shank ham frankfurter jowl ground round. Pancetta + pork belly salami, kielbasa fatback landjaeger short loin. Doner jowl meatloaf strip steak, pork + belly brisket cupim jerky bacon tongue pork loin tenderloin chuck porchetta buffalo. +

+

+ Mail: me@me.com
+ Phone: +44 3 14 15 96
+ Wobsite: Google
+

+ + diff --git a/app/src/main/java/at/allaboutapps/gdprpolicysdk/MainActivity.kt b/app/src/main/java/at/allaboutapps/gdprpolicysdk/MainActivity.kt new file mode 100644 index 0000000..5f1c177 --- /dev/null +++ b/app/src/main/java/at/allaboutapps/gdprpolicysdk/MainActivity.kt @@ -0,0 +1,44 @@ +package at.allaboutapps.gdprpolicysdk + +import android.os.Bundle +import android.os.Handler +import android.support.v7.app.AppCompatActivity +import android.widget.CompoundButton +import at.allaboutapps.gdpr.GDPRPolicyManager +import at.allaboutapps.gdpr.PolicyUpdateDialogFragment +import at.allaboutapps.gdpr.widget.PrivacyPolicySwitch + +class MainActivity : AppCompatActivity() { + + private lateinit var manager: GDPRPolicyManager + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContentView(R.layout.activity_main) + + val policySwitch = findViewById(R.id.policy_accepted) + + manager = GDPRPolicyManager.instance() + + //fetch latest policy version from server on a regular basis + Handler().postDelayed({ + // update date of latest changes + manager.updateLatestPolicyTimestamp(System.currentTimeMillis()) + }, 5 * 1000) + + policySwitch.checkedChangeListener = CompoundButton.OnCheckedChangeListener { _, checked -> + } + } + + override fun onStart() { + super.onStart() + + // check if there is s change queued + if (manager.shouldShowPolicy()) { + // show dialog to accept / read + PolicyUpdateDialogFragment.newInstance() + .show(supportFragmentManager) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/at/allaboutapps/gdprpolicysdk/ServicesBroadcastReceiver.kt b/app/src/main/java/at/allaboutapps/gdprpolicysdk/ServicesBroadcastReceiver.kt new file mode 100644 index 0000000..01de906 --- /dev/null +++ b/app/src/main/java/at/allaboutapps/gdprpolicysdk/ServicesBroadcastReceiver.kt @@ -0,0 +1,25 @@ +package at.allaboutapps.gdprpolicysdk + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import at.allaboutapps.gdpr.GdprServiceIntent + +class ServicesBroadcastReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + + + if (GdprServiceIntent.ACTION_SERVICES_CHANGED != intent.action) { + return + } + + val servicesEnabled = intent.getBooleanExtra(GdprServiceIntent.EXTRA_ENABLED, true) + + // + // e.g. FirebaseAnalytics.setAnalyticsCollectionEnabled(servicesEnabled ); + + // + // + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..971ea6b --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/error.xml b/app/src/main/res/layout/error.xml new file mode 100644 index 0000000..b1e8e4d --- /dev/null +++ b/app/src/main/res/layout/error.xml @@ -0,0 +1,18 @@ + + + + + +