Lint Report: 11 errors and 54 warnings
Issue Types

Overview

Correctness
8error AppLinkUrlError: URI invalid
3error ForegroundServiceType: Missing foregroundServiceType attribute in manifest
1warning UseSwitchCompatOrMaterialCode: Replace usage of Switch widget
Security
1warning UnsafeIntentLaunch: Launched Unsafe Intent
1warning AcceptsUserCertificates: Allowing User Certificates
1warning InsecureBaseConfiguration: Insecure Base Configuration
Performance
25warning NotifyDataSetChanged: Invalidating All RecyclerView Data
10warning StaticFieldLeak: Static Field Leaks
2warning NestedWeights: Nested layout weights
11warning Overdraw: Overdraw: Painting regions more than once
1warning UsableSpace: Using getUsableSpace()
Accessibility
1warning ClickableViewAccessibility: Accessibility in Custom Views
Included Additional Checks (85)
Disabled Checks (50)

URI invalid

../../src/main/AndroidManifest.xml:162: Android App Links' host attributes must be valid web domains
 159                 <category android:name="android.intent.category.BROWSABLE" />
 160 
 161                 <data android:scheme="http" />
 162                 <data android:host="*" />                                                           
 163                 <data android:pathPattern="/f/..*" />
 164             </intent-filter>
 165             <intent-filter android:autoVerify="true">
../../src/main/AndroidManifest.xml:172: Android App Links' host attributes must be valid web domains
 169                 <category android:name="android.intent.category.BROWSABLE" />
 170 
 171                 <data android:scheme="http" />
 172                 <data android:host="*" />                                                           
 173                 <data android:pathPattern="/..*/f/..*" />
 174             </intent-filter>
 175             <intent-filter android:autoVerify="true">
../../src/main/AndroidManifest.xml:182: Android App Links' host attributes must be valid web domains
 179                 <category android:name="android.intent.category.BROWSABLE" />
 180 
 181                 <data android:scheme="http" />
 182                 <data android:host="*" />                                                           
 183                 <data android:pathPattern="/..*/..*/f/..*" />
 184             </intent-filter>
 185             <intent-filter android:autoVerify="true">
../../src/main/AndroidManifest.xml:192: Android App Links' host attributes must be valid web domains
 189                 <category android:name="android.intent.category.BROWSABLE" />
 190 
 191                 <data android:scheme="http" />
 192                 <data android:host="*" />                                                           
 193                 <data android:pathPattern="/..*/..*/..*/f/..*" />
 194             </intent-filter>
 195             <intent-filter android:autoVerify="true">
../../src/main/AndroidManifest.xml:202: Android App Links' host attributes must be valid web domains
 199                 <category android:name="android.intent.category.BROWSABLE" />
 200 
 201                 <data android:scheme="https" />
 202                 <data android:host="*" />                                                           
 203                 <data android:pathPattern="/f/..*" />
 204             </intent-filter>
 205             <intent-filter android:autoVerify="true">
../../src/main/AndroidManifest.xml:212: Android App Links' host attributes must be valid web domains
 209                 <category android:name="android.intent.category.BROWSABLE" />
 210 
 211                 <data android:scheme="https" />
 212                 <data android:host="*" />                                                           
 213                 <data android:pathPattern="/..*/f/..*" />
 214             </intent-filter>
 215             <intent-filter android:autoVerify="true">
../../src/main/AndroidManifest.xml:222: Android App Links' host attributes must be valid web domains
 219                 <category android:name="android.intent.category.BROWSABLE" />
 220 
 221                 <data android:scheme="https" />
 222                 <data android:host="*" />                                                           
 223                 <data android:pathPattern="/..*/..*/f/..*" />
 224             </intent-filter>
 225             <intent-filter android:autoVerify="true">
../../src/main/AndroidManifest.xml:232: Android App Links' host attributes must be valid web domains
 229                 <category android:name="android.intent.category.BROWSABLE" />
 230 
 231                 <data android:scheme="https" />
 232                 <data android:host="*" />                                                           
 233                 <data android:pathPattern="/..*/..*/..*/f/..*" />
 234                 <!-- path pattern to handle deep link -->
 235                 <data android:pathPattern="/app/..*" />
