diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..5467b30
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "libs/pfa-core"]
+ path = libs/pfa-core
+ url = https://github.com/SecUSo/pfa-core
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 7b9f40e..0000000
--- a/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/AboutActivity.kt b/app/src/main/java/org/secuso/privacyfriendlyexample/ui/AboutActivity.kt
deleted file mode 100644
index fffb34e..0000000
--- a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/AboutActivity.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- This file is part of Privacy Friendly App Example.
-
- Privacy Friendly App Example is free software:
- you can redistribute it and/or modify it under the terms of the
- GNU General Public License as published by the Free Software Foundation,
- either version 3 of the License, or any later version.
-
- Privacy Friendly App Example is distributed in the hope
- that it will be useful, but WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Privacy Friendly App Example. If not, see .
- */
-package org.secuso.privacyfriendlyexample.ui
-
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import android.text.method.LinkMovementMethod
-
-import org.secuso.privacyfriendlyexample.BuildConfig
-import org.secuso.privacyfriendlyexample.R
-import org.secuso.privacyfriendlyexample.databinding.ActivityAboutBinding
-
-/**
- * This activity manages the AboutPage.
- * @author Christopher Beckmann (Kamuno), Karola Marky (yonjuni)
- * Created on 15.06.16.
- */
-class AboutActivity : AppCompatActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- val binding = ActivityAboutBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
-
- binding.mainContent.alpha = 0f
- binding.mainContent.animate().alpha(1f).duration = BaseActivity.MAIN_CONTENT_FADEIN_DURATION.toLong()
-
- overridePendingTransition(0, 0)
-
- binding.secusoWebsite.movementMethod = LinkMovementMethod.getInstance()
- binding.githubURL.movementMethod = LinkMovementMethod.getInstance()
- binding.textFieldVersion.text = getString(R.string.version_number, BuildConfig.VERSION_NAME)
- }
-}
-
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/BaseActivity.kt b/app/src/main/java/org/secuso/privacyfriendlyexample/ui/BaseActivity.kt
deleted file mode 100644
index 35a4947..0000000
--- a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/BaseActivity.kt
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- This file is part of Privacy Friendly App Example.
-
- Privacy Friendly App Example is free software:
- you can redistribute it and/or modify it under the terms of the
- GNU General Public License as published by the Free Software Foundation,
- either version 3 of the License, or any later version.
-
- Privacy Friendly App Example is distributed in the hope
- that it will be useful, but WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Privacy Friendly App Example. If not, see .
- */
-package org.secuso.privacyfriendlyexample.ui
-
-import android.content.Intent
-import android.content.SharedPreferences
-import android.os.Build
-import android.os.Bundle
-import android.os.Handler
-import android.preference.PreferenceActivity
-import android.preference.PreferenceManager
-import com.google.android.material.navigation.NavigationView
-import com.google.android.material.navigation.NavigationView.OnNavigationItemSelectedListener
-import androidx.core.app.TaskStackBuilder
-import androidx.core.view.GravityCompat
-import androidx.drawerlayout.widget.DrawerLayout
-import androidx.appcompat.app.ActionBarDrawerToggle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.widget.Toolbar
-import android.view.MenuItem
-import android.view.View
-
-import org.secuso.privacyfriendlyexample.R
-
-/**
- * This class is a parent class of all activities that can be accessed from the
- * Navigation Drawer (example see MainActivity.java)
- *
- * The default NavigationDrawer functionality is implemented in this class. If you wish to inherit
- * the default behaviour, make sure the content view has a NavigationDrawer with the id 'nav_view',
- * the header should point to 'nav_header_main' and the menu should be loaded from 'main_drawer'.
- *
- * Also the main layout that holds the content of the activity should have the id 'main_content'.
- * This way it will automatically fade in and out every time a transition is happening.
- *
- * @author Christopher Beckmann (Kamuno), Karola Marky (yonjuni)
- * @version 20161225
- */
-abstract class BaseActivity : AppCompatActivity(), OnNavigationItemSelectedListener {
- companion object {
- // delay to launch nav drawer item, to allow close animation to play
- internal const val NAVDRAWER_LAUNCH_DELAY = 250
- // fade in and fade out durations for the main content when switching between
- // different Activities of the app through the Nav Drawer
- internal const val MAIN_CONTENT_FADEOUT_DURATION = 150
- internal const val MAIN_CONTENT_FADEIN_DURATION = 250
- }
-
- // Navigation drawer:
- private var mDrawerLayout: DrawerLayout? = null
- private var mNavigationView: NavigationView? = null
-
- // Helper
- private val mHandler: Handler = Handler()
- protected val mSharedPreferences: SharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) }
-
- protected abstract val navigationDrawerID: Int
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- overridePendingTransition(0, 0)
- }
-
- override fun onBackPressed() {
- val drawer = findViewById(R.id.drawer_layout) as DrawerLayout
- if (drawer.isDrawerOpen(GravityCompat.START)) {
- drawer.closeDrawer(GravityCompat.START)
- } else {
- super.onBackPressed()
- }
- }
-
- override fun onNavigationItemSelected(item: MenuItem): Boolean = goToNavigationItem(item.itemId)
-
- protected fun goToNavigationItem(itemId: Int): Boolean {
- if (itemId == navigationDrawerID) {
- // just close drawer because we are already in this activity
- mDrawerLayout?.closeDrawer(GravityCompat.START)
- return true
- }
-
- // delay transition so the drawer can close
- mHandler.postDelayed({ callDrawerItem(itemId) }, NAVDRAWER_LAUNCH_DELAY.toLong())
-
- mDrawerLayout?.closeDrawer(GravityCompat.START)
-
- selectNavigationItem(itemId)
-
- // fade out the active activity
- val mainContent = findViewById(R.id.main_content)
- mainContent?.animate()!!.alpha(0f).duration = MAIN_CONTENT_FADEOUT_DURATION.toLong()
- return true
- }
-
- // set active navigation item
- private fun selectNavigationItem(itemId: Int) {
- mNavigationView ?: return
-
- for (i in 0 until mNavigationView!!.menu.size()) {
- val b = itemId == mNavigationView!!.menu.getItem(i).itemId
- mNavigationView!!.menu.getItem(i).isChecked = b
- }
- }
-
- /**
- * Enables back navigation for activities that are launched from the NavBar. See
- * `AndroidManifest.xml` to find out the parent activity names for each activity.
- * @param intent
- */
- private fun createBackStack(intent: Intent) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- val builder = TaskStackBuilder.create(this)
- builder.addNextIntentWithParentStack(intent)
- builder.startActivities()
- } else {
- startActivity(intent)
- finish()
- }
- }
-
- /**
- * This method manages the behaviour of the navigation drawer
- * Add your menu items (ids) to res/menu/main_drawer.xmlparam itemId Item that has been clicked by the user
- */
- private fun callDrawerItem(itemId: Int) {
-
- val intent: Intent
-
- when (itemId) {
- R.id.nav_example -> {
- intent = Intent(this, MainActivity::class.java).apply {
- flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
- }
- startActivity(intent)
- }
- R.id.nav_game -> {
- intent = Intent(this, GameActivity::class.java)
- createBackStack(intent)
- }
- R.id.nav_about -> {
- intent = Intent(this, AboutActivity::class.java)
- createBackStack(intent)
- }
- R.id.nav_help -> {
- intent = Intent(this, HelpActivity::class.java)
- createBackStack(intent)
- }
- R.id.nav_tutorial -> {
- intent = Intent(this, TutorialActivity::class.java).apply {
- flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
- }
- startActivity(intent)
- }
- R.id.nav_settings -> {
- intent = Intent(this, SettingsActivity::class.java)
- intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, SettingsActivity.GeneralPreferenceFragment::class.java.name)
- intent.putExtra(PreferenceActivity.EXTRA_NO_HEADERS, true)
- createBackStack(intent)
- }
- }
- }
-
- override fun onPostCreate(savedInstanceState: Bundle?) {
- super.onPostCreate(savedInstanceState)
-
- val toolbar = findViewById(R.id.toolbar) as Toolbar
- if (supportActionBar == null) {
- setSupportActionBar(toolbar)
- }
-
- mDrawerLayout = findViewById(R.id.drawer_layout) as DrawerLayout
- val toggle = ActionBarDrawerToggle(
- this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
- mDrawerLayout!!.addDrawerListener(toggle)
- toggle.syncState()
-
- mNavigationView = findViewById(R.id.nav_view) as NavigationView
- mNavigationView!!.setNavigationItemSelectedListener(this)
-
- selectNavigationItem(navigationDrawerID)
-
- val mainContent = findViewById(R.id.main_content)
- if (mainContent != null) {
- mainContent.alpha = 0f
- mainContent.animate().alpha(1f).duration = MAIN_CONTENT_FADEIN_DURATION.toLong()
- }
- }
-}
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/HelpActivity.kt b/app/src/main/java/org/secuso/privacyfriendlyexample/ui/HelpActivity.kt
deleted file mode 100644
index c1c4136..0000000
--- a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/HelpActivity.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- This file is part of Privacy Friendly App Example.
-
- Privacy Friendly App Example is free software:
- you can redistribute it and/or modify it under the terms of the
- GNU General Public License as published by the Free Software Foundation,
- either version 3 of the License, or any later version.
-
- Privacy Friendly App Example is distributed in the hope
- that it will be useful, but WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Privacy Friendly App Example. If not, see .
- */
-package org.secuso.privacyfriendlyexample.ui
-
-import android.os.Bundle
-
-import org.secuso.privacyfriendlyexample.R
-import org.secuso.privacyfriendlyexample.databinding.ActivityHelpBinding
-
-import org.secuso.privacyfriendlyexample.ui.adapter.ExpandableListAdapter
-import java.util.*
-import kotlin.collections.LinkedHashMap
-
-
-/**
- * Class structure taken from tutorial at http://www.journaldev.com/9942/android-expandablelistview-example-tutorial
- * last access 27th October 2016
- * @author Christopher Beckmann (Kamuno), Karola Marky (yonjuni)
- */
-class HelpActivity : BaseActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- val binding = ActivityHelpBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
- val expandableListDetail = buildData()
- val expandableListTitleGeneral = expandableListDetail.keys.toList()
-
- binding.generalExpandableListView.setAdapter(ExpandableListAdapter(this, expandableListTitleGeneral, expandableListDetail))
-
- overridePendingTransition(0, 0)
- }
-
- /**
- * ID of the menu item it belongs to
- */
- override val navigationDrawerID: Int = R.id.nav_help
-
- private fun buildData(): LinkedHashMap> {
- val expandableListDetail = LinkedHashMap>()
-
- expandableListDetail[getString(R.string.help_whatis)] = Collections.singletonList(getString(R.string.help_whatis_answer))
- expandableListDetail[getString(R.string.help_feature_one)] = Collections.singletonList(getString(R.string.help_feature_one_answer))
- expandableListDetail[getString(R.string.help_privacy)] = Collections.singletonList(getString(R.string.help_privacy_answer))
- expandableListDetail[getString(R.string.help_permission)] = Collections.singletonList(getString(R.string.help_permission_answer))
-
- return expandableListDetail
- }
-}
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/SettingsActivity.java b/app/src/main/java/org/secuso/privacyfriendlyexample/ui/SettingsActivity.java
deleted file mode 100644
index 6f088a4..0000000
--- a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/SettingsActivity.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- This file is part of Privacy Friendly App Example.
-
- Privacy Friendly App Example is free software:
- you can redistribute it and/or modify it under the terms of the
- GNU General Public License as published by the Free Software Foundation,
- either version 3 of the License, or any later version.
-
- Privacy Friendly App Example is distributed in the hope
- that it will be useful, but WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Privacy Friendly App Example. If not, see .
- */
-package org.secuso.privacyfriendlyexample.ui;
-
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.Build;
-import android.os.Bundle;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceManager;
-import android.view.MenuItem;
-
-import org.secuso.privacyfriendlyexample.R;
-
-/**
- * A {@link PreferenceActivity} that presents a set of application settings. On
- * handset devices, settings are presented as a single list. On tablets,
- * settings are split by category, with category headers shown to the left of
- * the list of settings.
- *
- * See
- * Android Design: Settings for design guidelines and the Settings
- * API Guide for more information on developing a Settings UI.
- */
-public class SettingsActivity extends BaseActivity {
- /**
- * A preference value change listener that updates the preference's summary
- * to reflect its new value.
- */
- private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object value) {
- String stringValue = value.toString();
-
- if (preference instanceof ListPreference) {
- // For list preferences, look up the correct display value in
- // the preference's 'entries' list.
- ListPreference listPreference = (ListPreference) preference;
- int index = listPreference.findIndexOfValue(stringValue);
-
- // Set the summary to reflect the new value.
- preference.setSummary(
- index >= 0
- ? listPreference.getEntries()[index]
- : null);
- } else {
- // For all other preferences, set the summary to the value's
- // simple string representation.
- preference.setSummary(stringValue);
- }
- return true;
- }
- };
-
- /**
- * Helper method to determine if the device has an extra-large screen. For
- * example, 10" tablets are extra-large.
- */
- private static boolean isXLargeTablet(Context context) {
- return (context.getResources().getConfiguration().screenLayout
- & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
- }
-
- /**
- * Binds a preference's summary to its value. More specifically, when the
- * preference's value is changed, its summary (line of text below the
- * preference title) is updated to reflect the value. The summary is also
- * immediately updated upon calling this method. The exact display format is
- * dependent on the type of preference.
- *
- * @see #sBindPreferenceSummaryToValueListener
- */
- private static void bindPreferenceSummaryToValue(Preference preference) {
- // Set the listener to watch for value changes.
- preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
-
- // Trigger the listener immediately with the preference's
- // current value.
- sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
- PreferenceManager
- .getDefaultSharedPreferences(preference.getContext())
- .getString(preference.getKey(), ""));
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.activity_settings);
-
- //setupActionBar();
-
-
- overridePendingTransition(0, 0);
- }
-
- @Override
- protected int getNavigationDrawerID() {
- return R.id.nav_settings;
- }
-
- /**
- * Set up the {@link android.app.ActionBar}, if the API is available.
- */
- /*private void setupActionBar() {
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- // Show the Up button in the action bar.
- actionBar.setDisplayHomeAsUpEnabled(true);
- }
- }*/
-
- /*@Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- int id = item.getItemId();
- if (id == android.R.id.home) {
- //finish();
- Intent intent = new Intent(this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- finish();
- return true;
-
- // (!super.onMenuItemSelected(featureId, item)) {
- // NavUtils.navigateUpFromSameTask(this);
- //}
- //return true;
- }
- return super.onMenuItemSelected(featureId, item);
- }*/
-
- /**
- * {@inheritDoc}
- */
- /*@Override
- public boolean onIsMultiPane() {
- return isXLargeTablet(this);
- }*/
-
- /**
- * {@inheritDoc}
- */
- /*@Override
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public void onBuildHeaders(List target) {
- loadHeadersFromResource(R.xml.pref_headers, target);
- }*/
-
- /**
- * This method stops fragment injection in malicious applications.
- * Make sure to deny any unknown fragments here.
- */
- protected boolean isValidFragment(String fragmentName) {
- return PreferenceFragment.class.getName().equals(fragmentName)
- || GeneralPreferenceFragment.class.getName().equals(fragmentName);
- }
-
- /**
- * This fragment shows general preferences only. It is used when the
- * activity is showing a two-pane settings UI.
- * The commented method bindPrefenceSummaryToValue should be added for all preferences
- * with a summary that is depended from the current value of the preference
- */
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public static class GeneralPreferenceFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.pref_general);
- //setHasOptionsMenu(true);
-
- // Bind the summaries of EditText/List/Dialog/Ringtone preferences
- // to their values. When their values change, their summaries are
- // updated to reflect the new value, per the Android Design
- // guidelines.
- //bindPreferenceSummaryToValue(findPreference("example_text"));
- //bindPreferenceSummaryToValue(findPreference("example_list"));
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- int id = item.getItemId();
- if (id == android.R.id.home) {
- //getActivity().finish();
- startActivity(new Intent(getActivity(), SettingsActivity.class));
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- }
-}
diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml
deleted file mode 100644
index 88fbf26..0000000
--- a/app/src/main/res/layout/activity_about.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_about_with_navigationdrawer.xml b/app/src/main/res/layout/activity_about_with_navigationdrawer.xml
deleted file mode 100644
index 4794c53..0000000
--- a/app/src/main/res/layout/activity_about_with_navigationdrawer.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_help.xml b/app/src/main/res/layout/activity_help.xml
deleted file mode 100644
index 6ae29e2..0000000
--- a/app/src/main/res/layout/activity_help.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index fbce05d..0000000
--- a/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
deleted file mode 100644
index ff2fb40..0000000
--- a/app/src/main/res/layout/activity_settings.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml
deleted file mode 100644
index fd40b78..0000000
--- a/app/src/main/res/xml/pref_general.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/xml/pref_headers.xml b/app/src/main/res/xml/pref_headers.xml
deleted file mode 100644
index b8a6e96..0000000
--- a/app/src/main/res/xml/pref_headers.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/build.gradle b/build.gradle
index 7028c8d..87af6e1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = "1.8.22"
+ ext.kotlin_version = "2.0.0"
repositories {
- jcenter()
+ mavenCentral()
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:8.1.2'
+ classpath 'com.android.tools.build:gradle:8.3.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
@@ -16,9 +16,13 @@ buildscript {
}
}
+plugins {
+ id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" apply false
+}
+
allprojects {
repositories {
- jcenter()
+ mavenCentral()
google()
}
}
diff --git a/app/.gitignore b/compose/.gitignore
similarity index 100%
rename from app/.gitignore
rename to compose/.gitignore
diff --git a/compose/build.gradle b/compose/build.gradle
new file mode 100644
index 0000000..a2c9c40
--- /dev/null
+++ b/compose/build.gradle
@@ -0,0 +1,79 @@
+plugins {
+ id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'org.jetbrains.kotlin.android'
+apply plugin: 'kotlin-kapt'
+apply plugin: 'org.jetbrains.kotlin.plugin.compose'
+
+
+android {
+ compileSdk 34
+ namespace "org.secuso.privacyfriendlyexample"
+
+ defaultConfig {
+ applicationId "org.secuso.privacyfriendlyexample"
+ minSdkVersion 21
+ targetSdkVersion 34
+ versionCode 7
+ versionName "4.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ buildFeatures {
+ viewBinding true
+ buildConfig true
+ compose true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion = "1.5.0"
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+}
+
+dependencies {
+ testImplementation 'junit:junit:4.13.1'
+
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "androidx.core:core-ktx:1.3.2"
+
+ implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+
+ def roomVersion = "2.5.2"
+ implementation("androidx.room:room-runtime:$roomVersion")
+ kapt("androidx.room:room-compiler:$roomVersion")
+ implementation("androidx.room:room-ktx:$roomVersion")
+
+ def workVersion = "2.8.1"
+ implementation("androidx.work:work-runtime:$workVersion")
+ implementation("androidx.work:work-runtime-ktx:$workVersion")
+ androidTestImplementation("androidx.work:work-testing:$workVersion")
+
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
+ implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
+
+ implementation("org.secuso.pfa-core:ui-compose")
+ implementation("org.secuso.pfa-core:model")
+ implementation("androidx.compose.runtime:runtime:1.6.4")
+ implementation("androidx.compose.ui:ui-viewbinding:1.6.7")
+ implementation 'androidx.activity:activity-compose:1.9.0'
+
+}
+repositories {
+ mavenCentral()
+}
diff --git a/app/proguard-rules.pro b/compose/proguard-rules.pro
similarity index 100%
rename from app/proguard-rules.pro
rename to compose/proguard-rules.pro
diff --git a/app/src/androidTest/java/org/secuso/privacyfriendlyexample/ApplicationTest.java b/compose/src/androidTest/java/org/secuso/privacyfriendlyexample/ApplicationTest.java
similarity index 100%
rename from app/src/androidTest/java/org/secuso/privacyfriendlyexample/ApplicationTest.java
rename to compose/src/androidTest/java/org/secuso/privacyfriendlyexample/ApplicationTest.java
diff --git a/compose/src/main/AndroidManifest.xml b/compose/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..eb9a605
--- /dev/null
+++ b/compose/src/main/AndroidManifest.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/compose/src/main/java/org/secuso/privacyfriendlyexample/PFApplicationData.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/PFApplicationData.kt
new file mode 100644
index 0000000..98cecd8
--- /dev/null
+++ b/compose/src/main/java/org/secuso/privacyfriendlyexample/PFApplicationData.kt
@@ -0,0 +1,129 @@
+package org.secuso.privacyfriendlyexample
+
+import android.content.Context
+import androidx.lifecycle.map
+import org.secuso.pfacore.application.PFData
+import org.secuso.pfacore.model.Theme
+import org.secuso.pfacore.model.about.About
+import org.secuso.pfacore.model.preferences.Preferable
+import org.secuso.pfacore.model.preferences.settings.ISettingData
+import org.secuso.pfacore.ui.help.Help
+import org.secuso.pfacore.ui.preferences.appPreferences
+import org.secuso.pfacore.ui.preferences.settings.DeviceInformationOnErrorReport
+import org.secuso.pfacore.ui.preferences.settings.PreferenceFirstTimeLaunch
+import org.secuso.pfacore.ui.preferences.settings.SettingThemeSelector
+import org.secuso.pfacore.ui.tutorial.buildTutorial
+
+class PFApplicationData private constructor(context: Context) {
+
+ lateinit var theme: ISettingData
+ private set
+ lateinit var exampleSwitch: Preferable
+ private set
+ lateinit var firstTimeLaunch: Preferable
+ private set
+ lateinit var includeDeviceDataInReport: Preferable
+ private set
+
+ private val preferences = appPreferences(context) {
+ preferences {
+ firstTimeLaunch = PreferenceFirstTimeLaunch().build().invoke(this)
+ }
+ settings {
+ category("Example Category") {
+ exampleSwitch = switch {
+ key = "pref_example_switch"
+ title { resource(R.string.pref_example_switch) }
+ summary { resource(R.string.pref_example_summary) }
+ default = false
+ backup = true
+ }
+ }
+ category("Design") {
+ theme = SettingThemeSelector().build().invoke(this)
+ }
+ category("Legal") {
+ menu("Legal") {
+ setting {
+ menu {
+ title { literal("Legal") }
+ }
+ }
+ content {
+
+ }
+ }
+ }
+ category("Error Report") {
+ includeDeviceDataInReport = DeviceInformationOnErrorReport().build().invoke(this)
+ }
+ }
+ }
+
+ private val help = Help.build(context) {
+ item {
+ title { resource(R.string.help_whatis) }
+ description { resource(R.string.help_whatis_answer) }
+ }
+ item {
+ title { resource(R.string.help_feature_one) }
+ description { resource(R.string.help_feature_one_answer) }
+ }
+ item {
+ title { resource(R.string.help_privacy) }
+ description { resource(R.string.help_privacy_answer) }
+ }
+ item {
+ title { resource(R.string.help_permission) }
+ description { resource(R.string.help_permission_answer) }
+ }
+ }
+
+ private val about = About(
+ name = context.resources.getString(R.string.app_name),
+ version = BuildConfig.VERSION_NAME,
+ authors = context.resources.getString(R.string.about_author_names),
+ repo = context.resources.getString(org.secuso.pfacore.R.string.about_github)
+ )
+
+ private val tutorial = buildTutorial {
+ stage {
+ title = context.getString(R.string.slide1_heading)
+ images = listOf(R.mipmap.ic_splash)
+ description = context.getString(R.string.slide1_text)
+ }
+ stage {
+ title = context.getString(R.string.slide2_heading)
+ images = listOf(R.mipmap.ic_splash)
+ description = context.getString(R.string.slide2_text)
+ }
+ stage {
+ title = context.getString(R.string.slide3_heading)
+ images = listOf(R.mipmap.ic_splash)
+ description = context.getString(R.string.slide3_text)
+ }
+ }
+
+ val data = PFData(
+ about = about,
+ help = help,
+ settings = preferences.settings,
+ tutorial = tutorial,
+ theme = theme.state.map { Theme.valueOf(it) },
+ firstLaunch = firstTimeLaunch,
+ includeDeviceDataInReport = includeDeviceDataInReport,
+ )
+
+ companion object {
+ private var _instance: PFApplicationData? = null
+ fun instance(context: Context): PFApplicationData {
+ if (_instance == null) {
+ _instance = PFApplicationData(context)
+ }
+ return _instance!!
+ }
+
+ }
+}
+
+
diff --git a/compose/src/main/java/org/secuso/privacyfriendlyexample/PFExample.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/PFExample.kt
new file mode 100644
index 0000000..ec94548
--- /dev/null
+++ b/compose/src/main/java/org/secuso/privacyfriendlyexample/PFExample.kt
@@ -0,0 +1,18 @@
+package org.secuso.privacyfriendlyexample
+
+import android.app.Activity
+import org.secuso.pfacore.application.PFApplication
+import org.secuso.pfacore.application.PFData
+import org.secuso.privacyfriendlyexample.database.AppDatabase
+import org.secuso.privacyfriendlyexample.ui.MainActivity
+
+class PFExample: PFApplication() {
+ override val name: String
+ get() = getString(R.string.app_name)
+
+ override val databaseName = AppDatabase.DB_NAME
+ override val database = AppDatabase::class.java
+ override val data: PFData
+ get() = PFApplicationData.instance(applicationContext).data
+ override val mainActivity: Class = MainActivity::class.java
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/database/AppDatabase.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/database/AppDatabase.kt
similarity index 100%
rename from app/src/main/java/org/secuso/privacyfriendlyexample/database/AppDatabase.kt
rename to compose/src/main/java/org/secuso/privacyfriendlyexample/database/AppDatabase.kt
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseExporter.java b/compose/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseExporter.java
similarity index 100%
rename from app/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseExporter.java
rename to compose/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseExporter.java
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseImporter.java b/compose/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseImporter.java
similarity index 100%
rename from app/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseImporter.java
rename to compose/src/main/java/org/secuso/privacyfriendlyexample/database/DatabaseImporter.java
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/database/dao/SampleDataDao.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/database/dao/SampleDataDao.kt
similarity index 100%
rename from app/src/main/java/org/secuso/privacyfriendlyexample/database/dao/SampleDataDao.kt
rename to compose/src/main/java/org/secuso/privacyfriendlyexample/database/dao/SampleDataDao.kt
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/database/model/SampleData.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/database/model/SampleData.kt
similarity index 100%
rename from app/src/main/java/org/secuso/privacyfriendlyexample/database/model/SampleData.kt
rename to compose/src/main/java/org/secuso/privacyfriendlyexample/database/model/SampleData.kt
diff --git a/app/src/main/java/org/secuso/privacyfriendlyexample/ui/AppCompatPreferenceActivity.java b/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/AppCompatPreferenceActivity.java
similarity index 100%
rename from app/src/main/java/org/secuso/privacyfriendlyexample/ui/AppCompatPreferenceActivity.java
rename to compose/src/main/java/org/secuso/privacyfriendlyexample/ui/AppCompatPreferenceActivity.java
diff --git a/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/BaseActivity.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/BaseActivity.kt
new file mode 100644
index 0000000..888d9b0
--- /dev/null
+++ b/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/BaseActivity.kt
@@ -0,0 +1,86 @@
+/*
+ This file is part of Privacy Friendly App Example.
+
+ Privacy Friendly App Example is free software:
+ you can redistribute it and/or modify it under the terms of the
+ GNU General Public License as published by the Free Software Foundation,
+ either version 3 of the License, or any later version.
+
+ Privacy Friendly App Example is distributed in the hope
+ that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Friendly App Example. If not, see .
+ */
+package org.secuso.privacyfriendlyexample.ui
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import org.secuso.pfacore.model.DrawerMenu
+import org.secuso.pfacore.ui.activities.DrawerActivity
+import org.secuso.privacyfriendlyexample.R
+
+/**
+ * This class is a parent class of all activities that can be accessed from the
+ * Navigation Drawer (example see MainActivity.java)
+ *
+ * The default NavigationDrawer functionality is implemented in this class. If you wish to inherit
+ * the default behaviour, make sure the content view has a NavigationDrawer with the id 'nav_view',
+ * the header should point to 'nav_header_main' and the menu should be loaded from 'main_drawer'.
+ *
+ * Also the main layout that holds the content of the activity should have the id 'main_content'.
+ * This way it will automatically fade in and out every time a transition is happening.
+ *
+ * @author Christopher Beckmann (Kamuno), Karola Marky (yonjuni)
+ * @version 20161225
+ */
+abstract class BaseActivity : DrawerActivity() {
+ companion object {
+ // delay to launch nav drawer item, to allow close animation to play
+ internal const val NAVDRAWER_LAUNCH_DELAY = 250
+ // fade in and fade out durations for the main content when switching between
+ // different Activities of the app through the Nav Drawer
+ internal const val MAIN_CONTENT_FADEOUT_DURATION = 150
+ internal const val MAIN_CONTENT_FADEIN_DURATION = 250
+ }
+
+ protected abstract val navigationDrawerID: Int
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ overridePendingTransition(0, 0)
+ }
+
+ override fun drawer(): DrawerMenu = DrawerMenu.build {
+ name = getString(R.string.app_name)
+ icon = R.mipmap.ic_launcher
+ section {
+ activity {
+ name = getString(R.string.action_main)
+ icon = R.drawable.ic_menu_home
+ clazz = MainActivity::class.java
+ extras = { it.apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TOP } }
+ }
+ activity {
+ name = getString(R.string.action_game)
+ icon = R.drawable.ic_menu_game
+ clazz = GameActivity::class.java
+ }
+ }
+ defaultDrawerSection(this)
+ }
+
+ override fun onPostCreate(savedInstanceState: Bundle?) {
+ super.onPostCreate(savedInstanceState)
+
+ val mainContent = findViewById(R.id.main_content)
+ if (mainContent != null) {
+ mainContent.alpha = 0f
+ mainContent.animate().alpha(1f).duration = MAIN_CONTENT_FADEIN_DURATION.toLong()
+ }
+ }
+}
diff --git a/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/GameActivity.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/GameActivity.kt
new file mode 100644
index 0000000..d3eb138
--- /dev/null
+++ b/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/GameActivity.kt
@@ -0,0 +1,143 @@
+/*
+ This file is part of Privacy Friendly App Example.
+
+ Privacy Friendly App Example is free software:
+ you can redistribute it and/or modify it under the terms of the
+ GNU General Public License as published by the Free Software Foundation,
+ either version 3 of the License, or any later version.
+
+ Privacy Friendly App Example is distributed in the hope
+ that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Friendly App Example. If not, see .
+ */
+package org.secuso.privacyfriendlyexample.ui
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.viewinterop.AndroidViewBinding
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentPagerAdapter
+import androidx.viewpager.widget.ViewPager
+import org.secuso.pfacore.application.PFApplication
+import org.secuso.pfacore.model.DrawerElement
+import org.secuso.privacyfriendlyexample.R
+import org.secuso.privacyfriendlyexample.databinding.ActivityGameBinding
+
+/**
+ * This activity is an example for the main menu of gaming applications
+ * @author Christopher Beckmann (Kamuno)
+ * @version 20161225
+ */
+class GameActivity : BaseActivity() {
+
+ /**
+ * ID of the menu item it belongs to
+ */
+ override val navigationDrawerID: Int = R.id.nav_game
+
+ @Composable
+ override fun Content(application: PFApplication) {
+ val context = LocalContext.current as FragmentActivity
+ AndroidViewBinding(ActivityGameBinding::inflate) {
+ val adapter = SectionsPagerAdapter(context.supportFragmentManager)
+ chooseGameTypeViewPager.adapter = adapter
+ val index = mSharedPreferences.getInt("lastChosenPage", 0)
+
+ chooseGameTypeViewPager.currentItem = index
+
+ //care for initial postiton of the ViewPager
+ arrowLeft.visibility = if (index == 0) View.INVISIBLE else View.VISIBLE
+ arrowRight.visibility = if (index == adapter.count - 1) View.INVISIBLE else View.VISIBLE
+
+ arrowLeft.setOnClickListener { chooseGameTypeViewPager.arrowScroll(View.FOCUS_LEFT) }
+ arrowRight.setOnClickListener { chooseGameTypeViewPager.arrowScroll(View.FOCUS_RIGHT) }
+
+ //Update ViewPager on change
+ chooseGameTypeViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
+ override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
+
+ }
+
+ override fun onPageSelected(position: Int) {
+ arrowLeft.visibility = if (position == 0) View.INVISIBLE else View.VISIBLE
+ arrowRight.visibility = if (position == adapter.count - 1) View.INVISIBLE else View.VISIBLE
+
+ //save position in settings
+ val editor = mSharedPreferences.edit()
+ editor.putInt("lastChosenPage", position)
+ editor.apply()
+ }
+
+ override fun onPageScrollStateChanged(state: Int) {}
+ })
+ }
+ }
+
+ override fun isActiveDrawerElement(element: DrawerElement): Boolean {
+ return element.name == getString(R.string.action_game)
+ }
+
+ inner class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
+
+
+ override fun getItem(position: Int): Fragment {
+ // getItem is called to instantiate the fragment for the given page.
+ // Return a PageFragment (defined as a static inner class below).
+ return PageFragment.newInstance(position)
+ }
+
+ override fun getCount(): Int {
+ // Show 3 total pages.
+ return 3
+ }
+ }
+
+ class PageFragment : Fragment() {
+
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ var id = 0
+ if (arguments != null) {
+ id = arguments!!.getInt(ARG_SECTION_NUMBER)
+ }
+
+ val rootView = inflater.inflate(R.layout.fragment_game_mode, container, false)
+
+ val textView = rootView.findViewById(R.id.section_label) as TextView
+ textView.text = "Mode: $id"
+ return rootView
+ }
+
+ companion object {
+ /**
+ * The fragment argument representing the section number for this
+ * fragment.
+ */
+ private val ARG_SECTION_NUMBER = "section_number"
+
+ /**
+ * Returns a new instance of this fragment for the given section
+ * number.
+ */
+ fun newInstance(sectionNumber: Int): PageFragment {
+ val fragment = PageFragment()
+ val args = Bundle()
+ args.putInt(ARG_SECTION_NUMBER, sectionNumber)
+ fragment.arguments = args
+ return fragment
+ }
+ }
+ }
+}
diff --git a/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/MainActivity.kt b/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/MainActivity.kt
new file mode 100644
index 0000000..7d039e2
--- /dev/null
+++ b/compose/src/main/java/org/secuso/privacyfriendlyexample/ui/MainActivity.kt
@@ -0,0 +1,88 @@
+/*
+ This file is part of Privacy Friendly App Example.
+
+ Privacy Friendly App Example is free software:
+ you can redistribute it and/or modify it under the terms of the
+ GNU General Public License as published by the Free Software Foundation,
+ either version 3 of the License, or any later version.
+
+ Privacy Friendly App Example is distributed in the hope
+ that it will be useful, but WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Friendly App Example. If not, see .
+ */
+package org.secuso.privacyfriendlyexample.ui
+
+import android.os.Bundle
+import android.util.Log
+import android.widget.Button
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.viewinterop.AndroidViewBinding
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
+import org.secuso.pfacore.application.PFApplication
+import org.secuso.pfacore.model.DrawerElement
+import org.secuso.pfacore.model.permission.PFAPermission
+import org.secuso.pfacore.ui.declareUsage
+import org.secuso.privacyfriendlyexample.R
+import org.secuso.privacyfriendlyexample.databinding.ActivityMainBinding
+import org.secuso.privacyfriendlyexample.ui.viewmodel.MainExampleViewModel
+
+/**
+ * This class displays some example Buttons and shows the usage of the database.
+ * @author Christopher Beckmann (Kamuno), Karola Marky (yonjuni)
+ */
+class MainActivity : BaseActivity() {
+ /**
+ * ID of the menu item it belongs to
+ */
+ override val navigationDrawerID: Int = R.id.nav_example
+
+ private lateinit var exampleViewModel: MainExampleViewModel
+
+ @Composable
+ override fun Content(application: PFApplication) {
+ val requestPermission = PFAPermission.AccessCoarseLocation.declareUsage(this) {
+ onGranted = {
+ Log.d("TestPermission", "permission should be granted: ${ContextCompat.checkSelfPermission(this@MainActivity, PFAPermission.AccessCoarseLocation.permission)}")
+ }
+ onDenied = {
+ Log.d("TestPermission", "permission should be denied: ${ContextCompat.checkSelfPermission(this@MainActivity, PFAPermission.AccessCoarseLocation.permission)}")
+ }
+ showRationale = {
+ rationaleTitle = "This requires the schedule exact alarm permission"
+ rationaleText = "Definitely needed."
+ }
+ }
+ AndroidViewBinding(ActivityMainBinding::inflate) {
+ // Access all UI-Elements here
+ fab.setOnClickListener {
+ requestPermission()
+ }
+ findViewById