Add lint baseline, enable linting on CI, fix some reported errors (#3291)

This PR:
- fixes some errors reported by `gradlew lint` and the Android Studio "Code Inspection" tool
- adds a snapshot file `lint-baseline.xml` of the remaining lint errors and warnings to be used by the linter as baseline
- adds a job for CI to run `gradlew lint` on every build

Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/3291
Reviewed-by: José Rebelo <joserebelo@noreply.codeberg.org>
Co-authored-by: Arjan Schrijver <a_gadgetbridge@anymore.nl>
Co-committed-by: Arjan Schrijver <a_gadgetbridge@anymore.nl>
This commit is contained in:
Arjan Schrijver 2023-09-11 09:17:04 +00:00 committed by Arjan Schrijver
parent 7359186cee
commit 557bfea35c
24 changed files with 33535 additions and 137 deletions

16
.woodpecker/run_lint.yml Normal file
View File

@ -0,0 +1,16 @@
steps:
lint:
image: codeberg.org/freeyourgadget/android-fdroid-tools:latest
commands:
- pwd #bump
- ./gradlew lint
#when:
#repo: Freeyourgadget/Gadgetbridge
#branch: master
#this doesn't work yet:
#https://github.com/woodpecker-ci/woodpecker/issues/687
when:
event:
exclude: ['cron', 'deployment']

View File

@ -7,7 +7,7 @@ apply plugin: "com.github.spotbugs"
apply plugin: "pmd"
apply plugin: 'com.google.protobuf'
def ABORT_ON_CHECK_FAILURE = false
def ABORT_ON_CHECK_FAILURE = true
tasks.withType(Test) {
systemProperty "MiFirmwareDir", System.getProperty("MiFirmwareDir", null)
@ -216,10 +216,12 @@ android {
lintOptions {
abortOnError ABORT_ON_CHECK_FAILURE
lintConfig file("${project.rootDir}/config/lint/lint.xml")
// If true, generate an HTML report (with issue explanations, sourcecode, etc)
// If true, generate an HTML report (with issue explanations, sourcecode, etc)
htmlReport true
// Optional path to report (default will be lint-results.html in the builddir)
// Optional path to report (default will be lint-results.html in the builddir)
htmlOutput file("$project.buildDir/reports/lint/lint.html")
// Ignore checks present in the snapshot
baseline file("lint-baseline.xml")
}
testOptions {

33393
app/lint-baseline.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@
-keepattributes JavascriptInterface
# https://github.com/tony19/logback-android/issues/29
-dontwarn javax.mail.**, javax.naming.Context, javax.naming.InitialContext
-dontwarn javax.mail.**
# To avoid any stacktrace ambiguity
-keepattributes SourceFile,LineNumberTable

View File

@ -478,7 +478,6 @@ public class SettingsActivity extends AbstractSettingsActivityV2 {
SharedPreferences.Editor editor = GBApplication.getPrefs().getPreferences().edit();
editor.putString("opentracks_packagename", fitnessAppEditText.getText().toString());
editor.apply();
editor.commit();
})
.setNegativeButton(R.string.Cancel, (dialog, which) -> {})
.show();

View File

@ -693,7 +693,6 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
SharedPreferences.Editor editor = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()).edit();
editor.putFloat((String.format("fm_preset%s", index)), frequency);
editor.apply();
editor.commit();
return true;
}
});

View File

