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:39: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
 36         foregroundServiceType: ForegroundServiceType
 37     ) {
 38         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
 39             ServiceCompat.startForeground(                                                          
 40                 service,
 41                 id,
 42                 notification,
../../src/main/java/com/nextcloud/utils/ForegroundServiceHelper.kt:46: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
 43                 foregroundServiceType.getId()
 44             )
 45         } else {
 46             service.startForeground(id, notification)                                               
 47         }
 48     }
../../src/main/java/com/nextcloud/client/media/PlayerService.kt:70: To call Service.startForeground(), the <service> element of manifest file must have the foregroundServiceType attribute specified
  67     private val playerListener = object : Player.Listener {
  68 
  69         override fun onRunning(file: OCFile) {
  70             startForeground(file)                                                                   
  71         }
  72 
  73         override fun onStart() {
ForegroundServiceType Correctness Error Priority 5/10

Behavior change when requesting photo library access

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

Replace usage of Switch widget

../../src/main/java/com/owncloud/android/ui/ThemeableSwitchPreference.java:72: Use SwitchCompat from AppCompat or SwitchMaterial from Material library
 69             View child = viewGroup.getChildAt(i);
 70 
 71             if (child instanceof Switch) {
 72                 Switch switchView = (Switch) child;                                                 
 73 
 74                 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:514: 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.
  511 
  512     // Is called with the flag FLAG_ACTIVITY_SINGLE_TOP and set the new file and intent
  513     @Override
  514     protected void onNewIntent(Intent intent) {                                                     
  515         super.onNewIntent(intent);
  516         setIntent(intent);
    ../../src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java:529: The unsafe intent is launched here.
      526             onOpenFileIntent(intent);
      527         } else if (RESTART.equals(intent.getAction())) {
      528             finish();
      529             startActivity(intent);                                                                  
      530         } else // Verify the action and get the query
      531             if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
      532                 setIntent(intent);
    
UnsafeIntentLaunch Security Warning Priority 6/10

Allowing User Certificates

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

Insecure Base Configuration

../../src/main/res/xml/network_security_config.xml:4: Insecure Base Configuration
  1 <?xml version="1.0" encoding="utf-8"?>
  2 
  3 <network-security-config>
  4     <base-config cleartextTrafficPermitted="true">                                                  
  5         <trust-anchors>
  6             <!-- Trust preinstalled CAs -->
  7             <certificates src="system"/>
InsecureBaseConfiguration Security Warning Priority 5/10

Invalidating All RecyclerView Data

../../src/main/java/com/owncloud/android/ui/adapter/ActivityAndVersionListAdapter.java:120: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 117             }
 118         }
 119 
 120         notifyDataSetChanged();                                                                     
 121     }
 122 
 123     @NonNull
../../src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java:142: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 139                 values.add(activity);
 140             }
 141         }
 142         notifyDataSetChanged();                                                                     
 143     }
 144 
 145     @NonNull
../../src/main/java/com/owncloud/android/ui/dialog/ChooseRichDocumentsTemplateDialogFragment.java:256: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 253 
 254     public void setTemplateList(List<Template> templateList) {
 255         adapter.setTemplateList(templateList);
 256         adapter.notifyDataSetChanged();                                                             
 257     }
 258 
 259     @Override