AppLinkUrlError Correctness Error Priority 5/10

Missing foregroundServiceType attribute in manifest

../../src/main/java/com/nextcloud/utils/ForegroundServiceHelper.kt:31: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
 28     ) {
 29         if (isAboveOrEqualAndroid10) {
 30             try {
 31                 ServiceCompat.startForeground(                                                      
 32                     service,
 33                     id,
 34                     notification,
../../src/main/java/com/nextcloud/utils/ForegroundServiceHelper.kt:41: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
 38                 Log.d(TAG, "Exception caught at ForegroundServiceHelper.startService: $e")
 39             }
 40         } else {
 41             service.startForeground(id, notification)                                               
 42         }
 43     }
../../src/main/java/com/nextcloud/client/media/PlayerService.kt:68: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
  65                 putExtra(IS_MEDIA_CONTROL_LAYOUT_READY, false)
  66             }
  67             LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)
  68             startForeground(file)                                                                   
  69         }
  70 
  71         override fun onStart() {
ForegroundServiceType Correctness Error Priority 5/10

Replace usage of Switch widget

../../src/main/java/com/owncloud/android/ui/ThemeableSwitchPreference.java:57: Use SwitchCompat from AppCompat or MaterialSwitch from Material library
 54         for (int i = 0; i < viewGroup.getChildCount(); i++) {
 55             View child = viewGroup.getChildAt(i);
 56 
 57             if (child instanceof Switch switchView) {                                               
 58                 viewThemeUtils.platform.colorSwitch(switchView);
 59 
 60                 break;
Vendor: Android Open Source Project
Identifier: androidx.appcompat
Feedback: https://issuetracker.google.com/issues/new?component=460343
UseSwitchCompatOrMaterialCode Correctness Warning Priority 5/10

Launched Unsafe Intent

../../src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java:619: This intent could be coming from an untrusted source. It is later launched by an unprotected component com.owncloud.android.ui.activity.FileDisplayActivity. You could either make the component com.owncloud.android.ui.activity.FileDisplayActivity protected; or sanitize this intent using androidx.core.content.IntentSanitizer.
  616 
  617     // Is called with the flag FLAG_ACTIVITY_SINGLE_TOP and set the new file and intent
  618     @Override
  619     protected void onNewIntent(Intent intent) {                                                     
  620         super.onNewIntent(intent);
  621         setIntent(intent);
    ../../src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java:634: The unsafe intent is launched here.
      631             onOpenFileIntent(intent);
      632         } else if (RESTART.equals(intent.getAction())) {
      633             finish();
      634             startActivity(intent);                                                                  
      635         } else {
      636             // Verify the action and get the query
      637             if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
    
UnsafeIntentLaunch Security Warning Priority 6/10

Allowing User Certificates

../../src/main/res/xml/network_security_config.xml:15: The Network Security Configuration allows the use of user certificates in the release version of your app
 12             <!-- Trust preinstalled CAs -->
 13             <certificates src="system"/>
 14             <!-- Additionally trust user added CAs -->
 15             <certificates src="user"/>                                                              
 16         </trust-anchors>
 17     </base-config>
 18 </network-security-config>
AcceptsUserCertificates Security Warning Priority 5/10

Insecure Base Configuration

../../src/main/res/xml/network_security_config.xml:10: Insecure Base Configuration
  7   ~ SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
  8 -->
  9 <network-security-config>
 10     <base-config cleartextTrafficPermitted="true">                                                  
 11         <trust-anchors>
 12             <!-- Trust preinstalled CAs -->
 13             <certificates src="system"/>
InsecureBaseConfiguration Security Warning Priority 5/10

Invalidating All RecyclerView Data

../../src/main/java/com/owncloud/android/ui/adapter/ActivityAndVersionListAdapter.java:102: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
  99             }
 100         }
 101 
 102         notifyDataSetChanged();                                                                     
 103     }
 104 
 105     @NonNull
../../src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java:128: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 125                 values.add(activity);
 126             }
 127         }
 128         notifyDataSetChanged();                                                                     
 129     }
 130 
 131     @NonNull
