diff --git a/app/build.gradle b/app/build.gradle index 18c9c58..e2223c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.flx_apps.digitaldetox" minSdkVersion 21 targetSdkVersion 29 - versionCode 10000 - versionName "1.0.0" + versionCode 10001 + versionName "1.0.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -62,6 +62,10 @@ dependencies { annotationProcessor "org.androidannotations:androidannotations:4.7.0" implementation "org.androidannotations:androidannotations-api:4.7.0" kapt "org.androidannotations:androidannotations:4.7.0" + + // About Info Screen + implementation 'com.github.ditacristianionut:AppInfoBadge:1.3' + // implementation 'androidx.room:room-runtime:2.3.0-alpha03' // kapt 'androidx.room:room-compiler:2.3.0-alpha03' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 92b9a75..e423d0c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,13 +14,15 @@ + android:theme="@style/AppTheme" + tools:replace="android:label"> + @@ -31,8 +33,8 @@ @@ -46,24 +48,11 @@ android:name=".QuickSettingsTileService" android:icon="@drawable/ic_quick_settings_tile" android:label="@string/app.quickSettingsTile" - android:permission="android.permission.BIND_QUICK_SETTINGS_TILE" - > + android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/flx_apps/digitaldetox/AboutFragment.kt b/app/src/main/java/com/flx_apps/digitaldetox/AboutFragment.kt new file mode 100644 index 0000000..b397115 --- /dev/null +++ b/app/src/main/java/com/flx_apps/digitaldetox/AboutFragment.kt @@ -0,0 +1,47 @@ +package com.flx_apps.digitaldetox + +import android.net.Uri +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import com.dci.dev.appinfobadge.AppInfoBadge +import com.dci.dev.appinfobadge.BaseInfoItem +import com.dci.dev.appinfobadge.InfoItemWithLink + +class AboutFragment : Fragment() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val appInfoBadgeFragment = AppInfoBadge + .headerColor { ContextCompat.getColor(context!!, R.color.colorPrimaryDark) } + .withAppIcon { true } + .withCustomItems { listOf( + InfoItemWithLink( + iconId = R.drawable.ic_coffee, + title = getString(R.string.about_coffee), + link = Uri.parse(getString(R.string.about_coffee_link)) + ), + InfoItemWithLink( + iconId = R.drawable.ic_patron, + title = getString(R.string.about_patron), + link = Uri.parse(getString(R.string.about_patron_link)) + ), + InfoItemWithLink( + iconId = R.drawable.ic_contact_mail_3, + title = getString(R.string.about_contact), + link = Uri.parse(getString(R.string.about_contact_link)) + ), + InfoItemWithLink( + iconId = R.drawable.ic_contact_site_github, + title = getString(R.string.about_github), + link = Uri.parse(getString(R.string.about_github_link)) + ) + )} + .withPermissions { false } + .withRater { false } + .withChangelog { false } + .withLibraries { false } + .withLicenses { false } + .show() + fragmentManager!!.beginTransaction().replace(R.id.nav_host_fragment, appInfoBadgeFragment).commit() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/flx_apps/digitaldetox/AppExceptionsListAdapter.kt b/app/src/main/java/com/flx_apps/digitaldetox/AppExceptionsListAdapter.kt index 5aae047..d77da73 100644 --- a/app/src/main/java/com/flx_apps/digitaldetox/AppExceptionsListAdapter.kt +++ b/app/src/main/java/com/flx_apps/digitaldetox/AppExceptionsListAdapter.kt @@ -4,34 +4,34 @@ import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.CheckBox import android.widget.ImageView import android.widget.TextView +import androidx.appcompat.widget.SwitchCompat import androidx.recyclerview.widget.RecyclerView import org.androidannotations.annotations.EBean @EBean open class AppExceptionsListAdapter(context: Context) : RecyclerView.Adapter() { - lateinit var values: List + lateinit var values: List var prefs: Prefs_ = Prefs_(context) - data class AppWhitelistItem(val title: String, val pckg: String) { + data class AppExceptionListItem(val title: String, val pckg: String) { var isException = false } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context) - .inflate(R.layout.fragment_app_whitelist_list_item, parent, false) + .inflate(R.layout.fragment_app_exceptions_list_item, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = values[position] - val context = holder.appIcon.context holder.appTitle.text = item.title + holder.appPackage.text = item.pckg holder.appIcon.setImageDrawable(holder.appIcon.context.packageManager.getApplicationIcon(item.pckg)) - holder.btnSetWhitelisted.setOnCheckedChangeListener { button, b -> + holder.btnToggleExceptionState.setOnCheckedChangeListener { _, b -> item.isException = b prefs.edit().grayscaleExceptions().put( prefs.grayscaleExceptions().get().let { @@ -39,14 +39,15 @@ open class AppExceptionsListAdapter(context: Context) : RecyclerView.Adapter = ArrayList() + val appList: MutableList = ArrayList() apps?.iterator()?.forEach { appList.add( - AppExceptionsListAdapter.AppWhitelistItem( + AppExceptionsListAdapter.AppExceptionListItem( it.loadLabel(pm) as String, it.packageName ) @@ -43,7 +43,7 @@ open class AppExceptionsListFragment : Fragment() { } @UiThread - open fun initAdapter(appList: List) { + open fun initAdapter(appList: List) { if (!this::list.isInitialized) return with(list) { diff --git a/app/src/main/java/com/flx_apps/digitaldetox/DetoxAccessibilityService.kt b/app/src/main/java/com/flx_apps/digitaldetox/DetoxAccessibilityService.kt index 4405121..4e0b35a 100644 --- a/app/src/main/java/com/flx_apps/digitaldetox/DetoxAccessibilityService.kt +++ b/app/src/main/java/com/flx_apps/digitaldetox/DetoxAccessibilityService.kt @@ -2,8 +2,11 @@ package com.flx_apps.digitaldetox import android.accessibilityservice.AccessibilityService import android.app.NotificationManager +import android.content.Context import android.view.KeyEvent +import android.view.WindowManager import android.view.accessibility.AccessibilityEvent +import android.view.inputmethod.InputMethodManager import org.androidannotations.annotations.EService import org.androidannotations.annotations.SystemService import org.androidannotations.annotations.sharedpreferences.Pref @@ -22,36 +25,58 @@ open class DetoxAccessibilityService : AccessibilityService() { @SystemService lateinit var notificationManager: NotificationManager - private var isGrayscale = false private var lastPackage = "" private var isPausing = false + private var ignoredEventClasses = mutableSetOf( + "android.inputmethodservice.SoftInputWindow", + "com.android.systemui.volume" + ) + private var ignoredPackages = mutableSetOf() + + override fun onCreate() { + super.onCreate() + + // add all known keyboard packages to list of apps where we will not interfere with grayscale / color settings + (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).enabledInputMethodList.forEach { + log(it.packageName) + ignoredPackages.add(it.packageName) + } + } override fun onAccessibilityEvent(accessibilityEvent: AccessibilityEvent) { +// log("event=$accessibilityEvent") + log("package=${accessibilityEvent.packageName}, class=${accessibilityEvent.className}, event=${accessibilityEvent.eventType}") + val now = System.currentTimeMillis() isPausing = now < prefs.pauseUntil().get() + // TYPE_ASSIST_READING_CONTEXT happens when the home button is long-pressed if (accessibilityEvent.eventType == AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT) { isPausing = DetoxUtil.togglePause(baseContext) isGrayscale = !isPausing } - val exceptions = setOf( - "android.inputmethodservice.SoftInputWindow", - "com.android.systemui.volume.VolumeDialogImpl\$CustomDialog" - ) - if (isPausing || accessibilityEvent.packageName == lastPackage || accessibilityEvent.text.isNullOrEmpty() || accessibilityEvent.contentChangeTypes != AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED || exceptions.contains( - accessibilityEvent.className - )) return + // decide whether we want to handle this event or not + var skipEvent = isPausing + || ignoredPackages.contains(accessibilityEvent.packageName) + || accessibilityEvent.packageName == lastPackage + || accessibilityEvent.text.isNullOrEmpty() + || accessibilityEvent.contentChangeTypes != AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED + ignoredEventClasses.forEach { + skipEvent = skipEvent || accessibilityEvent.className.contains(it) + } + if (skipEvent) { log("skip..."); return } + lastPackage = accessibilityEvent.packageName.toString() - log(accessibilityEvent.toString()) + // forcefully enable DoNotDisturb DetoxUtil.setZenMode(applicationContext, true) - val grayscale = prefs.grayscaleEnabled().get() && !prefs.grayscaleExceptions().get().contains( - accessibilityEvent.packageName - ) - if (grayscale != isGrayscale) { + // decide whether we want to grayscale or color the screen + val grayscale = prefs.grayscaleEnabled().get() + && !prefs.grayscaleExceptions().get().contains(accessibilityEvent.packageName) + if (grayscale != isGrayscale) { // wantedState != currentState DetoxUtil.setGrayscale(applicationContext, grayscale) isGrayscale = grayscale } @@ -59,6 +84,7 @@ open class DetoxAccessibilityService : AccessibilityService() { override fun onKeyEvent(event: KeyEvent?): Boolean { // TODO: implement pause feature here? + log("onKeyEvent=$event") return super.onKeyEvent(event) } diff --git a/app/src/main/java/com/flx_apps/digitaldetox/DetoxUtil.kt b/app/src/main/java/com/flx_apps/digitaldetox/DetoxUtil.kt index 4769f57..72670cf 100644 --- a/app/src/main/java/com/flx_apps/digitaldetox/DetoxUtil.kt +++ b/app/src/main/java/com/flx_apps/digitaldetox/DetoxUtil.kt @@ -57,7 +57,7 @@ object DetoxUtil { DISPLAY_DALTONIZER, if (grayscale) 0 else -1 ) - return result1 && result2; + return result1 && result2 } @JvmStatic @@ -106,12 +106,42 @@ object DetoxUtil { ): Boolean { val now = System.currentTimeMillis() val prefs = Prefs_(context) - val isPausing = !(now < prefs.pauseUntil().get()) // new pause state: inversion of "are we currently pausing?" + var isPausing = (now < prefs.pauseUntil().get()) + if (!isPausing && now < prefs.nextPauseAllowedAt().get()) { + // we are currently not in a pause, and a pause is not allowed right now either + Toast.makeText( + context, + context.getString( + R.string.app_quickSettingsTile_noPause, + TimeUnit.MILLISECONDS.toMinutes(prefs.nextPauseAllowedAt().get() - now) + 1 + ), + Toast.LENGTH_SHORT + ).show() + return false + } + + isPausing = !isPausing // new pause state: inversion of "are we currently pausing?" prefs.edit().pauseUntil().put(if (isPausing) now + TimeUnit.MINUTES.toMillis(prefs.pauseDuration().get().toLong()) else -1).apply() setGrayscale(context, !isPausing) setZenMode(context, !isPausing) if (isPausing) { - Toast.makeText(context, context.getString(R.string.app_quickSettingsTile_paused, prefs.pauseDuration().get()), Toast.LENGTH_SHORT).show() + // a pause was made, let's show a hint to the user + Toast.makeText( + context, + context.getString( + R.string.app_quickSettingsTile_paused, + prefs.pauseDuration().get() + ), + Toast.LENGTH_SHORT + ).show() + prefs.edit().nextPauseAllowedAt() + .put(prefs.pauseUntil().get() + TimeUnit.MINUTES.toMillis(prefs.timeBetweenPauses().get().toLong())) + .apply() + } else { + // a pause was interrupted + prefs.edit().nextPauseAllowedAt() + .put(now + TimeUnit.MINUTES.toMillis(prefs.timeBetweenPauses().get().toLong())) + .apply() } return isPausing } diff --git a/app/src/main/java/com/flx_apps/digitaldetox/HomeFragment.kt b/app/src/main/java/com/flx_apps/digitaldetox/HomeFragment.kt index 9f2aa6c..635f074 100644 --- a/app/src/main/java/com/flx_apps/digitaldetox/HomeFragment.kt +++ b/app/src/main/java/com/flx_apps/digitaldetox/HomeFragment.kt @@ -6,6 +6,7 @@ import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.provider.Settings +import android.widget.Button import android.widget.NumberPicker import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment @@ -43,7 +44,7 @@ open class HomeFragment : Fragment() { return } - setDetoxIsActive(prefs.isRunning().get()) + setDetoxIsActive(prefs.isRunning.get()) } @AfterViews @@ -88,7 +89,7 @@ open class HomeFragment : Fragment() { } btnToggleGrayscale.isChecked = prefs.grayscaleEnabled().get() if (prefs.isRunning.get()) { - DetoxUtil.setGrayscale(context!!, btnToggleGrayscale.isChecked) + DetoxUtil.setGrayscale(context!!, btnToggleGrayscale.isChecked && !prefs.grayscaleExceptions().get().contains(context!!.packageName)) } } @@ -99,18 +100,22 @@ open class HomeFragment : Fragment() { ?.addToBackStack(javaClass.name)?.commit() } - @Click - fun btnSetPauseDurationClicked() { + @Click(R.id.btnSetPauseDuration, R.id.btnSetTimeBetweenPauses) + fun btnConfigurePauseClicked(btn: Button) { val numberPicker = NumberPicker(context).apply { - minValue = 1 + minValue = if (btn.id == R.id.btnSetPauseDuration) 1 else 0 maxValue = 60 - value = prefs.pauseDuration().get() + value = if (btn.id == R.id.btnSetPauseDuration) prefs.pauseDuration().get() else prefs.timeBetweenPauses().get() } MaterialAlertDialogBuilder(context!!).apply { - setTitle(R.string.home_pauseButton_setDuration) + setTitle(btn.text) setView(numberPicker) setPositiveButton(R.string.action_save) { _, _ -> - prefs.edit().pauseDuration().put(numberPicker.value).apply() + val editorField = when (btn.id) { + R.id.btnSetPauseDuration -> prefs.edit().pauseDuration() + else -> prefs.edit().timeBetweenPauses() + } + editorField.put(numberPicker.value).apply() } setNegativeButton(R.string.action_cancel, null) }.show() diff --git a/app/src/main/java/com/flx_apps/digitaldetox/MainActivity.kt b/app/src/main/java/com/flx_apps/digitaldetox/MainActivity.kt index 7500d2b..5e0ac89 100644 --- a/app/src/main/java/com/flx_apps/digitaldetox/MainActivity.kt +++ b/app/src/main/java/com/flx_apps/digitaldetox/MainActivity.kt @@ -2,10 +2,14 @@ package com.flx_apps.digitaldetox import android.os.Bundle import android.view.Menu +import android.view.MenuItem import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.drawerlayout.widget.DrawerLayout -import androidx.navigation.findNavController +import androidx.fragment.app.Fragment +import androidx.navigation.* +import androidx.navigation.fragment.FragmentNavigator +import androidx.navigation.fragment.FragmentNavigatorDestinationBuilder import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController @@ -31,9 +35,11 @@ class MainActivity : AppCompatActivity() { // menu should be considered as top level destinations. appBarConfiguration = AppBarConfiguration( setOf( - R.id.nav_home + R.id.nav_home, + R.id.nav_about ), drawerLayout ) + setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) } diff --git a/app/src/main/java/com/flx_apps/digitaldetox/Prefs.kt b/app/src/main/java/com/flx_apps/digitaldetox/Prefs.kt index 0b33ef3..4c0b8d1 100644 --- a/app/src/main/java/com/flx_apps/digitaldetox/Prefs.kt +++ b/app/src/main/java/com/flx_apps/digitaldetox/Prefs.kt @@ -25,4 +25,10 @@ interface Prefs { @DefaultInt(1) fun pauseDuration(): Int + + @DefaultLong(-1) + fun nextPauseAllowedAt(): Long + + @DefaultInt(5) + fun timeBetweenPauses(): Int } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_coffee.xml b/app/src/main/res/drawable/ic_coffee.xml new file mode 100644 index 0000000..1e7fe77 --- /dev/null +++ b/app/src/main/res/drawable/ic_coffee.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml new file mode 100644 index 0000000..17255b7 --- /dev/null +++ b/app/src/main/res/drawable/ic_info.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_patron.xml b/app/src/main/res/drawable/ic_patron.xml new file mode 100644 index 0000000..903bae8 --- /dev/null +++ b/app/src/main/res/drawable/ic_patron.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_app_exceptions.xml b/app/src/main/res/layout/fragment_app_exceptions.xml index b65d83d..924f52d 100644 --- a/app/src/main/res/layout/fragment_app_exceptions.xml +++ b/app/src/main/res/layout/fragment_app_exceptions.xml @@ -10,11 +10,11 @@ android:name="com.flx_apps.digitaldetox.AppItemFragment" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginLeft="16dp" - android:layout_marginRight="16dp" + android:paddingLeft="16dp" + android:paddingRight="16dp" app:layoutManager="LinearLayoutManager" tools:context=".AppExceptionsListFragment" - tools:listitem="@layout/fragment_app_whitelist_list_item" /> + tools:listitem="@layout/fragment_app_exceptions_list_item" /> + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_app_whitelist_list_item.xml b/app/src/main/res/layout/fragment_app_whitelist_list_item.xml deleted file mode 100644 index 25959d2..0000000 --- a/app/src/main/res/layout/fragment_app_whitelist_list_item.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 303bab2..f9a55e4 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -100,6 +100,13 @@ android:layout_height="wrap_content" android:text="@string/home.pauseButton.setDuration" /> + + diff --git a/app/src/main/res/layout/fragment_home_card.xml b/app/src/main/res/layout/fragment_home_card.xml index 654b719..2429074 100644 --- a/app/src/main/res/layout/fragment_home_card.xml +++ b/app/src/main/res/layout/fragment_home_card.xml @@ -42,7 +42,7 @@ android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal"> + android:orientation="vertical"> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_no_permissions.xml b/app/src/main/res/layout/fragment_no_permissions.xml index f2cadb0..b5699e6 100644 --- a/app/src/main/res/layout/fragment_no_permissions.xml +++ b/app/src/main/res/layout/fragment_no_permissions.xml @@ -1,17 +1,36 @@ - + + + android:text="@string/noPermissions.text" + android:textAppearance="@style/TextAppearance.AppCompat.Medium" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/appCompatImageView" /> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml index 44cb0d3..6b40df8 100644 --- a/app/src/main/res/layout/nav_header_main.xml +++ b/app/src/main/res/layout/nav_header_main.xml @@ -23,12 +23,12 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/nav_header_vertical_spacing" - android:text="@string/app.name" + android:text="@string/app.name_" android:textAppearance="@style/TextAppearance.AppCompat.Body1" /> + android:text="@string/app.subtitle" /> \ No newline at end of file diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml index 9f9d9f1..d584d3c 100644 --- a/app/src/main/res/menu/activity_main_drawer.xml +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -7,5 +7,8 @@ + \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 8128060..edb84a9 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -10,4 +10,9 @@ android:name="com.flx_apps.digitaldetox.HomeFragment_" android:label="@string/navigation.home" tools:layout="@layout/fragment_home" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index caeeaa7..4108c0f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,9 +1,10 @@ - DetoxDroid - detoxdroid.flx-apps.com + DetoxDroid + detoxdroid.flx-apps.com Pause DetoxDroid DetoxDroid has been paused for %d minutes. + Take another pause in %d minutes. DetoxDroid Accessibility Service This services disables and enables grayscale mode depending on which app is currently open. It also reacts to long-pressing the home button and manages detoxing mode pauses. @@ -18,6 +19,7 @@ Click to (de-)activate Home + About Donate Welcome to DetoxDroid! @@ -31,20 +33,32 @@ Automatic Grayscale Color up by coloring down your phone Strip away all the neuron-stimulating colors (hint: you can add your camera and gallery app to the exceptions). + Gray + Colors + Ignored Pause Button Take a break from taking a break - DetoxDroid can be paused for a defined period of time, for example if you want to take a quick look on a photo somebody sent you. It will automatically come back into life, once the pause is over. A pause can be made by pressing the quick settings tile or by long-pressing the home button. + DetoxDroid can be paused for a defined period of time, for example if you want to take a quick look on a photo somebody sent you. It will automatically come back into life, once the pause is over. A pause can be made by pressing the quick settings tile or by long-pressing the home button. You can also set a minimum time between the pauses to prevent yourself from tricking yourself by pausing all the time. Set Pause Duration + Set Time Between Pauses - Donate - DetoxDroid is open-source and without ads. If you find the app useful, please consider leaving a donation to support the development of the app. + Buy me a coffee + https://ko-fi.com/flxapps + Become a patron + https://liberapay.com/DetoxDroid/donate + Contact me + mailto:detoxdroid@flx-apps.com + Contribute on GitHub + https://github.com/flxapps/DetoxDroid - You need to grant this app elevated privileges from your computer.\n\n - Please visit https://detoxdroid.flx-apps.com/ to find out how. + You need to grant this app elevated privileges from your computer. + \n\nDon\'t worry, it takes you only a couple of minutes: Please visit https://detoxdroid.flx-apps.com/ to find out how. + + Hello blank fragment \ No newline at end of file diff --git a/build.gradle b/build.gradle index bbbf0e6..3a2c356 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,7 @@ allprojects { repositories { google() jcenter() + maven { url "https://jitpack.io" } } } diff --git a/fastlane/metadata/android/en-US/changelogs/10000.txt b/fastlane/metadata/android/en-US/changelogs/10000.txt new file mode 100644 index 0000000..03081f0 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/10000.txt @@ -0,0 +1 @@ +Initial release \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/10001.txt b/fastlane/metadata/android/en-US/changelogs/10001.txt new file mode 100644 index 0000000..1ba7c7b --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/10001.txt @@ -0,0 +1 @@ +Implemented "minimum time between pauses" feature \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b2137c0 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Nov 15 11:19:38 CET 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/install/README.txt b/install/README.txt new file mode 100644 index 0000000..913a353 --- /dev/null +++ b/install/README.txt @@ -0,0 +1,42 @@ +=========================================================== + + DETOXDROID INSTALLATION INSTRUCTIONS + +=========================================================== + +BEFORE RUNNING THE INSTALLATION SCRIPT: + +If you haven't already, you need to enable USB debugging on +your phone. In order to do this, follow these steps: + +1. Go to Android Settings → System → About Phone + +2. Look for the build number option and touch it + multiple times. A message should appear saying that + developer mode has been enabled. + +3. Go to Android Settings → System → Developer Options. + Look for USB debugging and enable it. + +4. Connect your device with your computer. + +The following video will also show you these steps: +https://www.youtube.com/watch?v=0usgePpr8_Y + +=========================================================== + +RUNNING THE INSTALLATION SCRIPT: + + * If you are on Windows, you should be able to run + "install_windows.bat" by simply double-clicking the file. + + * If you are on Mac/Linux, you should be able to run the + installation script from the console using + "bash install_.sh" + +=========================================================== + +If you do not trust the installation scripts, you can +always follow the manual installation steps on: + +https://github.com/flxapps/DetoxDroid/wiki/Manual-Installation diff --git a/releases/1.0.0/release/app-release.apk b/releases/1.0.0/release/app-release.apk new file mode 100644 index 0000000..3771b20 Binary files /dev/null and b/releases/1.0.0/release/app-release.apk differ diff --git a/releases/1.0.0/release/output-metadata.json b/releases/1.0.0/release/output-metadata.json new file mode 100644 index 0000000..0818e2f --- /dev/null +++ b/releases/1.0.0/release/output-metadata.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.flx_apps.digitaldetox", + "variantName": "processReleaseResources", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "versionCode": 10000, + "versionName": "1.0.0", + "outputFile": "app-release.apk" + } + ] +} \ No newline at end of file diff --git a/releases/1.0.1/release/app-release.apk b/releases/1.0.1/release/app-release.apk new file mode 100644 index 0000000..fea389a Binary files /dev/null and b/releases/1.0.1/release/app-release.apk differ diff --git a/releases/1.0.1/release/output-metadata.json b/releases/1.0.1/release/output-metadata.json new file mode 100644 index 0000000..cf51aab --- /dev/null +++ b/releases/1.0.1/release/output-metadata.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.flx_apps.digitaldetox", + "variantName": "processReleaseResources", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "versionCode": 10001, + "versionName": "1.0.1", + "outputFile": "app-release.apk" + } + ] +} \ No newline at end of file