Overview
| Correctness | |
| 1 | warning OldTargetApi: Target SDK attribute is not targeting latest version |
| 8 | warning GradleDependency: Obsolete Gradle Dependency |
| 2 | warning DiscouragedApi: Using discouraged APIs |
| 1 | warning
UseCompatLoadingForDrawables: Should not call Context.getDrawable or Resources.getDrawable directly |
| Performance | |
| 6 | warning NotifyDataSetChanged: Invalidating All RecyclerView Data |
| 3 | warning ObsoleteSdkInt: Obsolete SDK_INT Version Check |
| 2 | warning
DisableBaselineAlignment: Missing baselineAligned attribute |
| 12 | warning Overdraw: Overdraw: Painting regions more than once |
| 2 | warning UselessParent: Unnecessary parent layout |
| 1 | warning TooManyViews: Layout has too many views |
| Usability | |
| 20 | warning SmallSp: Text size is too small |
| 4 | warning Autofill: Use Autofill |
| Accessibility | |
| 3 | warning ClickableViewAccessibility: Accessibility in Custom Views |
| Internationalization | |
| 42 | warning SetTextI18n: TextView Internationalization |
| 90 | warning HardcodedText: Hardcoded text |
| Included Additional Checks (29) | |
| Disabled Checks (39) |
Target SDK attribute is not targeting latest version
../../build.gradle.kts:14:
11 defaultConfig { 12 applicationId = "com.ratio.launcher" 13 minSdk = 26 14 targetSdk = 34 15 versionCode = 1 16 versionName = "1.0.0" 17 }
OldTargetApi
Correctness
Warning
Priority 6/10
Obsolete Gradle Dependency
../../build.gradle.kts:48:
45 } 46 47 dependencies { 48 implementation("androidx.core:core-ktx:1.12.0") 49 implementation("androidx.appcompat:appcompat:1.6.1") 50 implementation("com.google.android.material:material:1.11.0") 51 implementation("androidx.constraintlayout:constraintlayout:2.1.4")../../build.gradle.kts:49:
46 47 dependencies { 48 implementation("androidx.core:core-ktx:1.12.0") 49 implementation("androidx.appcompat:appcompat:1.6.1") 50 implementation("com.google.android.material:material:1.11.0") 51 implementation("androidx.constraintlayout:constraintlayout:2.1.4") 52 implementation("androidx.viewpager2:viewpager2:1.0.0")../../build.gradle.kts:50:
47 dependencies { 48 implementation("androidx.core:core-ktx:1.12.0") 49 implementation("androidx.appcompat:appcompat:1.6.1") 50 implementation("com.google.android.material:material:1.11.0") 51 implementation("androidx.constraintlayout:constraintlayout:2.1.4") 52 implementation("androidx.viewpager2:viewpager2:1.0.0") 53 implementation("androidx.recyclerview:recyclerview:1.3.2")../../build.gradle.kts:51:
48 implementation("androidx.core:core-ktx:1.12.0") 49 implementation("androidx.appcompat:appcompat:1.6.1") 50 implementation("com.google.android.material:material:1.11.0") 51 implementation("androidx.constraintlayout:constraintlayout:2.1.4") 52 implementation("androidx.viewpager2:viewpager2:1.0.0") 53 implementation("androidx.recyclerview:recyclerview:1.3.2") 54 implementation("androidx.cardview:cardview:1.0.0")../../build.gradle.kts:52:
49 implementation("androidx.appcompat:appcompat:1.6.1") 50 implementation("com.google.android.material:material:1.11.0") 51 implementation("androidx.constraintlayout:constraintlayout:2.1.4") 52 implementation("androidx.viewpager2:viewpager2:1.0.0") 53 implementation("androidx.recyclerview:recyclerview:1.3.2") 54 implementation("androidx.cardview:cardview:1.0.0") 55 implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")../../build.gradle.kts:53:
50 implementation("com.google.android.material:material:1.11.0") 51 implementation("androidx.constraintlayout:constraintlayout:2.1.4") 52 implementation("androidx.viewpager2:viewpager2:1.0.0") 53 implementation("androidx.recyclerview:recyclerview:1.3.2") 54 implementation("androidx.cardview:cardview:1.0.0") 55 implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") 56 implementation("androidx.fragment:fragment-ktx:1.6.2")../../build.gradle.kts:55:
52 implementation("androidx.viewpager2:viewpager2:1.0.0") 53 implementation("androidx.recyclerview:recyclerview:1.3.2") 54 implementation("androidx.cardview:cardview:1.0.0") 55 implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") 56 implementation("androidx.fragment:fragment-ktx:1.6.2") 57 implementation("io.sentry:sentry-android:8.34.0") 58 }../../build.gradle.kts:56:
53 implementation("androidx.recyclerview:recyclerview:1.3.2") 54 implementation("androidx.cardview:cardview:1.0.0") 55 implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") 56 implementation("androidx.fragment:fragment-ktx:1.6.2") 57 implementation("io.sentry:sentry-android:8.34.0") 58 }
GradleDependency
Correctness
Warning
Priority 4/10
Using discouraged APIs
../../src/main/java/com/ratio/launcher/utils/IconPackManager.kt:76:
73 74 return try { 75 val res = context.packageManager.getResourcesForApplication(packPackage) 76 val resId = res.getIdentifier(componentName, "drawable", packPackage) 77 if (resId != 0) res.getDrawable(resId, null) else null 78 } catch (_: Exception) { 79 null../../src/main/java/com/ratio/launcher/utils/IconPackManager.kt:88:
85 86 try { 87 val res = context.packageManager.getResourcesForApplication(packPackage) 88 val appfilterResId = res.getIdentifier("appfilter", "xml", packPackage) 89 90 if (appfilterResId != 0) { 91 val parser = res.getXml(appfilterResId)
DiscouragedApi
Correctness
Warning
Priority 2/10
Should not call Context.getDrawable or Resources.getDrawable directly
../../src/main/java/com/ratio/launcher/utils/IconPackManager.kt:77:
74 return try { 75 val res = context.packageManager.getResourcesForApplication(packPackage) 76 val resId = res.getIdentifier(componentName, "drawable", packPackage) 77 if (resId != 0) res.getDrawable(resId, null) else null 78 } catch (_: Exception) { 79 null 80 }
Vendor: Android Open Source Project
Identifier: androidx.appcompat
Feedback: https://issuetracker.google.com/issues/new?component=460343
Identifier: androidx.appcompat
Feedback: https://issuetracker.google.com/issues/new?component=460343
UseCompatLoadingForDrawables
Correctness
Warning
Priority 1/10
Invalidating All RecyclerView Data
../../src/main/java/com/ratio/launcher/adapters/AppListAdapter.kt:56:
53 allApps.filter { it.name.contains(query, ignoreCase = true) } 54 } 55 buildList(filtered) 56 notifyDataSetChanged() 57 } 58 59 private fun buildList(apps: List<AppInfo>) {../../src/main/java/com/ratio/launcher/adapters/AppListAdapter.kt:84:
81 fun collapseAll() { 82 categories.keys.forEach { categories[it] = false } 83 buildList(allApps) 84 notifyDataSetChanged() 85 } 86 87 fun expandAll() {../../src/main/java/com/ratio/launcher/adapters/AppListAdapter.kt:90:
87 fun expandAll() { 88 categories.keys.forEach { categories[it] = true } 89 buildList(allApps) 90 notifyDataSetChanged() 91 } 92 93 private fun showCategoryPicker(context: Context, app: AppInfo) {../../src/main/java/com/ratio/launcher/adapters/AppListAdapter.kt:175:
172 header.expanded = !header.expanded 173 categories[header.category] = header.expanded 174 buildList(allApps) 175 notifyDataSetChanged() 176 } 177 } 178 }../../src/main/java/com/ratio/launcher/fragments/RootFragment.kt:445:
442 dockApps.add(AppInfo(pm.getApplicationLabel(appInfo).toString(), pkg, pm.getApplicationIcon(pkg), "")) 443 } catch (_: PackageManager.NameNotFoundException) {} 444 } 445 dockAdapter.notifyDataSetChanged() 446 saveDockApps() 447 }../../src/main/java/com/ratio/launcher/fragments/RootFragment.kt:602:
599 dockApps.add(AppInfo(name = label, packageName = pkg, icon = icon, category = "")) 600 } catch (_: PackageManager.NameNotFoundException) {} 601 } 602 dockAdapter.notifyDataSetChanged() 603 } 604 }
NotifyDataSetChanged
Performance
Warning
Priority 8/10
Obsolete SDK_INT Version Check
../../src/main/java/com/ratio/launcher/utils/HapticHelper.kt:71:
68 } else { 69 @Suppress("DEPRECATION") 70 val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator 71 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 72 vibrator.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE)) 73 } else { 74 @Suppress("DEPRECATION")../../src/main/java/com/ratio/launcher/fragments/TilesFragment.kt:166:
163 } 164 165 private fun categorizeApp(appInfo: ApplicationInfo, pm: PackageManager): String { 166 val category = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { 167 appInfo.category 168 } else { 169 ApplicationInfo.CATEGORY_UNDEFINED../../src/main/java/com/ratio/launcher/utils/UsageGoalsManager.kt:50:
47 private fun showWarningNotification(context: Context, remainingMinutes: Int) { 48 val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 49 50 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 51 val channel = NotificationChannel( 52 CHANNEL_ID, "Usage Goals", 53 NotificationManager.IMPORTANCE_DEFAULT
ObsoleteSdkInt
Performance
Warning
Priority 6/10
Missing baselineAligned attribute
../../src/main/res/layout/fragment_root.xml:69:
66 </LinearLayout> 67 68 <!-- Media player card --> 69 <LinearLayout 70 android:id="@+id/mediaPlayerCard" 71 android:layout_width="match_parent" 72 android:layout_height="wrap_content"../../src/main/res/layout/fragment_root.xml:290:
287 </LinearLayout> 288 289 <!-- Weather details row --> 290 <LinearLayout 291 android:id="@+id/weatherDetailsRow" 292 android:layout_width="match_parent" 293 android:layout_height="wrap_content"
DisableBaselineAlignment
Performance
Warning
Priority 3/10
Overdraw: Painting regions more than once
../../src/main/res/layout/activity_clock_picker.xml:6:
3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="@color/ratio_black" 7 android:orientation="vertical" 8 android:gravity="center">../../src/main/res/layout/activity_main.xml:6:
3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="@color/ratio_black"> 7 8 <androidx.viewpager2.widget.ViewPager2 9 android:id="@+id/viewPager"../../src/main/res/layout/activity_note_editor.xml:6:
3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="@color/ratio_black" 7 android:orientation="vertical" 8 android:paddingTop="80dp" 9 android:paddingHorizontal="32dp"../../src/main/res/layout/activity_onboarding.xml:6:
3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="@color/ratio_black"> 7 8 <androidx.viewpager2.widget.ViewPager2 9 android:id="@+id/onboardingPager"../../src/main/res/layout/activity_reorder.xml:6:
3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:background="@color/ratio_black" 7 android:orientation="vertical" 8 android:paddingTop="80dp" 9 android:paddingHorizontal="32dp">+ 7 More Occurrences...
Overdraw
Performance
Warning
Priority 3/10
Unnecessary parent layout
../../src/main/res/layout/item_app_tile.xml:8:
5 android:layout_height="wrap_content" 6 android:padding="4dp"> 7 8 <LinearLayout 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:orientation="vertical"../../src/main/res/layout/item_clock_preview.xml:10:
7 android:background="@drawable/tile_background" 8 android:padding="24dp"> 9 10 <LinearLayout 11 android:layout_width="match_parent" 12 android:layout_height="match_parent" 13 android:orientation="vertical"
UselessParent
Performance
Warning
Priority 2/10
Layout has too many views
../../src/main/res/layout/activity_settings.xml:677:
674 </LinearLayout> 675 676 <!-- Divider --> 677 <View 678 android:layout_width="match_parent" 679 android:layout_height="0.5dp" 680 android:background="@color/gray_70"
TooManyViews
Performance
Warning
Priority 1/10
Text size is too small
../../src/main/res/layout/activity_settings.xml:36:
33 android:layout_height="wrap_content" 34 android:text="GENERAL" 35 android:textColor="@color/ratio_accent" 36 android:textSize="10sp" 37 android:fontFamily="@font/inter_medium" 38 android:letterSpacing="0.2" 39 android:layout_marginBottom="16dp" />../../src/main/res/layout/activity_settings.xml:217:
214 android:layout_height="wrap_content" 215 android:text="TILES" 216 android:textColor="@color/ratio_accent" 217 android:textSize="10sp" 218 android:fontFamily="@font/inter_medium" 219 android:letterSpacing="0.2" 220 android:layout_marginBottom="16dp" />../../src/main/res/layout/activity_settings.xml:389:
386 android:layout_height="wrap_content" 387 android:text="DIGITAL WELLBEING" 388 android:textColor="@color/ratio_accent" 389 android:textSize="10sp" 390 android:fontFamily="@font/inter_medium" 391 android:letterSpacing="0.2" 392 android:layout_marginBottom="16dp" />../../src/main/res/layout/activity_settings.xml:435:
432 android:layout_height="wrap_content" 433 android:text="WEATHER" 434 android:textColor="@color/ratio_accent" 435 android:textSize="10sp" 436 android:fontFamily="@font/inter_medium" 437 android:letterSpacing="0.2" 438 android:layout_marginBottom="16dp" />../../src/main/res/layout/activity_settings.xml:497:
494 android:layout_height="wrap_content" 495 android:text="ROOT CARDS" 496 android:textColor="@color/ratio_accent" 497 android:textSize="10sp" 498 android:fontFamily="@font/inter_medium" 499 android:letterSpacing="0.2" 500 android:layout_marginBottom="16dp" />+ 15 More Occurrences...
SmallSp
Usability
Warning
Priority 4/10
Use Autofill
../../src/main/res/layout/activity_note_editor.xml:56:
53 </LinearLayout> 54 55 <!-- Editor --> 56 <EditText 57 android:id="@+id/noteEditorText" 58 android:layout_width="match_parent" 59 android:layout_height="0dp"../../src/main/res/layout/activity_settings.xml:468:
465 </LinearLayout> 466 467 <!-- City --> 468 <EditText 469 android:id="@+id/settingsCity" 470 android:layout_width="match_parent" 471 android:layout_height="44dp"../../src/main/res/layout/fragment_root.xml:510:
507 android:gravity="center_vertical" 508 android:layout_marginTop="12dp"> 509 510 <EditText 511 android:id="@+id/noteInput" 512 android:layout_width="0dp" 513 android:layout_height="40dp"../../src/main/res/layout/fragment_tiles.xml:13:
10 android:focusableInTouchMode="true"> 11 12 <!-- Search Bar --> 13 <EditText 14 android:id="@+id/searchBar" 15 android:layout_width="match_parent" 16 android:layout_height="44dp"
Autofill
Usability
Warning
Priority 3/10
Accessibility in Custom Views
../../src/main/java/com/ratio/launcher/fragments/RootFragment.kt:564:
561 } 562 }) 563 564 view.setOnTouchListener { _, event -> 565 gestureDetector.onTouchEvent(event) 566 false 567 }../../src/main/java/com/ratio/launcher/fragments/TilesFragment.kt:125:
122 } 123 }) 124 125 appList.setOnTouchListener { _, event -> 126 gestureDetector.onTouchEvent(event) 127 false 128 }../../src/main/java/com/ratio/launcher/fragments/TilesFragment.kt:125:
122 } 123 }) 124 125 appList.setOnTouchListener { _, event -> 126 gestureDetector.onTouchEvent(event) 127 false 128 }
ClickableViewAccessibility
Accessibility
Warning
Priority 6/10
TextView Internationalization
../../src/main/java/com/ratio/launcher/MainActivity.kt:176:
173 // Battery 174 val bm = getSystemService(BATTERY_SERVICE) as BatteryManager 175 val level = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) 176 statusBattery.text = "$level%" 177 178 // WiFi/connectivity 179 val cm = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager../../src/main/java/com/ratio/launcher/OnboardingActivity.kt:88:
85 86 when (page) { 87 0 -> { 88 title.text = "Welcome to Ratio" 89 desc.text = "A mindful launcher that helps you\nfocus on what matters" 90 button.text = "GET STARTED" 91 button.setOnClickListener { (activity as OnboardingActivity).nextPage() }../../src/main/java/com/ratio/launcher/OnboardingActivity.kt:89:
86 when (page) { 87 0 -> { 88 title.text = "Welcome to Ratio" 89 desc.text = "A mindful launcher that helps you\nfocus on what matters" 90 button.text = "GET STARTED" 91 button.setOnClickListener { (activity as OnboardingActivity).nextPage() } 92 }../../src/main/java/com/ratio/launcher/OnboardingActivity.kt:89:
86 when (page) { 87 0 -> { 88 title.text = "Welcome to Ratio" 89 desc.text = "A mindful launcher that helps you\nfocus on what matters" 90 button.text = "GET STARTED" 91 button.setOnClickListener { (activity as OnboardingActivity).nextPage() } 92 }../../src/main/java/com/ratio/launcher/OnboardingActivity.kt:89:
86 when (page) { 87 0 -> { 88 title.text = "Welcome to Ratio" 89 desc.text = "A mindful launcher that helps you\nfocus on what matters" 90 button.text = "GET STARTED" 91 button.setOnClickListener { (activity as OnboardingActivity).nextPage() } 92 }+ 37 More Occurrences...
SetTextI18n
Internationalization
Warning
Priority 6/10
Hardcoded text
../../src/main/res/layout/activity_clock_picker.xml:14:
11 <TextView 12 android:layout_width="wrap_content" 13 android:layout_height="wrap_content" 14 android:text="Choose clock style" 15 android:textColor="@color/ratio_white" 16 android:textSize="20sp" 17 android:fontFamily="@font/ratio_light"../../src/main/res/layout/activity_clock_picker.xml:45:
42 android:layout_width="wrap_content" 43 android:layout_height="44dp" 44 android:gravity="center" 45 android:text="SELECT" 46 android:textColor="@color/ratio_accent" 47 android:textSize="14sp" 48 android:fontFamily="@font/inter_medium"../../src/main/res/layout/activity_note_editor.xml:24:
21 android:layout_width="0dp" 22 android:layout_height="wrap_content" 23 android:layout_weight="1" 24 android:text="Note" 25 android:textColor="@color/ratio_white" 26 android:textSize="24sp" 27 android:fontFamily="@font/ratio_light" />../../src/main/res/layout/activity_note_editor.xml:34:
31 android:layout_width="wrap_content" 32 android:layout_height="36dp" 33 android:gravity="center" 34 android:text="DELETE" 35 android:textColor="@color/ratio_gray_light" 36 android:textSize="12sp" 37 android:fontFamily="@font/inter_medium"../../src/main/res/layout/activity_note_editor.xml:46:
43 android:layout_width="wrap_content" 44 android:layout_height="36dp" 45 android:gravity="center" 46 android:text="SAVE" 47 android:textColor="@color/ratio_accent" 48 android:textSize="12sp" 49 android:fontFamily="@font/inter_medium"+ 85 More Occurrences...
HardcodedText
Internationalization
Warning
Priority 5/10
Included Additional Checks
This card lists all the extra checks run by lint, provided from libraries,
build configuration and extra flags. This is included to help you verify
whether a particular check is included in analysis when configuring builds.
(Note that the list does not include the hundreds of built-in checks into lint,
only additional ones.)
Disabled Checks
One or more issues were not run by lint, either
because the check is not enabled by default, or because
it was disabled with a command line flag or via one or
more
lint.xml configuration files in the project directories.
Suppressing Warnings and Errors
Lint errors can be suppressed in a variety of ways:
1. With a
2. With a
3. With a //noinspection comment in the source code
4. With ignore flags specified in the
5. With a
6. With a
7. With the --ignore flag passed to lint.
To suppress a lint warning with an annotation, add a
To suppress a lint warning with a comment, add a
To suppress a lint warning in an XML file, add a
To suppress a lint warning in a
Here we specify a comma separated list of issue id's after the disable command. You can also use
To suppress lint warnings with a configuration XML file, create a file named
The format of the
To suppress lint checks from the command line, pass the --ignore flag with a comma separated list of ids to be suppressed, such as:
For more information, see https://developer.android.com/studio/write/lint.html#config
1. With a
@SuppressLint annotation in the Java code2. With a
tools:ignore attribute in the XML file3. With a //noinspection comment in the source code
4. With ignore flags specified in the
build.gradle file, as explained below5. With a
lint.xml configuration file in the project6. With a
lint.xml configuration file passed to lint via the --config flag7. With the --ignore flag passed to lint.
To suppress a lint warning with an annotation, add a
@SuppressLint("id") annotation on the class, method or variable declaration closest to the warning instance you want to disable. The id can be one or more issue id's, such as "UnusedResources" or {"UnusedResources","UnusedIds"}, or it can be "all" to suppress all lint warnings in the given scope.To suppress a lint warning with a comment, add a
//noinspection id comment on the line before the statement with the error.To suppress a lint warning in an XML file, add a
tools:ignore="id" attribute on the element containing the error, or one of its surrounding elements. You also need to define the namespace for the tools prefix on the root element in your document, next to the xmlns:android declaration:xmlns:tools="http://schemas.android.com/tools"To suppress a lint warning in a
build.gradle file, add a section like this:
android {
lintOptions {
disable 'TypographyFractions','TypographyQuotes'
}
}
Here we specify a comma separated list of issue id's after the disable command. You can also use
warning or error instead of disable to change the severity of issues.To suppress lint warnings with a configuration XML file, create a file named
lint.xml and place it at the root directory of the module in which it applies.The format of the
lint.xml file is something like the following:
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<!-- Ignore everything in the test source set -->
<issue id="all">
<ignore path="\*/test/\*" />
</issue>
<!-- Disable this given check in this project -->
<issue id="IconMissingDensityFolder" severity="ignore" />
<!-- Ignore the ObsoleteLayoutParam issue in the given files -->
<issue id="ObsoleteLayoutParam">
<ignore path="res/layout/activation.xml" />
<ignore path="res/layout-xlarge/activation.xml" />
<ignore regexp="(foo|bar)\.java" />
</issue>
<!-- Ignore the UselessLeaf issue in the given file -->
<issue id="UselessLeaf">
<ignore path="res/layout/main.xml" />
</issue>
<!-- Change the severity of hardcoded strings to "error" -->
<issue id="HardcodedText" severity="error" />
</lint>
To suppress lint checks from the command line, pass the --ignore flag with a comma separated list of ids to be suppressed, such as:
$ lint --ignore UnusedResources,UselessLeaf /my/project/pathFor more information, see https://developer.android.com/studio/write/lint.html#config