../../src/main/java/com/nextcloud/client/etm/pages/EtmFileTransferFragment.kt:68: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
  65 
  66   fun setStatus(status: TransferManager.Status) {
  67       transfers = listOf(status.pending, status.running, status.completed).flatten().reversed()
  68       notifyDataSetChanged()                                                                  
  69   }
  70 
  71   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
../../src/main/java/com/nextcloud/client/etm/EtmMenuAdapter.kt:27: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 24     var pages: List<EtmMenuEntry> = listOf()
 25         set(value) {
 26             field = value
 27             notifyDataSetChanged()                                                                  
 28         }
 29 
 30     class PageViewHolder(view: View, onClick: (Int) -> Unit) : RecyclerView.ViewHolder(view) {
../../src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java:381: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 378 
 379             preferences.setGridColumns(mScale);
 380 
 381             getRecyclerView().getAdapter().notifyDataSetChanged();                                  
 382 
 383             return true;
 384         }
NotifyDataSetChanged Performance Warning Priority 8/10

Static Field Leaks

../../src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java:197: This AsyncTask class should be static or leaks might occur (com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity.MoveFilesTask)
 194     /**
 195      * Asynchronous task performing the move of all the local files to the ownCloud folder.
 196      */
 197     private class MoveFilesTask extends AsyncTask<Void, Void, Boolean> {                            
 198 
 199         /**
 200          * Updates the UI before trying the movement
../../src/main/java/com/owncloud/android/ui/asynctasks/FetchRemoteFileTask.java:33: This field leaks a context object
  30     private final User user;
  31     private final String fileId;
  32     private final FileDataStorageManager storageManager;
  33     private final FileDisplayActivity fileDisplayActivity;                                          
  34     private OCFile ocFile;
  35 
  36     public FetchRemoteFileTask(User user,
../../src/main/java/com/owncloud/android/ui/activities/data/files/FilesServiceApiImpl.java:60: This field leaks a context object
  57         private final FilesServiceCallback<OCFile> callback;
  58         private OCFile remoteOcFile;
  59         private String errorMessage;
  60         // TODO: Figure out a better way to do this than passing a BaseActivity reference.          
  61         private final BaseActivity baseActivity;
  62         private final String fileUrl;
  63         private final User user;
../../src/main/java/com/nextcloud/client/logger/ui/LogsViewModel.kt:21: This field leaks a context object
  18 import javax.inject.Inject
  19 
  20 class LogsViewModel @Inject constructor(
  21     private val context: Context,                                                                   
  22     clock: Clock,
  23     asyncRunner: AsyncRunner,
  24     private val logsRepository: LogsRepository
../../src/main/java/com/owncloud/android/ui/activity/ManageSpaceActivity.kt:65: This AsyncTask class should be static or leaks might occur (com.owncloud.android.ui.activity.ManageSpaceActivity.ClearDataAsyncTask)
  62     /**
  63      * AsyncTask for Clear Data, saving the passcode
  64      */
  65     private inner class ClearDataAsyncTask : AsyncTask<Void, Void, Boolean>() {                     
  66         private val preferences = this@ManageSpaceActivity.preferences
  67         private val userAccountManager = this@ManageSpaceActivity.userAccountManager
StaticFieldLeak Performance Warning Priority 6/10

Nested layout weights

../../src/main/res/layout/first_run_activity.xml:27: Nested weights are bad for performance
 24             android:id="@+id/contentPanel"
 25             android:layout_width="match_parent"
 26             android:layout_height="0dp"
 27             android:layout_weight="1"/>                                                             
 28 
 29         <com.owncloud.android.ui.whatsnew.ProgressIndicator
 30             android:id="@+id/progressIndicator"
../../src/main/res/layout/whats_new_activity.xml:50: Nested weights are bad for performance
 47             android:layout_width="0dp"
 48             android:layout_height="match_parent"
 49             android:layout_gravity="center_vertical|center_horizontal"
 50             android:layout_weight="1"                                                               
 51             android:gravity="center"
 52             android:paddingLeft="0dp"
 53             android:paddingRight="0dp"
NestedWeights Performance Warning Priority 3/10

Overdraw: Painting regions more than once

../../src/main/res/layout/activity_edit_image.xml:13: Possible overdraw: Root element paints background @color/black with a theme that also paints a background (inferred theme is @style/Theme.ownCloud.Toolbar)
 10     xmlns:app="http://schemas.android.com/apk/res-auto"
 11     android:layout_width="match_parent"
 12     android:layout_height="match_parent"
 13     android:background="@color/black">                                                              
 14 
 15     <androidx.appcompat.widget.Toolbar
 16         android:id="@+id/toolbar"
../../src/main/res/layout/activity_row.xml:12: Possible overdraw: Root element paints background ?android:attr/activatedBackgroundIndicator with a theme that also paints a background (inferred theme is @style/Theme.ownCloud.Toolbar)
  9     android:id="@+id/list_item"
 10     android:layout_width="match_parent"
 11     android:layout_height="@dimen/activity_row_layout_height"
 12     android:background="?android:attr/activatedBackgroundIndicator"                                    
 13     android:minWidth="@dimen/activity_row_layout_min_width_independent"
 14     android:orientation="horizontal"
 15     android:paddingEnd="@dimen/standard_padding"
../../src/main/res/layout/activity_splash.xml:12: Possible overdraw: Root element paints background @color/primary with a theme that also paints a background (inferred theme is @style/Theme.ownCloud.Toolbar)
  9     xmlns:app="http://schemas.android.com/apk/res-auto"
 10     android:layout_width="match_parent"
 11     android:layout_height="match_parent"
 12     android:background="@color/primary">                                                            
 13 
 14     <androidx.appcompat.widget.AppCompatImageView
 15         android:id="@+id/ivSplash"
../../src/main/res/layout/dialog_preview_video.xml:15: Possible overdraw: Root element paints background @color/black with a theme that also paints a background (inferred theme is @style/Theme.ownCloud.Toolbar)
 12     android:layout_width="match_parent"
 13     android:layout_height="match_parent"
 14     android:layout_gravity="center"
 15     android:background="@color/black"                                                               
 16     app:show_buffering="always" />
../../src/main/res/layout/drawer_header.xml:15: Possible overdraw: Root element paints background @color/primary with a theme that also paints a background (inferred theme is @style/Theme.ownCloud.Toolbar)
  12     android:id="@+id/drawer_header_view"
  13     android:layout_width="match_parent"
  14     android:layout_height="wrap_content"
  15     android:background="@color/primary"                                                             
  16     android:gravity="center"
  17     android:orientation="vertical">
Overdraw Performance Warning Priority 3/10

Using getUsableSpace()

../../src/main/java/com/owncloud/android/utils/FileStorageUtils.java:142: Consider also using StorageManager#getAllocatableBytes and allocateBytes which will consider clearable cached data
 139      */
 140     public static long getUsableSpace() {
 141         File savePath = new File(MainApp.getStoragePath());
 142         return savePath.getUsableSpace();                                                           
 143     }
 144 
 145     /**
UsableSpace Performance Warning Priority 3/10

Accessibility in Custom Views

../../src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java:341: Custom view `RecyclerView` has setOnTouchListener called on it but does not override performClick
 338 
 339   mScaleGestureDetector = new ScaleGestureDetector(MainApp.getAppContext(), new ScaleListener());
 340 
 341   getRecyclerView().setOnTouchListener((view, motionEvent) -> {                               
 342       mScaleGestureDetector.onTouchEvent(motionEvent);
 343 
 344       if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
ClickableViewAccessibility Accessibility Warning Priority 6/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 @SuppressLint annotation in the Java code
2. With a tools:ignore attribute in the XML file
3. With a //noinspection comment in the source code
4. With ignore flags specified in the build.gradle file, as explained below
5. With a lint.xml configuration file in the project
6. With a lint.xml configuration file passed to lint via the --config flag
7. 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/path

For more information, see https://developer.android.com/studio/write/lint.html#config