@ -18,6 +18,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices;
import static nodomain.freeyourgadget.gadgetbridge.GBApplication.getPrefs;
import android.app.Activity;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
@ -62,12 +64,9 @@ import nodomain.freeyourgadget.gadgetbridge.model.PaiSample;
import nodomain.freeyourgadget.gadgetbridge.model.SleepRespiratoryRateSample;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
import nodomain.freeyourgadget.gadgetbridge.model.StressSample;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.ServiceDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.GBApplication.getPrefs;
public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceCoordinator.class);
@ -110,13 +109,13 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
}
Prefs prefs = getPrefs();
String lastDevice = prefs.getPreferences().getString("last_device_address","");
String lastDevice = prefs.getPreferences().getString("last_device_address", "");
if (gbDevice.getAddress().equals(lastDevice)) {
LOG.debug("#1605 removing last device");
prefs.getPreferences().edit().remove("last_device_address").apply();
}
String macAddress = prefs.getPreferences().getString(MiBandConst.PREF_MIBAND_ADDRESS,"");
String macAddress = prefs.getPreferences().getString(MiBandConst.PREF_MIBAND_ADDRESS, "");
if (gbDevice.getAddress().equals(macAddress)) {
LOG.debug("#1605 removing devel miband");
prefs.getPreferences().edit().remove(MiBandConst.PREF_MIBAND_ADDRESS).apply();
@ -201,7 +200,13 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
}
public boolean isHealthWearable(BluetoothDevice device) {
BluetoothClass bluetoothClass = device.getBluetoothClass();
BluetoothClass bluetoothClass;
try {
bluetoothClass = device.getBluetoothClass();
} catch (SecurityException se) {
LOG.warn("missing bluetooth permission: ", se);
return false;
}
if (bluetoothClass == null) {
LOG.warn("unable to determine bluetooth device class of " + device);
return false;

View File

@ -1,4 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge.devices.um25.Coordinator;
package nodomain.freeyourgadget.gadgetbridge.devices.binary_sensor.coordinator;
import android.app.Activity;
import android.bluetooth.le.ScanFilter;

View File

@ -53,7 +53,7 @@ public class AmazfitBand5Coordinator extends HuamiCoordinator {
if (name != null && name.equalsIgnoreCase(HuamiConst.AMAZFIT_BAND5_NAME)) {
return DeviceType.AMAZFITBAND5;
}
} catch (Exception ex) {
} catch (SecurityException ex) {
LOG.error("unable to check device support", ex);
}
return DeviceType.UNKNOWN;

View File

@ -46,7 +46,7 @@ public class AmazfitBand7Coordinator extends Huami2021Coordinator {
if (name != null && name.startsWith(HuamiConst.AMAZFIT_BAND7_NAME)) {
return DeviceType.AMAZFITBAND7;
}
} catch (final Exception e) {
} catch (SecurityException e) {
LOG.error("unable to check device support", e);
}

View File

@ -1,20 +1,18 @@
package nodomain.freeyourgadget.gadgetbridge.devices.smaq2oss;
import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelUuid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
@ -29,7 +27,6 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.smaq2oss.SMAQ2OSSSupport;
public class SMAQ2OSSCoordinator extends AbstractBLEDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(SMAQ2OSSCoordinator.class);

View File

@ -1,4 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.smaq2oss;
package nodomain.freeyourgadget.gadgetbridge.devices.smaq2oss;
import android.bluetooth.BluetoothGatt;

View File

@ -320,7 +320,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
protected void handleGBDeviceEvent(GBDeviceEventLEDColor colorEvent) {
Context context = getContext();
LOG.info("Got event for LED Color: #" + Integer.toHexString(colorEvent.color).toUpperCase());
LOG.info("Got event for LED Color: #" + Integer.toHexString(colorEvent.color).toUpperCase(Locale.ROOT));
if (gbDevice == null) {
return;
}

View File

@ -17,6 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.util;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
@ -124,6 +125,7 @@ public class AndroidUtils {
dynamicColorContext = DynamicColors.wrapContextIfAvailable(context, R.style.GadgetbridgeThemeDynamicLight);
}
int[] attrsToResolve = {R.attr.colorOnSurface};
@SuppressLint("ResourceType")
TypedArray ta = dynamicColorContext.obtainStyledAttributes(attrsToResolve);
color = ta.getColor(0, 0);
ta.recycle();
@ -149,6 +151,7 @@ public class AndroidUtils {
dynamicColorContext = DynamicColors.wrapContextIfAvailable(context, R.style.GadgetbridgeThemeDynamicLight);
}
int[] attrsToResolve = {R.attr.colorSurface};
@SuppressLint("ResourceType")
TypedArray ta = dynamicColorContext.obtainStyledAttributes(attrsToResolve);
color = ta.getColor(0, 0);
ta.recycle();

View File

@ -143,7 +143,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWH1000XM4Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sonyswr12.SonySWR12DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.tlw64.TLW64Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.um25.Coordinator.BinarySensorCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.binary_sensor.coordinator.BinarySensorCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.um25.Coordinator.UM25Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.vesc.VescCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator;

View File

@ -29,7 +29,6 @@ import org.slf4j.LoggerFactory;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.Widget;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class WidgetPreferenceStorage {
@ -97,7 +96,6 @@ public class WidgetPreferenceStorage {
}
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(PREFS_WIDGET_SETTINGS, savedWidgetsPreferencesDataArray.toString());
editor.commit();
editor.apply();
}
@ -127,7 +125,6 @@ public class WidgetPreferenceStorage {
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(PREFS_WIDGET_SETTINGS, savedWidgetsPreferencesDataArray.toString());
editor.commit();
editor.apply();
}
@ -139,7 +136,6 @@ public class WidgetPreferenceStorage {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.putString(PREFS_WIDGET_SETTINGS, "");
editor.commit();
editor.apply();
}

View File

@ -18,7 +18,6 @@ package nodomain.freeyourgadget.gadgetbridge.util.dialogs;
import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import androidx.annotation.NonNull;
@ -33,7 +32,7 @@ public class MaterialDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity());
theDialogView = onCreateView(LayoutInflater.from(requireContext()), null, savedInstanceState);
theDialogView = onCreateView(getLayoutInflater(), null, savedInstanceState);
builder.setView(theDialogView);
return builder.create();

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@ -87,10 +87,10 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<android.support.constraint.Guideline
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
</androidx.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,38 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal">
<LinearLayout
<TextView
android:id="@+id/text_sensor_state"
android:layout_width="250dp"
android:layout_height="250dp"
android:background="@android:color/holo_red_light"
android:text="@string/unknown"
android:textSize="50sp"
android:gravity="center"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal">
android:text="@string/unknown"
android:textSize="50sp"
android:id="@+id/text_sensor_count"/>
<TextView
android:id="@+id/text_sensor_state"
android:layout_width="250dp"
android:layout_height="250dp"
android:background="@android:color/holo_red_light"
android:text="@string/unknown"
android:textSize="50dp"
android:gravity="center"/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/unknown"
android:textSize="50dp"
android:id="@+id/text_sensor_count"/>
</LinearLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>

View File

@ -34,7 +34,7 @@
</LinearLayout>
<Space
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="20dp" />

View File

@ -1,76 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
android:orientation="horizontal">
<LinearLayout
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:text="RPM: "
android:labelFor="@+id/vesc_control_input_rpm"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RPM: "
android:labelFor="@+id/vesc_control_input_rpm"/>
<EditText
android:layout_width="100dp"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:id="@+id/vesc_control_input_rpm"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
<EditText
android:layout_width="100dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Break current (A): " />
<EditText
android:layout_width="100dp"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:id="@+id/vesc_control_input_break_current"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_weight="0.5"
android:text="break"
android:id="@+id/vesc_control_button_break"/>
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_weight="0.5"
android:text="fwd"
android:id="@+id/vesc_control_button_fwd" />
</LinearLayout>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Volume keys control"
android:id="@+id/vesc_control_checkbox_volume_keys" />
android:inputType="numberDecimal"
android:id="@+id/vesc_control_input_rpm"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Break current (A): " />
<EditText
android:layout_width="100dp"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:id="@+id/vesc_control_input_break_current"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_weight="0.5"
android:text="break"
android:id="@+id/vesc_control_button_break"/>
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_weight="0.5"
android:text="fwd"
android:id="@+id/vesc_control_button_fwd" />
</LinearLayout>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Volume keys control"
android:id="@+id/vesc_control_checkbox_volume_keys" />
</LinearLayout>

View File

@ -372,7 +372,7 @@
android:padding="4dp"
android:scaleType="fitXY"
card_view:srcCompat="@drawable/ic_device_set_reminders"
android:tint="@color/secondarytext" />
app:tint="@color/secondarytext" />
<ImageView
android:id="@+id/device_action_show_activity_graphs"

View File

@ -24,7 +24,7 @@
android:layout_height="1.5dp"
android:background="#000" />
<Space
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
@ -43,7 +43,7 @@
android:layout_height="1.5dp"
android:background="#000" />
<Space
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
@ -77,7 +77,7 @@
android:layout_height="1.5dp"
android:background="#000" />
<Space
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
@ -119,7 +119,7 @@
android:layout_height="1.5dp"
android:background="#000" />
<Space
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
@ -175,7 +175,7 @@
android:layout_height="1.5dp"
android:background="#000" />
<Space
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
@ -217,7 +217,7 @@
android:layout_height="1.5dp"
android:background="#000" />
<Space
<android.widget.Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"

View File

@ -8,7 +8,7 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/streaks_dashboard_inner"
@ -18,7 +18,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"