../../src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.kt:215: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
 212 
 213     fun setTemplateList(templateList: TemplateList?) {
 214         adapter?.setTemplateList(templateList)
 215         adapter?.notifyDataSetChanged()                                                             
 216     }
 217 
 218     override fun onClick(template: Template) {
../../src/main/java/com/nextcloud/client/etm/pages/EtmBackgroundJobsFragment.kt:98: It will always be more efficient to use more specific change events if you can. Rely on notifyDataSetChanged as a last resort.
  95         var backgroundJobs: List<JobInfo> = emptyList()
  96             set(value) {
  97                 field = value
  98                 notifyDataSetChanged()                                                              
  99             }
 100 
 101         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:210: This AsyncTask class should be static or leaks might occur (com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity.MoveFilesTask)
 207     /**
 208      * Asynchronous task performing the move of all the local files to the ownCloud folder.
 209      */
 210     private class MoveFilesTask extends AsyncTask<Void, Void, Boolean> {                            
 211 
 212         /**
 213          * Updates the UI before trying the movement
../../src/main/java/com/owncloud/android/ui/asynctasks/FetchRemoteFileTask.java:45: This field leaks a context object
  42     private final User user;
  43     private final String fileId;
  44     private final FileDataStorageManager storageManager;
  45     private final FileDisplayActivity fileDisplayActivity;                                          
  46     private OCFile ocFile;
  47 
  48     public FetchRemoteFileTask(User user,
../../src/main/java/com/owncloud/android/ui/activities/data/files/FilesServiceApiImpl.java:75: This field leaks a context object
  72         private final FilesServiceCallback<OCFile> callback;
  73         private OCFile remoteOcFile;
  74         private String errorMessage;
  75         // TODO: Figure out a better way to do this than passing a BaseActivity reference.          
  76         private final BaseActivity baseActivity;
  77         private final String fileUrl;
  78         private final User user;
../../src/main/java/com/nextcloud/client/logger/ui/LogsViewModel.kt:34: This field leaks a context object
  31 import javax.inject.Inject
  32 
  33 class LogsViewModel @Inject constructor(
  34     private val context: Context,                                                                   
  35     clock: Clock,
  36     asyncRunner: AsyncRunner,
  37     private val logsRepository: LogsRepository
../../src/main/java/com/owncloud/android/MainApp.java:139: Do not place Android context classes in static fields; this is a memory leak
 136     private static final String TAG = MainApp.class.getSimpleName();
 137     public static final String DOT = ".";
 138 
 139     private static Context mContext;                                                                
 140 
 141     private static String storagePath;
StaticFieldLeak Performance Warning Priority 6/10

Nested layout weights

../../src/main/res/layout/first_run_activity.xml:40: Nested weights are bad for performance
  37             android:id="@+id/contentPanel"
  38             android:layout_width="match_parent"
  39             android:layout_height="0dp"
  40             android:layout_weight="1"/>                                                             
  41 
  42         <com.owncloud.android.ui.whatsnew.ProgressIndicator
  43             android:id="@+id/progressIndicator"
../../src/main/res/layout/whats_new_activity.xml:63: Nested weights are bad for performance
 60             android:layout_width="0dp"
 61             android:layout_height="match_parent"
 62             android:layout_gravity="center_vertical|center_horizontal"
 63             android:layout_weight="1"                                                               
 64             android:gravity="center"
 65             android:paddingLeft="0dp"
 66             android:paddingRight="0dp"
NestedWeights Performance Warning Priority 3/10

Overdraw: Painting regions more than once

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

Unused resources

../../src/main/res/drawable/ripple.xml:21: The resource R.drawable.ripple appears to be unused
 18   ~ You should have received a copy of the GNU General Public License
 19   ~ along with this program. If not, see <https://www.gnu.org/licenses/>.
 20   -->
 21 <ripple xmlns:android="http://schemas.android.com/apk/res/android"                                  
 22     android:color="@color/grey_200">
 23     <item android:id="@android:id/mask">
 24         <shape android:shape="oval">
UnusedResources Performance Warning Priority 3/10

Using getUsableSpace()

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

Accessibility in Custom Views

../../src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java:343: Custom view `RecyclerView` has setOnTouchListener called on it but does not override performClick
 340 
 341   mScaleGestureDetector = new ScaleGestureDetector(MainApp.getAppContext(), new ScaleListener());
 342 
 343   getRecyclerView().setOnTouchListener((view, motionEvent) -> {                               
 344       mScaleGestureDetector.onTouchEvent(motionEvent);
 345 
 346       if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
../../src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java:628: PreviewMediaFragment#onTouch should call View#performClick when a click is detected
 625   }
 626 
 627   @Override
 628   public boolean onTouch(View v, MotionEvent event) {                                             
 629       if (event.getAction() == MotionEvent.ACTION_DOWN && v.equals(binding.exoplayerView)) {
 630           // added a margin on the left to avoid interfering with gesture to open navigation drawer
 631           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