1
1
mirror of https://github.com/Pygmalion69/OpenTopoMapViewer.git synced 2025-10-05 15:52:55 +02:00

Settings screen

This commit is contained in:
Pygmalion69
2024-11-03 14:06:23 +01:00
parent ff4f1d4a74
commit 76bfb7404c
14 changed files with 188 additions and 117 deletions

View File

@@ -88,7 +88,7 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//noinspection GradleCompatible
implementation 'androidx.core:core-ktx:1.13.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6"
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
@@ -96,8 +96,8 @@ dependencies {
implementation 'org.osmdroid:osmdroid-android:6.1.18'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.room:room-runtime:2.6.1'
@@ -108,7 +108,7 @@ dependencies {
implementation "androidx.preference:preference:1.2.1"
implementation 'net.danlew:android.joda:2.10.9.1'
implementation 'com.github.k3b:k3b-geoHelper:1.1.5'
implementation 'com.github.ticofab:android-gpx-parser:2.0.1'
implementation 'com.github.ticofab:android-gpx-parser:2.3.1'
implementation('com.squareup.picasso:picasso:2.71828') {
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'appcompat-v7'

View File

@@ -1,12 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- PROTECTION_NORMAL permissions, automatically granted -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- DANGEROUS PERMISSIONS, must request -->
<uses-permission android:name="android.permission.INTERNET" /> <!-- DANGEROUS PERMISSIONS, must request -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -17,12 +14,17 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".SettingsActivity"
android:parentActivityName=".MainActivity"
android:exported="false"
android:label="@string/settings" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
@@ -33,10 +35,10 @@
<data android:scheme="geo" />
<data android:mimeType="application/gpx+xml" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
@@ -64,10 +66,8 @@
<data android:host="*" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.gpx" />
<data android:pathPattern=".*\\..*\\.gpx" />
<data android:pathPattern=".*\\..*\\..*\\.gpx" />
@@ -87,7 +87,6 @@
<data android:host="*" />
<data android:scheme="file" />
<data android:pathPattern=".*\\.gpx" />
<data android:pathPattern=".*\\..*\\.gpx" />
<data android:pathPattern=".*\\..*\\..*\\.gpx" />

View File

@@ -1,9 +1,14 @@
package org.nitri.opentopo
import android.Manifest
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -18,15 +23,22 @@ import androidx.activity.viewModels
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.preference.PreferenceManager
import de.k3b.geo.api.GeoPointDto
import de.k3b.geo.io.GeoUri
import io.ticofab.androidgpxparser.parser.GPXParser
import io.ticofab.androidgpxparser.parser.domain.Gpx
import kotlinx.coroutines.CoroutineScope
import org.nitri.opentopo.CacheSettingsFragment.Companion.PREF_CACHE_SIZE
import org.nitri.opentopo.CacheSettingsFragment.Companion.PREF_EXTERNAL_STORAGE
import org.nitri.opentopo.CacheSettingsFragment.Companion.PREF_TILE_CACHE
import org.nitri.opentopo.SettingsActivity.Companion.PREF_FULLSCREEN
import org.nitri.opentopo.SettingsActivity.Companion.PREF_FULLSCREEN_ON_MAP_TAP
import org.nitri.opentopo.SettingsActivity.Companion.PREF_KEEP_SCREEN_ON
import org.nitri.opentopo.model.GpxViewModel
import org.nitri.opentopo.nearby.NearbyFragment
import org.nitri.opentopo.nearby.entity.NearbyItem
@@ -50,23 +62,22 @@ open class BaseMainActivity : AppCompatActivity(), MapFragment.OnFragmentInterac
}
private var windowInsetsController: WindowInsetsControllerCompat? = null
private var actionBar: ActionBar? = null
override var isFullscreenOnMapTap = false
set(value) {
field = value
mPrefs.edit().putBoolean(
PREF_FULLSCREEN_ON_MAP_TAP,
value
).apply()
private val preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
when (key) {
PREF_KEEP_SCREEN_ON -> {
mMapFragment?.setKeepScreenOn(sharedPreferences.getBoolean(key, false))
}
}
override var isKeepScreenOn = false
set(value) {
field = value
mPrefs.edit().putBoolean(
PREF_KEEP_SCREEN_ON,
value
).apply()
}
private val cacheChangedReceiver = object: BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
restart()
}
}
override fun isPrivacyOptionsRequired(): Boolean {
return false
}
@@ -85,8 +96,6 @@ open class BaseMainActivity : AppCompatActivity(), MapFragment.OnFragmentInterac
}
handler = Handler(mainLooper)
mPrefs = PreferenceManager.getDefaultSharedPreferences(this)
isFullscreenOnMapTap = mPrefs.getBoolean(PREF_FULLSCREEN_ON_MAP_TAP, false)
isKeepScreenOn = mPrefs.getBoolean(PREF_KEEP_SCREEN_ON, false)
val intent = intent
if (intent != null && intent.data != null) {
handleIntent(intent)
@@ -120,6 +129,10 @@ open class BaseMainActivity : AppCompatActivity(), MapFragment.OnFragmentInterac
}
actionBar = supportActionBar
mPrefs.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
LocalBroadcastManager.getInstance(this).registerReceiver(cacheChangedReceiver, IntentFilter(CacheSettingsFragment.ACTION_CACHE_CHANGED))
Log.d(TAG, "SEMH receiver registered")
}
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
@@ -334,6 +347,12 @@ open class BaseMainActivity : AppCompatActivity(), MapFragment.OnFragmentInterac
return pointFromIntent
}
override fun onDestroy() {
super.onDestroy()
mPrefs.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
LocalBroadcastManager.getInstance(this).unregisterReceiver(cacheChangedReceiver)
}
override fun getGpx(): Gpx? {
return gpxViewModel.gpx
}
@@ -357,7 +376,7 @@ open class BaseMainActivity : AppCompatActivity(), MapFragment.OnFragmentInterac
override fun onMapTap() {
if (mapFragmentAdded()) {
if (isFullscreenOnMapTap) {
if (mPrefs.getBoolean(PREF_FULLSCREEN_ON_MAP_TAP, false)) {
toggleFullscreen()
}
}
@@ -365,18 +384,31 @@ open class BaseMainActivity : AppCompatActivity(), MapFragment.OnFragmentInterac
override fun onMapLongPress() {}
/**
* Restart the rude way
*/
private fun restart() {
finish()
startActivity(intent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overrideActivityTransition(
Activity.OVERRIDE_TRANSITION_CLOSE,
0,
0,
Color.TRANSPARENT
)
} else {
overridePendingTransition(0, 0)
}
}
companion object {
private val TAG = BaseMainActivity::class.java.simpleName
private const val MAP_FRAGMENT_TAG = "map_fragment"
const val GPX_DETAIL_FRAGMENT_TAG = "gpx_detail_fragment"
const val WAY_POINT_DETAIL_FRAGMENT_TAG = "way_point_detail_fragment"
private const val NEARBY_FRAGMENT_TAG = "nearby_fragment"
const val PREF_FULLSCREEN = "fullscreen"
private const val PREF_FULLSCREEN_ON_MAP_TAP = "fullscreen_on_map_tap"
private const val PREF_KEEP_SCREEN_ON = "keep_screen_on"
private const val REQUEST_LOCATION_PERMISSION = 1
private const val REQUEST_STORAGE_PERMISSION = 2
private const val READ_REQUEST_CODE = 69
private const val GPX_URI_STATE = "gpx_uri"
}
}

View File

@@ -1,12 +1,10 @@
package org.nitri.opentopo
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.graphics.Color
import android.os.Build
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.Window
@@ -15,12 +13,16 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.SwitchCompat
import androidx.fragment.app.DialogFragment
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import org.osmdroid.config.Configuration
import java.io.File
class CacheSettingsFragment : DialogFragment() {
private lateinit var etTileCache: EditText
private lateinit var etCacheSize: EditText
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(requireActivity())
val inflater = requireActivity().layoutInflater
@@ -61,12 +63,16 @@ class CacheSettingsFragment : DialogFragment() {
configuration.tileFileSystemCacheMaxBytes =
newCacheSize.toLong() * 1024 * 1024
configuration.save(requireActivity().applicationContext, prefs)
if (
newExternalStorage != currentExternalStorage
|| newTileCache != currentTileCache
|| newCacheSize != currentCacheSize
) restart()
val intent = Intent(ACTION_CACHE_CHANGED);
val localBroadcastManager = LocalBroadcastManager.getInstance(
requireActivity()
)
if (currentExternalStorage != newExternalStorage || currentTileCache != newTileCache || currentCacheSize != newCacheSize) {
localBroadcastManager.sendBroadcast(intent)
requireActivity().finish()
}
dismiss()
}
.setNegativeButton(android.R.string.cancel) { _: DialogInterface?, _: Int -> dismiss() }
.setNeutralButton(R.string.reset) { _: DialogInterface?, _: Int -> }
@@ -76,23 +82,6 @@ class CacheSettingsFragment : DialogFragment() {
return dialog
}
/**
* Restart the rude way
*/
private fun restart() {
requireActivity().finish()
startActivity(requireActivity().intent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
requireActivity().overrideActivityTransition(
Activity.OVERRIDE_TRANSITION_CLOSE,
0,
0,
Color.TRANSPARENT
)
} else {
requireActivity().overridePendingTransition(0, 0)
}
}
override fun onResume() {
super.onResume()
@@ -115,5 +104,6 @@ class CacheSettingsFragment : DialogFragment() {
const val PREF_TILE_CACHE = "tile_cache"
const val PREF_CACHE_SIZE = "cache_size"
const val PREF_EXTERNAL_STORAGE = "external_storage"
const val ACTION_CACHE_CHANGED = "cache_changed"
}
}

View File

@@ -4,6 +4,7 @@ import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.location.GpsStatus.NmeaListener
@@ -36,6 +37,8 @@ import androidx.fragment.app.FragmentManager
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import io.ticofab.androidgpxparser.parser.domain.Gpx
import org.nitri.opentopo.SettingsActivity.Companion.PREF_FULLSCREEN
import org.nitri.opentopo.SettingsActivity.Companion.PREF_KEEP_SCREEN_ON
import org.nitri.opentopo.model.LocationViewModel
import org.nitri.opentopo.overlay.model.MarkerModel
import org.nitri.opentopo.overlay.viewmodel.MarkerViewModel
@@ -102,6 +105,11 @@ class MapFragment : Fragment(), LocationListener, PopupMenu.OnMenuItemClickListe
return false
}
}
fun setKeepScreenOn(value: Boolean) {
mMapView.keepScreenOn = value
}
private var mFollow = false
private var mListener: OnFragmentInteractionListener? = null
private lateinit var mPrefs: SharedPreferences
@@ -315,8 +323,8 @@ class MapFragment : Fragment(), LocationListener, PopupMenu.OnMenuItemClickListe
return true
}
}))
mMapView.keepScreenOn = mListener?.isKeepScreenOn ?: false
mListener?.isFullscreen = mPrefs.getBoolean(BaseMainActivity.PREF_FULLSCREEN, false)
setKeepScreenOn(mPrefs.getBoolean(PREF_KEEP_SCREEN_ON, false))
mListener?.isFullscreen = mPrefs.getBoolean(PREF_FULLSCREEN, false)
markerViewModel.markers.observe(viewLifecycleOwner) { markers ->
mOverlayHelper?.setMarkers(markers, object : OverlayHelper.MarkerInteractionListener {
@@ -613,10 +621,6 @@ class MapFragment : Fragment(), LocationListener, PopupMenu.OnMenuItemClickListe
mListener?.let {
it.setUpNavigation(false)
inflater.inflate(R.menu.menu_main, menu)
val fullscreenItem = menu.findItem(R.id.action_fullscreen)
val keepScreenOnItem = menu.findItem(R.id.action_keep_screen_on)
fullscreenItem.isChecked = it.isFullscreenOnMapTap
keepScreenOnItem.isChecked = it.isKeepScreenOn
}
}
@@ -688,17 +692,9 @@ class MapFragment : Fragment(), LocationListener, PopupMenu.OnMenuItemClickListe
}
return true
}
R.id.action_cache_settings -> {
mMapCenterState = mMapView.mapCenter as GeoPoint
saveMapCenterPrefs()
fm = requireActivity().supportFragmentManager
val cacheSettingsFragment = CacheSettingsFragment()
cacheSettingsFragment.show(fm, "cache_settings")
return true
}
R.id.action_gpx_zoom -> {
disableFollow()
mListener?.let {zoomToBounds(Util.area(it.getGpx())) }
mListener?.let { zoomToBounds(Util.area(it.getGpx())) }
return true
}
R.id.action_layers -> {
@@ -727,20 +723,11 @@ class MapFragment : Fragment(), LocationListener, PopupMenu.OnMenuItemClickListe
}
return false
}
R.id.action_fullscreen -> {
mListener?.let {
item.isChecked = !item.isChecked
it.isFullscreenOnMapTap = item.isChecked
}
return true
}
R.id.action_keep_screen_on -> {
mListener?.let{
item.isChecked = !item.isChecked
it.isKeepScreenOn = item.isChecked
mMapView.keepScreenOn = item.isChecked
}
return true
R.id.action_settings -> {
mMapCenterState = mMapView.mapCenter as GeoPoint
saveMapCenterPrefs()
val settingsIntent = Intent(activity, SettingsActivity::class.java)
startActivity(settingsIntent)
}
R.id.action_about -> {
showAboutDialog()
@@ -913,13 +900,7 @@ class MapFragment : Fragment(), LocationListener, PopupMenu.OnMenuItemClickListe
*/
fun onMapLongPress()
/**
* Fullscreen on map tap
*/
var isFullscreenOnMapTap: Boolean
var isFullscreen: Boolean
var isKeepScreenOn: Boolean
/**
* Need to enable privacy stettings or not

View File

@@ -0,0 +1,60 @@
package org.nitri.opentopo
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NavUtils
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
class SettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_activity)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> NavUtils.navigateUpFromSameTask(this);
}
return super.onOptionsItemSelected(item)
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
override fun onPreferenceTreeClick(preference: Preference): Boolean {
when (preference.key) {
"cache_settings" -> {
showCacheSettings()
return true
}
}
return super.onPreferenceTreeClick(preference)
}
private fun showCacheSettings() {
val cacheSettingsFragment = CacheSettingsFragment()
val fm = requireActivity().supportFragmentManager
cacheSettingsFragment.show(fm, "cache_settings")
}
}
companion object {
const val PREF_FULLSCREEN = "fullscreen"
const val PREF_FULLSCREEN_ON_MAP_TAP = "fullscreen_on_map_tap"
const val PREF_KEEP_SCREEN_ON = "keep_screen_on"
}
}

View File

@@ -41,18 +41,6 @@
android:title="@string/layers"
android:visible="true"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_fullscreen"
android:checkable="true"
android:title="@string/fullscreen_on_map_tap"
app:actionViewClass="android.widget.CheckBox"
app:showAsAction="never" />
<item
android:id="@+id/action_keep_screen_on"
android:checkable="true"
android:title="@string/keep_screen_on"
app:actionViewClass="android.widget.CheckBox"
app:showAsAction="never" />
<item
android:id="@+id/action_location_details"
android:icon="@drawable/ic_action_location_detail"
@@ -66,9 +54,9 @@
android:visible="true"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_cache_settings"
android:icon="@drawable/ic_action_cache_settings"
android:title="@string/cache_settings"
android:id="@+id/action_settings"
android:icon="@drawable/ic_action_settings"
android:title="@string/settings"
android:visible="true"
app:showAsAction="ifRoom" />
<item

View File

@@ -40,7 +40,7 @@
<string name="tile_cache">Kachel-Cache</string>
<string name="max_cache_size">Max. Cache-Größe (MB)</string>
<string name="reset">Zurücksetzen</string>
<string name="storage_root">Externer Speicherpfad: %1$s</string>
<string name="storage_root">Speicherpfad: %1$s</string>
<string name="external_storage">Externer Speicher</string>
<string name="privacy_settings">Datenschutzeinstellungen</string>
@@ -64,4 +64,8 @@
<string name="delete">Löschen</string>
<string name="confirm_delete">Löschen bestätigen</string>
<string name="prompt_confirm_delete">Sind Sie sicher, dass Sie dieses Element löschen möchten?</string>
<string name="settings">Einstellungen</string>
<string name="screen_header">Bildschirm</string>
<string name="cache_header">Cache</string>
</resources>

View File

@@ -40,7 +40,7 @@
<string name="tile_cache">Caché de teselas</string>
<string name="max_cache_size">Tamaño máx. de caché (MB)</string>
<string name="reset">Restablecer</string>
<string name="storage_root">Raíz del almacenamiento externo: %1$s</string>
<string name="storage_root">Raíz del almacenamiento: %1$s</string>
<string name="external_storage">Almacenamiento externo</string>
<string name="privacy_settings">Ajustes de privacidad</string>
@@ -65,4 +65,8 @@
<string name="confirm_delete">Confirmar eliminación</string>
<string name="prompt_confirm_delete">¿Está seguro de que desea eliminar este elemento?</string>
<string name="settings">Configuración</string>
<string name="screen_header">Pantalla</string>
<string name="cache_header">Caché</string>
</resources>

View File

@@ -40,7 +40,7 @@
<string name="tile_cache">Cache de tuiles</string>
<string name="max_cache_size">Taille max. du cache (MB)</string>
<string name="reset">Réinitialiser</string>
<string name="storage_root">Racine du stockage externe : %1$s</string>
<string name="storage_root">Racine du stockage : %1$s</string>
<string name="external_storage">Stockage externe</string>
<string name="privacy_settings">Paramètres de confidentialité</string>
@@ -65,4 +65,9 @@
<string name="confirm_delete">Confirmer la suppression</string>
<string name="prompt_confirm_delete">Êtes-vous sûr de vouloir supprimer cet élément ?</string>
<string name="settings">Paramètres</string>
<string name="screen_header">Écran</string>
<string name="cache_header">Cache</string>
</resources>

View File

@@ -40,7 +40,7 @@
<string name="tile_cache">Tegelcache</string>
<string name="max_cache_size">Max. cachegrootte (MB)</string>
<string name="reset">Resetten</string>
<string name="storage_root">Externe opslag root: %1$s</string>
<string name="storage_root">Opslag-root: %1$s</string>
<string name="external_storage">Externe opslag</string>
<string name="privacy_settings">Privacy-instellingen</string>
@@ -65,4 +65,8 @@
<string name="confirm_delete">Verwijdering bevestigen</string>
<string name="prompt_confirm_delete">Weet u zeker dat u dit item wilt verwijderen?</string>
<string name="settings">Instellingen</string>
<string name="screen_header">Scherm</string>
<string name="cache_header">Cache</string>
</resources>

View File

@@ -40,7 +40,7 @@
<string name="tile_cache">Tile cache</string>
<string name="max_cache_size">Max. cache size (MB)</string>
<string name="reset">Reset</string>
<string name="storage_root">External storage root: %1$s</string>
<string name="storage_root">Storage root: %1$s</string>
<string name="external_storage">External storage</string>
<string name="privacy_settings">Privacy Settings</string>
@@ -65,4 +65,8 @@
<string name="confirm_delete">Confirm Delete</string>
<string name="prompt_confirm_delete">Are you sure you want to delete this item?"</string>
<string name="settings">Settings</string>
<string name="screen_header">Screen</string>
<string name="cache_header">Cache</string>
</resources>

View File

@@ -15,5 +15,5 @@ org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.enableJetifier=false
android.nonTransitiveRClass=true
android.nonFinalResIds=false
android.nonFinalResIds=true
org.gradle.configuration-cache=true