Lint Report: 3 errors and 71 warnings
Issue Types

Overview

Correctness
3error ForegroundServiceType: Missing foregroundServiceType attribute in manifest
2warning SelectedPhotoAccess: Behavior change when requesting photo library access
1warning UseSwitchCompatOrMaterialCode: Replace usage of Switch widget
Security
1warning UnsafeIntentLaunch: Launched Unsafe Intent
1warning AcceptsUserCertificates: Allowing User Certificates
1warning InsecureBaseConfiguration: Insecure Base Configuration
Performance
36warning NotifyDataSetChanged: Invalidating All RecyclerView Data
12warning StaticFieldLeak: Static Field Leaks
2warning NestedWeights: Nested layout weights
11warning Overdraw: Overdraw: Painting regions more than once
1warning UnusedResources: Unused resources
1warning UsableSpace: Using getUsableSpace()
Accessibility
2warning ClickableViewAccessibility: Accessibility in Custom Views
Included Additional Checks (81)
Disabled Checks (50)

Missing foregroundServiceType attribute in manifest

../../src/main/java/com/nextcloud/utils/ForegroundServiceHelper.kt:25: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
 22         foregroundServiceType: ForegroundServiceType
 23     ) {
 24         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
 25             ServiceCompat.startForeground(                                                          
 26                 service,
 27                 id,
 28                 notification,
../../src/main/java/com/nextcloud/utils/ForegroundServiceHelper.kt:32: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
 29                 foregroundServiceType.getId()
 30             )
 31         } else {
 32             service.startForeground(id, notification)                                               
 33         }
 34     }
../../src/main/java/com/nextcloud/client/media/PlayerService.kt:57: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
  54     private val playerListener = object : Player.Listener {
  55 
  56         override fun onRunning(file: OCFile) {
  57             startForeground(file)                                                                   
  58         }
  59 
  60         override fun onStart() {
ForegroundServiceType Correctness Error Priority 5/10

Behavior change when requesting photo library access

../../src/main/AndroidManifest.xml:56: Your app is currently not handling Selected Photos Access introduced in Android 14+
  53   -->
  54   <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Runtime permissions introduced in Android 13 (API level 33) -->
  55   <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  56   <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />                         
  57   <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- Needed for Android 14 (API level 34) -->
  58   <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
  59   <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
../../src/main/AndroidManifest.xml:57: Your app is currently not handling Selected Photos Access introduced in Android 14+
  54   <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Runtime permissions introduced in Android 13 (API level 33) -->
  55   <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  56   <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
  57   <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- Needed for Android 14 (API level 34) -->
  58   <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
  59   <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
  60   <!--
SelectedPhotoAccess Correctness Warning Priority 5/10

Replace usage of Switch widget

../../src/main/java/com/owncloud/android/ui/ThemeableSwitchPreference.java:58: Use SwitchCompat from AppCompat or SwitchMaterial from Material library
 55             View child = viewGroup.getChildAt(i);
 56 
 57             if (child instanceof Switch) {
 58                 Switch switchView = (Switch) child;                                                 
 59 
 60                 viewThemeUtils.platform.colorSwitch(switchView);
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:503: 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.
  500 
  501     // Is called with the flag FLAG_ACTIVITY_SINGLE_TOP and set the new file and intent
  502     @Override
  503     protected void onNewIntent(Intent intent) {                                                     
  504         super.onNewIntent(intent);
  505         setIntent(intent);
    ../../src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java:518: The unsafe intent is launched here.
      515             onOpenFileIntent(intent);
      516         } else if (RESTART.equals(intent.getAction())) {
      517             finish();
      518             startActivity(intent);                                                                  
      519         } else // Verify the action and get the query
      520             if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
      521                 setIntent(intent);
    
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
  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:103: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 100             }
 101         }
 102 
 103         notifyDataSetChanged();                                                                     
 104     }
 105 
 106     @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/owncloud/android/ui/dialog/ChooseRichDocumentsTemplateDialogFragment.java:245: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 242 
 243     public void setTemplateList(List<Template> templateList) {
 244         adapter.setTemplateList(templateList);
 245         adapter.notifyDataSetChanged();                                                             
 246     }
 247 
 248     @Override
../../src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.kt:200: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 197 
 198     fun setTemplateList(templateList: TemplateList?) {
 199         adapter?.setTemplateList(templateList)
 200         adapter?.notifyDataSetChanged()                                                             
 201     }
 202 
 203     override fun onClick(template: Template) {
../../src/main/java/com/nextcloud/client/etm/pages/EtmBackgroundJobsFragment.kt:85: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
  82         var backgroundJobs: List<JobInfo> = emptyList()
  83             set(value) {
  84                 field = value
  85                 notifyDataSetChanged()                                                              
  86             }
  87 
  88         override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
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:31: This field leaks a context object
  28     private final User user;
  29     private final String fileId;
  30     private final FileDataStorageManager storageManager;
  31     private final FileDisplayActivity fileDisplayActivity;                                          
  32     private OCFile ocFile;
  33 
  34     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/MainApp.java:133: Do not place Android context classes in static fields; this is a memory leak
 130     private static final String TAG = MainApp.class.getSimpleName();
 131     public static final String DOT = ".";
 132 
 133     private static Context mContext;                                                                
 134 
 135     private static String storagePath;
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:fitsSystemWindows="true"
  17     android:gravity="center"
  18     android:orientation="vertical">
Overdraw Performance Warning Priority 3/10

Unused resources

../../src/main/res/drawable/ripple.xml:9: The resource R.drawable.ripple appears to be unused
  6   ~ SPDX-FileCopyrightText: 2022 Nextcloud GmbH
  7   ~ SPDX-License-Identifier: AGPL-3.0-or-later
  8 -->
  9 <ripple xmlns:android="http://schemas.android.com/apk/res/android"                                  
 10     android:color="@color/grey_200">
 11     <item android:id="@android:id/mask">
 12         <shape android:shape="oval">
UnusedResources 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:334: Custom view `RecyclerView` has setOnTouchListener called on it but does not override performClick
 331 
 332   mScaleGestureDetector = new ScaleGestureDetector(MainApp.getAppContext(), new ScaleListener());
 333 
 334   getRecyclerView().setOnTouchListener((view, motionEvent) -> {                               
 335       mScaleGestureDetector.onTouchEvent(motionEvent);
 336 
 337       if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
../../src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java:612: PreviewMediaFragment#onTouch should call View#performClick when a click is detected
 609   }
 610 
 611   @Override
 612   public boolean onTouch(View v, MotionEvent event) {                                             
 613       if (event.getAction() == MotionEvent.ACTION_DOWN && v.equals(binding.exoplayerView)) {
 614           // added a margin on the left to avoid interfering with gesture to open navigation drawer
 615           if (event.getX() / Resources.getSystem().getDisplayMetrics().density > MIN_DENSITY_RATIO) {
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