Skip to content

Commit

Permalink
v1.0.4 (#22)
Browse files Browse the repository at this point in the history
* Updated Gradle and Kotlin deps, minor cleanup, made the commands text selectable to allow copy/paste

* Added feature to view licenses

* Added feature to rate the app

* Added feature to request a feature

* Added Timber

* New features list implementation, Circle CI setup

* Added build status badge

* Added help menu item, bumped version numbers
  • Loading branch information
mustafa01ali authored Sep 19, 2017
1 parent 36f0eee commit e0282a4
Show file tree
Hide file tree
Showing 24 changed files with 300 additions and 80 deletions.
27 changes: 27 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: 2
jobs:
build:
working_directory: ~/code
docker:
- image: circleci/android:api-26-alpha
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Compile & Run Tests
command: ./gradlew assemble test
- store_artifacts:
path: app/build/reports
destination: reports
- store_test_results:
path: app/build/test-results
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Android Quick Settings tiles for developers. Works on Android 7.0+.

[![CircleCI](https://circleci.com/gh/mustafa01ali/Dev-Tiles.svg?style=svg)](https://circleci.com/gh/mustafa01ali/Dev-Tiles)

## Usage
1. Install the app
2. Grant permissions - `adb shell pm grant xyz.mustafaali.devqstiles android.permission.WRITE_SECURE_SETTINGS`, `adb shell pm grant xyz.mustafaali.devqstiles android.permission.DUMP`
Expand Down
20 changes: 13 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.gms.oss.licenses.plugin'

repositories {
mavenCentral()
google()
}

android {
compileSdkVersion 25
compileSdkVersion 26
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "xyz.mustafaali.devqstiles"
Expand All @@ -12,8 +18,8 @@ android {
// Writing show taps setting fails on higher versions
targetSdkVersion 22

versionCode 5
versionName "1.0.3"
versionCode 6
versionName "1.0.4"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand All @@ -36,10 +42,10 @@ dependencies {
})

compile "com.android.support:appcompat-v7:$support_lib_version"
compile "com.android.support:recyclerview-v7:$support_lib_version"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile 'com.google.android.gms:play-services-oss-licenses:11.2.2'
compile 'com.jakewharton.timber:timber:4.5.1'

testCompile 'junit:junit:4.12'
}
repositories {
mavenCentral()
}
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
tools:ignore="ProtectedPermissions" />

<application
android:name=".DevQSApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/kotlin/xyz/mustafaali/devqstiles/DevQSApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package xyz.mustafaali.devqstiles

import android.app.Application
import timber.log.Timber

class DevQSApplication : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}
}
69 changes: 63 additions & 6 deletions app/src/main/kotlin/xyz/mustafaali/devqstiles/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package xyz.mustafaali.devqstiles;

import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.text.Html
import android.support.v7.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import kotlinx.android.synthetic.main.activity_main.*
import timber.log.Timber
import xyz.mustafaali.devqstiles.model.Feature
import xyz.mustafaali.devqstiles.ui.FeaturesAdapter


class MainActivity : AppCompatActivity() {

Expand All @@ -22,18 +29,58 @@ class MainActivity : AppCompatActivity() {
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
return when (item.itemId) {
R.id.menu_help -> {
openHelpVideo()
true
}
R.id.menu_share_app -> {
shareApp()
return true
true
}
R.id.menu_rate_app -> {
openStoreListing()
true
}
R.id.menu_request_feature -> {
openEmailClient()
true
}
else -> return super.onOptionsItemSelected(item)
R.id.menu_oss_licenses -> {
startActivity(Intent(this, OssLicensesMenuActivity::class.java))
true
}
else -> super.onOptionsItemSelected(item)
}
}

private fun openStoreListing() {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("market://details?id=xyz.mustafaali.devqstiles")
try {
startActivity(intent)
} catch(e: ActivityNotFoundException) {
Timber.e("Couldn't launch activity, maybe PlayStore is not installed")
}
}

fun initUi() {
private fun openHelpVideo() {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://www.youtube.com/watch?v=tdSAobQq1nQ")))
}

private fun openEmailClient() {
val intent = Intent(Intent.ACTION_SEND)
intent.type = "message/rfc822"
intent.putExtra(android.content.Intent.EXTRA_EMAIL, arrayOf("[email protected]"))
intent.putExtra(Intent.EXTRA_SUBJECT, "[DevTiles] Feature Request")
startActivity(intent)
}

private fun initUi() {
copyButton.setOnClickListener({ sharePermissionsCommand() })
featuresDescriptionTextView.text = Html.fromHtml(getString(R.string.features_description), Html.FROM_HTML_MODE_COMPACT)
featuresRecyclerView.layoutManager = LinearLayoutManager(this)
featuresRecyclerView.setHasFixedSize(true)
featuresRecyclerView.adapter = FeaturesAdapter(getFeaturesList()) {}
}

private fun shareApp() {
Expand All @@ -51,4 +98,14 @@ class MainActivity : AppCompatActivity() {
sendIntent.type = "text/plain"
startActivity(sendIntent)
}

private fun getFeaturesList(): List<Feature> {
return listOf(
Feature("Toggle USB Debugging", "Enable/disable USB debugging from your notification drawer", R.drawable.ic_toggle_usb_debugging),
Feature("Keep Screen On", "Keep screen on when connected via USB, but turn it off when connected to a charger", R.drawable.ic_toggle_keep_screen_on),
Feature("Show Touches", "Show touch points when you touch the screen, ideal for demos", R.drawable.ic_toggle_show_taps),
Feature("Demo Mode", "Cleans up the status bar for those perfect screenshots", R.drawable.ic_toggle_demo_mode),
Feature("Change Animator Duration", "Change the default animator duration to easily debug animations", R.drawable.ic_animator_duration)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package xyz.mustafaali.devqstiles.model

data class Feature (val title: String, val description: String, val drawableId: Int)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package xyz.mustafaali.devqstiles.service

import android.annotation.SuppressLint
import android.graphics.drawable.Icon
import android.service.quicksettings.TileService
import android.support.v7.app.AlertDialog
Expand All @@ -15,7 +16,7 @@ import xyz.mustafaali.devqstiles.util.AnimatorDurationScaler.getIcon
*/
class ToggleAnimatorDurationService : TileService() {

val choices = arrayOf(
private val choices = arrayOf(
"Animation off",
"Animation scale .5x",
"Animation scale 1x",
Expand All @@ -25,7 +26,7 @@ class ToggleAnimatorDurationService : TileService() {
"Animation scale 10x"
)

val scales = listOf(
private val scales = listOf(
0f,
0.5f,
1f,
Expand All @@ -44,6 +45,7 @@ class ToggleAnimatorDurationService : TileService() {
showDialog(getDialog(scales.indexOf(current)))
}

@SuppressLint("RestrictedApi")
private fun getDialog(selectedIndex: Int): AlertDialog {
val builder = AlertDialog.Builder(ContextThemeWrapper(this, R.style.AppTheme_Dialog))
builder.setTitle(R.string.dialog_animator_duration_title)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import android.provider.Settings
*/
class ToggleDemoModeService : BaseTileService() {

val DEMO_MODE_ALLOWED = "sysui_demo_allowed"
val DEMO_MODE_ON = "sysui_tuner_demo_on"
private val DEMO_MODE_ALLOWED = "sysui_demo_allowed"
private val DEMO_MODE_ON = "sysui_tuner_demo_on"

val STATUS_ICONS = listOf(
private val STATUS_ICONS = listOf(
"volume",
"bluetooth",
"location",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ package xyz.mustafaali.devqstiles.service

import android.os.BatteryManager
import android.provider.Settings
import android.util.Log
import timber.log.Timber

/**
* Tile Service to keep the screen on when the device is connected to a USB port on a computer.
*
* If the device is connected to a wall charger, the screen will turn off.
*/
class ToggleKeepScreenOnService : BaseTileService() {
val TAG = javaClass.simpleName

override fun onClick() {
val newValue = if (isFeatureEnabled()) 0 else BatteryManager.BATTERY_PLUGGED_USB

Expand All @@ -27,7 +25,7 @@ class ToggleKeepScreenOnService : BaseTileService() {
try {
return Settings.Global.getInt(contentResolver, Settings.Global.STAY_ON_WHILE_PLUGGED_IN) == BatteryManager.BATTERY_PLUGGED_USB
} catch (e: Settings.SettingNotFoundException) {
Log.e(TAG, e.message)
Timber.e(e, e.message)
}
return false
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
package xyz.mustafaali.devqstiles.service

import android.provider.Settings
import android.util.Log
import android.widget.Toast

import xyz.mustafaali.devqstiles.R
import timber.log.Timber

class ToggleShowTapsService : BaseTileService() {
val TAG = this.javaClass.simpleName
val SHOW_TOUCHES = "show_touches"
private val SHOW_TOUCHES = "show_touches"

override fun onClick() {
val newValue = if (isFeatureEnabled()) 0 else 1

try {
Settings.System.putInt(contentResolver, SHOW_TOUCHES, newValue)
} catch (se: SecurityException) {
} catch (e: Exception) {
showPermissionError()
Log.e(TAG, se.message)
Timber.e(e, e.message)
}

updateTile()
}

override fun isFeatureEnabled(): Boolean {
try {
return Settings.System.getInt(contentResolver, SHOW_TOUCHES) == 1
return try {
Settings.System.getInt(contentResolver, SHOW_TOUCHES) == 1
} catch (e: Settings.SettingNotFoundException) {
e.printStackTrace()
return false
Timber.e(e, e.message)
false
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package xyz.mustafaali.devqstiles.service

import android.provider.Settings
import android.util.Log
import timber.log.Timber

/**
* Tile Service to toggle USB Debugging.
*/
class ToggleUsbDebuggingService : BaseTileService() {

val TAG = javaClass.simpleName

override fun onStartListening() {
super.onStartListening()
updateTile()
Expand All @@ -21,7 +19,7 @@ class ToggleUsbDebuggingService : BaseTileService() {
try {
Settings.Global.putString(contentResolver, Settings.Global.ADB_ENABLED, newValue)
} catch (se: SecurityException) {
Log.e(TAG, se.message)
Timber.e(se, se.message)
showPermissionError()
}
updateTile()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package xyz.mustafaali.devqstiles.ui

import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.feature_item_layout.view.*
import xyz.mustafaali.devqstiles.R
import xyz.mustafaali.devqstiles.model.Feature
import xyz.mustafaali.devqstiles.util.inflate

class FeaturesAdapter(val features: List<Feature>, val listener: (Feature) -> Unit) : RecyclerView.Adapter<FeaturesAdapter.ViewHolder>() {
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(feature: Feature, listener: (Feature) -> Unit) = with(itemView) {
featureImageView.setImageResource(feature.drawableId)
featureTitle.text = feature.title
featureDescription.text = feature.description
setOnClickListener { listener(feature) }
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(parent.inflate(R.layout.feature_item_layout))

override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(features[position], listener)

override fun getItemCount(): Int = features.size

}
Loading

0 comments on commit e0282a4

Please sign in to comment.