From 79fa1e18b51ee62a55267bb573c359163d222a79 Mon Sep 17 00:00:00 2001 From: Francisco Franco Date: Wed, 23 Sep 2020 15:48:23 +0100 Subject: [PATCH] Convert to Kotlin + v1.6 release --- .gitignore | 3 +- .idea/compiler.xml | 22 --- .idea/copyright/profiles_settings.xml | 3 - .idea/encodings.xml | 6 - .idea/gradle.xml | 18 -- .idea/misc.xml | 33 ---- .idea/modules.xml | 9 - .idea/runConfigurations.xml | 12 -- app/build.gradle | 42 +++-- app/src/main/AndroidManifest.xml | 25 ++- .../main/java/com/franco/demomode/Utils.java | 112 ------------- .../main/java/com/franco/demomode/Utils.kt | 140 ++++++++++++++++ .../demomode/activities/MainActivity.java | 154 ------------------ .../demomode/activities/MainActivity.kt | 51 ++++++ .../com/franco/demomode/application/App.java | 14 -- .../demomode/fragments/SettingsFragment.kt | 71 ++++++++ .../demomode/fragments/SettingsViewModel.kt | 32 ++++ .../franco/demomode/tiles/DemoModeTile.java | 54 ------ .../com/franco/demomode/tiles/DemoModeTile.kt | 70 ++++++++ .../main/res/drawable-xhdpi/ic_demo_off.png | Bin 849 -> 0 bytes .../main/res/drawable-xhdpi/ic_demo_on.png | Bin 900 -> 0 bytes .../main/res/drawable-xxhdpi/ic_demo_off.png | Bin 1257 -> 0 bytes .../main/res/drawable-xxhdpi/ic_demo_on.png | Bin 1343 -> 0 bytes .../main/res/drawable-xxxhdpi/ic_demo_off.png | Bin 1689 -> 0 bytes .../main/res/drawable-xxxhdpi/ic_demo_on.png | Bin 1889 -> 0 bytes app/src/main/res/drawable/bug.xml | 8 + app/src/main/res/drawable/code_braces.xml | 8 + .../res/drawable/ic_settings_black_24dp.xml | 9 + app/src/main/res/drawable/twitter.xml | 8 + app/src/main/res/layout/activity_main.xml | 27 +-- app/src/main/res/values-fr/string.xml | 17 -- app/src/main/res/values-it/strings.xml | 17 -- app/src/main/res/values-tr/strings.xml | 17 -- app/src/main/res/values/strings.xml | 1 - app/src/main/res/values/styles.xml | 2 +- app/src/main/res/xml/settings.xml | 47 +++--- build.gradle | 4 +- gradle.properties | 17 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 0 40 files changed, 479 insertions(+), 576 deletions(-) delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/runConfigurations.xml delete mode 100644 app/src/main/java/com/franco/demomode/Utils.java create mode 100644 app/src/main/java/com/franco/demomode/Utils.kt delete mode 100644 app/src/main/java/com/franco/demomode/activities/MainActivity.java create mode 100644 app/src/main/java/com/franco/demomode/activities/MainActivity.kt delete mode 100644 app/src/main/java/com/franco/demomode/application/App.java create mode 100644 app/src/main/java/com/franco/demomode/fragments/SettingsFragment.kt create mode 100644 app/src/main/java/com/franco/demomode/fragments/SettingsViewModel.kt delete mode 100644 app/src/main/java/com/franco/demomode/tiles/DemoModeTile.java create mode 100644 app/src/main/java/com/franco/demomode/tiles/DemoModeTile.kt delete mode 100644 app/src/main/res/drawable-xhdpi/ic_demo_off.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_demo_on.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_demo_off.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_demo_on.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/ic_demo_off.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/ic_demo_on.png create mode 100644 app/src/main/res/drawable/bug.xml create mode 100644 app/src/main/res/drawable/code_braces.xml create mode 100644 app/src/main/res/drawable/ic_settings_black_24dp.xml create mode 100644 app/src/main/res/drawable/twitter.xml delete mode 100644 app/src/main/res/values-fr/string.xml delete mode 100644 app/src/main/res/values-it/strings.xml delete mode 100644 app/src/main/res/values-tr/strings.xml mode change 100755 => 100644 gradlew diff --git a/.gitignore b/.gitignore index 39fb081..5393359 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,8 @@ *.iml .gradle /local.properties -/.idea/workspace.xml -/.idea/libraries .DS_Store /build /captures .externalNativeBuild +/.idea \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43e..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 7ac24c7..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 635999d..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 1fff92a..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index c4613a2..88f9d8b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,16 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' android { - compileSdkVersion 26 - buildToolsVersion "26.0.1" + compileSdkVersion 30 + buildToolsVersion "30.0.2" defaultConfig { applicationId "com.franco.demomode" minSdkVersion 24 - targetSdkVersion 26 - versionName "1.2" - versionCode getVersionCodeTimestamp() + targetSdkVersion 30 + versionName "1.6" + versionCode 1910030257 archivesBaseName = "DemoModeTile-${android.defaultConfig.versionName}" } @@ -46,15 +47,20 @@ android { shrinkResources true signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - manifestPlaceholders = [vmSafeModeEnabled: "false"] } debug { minifyEnabled false shrinkResources false - manifestPlaceholders = [vmSafeModeEnabled: "true"] } } + + buildFeatures { + viewBinding = true + } + kotlinOptions { + jvmTarget = '1.8' + } } def readKeystoreProperties(def configName) { @@ -70,13 +76,21 @@ def readKeystoreProperties(def configName) { } } -static def getVersionCodeTimestamp() { - return new Date().format('yyMMddHHmm').toInteger() +dependencies { + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.2.1' + implementation 'androidx.preference:preference-ktx:1.1.1' + implementation "androidx.fragment:fragment-ktx:1.2.5" + implementation "androidx.core:core-ktx:1.3.1" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9' + + def lifecycle_version = "2.3.0-alpha07" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" } -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:design:26.1.0' - compile 'com.jakewharton:butterknife:8.8.1' - annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' +repositories { + mavenCentral() } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cdbe115..59f7652 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,31 +1,26 @@ - + + tools:ignore="ProtectedPermissions" /> + tools:ignore="ProtectedPermissions" /> + android:theme="@style/DemoModeTheme"> - + - + - + @@ -35,7 +30,7 @@ android:label="@string/demo_mode" android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> - + diff --git a/app/src/main/java/com/franco/demomode/Utils.java b/app/src/main/java/com/franco/demomode/Utils.java deleted file mode 100644 index 536ab2d..0000000 --- a/app/src/main/java/com/franco/demomode/Utils.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.franco.demomode; - -import android.Manifest; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.provider.Settings; - -import com.franco.demomode.application.App; - -public class Utils { - private static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed"; - private static final String DEMO_MODE_ON = "sysui_tuner_demo_on"; - public static final String MISSING_PERMISSION = "missing_permission"; - - public static void enableDemoMode() { - if (!isDemoModeAllowed()) { - Settings.Global.putInt(App.CONTEXT.getContentResolver(), DEMO_MODE_ALLOWED, 1); - } - - Settings.Global.putInt(App.CONTEXT.getContentResolver(), DEMO_MODE_ON, 1); - - // clock with the latest release string - Intent clock = new Intent("com.android.systemui.demo"); - clock.putExtra("command", "clock"); - clock.putExtra("hhmm", "0800"); - App.CONTEXT.sendBroadcast(clock); - - // battery icon needs to be perfect - Intent battery = new Intent("com.android.systemui.demo"); - battery.putExtra("command", "battery"); - battery.putExtra("level", "100"); - battery.putExtra("plugged", "false"); - App.CONTEXT.sendBroadcast(battery); - - // signal icon - Intent data = new Intent("com.android.systemui.demo"); - data.putExtra("command", "network"); - data.putExtra("mobile", "show"); - data.putExtra("datatype", "hide"); - data.putExtra("level", "4"); - App.CONTEXT.sendBroadcast(data); - - // mock sim carrier connection - Intent signal = new Intent("com.android.systemui.demo"); - signal.putExtra("command", "network"); - signal.putExtra("fully", "true"); - App.CONTEXT.sendBroadcast(signal); - - // WiFi icon - Intent wifi = new Intent("com.android.systemui.demo"); - wifi.putExtra("command", "network"); - wifi.putExtra("wifi", "show"); - wifi.putExtra("level", "4"); - App.CONTEXT.sendBroadcast(wifi); - - // rip icons - Intent miscNetwork = new Intent("com.android.systemui.demo"); - miscNetwork.putExtra("command", "network"); - miscNetwork.putExtra("airplane", "hide"); - miscNetwork.putExtra("nosim", "hide"); - miscNetwork.putExtra("sims", 1); - App.CONTEXT.sendBroadcast(miscNetwork); - - - // if there's one thing I hate is cluttered statusbar with notifs - Intent notifs = new Intent("com.android.systemui.demo"); - notifs.putExtra("command", "notifications"); - notifs.putExtra("visible", "false"); - App.CONTEXT.sendBroadcast(notifs); - - // goodbye more icons! - Intent miscIcons = new Intent("com.android.systemui.demo"); - miscIcons.putExtra("command", "status"); - miscIcons.putExtra("bluetooth", "hide"); - miscIcons.putExtra("volume", "hide"); - miscIcons.putExtra("mute", "hide"); - App.CONTEXT.sendBroadcast(miscIcons); - } - - public static void disableDemoMode() { - Settings.Global.putInt(App.CONTEXT.getContentResolver(), Utils.DEMO_MODE_ON, 0); - - Intent enableDemoMode = new Intent("com.android.systemui.demo"); - enableDemoMode.putExtra("command", "exit"); - App.CONTEXT.sendBroadcast(enableDemoMode); - } - - public static boolean isDemoModeAllowed() { - try { - return Settings.Global.getInt(App.CONTEXT.getContentResolver(), DEMO_MODE_ALLOWED) == 1; - } catch (Settings.SettingNotFoundException e) { - e.printStackTrace(); - return false; - } - } - - public static boolean isDemoModeOn() { - return Settings.Global.getInt(App.CONTEXT.getContentResolver(), - DEMO_MODE_ON, 0) != 0; - } - - public static boolean isDumpPermissionGranted() { - return App.CONTEXT.getPackageManager().checkPermission(Manifest.permission.DUMP, App.CONTEXT.getPackageName()) - == PackageManager.PERMISSION_GRANTED; - } - - public static boolean isWriteSecureSettingsPermissionGranted() { - return App.CONTEXT.getPackageManager() - .checkPermission(Manifest.permission.WRITE_SECURE_SETTINGS, App.CONTEXT.getPackageName()) - == PackageManager.PERMISSION_GRANTED; - } -} diff --git a/app/src/main/java/com/franco/demomode/Utils.kt b/app/src/main/java/com/franco/demomode/Utils.kt new file mode 100644 index 0000000..53523f9 --- /dev/null +++ b/app/src/main/java/com/franco/demomode/Utils.kt @@ -0,0 +1,140 @@ +package com.franco.demomode + +import android.Manifest +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build +import android.provider.Settings +import android.provider.Settings.SettingNotFoundException +import android.view.View +import androidx.core.content.ContextCompat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class Utils { + suspend fun enableDemoMode(context: Context) { + withContext(Dispatchers.IO) { + if (!isDemoModeAllowed(context)) { + Settings.Global.putInt(context.contentResolver, DEMO_MODE_ALLOWED, 1) + } + + Settings.Global.putInt(context.contentResolver, DEMO_MODE_ON, 1) + } + + // clock with the latest release string + val clock = Intent("com.android.systemui.demo") + clock.putExtra("command", "clock") + clock.putExtra("hhmm", "1100") + context.sendBroadcast(clock) + + // battery icon needs to be perfect + val battery = Intent("com.android.systemui.demo") + battery.putExtra("command", "battery") + battery.putExtra("level", "100") + battery.putExtra("plugged", "false") + context.sendBroadcast(battery) + + // signal icon + val data = Intent("com.android.systemui.demo") + data.putExtra("command", "network") + data.putExtra("mobile", "show") + data.putExtra("datatype", "hide") + data.putExtra("level", "4") + context.sendBroadcast(data) + + // mock sim carrier connection + val signal = Intent("com.android.systemui.demo") + signal.putExtra("command", "network") + signal.putExtra("fully", "true") + context.sendBroadcast(signal) + + // WiFi icon + val wifi = Intent("com.android.systemui.demo") + wifi.putExtra("command", "network") + wifi.putExtra("wifi", "show") + wifi.putExtra("level", "4") + context.sendBroadcast(wifi) + + // rip icons + val miscNetwork = Intent("com.android.systemui.demo") + miscNetwork.putExtra("command", "network") + miscNetwork.putExtra("airplane", "hide") + miscNetwork.putExtra("nosim", "hide") + miscNetwork.putExtra("sims", 1) + context.sendBroadcast(miscNetwork) + + + // if there's one thing I hate is cluttered statusbar with notifs + val notifs = Intent("com.android.systemui.demo") + notifs.putExtra("command", "notifications") + notifs.putExtra("visible", "false") + context.sendBroadcast(notifs) + + // goodbye more icons! + val miscIcons = Intent("com.android.systemui.demo") + miscIcons.putExtra("command", "status") + miscIcons.putExtra("bluetooth", "hide") + miscIcons.putExtra("volume", "hide") + miscIcons.putExtra("mute", "hide") + context.sendBroadcast(miscIcons) + } + + suspend fun disableDemoMode(context: Context) { + withContext(Dispatchers.IO) { + Settings.Global.putInt(context.contentResolver, DEMO_MODE_ON, 0) + } + + val enableDemoMode = Intent("com.android.systemui.demo") + enableDemoMode.putExtra("command", "exit") + context.sendBroadcast(enableDemoMode) + } + + suspend fun isDemoModeAllowed(context: Context): Boolean = withContext(Dispatchers.IO) { + try { + Settings.Global.getInt(context.contentResolver, DEMO_MODE_ALLOWED) == 1 + } catch (e: SettingNotFoundException) { + e.printStackTrace() + false + } + } + + suspend fun isDemoModeOn(context: Context): Boolean = withContext(Dispatchers.IO) { + Settings.Global.getInt(context.contentResolver, DEMO_MODE_ON, 0) != 0 + } + + suspend fun isDumpPermissionGranted(context: Context): Boolean = withContext(Dispatchers.IO) { + (context.packageManager.checkPermission(Manifest.permission.DUMP, context.packageName) + == PackageManager.PERMISSION_GRANTED) + } + + suspend fun isWriteSecureSettingsPermissionGranted(context: Context): Boolean = withContext(Dispatchers.IO) { + (context.packageManager.checkPermission( + Manifest.permission.WRITE_SECURE_SETTINGS, context.packageName) + == PackageManager.PERMISSION_GRANTED) + } + + fun setLightNavBar(view: View) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + var flags = view.systemUiVisibility + flags = flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR + view.systemUiVisibility = flags + (view.context as Activity).window.navigationBarColor = ContextCompat.getColor(view.context, R.color.primary) + } + } + + fun clearLightNavBar(view: View) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + var flags = view.systemUiVisibility + flags = flags and View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv() + view.systemUiVisibility = flags + } + } + + companion object { + private const val DEMO_MODE_ALLOWED = "sysui_demo_allowed" + private const val DEMO_MODE_ON = "sysui_tuner_demo_on" + const val MISSING_PERMISSION = "missing_permission" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/franco/demomode/activities/MainActivity.java b/app/src/main/java/com/franco/demomode/activities/MainActivity.java deleted file mode 100644 index 58a8365..0000000 --- a/app/src/main/java/com/franco/demomode/activities/MainActivity.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.franco.demomode.activities; - -import android.app.AlertDialog; -import android.os.Bundle; -import android.os.Process; -import android.preference.Preference; -import android.preference.PreferenceFragment; -import android.support.annotation.Nullable; -import android.support.design.widget.Snackbar; -import android.support.v7.app.AppCompatActivity; -import android.view.View; -import android.widget.Toolbar; - -import com.franco.demomode.R; -import com.franco.demomode.Utils; - -import butterknife.BindView; -import butterknife.ButterKnife; - - -public class MainActivity extends AppCompatActivity { - @BindView(R.id.toolbar) - protected Toolbar toolbar; - @BindView(R.id.root_layout) - protected View rootLayout; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - ButterKnife.bind(this); - - setActionBar(toolbar); - - if (getIntent() != null) { - if (getIntent().getAction() != null) { - if (getIntent().getAction().equals(Utils.MISSING_PERMISSION)) { - final Snackbar snackbar = Snackbar.make(rootLayout, - R.string.permissions_need_to_be_granted, Snackbar.LENGTH_INDEFINITE); - snackbar.setAction(R.string.ok, view -> snackbar.dismiss()); - snackbar.show(); - } - } - } - - if (!Utils.isDemoModeAllowed()) { - new AlertDialog.Builder(this) - .setTitle(R.string.demo_mode_allowed_title) - .setMessage(R.string.demo_mode_allowed_message) - .setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()) - .show(); - } - } - - public static class SettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener { - private static final String KEY_DUMP = "dump_permission"; - private static final String KET_WRITE_SECURE_SETTINGS = "write_secure_settings"; - - private Preference dump; - private Preference writeSecureSettings; - - private Thread permissionsPollThread; - - private boolean isDumpPermissionGranted; - private boolean isWriteSecureSettingsPermissionGranted; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.settings); - - dump = findPreference(KEY_DUMP); - writeSecureSettings = findPreference(KET_WRITE_SECURE_SETTINGS); - - dump.setOnPreferenceClickListener(this); - writeSecureSettings.setOnPreferenceClickListener(this); - } - - @Override - public boolean onPreferenceClick(Preference preference) { - new AlertDialog.Builder(getActivity()) - .setTitle(R.string.permission_request_title) - .setMessage(preference.getKey().equals(KEY_DUMP) ? - R.string.dump_permission_msg : - R.string.write_secure_settings_permission_msg) - .show(); - - return false; - } - - @Override - public void onStart() { - super.onStart(); - - isDumpPermissionGranted = Utils.isDumpPermissionGranted(); - isWriteSecureSettingsPermissionGranted = Utils.isWriteSecureSettingsPermissionGranted(); - - dump.setSummary(isDumpPermissionGranted ? R.string.granted : R.string.not_granted); - writeSecureSettings.setSummary(isWriteSecureSettingsPermissionGranted - ? R.string.granted : R.string.not_granted); - - // there isn't a listener for when these permissions states change, so we have to poll it - // Runs in a BG thread so it's ok - permissionsPollThread = new Thread(new Runnable() { - long lastNow = System.currentTimeMillis(); - - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - - try { - while (permissionsPollThread != null && permissionsPollThread.isAlive()) { - if ((lastNow + 1000) < System.currentTimeMillis()) { - lastNow = System.currentTimeMillis(); - - if (isDumpPermissionGranted != Utils.isDumpPermissionGranted()) { - isDumpPermissionGranted = Utils.isDumpPermissionGranted(); - - getActivity().runOnUiThread(() -> - dump.setSummary(isDumpPermissionGranted ? - R.string.granted : R.string.not_granted)); - } - - if (isWriteSecureSettingsPermissionGranted != Utils.isWriteSecureSettingsPermissionGranted()) { - isWriteSecureSettingsPermissionGranted = Utils.isWriteSecureSettingsPermissionGranted(); - - getActivity().runOnUiThread(() -> - writeSecureSettings.setSummary(isWriteSecureSettingsPermissionGranted - ? R.string.granted : R.string.not_granted)); - } - } - } - } catch (Exception ignored) { - // it's ok to catch the exception here and not treat it properly. - // not doing anything important and the thread object might be null even after the null check - // so fail gracefully and in peace - } - } - }); - - permissionsPollThread.start(); - } - - @Override - public void onStop() { - super.onStop(); - - if (permissionsPollThread != null && !permissionsPollThread.isInterrupted()) { - permissionsPollThread.interrupt(); - permissionsPollThread = null; - } - } - } -} diff --git a/app/src/main/java/com/franco/demomode/activities/MainActivity.kt b/app/src/main/java/com/franco/demomode/activities/MainActivity.kt new file mode 100644 index 0000000..4bc9f68 --- /dev/null +++ b/app/src/main/java/com/franco/demomode/activities/MainActivity.kt @@ -0,0 +1,51 @@ +package com.franco.demomode.activities + +import android.content.DialogInterface +import android.os.Bundle +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import com.franco.demomode.R +import com.franco.demomode.Utils +import com.franco.demomode.databinding.ActivityMainBinding +import com.google.android.material.snackbar.Snackbar +import kotlinx.coroutines.launch + +class MainActivity : AppCompatActivity() { + private lateinit var binding: ActivityMainBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityMainBinding.inflate(layoutInflater) + + setContentView(binding.root) + setSupportActionBar(binding.toolbar) + supportActionBar!!.setDisplayShowTitleEnabled(false) + + val action = intent?.action ?: "" + if (action == Utils.MISSING_PERMISSION) { + Snackbar.make(binding.root, R.string.permissions_need_to_be_granted, + Snackbar.LENGTH_INDEFINITE).apply { + setAction(R.string.ok) { dismiss() } + show() + } + } + + lifecycleScope.launch { + val isDemoModeAllowed = Utils().isDemoModeAllowed(this@MainActivity) + + if (!isDemoModeAllowed) { + AlertDialog.Builder(this@MainActivity) + .setTitle(R.string.demo_mode_allowed_title) + .setMessage(R.string.demo_mode_allowed_message) + .setPositiveButton(android.R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() } + .show() + } + } + } + + override fun onResume() { + super.onResume() + Utils().setLightNavBar(binding.root) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/franco/demomode/application/App.java b/app/src/main/java/com/franco/demomode/application/App.java deleted file mode 100644 index 2fbe6cc..0000000 --- a/app/src/main/java/com/franco/demomode/application/App.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.franco.demomode.application; - -import android.app.Application; -import android.content.Context; - -public class App extends Application { - public static Context CONTEXT; - - @Override - public void onCreate() { - super.onCreate(); - CONTEXT = this; - } -} diff --git a/app/src/main/java/com/franco/demomode/fragments/SettingsFragment.kt b/app/src/main/java/com/franco/demomode/fragments/SettingsFragment.kt new file mode 100644 index 0000000..86fd6f4 --- /dev/null +++ b/app/src/main/java/com/franco/demomode/fragments/SettingsFragment.kt @@ -0,0 +1,71 @@ +package com.franco.demomode.fragments + +import android.os.Bundle +import android.view.View +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.viewModels +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import com.franco.demomode.R +import kotlin.time.ExperimentalTime + +@ExperimentalTime +class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClickListener { + private lateinit var dumpPermissionPref: Preference + private lateinit var writeSecureSettingsPref: Preference + + private val viewModel by viewModels() + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {} + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + addPreferencesFromResource(R.xml.settings) + + dumpPermissionPref = findPreference(KEY_DUMP)!! + writeSecureSettingsPref = findPreference(KET_WRITE_SECURE_SETTINGS)!! + + dumpPermissionPref.onPreferenceClickListener = this + writeSecureSettingsPref.onPreferenceClickListener = this + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel.isDumpPermissionUpdates(requireContext()).observe(viewLifecycleOwner, ::renderDump) + viewModel.isWriteSecureSettingsPermissionUpdates(requireContext()) + .observe(viewLifecycleOwner, ::renderWriteSecureSettings) + } + + private fun renderDump(isGranted: Boolean) { + dumpPermissionPref.summary = when (isGranted) { + true -> getString(R.string.granted) + false -> getString(R.string.not_granted) + } + } + + private fun renderWriteSecureSettings(isGranted: Boolean) { + writeSecureSettingsPref.summary = when (isGranted) { + true -> getString(R.string.granted) + false -> getString(R.string.not_granted) + } + } + + override fun onPreferenceClick(preference: Preference): Boolean { + AlertDialog.Builder(requireActivity()) + .setTitle(R.string.permission_request_title) + .setMessage(when (preference.key) { + KEY_DUMP -> R.string.dump_permission_msg + KET_WRITE_SECURE_SETTINGS -> R.string.write_secure_settings_permission_msg + else -> throw IllegalArgumentException("well, this shouldn't ever happen") + }) + .show() + return false + } + + companion object { + private const val KEY_DUMP = "dump_permission" + private const val KET_WRITE_SECURE_SETTINGS = "write_secure_settings" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/franco/demomode/fragments/SettingsViewModel.kt b/app/src/main/java/com/franco/demomode/fragments/SettingsViewModel.kt new file mode 100644 index 0000000..0da85de --- /dev/null +++ b/app/src/main/java/com/franco/demomode/fragments/SettingsViewModel.kt @@ -0,0 +1,32 @@ +package com.franco.demomode.fragments + +import android.content.Context +import androidx.lifecycle.ViewModel +import androidx.lifecycle.asLiveData +import com.franco.demomode.Utils +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flow +import kotlin.random.Random +import kotlin.time.ExperimentalTime +import kotlin.time.seconds + +@ExperimentalTime +class SettingsViewModel : ViewModel() { + + fun isDumpPermissionUpdates(context: Context) = flow { + while (true) { + emit(Utils().isDumpPermissionGranted(context)) + delay(Random.nextLong(1.seconds.toLongMilliseconds(), + 2.seconds.toLongMilliseconds())) + } + }.asLiveData(Dispatchers.IO) + + fun isWriteSecureSettingsPermissionUpdates(context: Context) = flow { + while (true) { + emit(Utils().isWriteSecureSettingsPermissionGranted(context)) + delay(Random.nextLong(1.seconds.toLongMilliseconds(), + 2.seconds.toLongMilliseconds())) + } + }.asLiveData(Dispatchers.IO) +} \ No newline at end of file diff --git a/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.java b/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.java deleted file mode 100644 index b4b5a6a..0000000 --- a/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.franco.demomode.tiles; - -import android.content.Intent; -import android.graphics.drawable.Icon; -import android.service.quicksettings.Tile; -import android.service.quicksettings.TileService; - -import com.franco.demomode.R; -import com.franco.demomode.Utils; -import com.franco.demomode.activities.MainActivity; - -public class DemoModeTile extends TileService { - @Override - public void onCreate() { - super.onCreate(); - } - - @Override - public void onStartListening() { - super.onStartListening(); - - getQsTile().setState(Utils.isDemoModeOn() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); - getQsTile().setIcon(Utils.isDemoModeOn() ? - Icon.createWithResource(getApplicationContext(), R.drawable.ic_on) : - Icon.createWithResource(getApplicationContext(), R.drawable.ic_off)); - getQsTile().updateTile(); - } - - @Override - public void onClick() { - super.onClick(); - - if (!Utils.isDumpPermissionGranted() || !Utils.isWriteSecureSettingsPermissionGranted()) { - Intent mainActivity = new Intent(getApplicationContext(), MainActivity.class); - mainActivity.setAction(Utils.MISSING_PERMISSION); - mainActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - startActivity(mainActivity); - } else { - if (getQsTile().getState() == Tile.STATE_ACTIVE) { - getQsTile().setState(Tile.STATE_INACTIVE); - getQsTile().setIcon(Icon.createWithResource(getApplicationContext(), R.drawable.ic_off)); - getQsTile().updateTile(); - - Utils.disableDemoMode(); - } else { - getQsTile().setState(Tile.STATE_ACTIVE); - getQsTile().setIcon(Icon.createWithResource(getApplicationContext(), R.drawable.ic_on)); - getQsTile().updateTile(); - - Utils.enableDemoMode(); - } - } - } -} diff --git a/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.kt b/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.kt new file mode 100644 index 0000000..6fdb8c0 --- /dev/null +++ b/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.kt @@ -0,0 +1,70 @@ +package com.franco.demomode.tiles + +import android.content.Intent +import android.graphics.drawable.Icon +import android.service.quicksettings.Tile +import android.service.quicksettings.TileService +import com.franco.demomode.R +import com.franco.demomode.Utils +import com.franco.demomode.activities.MainActivity +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + +class DemoModeTile : TileService() { + override fun onStartListening() { + super.onStartListening() + + GlobalScope.launch { + val isDemoModeAllowed = Utils().isDemoModeAllowed(applicationContext) + val isDemoMode = Utils().isDemoModeOn(applicationContext) + + qsTile?.state = when { + !isDemoModeAllowed -> Tile.STATE_UNAVAILABLE + isDemoMode -> Tile.STATE_ACTIVE + else -> Tile.STATE_INACTIVE + } + + qsTile?.icon = when { + isDemoMode -> Icon.createWithResource(applicationContext, R.drawable.ic_on) + else -> Icon.createWithResource(applicationContext, R.drawable.ic_off) + } + + qsTile?.updateTile() + } + } + + override fun onClick() { + super.onClick() + + GlobalScope.launch { + val hasDumpPermission = Utils().isDumpPermissionGranted(applicationContext) + val hasWriteSecurePermission = Utils().isWriteSecureSettingsPermissionGranted(applicationContext) + + when { + !hasDumpPermission || !hasWriteSecurePermission -> { + Intent(applicationContext, MainActivity::class.java).apply { + action = Utils.MISSING_PERMISSION + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + startActivity(this) + } + } + + else -> { + qsTile?.apply { + if (state == Tile.STATE_ACTIVE) { + state = Tile.STATE_INACTIVE + icon = Icon.createWithResource(applicationContext, R.drawable.ic_off) + Utils().disableDemoMode(applicationContext) + } else { + state = Tile.STATE_ACTIVE + icon = Icon.createWithResource(applicationContext, R.drawable.ic_on) + Utils().enableDemoMode(applicationContext) + } + + updateTile() + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/ic_demo_off.png b/app/src/main/res/drawable-xhdpi/ic_demo_off.png deleted file mode 100644 index 1e54e218f7f8234ed1e4580e1d4bb1ad3ea5ca6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 849 zcmV-X1FrmuP)Px&3rR#lRA>e5m`#XJQ5ePtiBO`1#UvvoVyS$@LRra1lFh`zLP?Uu$}B{qtZeMe zC<|*Vkt|qPhD=brn#&vWm4@45H( z^mLAquEHNUz6fx;t9x6 zlF;OfbrGtWj6Vi;_N_e@nO|ghfUK(TeSz$A7<&UuxV7IITN{|)_|O0uO;pT8A9F$` zR7wj#u~6Aav>8xa*TfBuQJEDBmCbZb48ifwo4AUJ*`QeDxDt0zzqo{hxgrYg~lgU15FUZojSx9s3q+Xs3fCkbeWN(5mga zCLY4QGGL&Wu_b}=mWGtz7N`>L?n^PDlX4h@9<5sVo&n{Y0kXwGm_7qnY-~GbVg<)v z0ev7A*V$pbCu5UZ9ap`+cM@2lP#ZH*mHULpEsp(F2eh(JB{c>@qW!T{6MFSN2Yv^5 z^$_U?Sz{?|kAN>Y)St@4GI;Jz!6jptz&wyGl=uS(iT1~0CUlcNNaPUb3$PPpi|sH; zoG&=kkC{+Ojwf;$uO7d9K$bWKixIo69+keiTqZ`~J^-?W%HSq&#cNxOV4WAhlq>NL z&b>f6v&MSZ+*c0OwJlP)Obo-hFso{h>>7Q$3Y)!sN^bkCO)V!qflhmTZRxIp^#{1^ zvG1bqUL7-_HfBOA^*GR+qoA=kOQuauHhoin0j_9&yUK(f5XE9SnO_25aHttj<^!N2zu&?as}G< zN9O3KL7l~p>CMC<(%c6o)^A_2Pev^|(u97SJO{pbebt3ND?8G}8pM8eOlVc!24WF2 zp+&J+=*G6IFqojiH*qH6n6^&QH}5FW;-=pwDPbmxi#M_Qf;w)U#I|VJBx>wV>z;v* bIRk$IUx@=jpTAY#00000NkvXXu0mjfqI`*9 diff --git a/app/src/main/res/drawable-xhdpi/ic_demo_on.png b/app/src/main/res/drawable-xhdpi/ic_demo_on.png deleted file mode 100644 index b04ce48b73061b25cb0d731e169d7f7ec04363ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 900 zcmV-~1AF|5P)Px&K1oDDRA>e5nMr6BK@f)H5+g!Tl;AEguAmasgQ7Q2-aLpNL|i}!C{ZCEJa`f{ z7d;4y7f<3v5%lPS;6=T-YjD8@f)O_eDshR5em_{yHa#zI=FOX#2e06#r>ncF{;D_A z-7~MDp)U0b)GJVF1-9Z~Mx{>jvY$%eAK+A81S*Yt6bFC6PcW-eXIb0NBj6xV0>XJv zQ*s%$M&8=hwUWX10C^?R2gVmYiFOEn1y*&xy};P8q9!p3V!b8ETQc26Oke_}?v_E` zlGt6OBw8SIF9vx_qN@l=EQG|X1mrD=W7v+&E0IkE{#*fhOX31r{J~ zdm7uO2sS!5-3s{bL8pZzHPIWFDifFdff5YnFy>a?_x+Ud1tsib4^6=$P7?bgBIwrK z0d&v%r2YPP=IjBX#RheJX~pC{@B{h%69LyEu^!wh!`}Dz5Sxu4l^uNrjs{DRxEc}Y zObHvGa8&;yK2njrcnJmhh<>sY!QFLry$0L_A=^?qtzzpyYPXUcT@MgZ5La{>)!Umd z+fbCV+v~-t6S#%&eI@QM#_~6?%3bk1X~+El-heUQn7T88Dr@$B`-ri*psI2b?+UC$ zbnJHJARQyM&mC~CwTXppDZP8NIP)jz!@pzlU2y*bv^FXjFckLhcJ z%S^h7w8)7zjq7*7$XojwUDWQXP3;TNy5A0Rli5Um35>MgY9nj~Az6!Zb7&wd-Esnj zD(@%J$GoLkkt!#SR+z&;&w@`js;_6_5Eu<|m*X&qB07}*Nbc+*piQk4=ph`6u#JCW zZU?B!28G{5q9wJQ(`pa%3j2qMHXnCQw~AY*ybj`87Y(ia diff --git a/app/src/main/res/drawable-xxhdpi/ic_demo_off.png b/app/src/main/res/drawable-xxhdpi/ic_demo_off.png deleted file mode 100644 index ccbca1a2287adfd1eb124e4bcd720a2ddbc94ba1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1257 zcmV=P)Px(qe(L6vUI# zf*^YE-~v4eqMk$)5kYV{6mbU^a6w!U4^mWAaNqU+#}^pVWRko|=S|+55B|=ZBro6h z{az+BnbfMP+;Rdrft)~2ASaL$&=Y7v)eWeJzDecQ5Xyb%FEqDuG3Ybr=ph{HioRLp z*4!z;5s;==E{d+1FP7jC(ru_`*QS+MG6*SmLSp1Zk88>qN3~^g?HV`)^%@##*-uc- zS`qD8sMZj59qRu;(NQCRK4Iu1xN5=?Ntz(_Lfeax_Tqc;u{k&jnt)ps$(kVb#dl1Q zKA=s##%D0aDmY>!_<-~jB!ZofI3W{)0HQkjfYbpWy`dnD6LK1mPQgzO2@q7HP?Y76 z0LV0PpFx}cP>`0^<#rczMg~a;K@Wr8LE^Gd9eqsPT&6TaLD>{U`vg)!k;{BQ`UPJ* zAU=3z+G-HpcIYQ0gNQr#0g3(dZDa$KNt=nN9zk&+;_7@s;*YZj8VF^^jv|t{yWbc%JzogG28OPUEhIi~ErM+A02)Sp z@)4mVwgp~IZw#Y>sy>?_@z?L?kR3<3?B_SiW;^uZwJGNV*XJTR0TU$KfVq33`@z1V zZjNn7zT0u9^a~^>?sA?K(pva8{ZPCU&x1;0)8O?zL}9RX?(8^O5LWyW73C88%SLGBz@fAzFbr4gy3)^uK$1VC&9Us7d3seK8ZtLMu6%@-}L4%=Ms1%U+<8d`m4VBEe$Mpbo!j>Tl84v@MEiFiU;W*VhmYk@3&S36AQAm7VQrSurM%$@A7dt2Y zLf;!yPP0%pKa%)4O+b7y=3jcKpvYy#Kx)?b%}nw2Lh_A@hkNHGZT>I0BprQWvM86!1;q@q}>77Sbqy;U6c6 z1brOKVkGgBS_QrJ3`YPC8d5!=TxshAjUWk zt%E*7Nk-5?e4isFu8&|x67s5=3~~QFE{`@g4*{yQFVy?|68RAqdJ zGegRy>>-Un!jCN=akpfa1V@~fJ){O?8n=zZ{q=={hUQrIkd`8G)n&!9of;@|u`Q&M zzGjt!b~$fHV;Rydl)3!(1QVn-mw>X?mJ8TUNI?3A&wK)RH65fj*N(E-KDraKKS6*p zq_TiR9(=p_9OANMIF!T$q_!lTWbwP)658!4uwW--Px?}Bt diff --git a/app/src/main/res/drawable-xxhdpi/ic_demo_on.png b/app/src/main/res/drawable-xxhdpi/ic_demo_on.png deleted file mode 100644 index b55c5636a3c52df8875555ec7e8841dd7891ef67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1343 zcmV-F1;F}=P)Px(`AI}URCodHn_I{gRTRg+%AzkcO;E`|#Jrn|S!&=VEJ(!%K~aJp>?uoBsOW+O zed&vsp@OK0Dbhn(J$fndK~xkk(M7Nqk<5n#HN><`&3=D$<1p?$v*(;SbLO1c3;ygg zYp+>*t^e%X?BR5D1PKfT1_A?tfxtjuz|Fu=s%E*XL(L&5xB&(PD(+`sDyrLevHt$* zpxGNC=o-KK21@QR@N$G4(~CCUtFHF1Zlr(GLeMRAW2;Tgo$Qxd$T7WWKXngOnWVua z|5pM*B5Fxh3DVFyl0uFM(u6$%R8Cfsu^CEfP_mf<)j~pc3=Z1QPu_ zBRQsrb#Y%?%Sf_24@|=!F8wF{G-eehMB1 zrIaB=wHug#n^m462F-h=k`+XA9W;v+Te}+Kh4!Wg6CO!F>K;z0Z$?!g8cm8>C8#H{X#`^(mK#6QjFi@v@yUlv;NqfcEt1t zdacBT%Nw+)kAWtkJj-wJ`>qq@2hV{* zWDBjtNpM|jX-+%y*?^6baQVnXues?V5}m7h2w(&wWwjyk<=tOd2sbtVp-F{!8b15J}IS~da2%O9z;%{%Ji zdX?D^lH^$`e*tm7KGz!7T6LQ)8fw1*ThP-S(anq4zv8elYWe>>VsC3FuKO1Ip2k5L z%K4TAb~*xk2>q#uz23#tqtfI94B|xCu2*B{<1ekf-0KfV63}Wf(9yz@h@DArp~E(= z)~?#zV=F(3-%zIO*^%J4I|9=l#I}^{yPNNh_kC<_n$8bwjTA9uO zTXNEA%g`P8$PSF6e)e#!!@knXbRx8MbFE~%K{P4b@2|1(NmLW}$-Dl3r%c;~Vp3kw zdCx9jBgCc?NsoA>^E@`%C(ZP*Ev<>3>>*$yB1yN8dwO_eRoE8|k61FBXdW`dAc+iD zotFPWnOkjv8+4Yv9N1PX7a1y{=+)pS;7Yhw{ZV{A(`bf#R)>0Hn1X{5 z^*XWKub0|M7JW;qMiaH3c&)u9e%}Fn4Qojz5`xy8@iwSu9@6gmEl|q$D&opTUc^f+ zhhG=DZ(=SHw1AUw#CRUWhmPx7JL5*oW2L5QFwvd!An7zV`hr?X(JGX5JbR7$%KyJC z>2uNRmFzZ_q<5l=&p%r&c9m82A@k@r{tH|`URgFAiFctlz35$sO{LZ9G3q&5**eR@ zM48@*uS1I7)b|1%YXk`l1O@^Ffq}q4V4yAr{s&YJDhCFtLd^gG002ovPDHLkV1o7< BgUA2? diff --git a/app/src/main/res/drawable-xxxhdpi/ic_demo_off.png b/app/src/main/res/drawable-xxxhdpi/ic_demo_off.png deleted file mode 100644 index 3c8545ecd066c7f35a7b7605b8b49f51860be02e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1689 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 + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/code_braces.xml b/app/src/main/res/drawable/code_braces.xml new file mode 100644 index 0000000..50f01a8 --- /dev/null +++ b/app/src/main/res/drawable/code_braces.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_settings_black_24dp.xml b/app/src/main/res/drawable/ic_settings_black_24dp.xml new file mode 100644 index 0000000..24a5623 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/twitter.xml b/app/src/main/res/drawable/twitter.xml new file mode 100644 index 0000000..ae08ca6 --- /dev/null +++ b/app/src/main/res/drawable/twitter.xml @@ -0,0 +1,8 @@ + + + + \ 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 index 5caafb8..056a9b7 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,20 +1,27 @@ - - + android:layout_height="?attr/actionBarSize" + android:gravity="center"> - + + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/string.xml b/app/src/main/res/values-fr/string.xml deleted file mode 100644 index 9d050cf..0000000 --- a/app/src/main/res/values-fr/string.xml +++ /dev/null @@ -1,17 +0,0 @@ - - Demo Mode tile - Demo mode - Autorisations - Pour que cette application fonctionne, elle a besoin de l\'autorisation \"DUMP\". Malheureusement, cela n\'est possible qu\'à partir d\'un \"shell adb\" depuis votre ordinateur :\n\nadb -d shell pm grant com.franco.demomode android.permission.DUMP\n\nPour plus de transparence, le code source de cette application est disponible. - Pour que cette application fonctionne, elle a besoin de l\'autorisation \"WRITE_SECURE_SETTINGS\". Malheureusement, cela n\'est possible qu\'à partir d\'un \"shell adb\" depuis votre ordinateur :\n\nadb -d shell pm grant com.franco.demomode android.permission.WRITE_SECURE_SETTINGS\n\nPour plus de transparence, le code source de cette application est disponible. - Non - OK - Autorisation \"DUMP\" - Autorisation \"WRITE_SECURE_SETTINGS\" - Non accordée - Autorisations - Accordée - Suivez-moi - Code source - Les deux autorisations doivent être accordées pour que la tuile puisse fonctionner - diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml deleted file mode 100644 index 1b32e1b..0000000 --- a/app/src/main/res/values-it/strings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - Demo Mode tile - Demo mode - Demo mode tile richesta dei permessi - Perchè l\'applicazione funzioni è necessario dare il consenso al permesso DUMP. Sfortunatamente questo è possibile solo tramite adb shell dal tuo computer:\n\nadb -d shell pm grant com.franco.demomode android.permission.DUMP\n\nPer trasparenza, il codice sorgente di questa applicazione è disponibile. - Perchè l\'applicazione funzioni è necessario dare il consenso al permesso WRITE_SECURE_SETTINGS. Sfortunatamente questo è possibile solo tramite adb shell dal tuo computer:\n\nadb -d shell pm grant com.franco.demomode android.permission.WRITE_SECURE_SETTINGS\n\nPer trasparenza, il codice sorgente di questa applicazione è disponibile. - No - OK - android.permission.DUMP - android.permission.WRITE_SECURE_SETTINGS - Negato - Permessi - Consentito - Seguimi - Codice sorgente - Entrambi i permessi sono necessari perchè il tile funzioni correttamente - diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml deleted file mode 100644 index aeb9789..0000000 --- a/app/src/main/res/values-tr/strings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - Demo Mode Tile - Demo Modu - Demo modu blok izni isteği - Bu uygulamanın çalışması için DUMP izninin verilmesi gerekiyor. Ne yazık ki, bu yalnızca bilgisayarınızdaki ADB Shell ile mümkündür:\n\nadb -d shell pm grant com.franco.demomode android.permission.DUMP\n\nŞeffaflık için bu uygulamanın kaynak kodu mevcuttur. - Bu uygulamanın çalışması için WRITE_SECURE_SETTINGS izni verilmesi gerekiyor. Ne yazık ki, bu yalnızca bilgisayarınızdaki ADB Shell ile mümkündür:\n\nadb -d shell pm grant com.franco.demomode android.permission.WRITE_SECURE_SETTINGS\n\nŞeffaflık için bu uygulamanın kaynak kodu mevcuttur. - Hayır - EVET - android.permission.DUMP - android.permission.WRITE_SECURE_SETTINGS - Verilmemiş - İzinler - Verildi - Beni takip et - Kaynak kodu - Bloğun çalışması için her iki izinin de verilmesi gerekir - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1194ad3..b636baa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,7 +4,6 @@ Demo mode tile permission request For this app to work it needs DUMP permission to be granted. Unfortunately that is only possible through adb shell from your computer:\n\nadb -d shell pm grant com.franco.demomode android.permission.DUMP\n\nFor transparency this app\'s source code is available. For this app to work it needs WRITE_SECURE_SETTINGS permission to be granted. Unfortunately that is only possible through adb shell from your computer:\n\nadb -d shell pm grant com.franco.demomode android.permission.WRITE_SECURE_SETTINGS\n\nFor transparency this app\'s source code is available. - No OK DUMP WRITE_SECURE_SETTINGS diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index fb14d31..7a6748f 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,6 +1,6 @@ -