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: "pmd"
apply plugin: 'com.google.protobuf' apply plugin: 'com.google.protobuf'
def ABORT_ON_CHECK_FAILURE = false def ABORT_ON_CHECK_FAILURE = true
tasks.withType(Test) { tasks.withType(Test) {
systemProperty "MiFirmwareDir", System.getProperty("MiFirmwareDir", null) systemProperty "MiFirmwareDir", System.getProperty("MiFirmwareDir", null)
@ -216,10 +216,12 @@ android {
lintOptions { lintOptions {
abortOnError ABORT_ON_CHECK_FAILURE abortOnError ABORT_ON_CHECK_FAILURE
lintConfig file("${project.rootDir}/config/lint/lint.xml") 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 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") htmlOutput file("$project.buildDir/reports/lint/lint.html")
// Ignore checks present in the snapshot
baseline file("lint-baseline.xml")
} }
testOptions { 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 -keepattributes JavascriptInterface
# https://github.com/tony19/logback-android/issues/29 # 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 # To avoid any stacktrace ambiguity
-keepattributes SourceFile,LineNumberTable -keepattributes SourceFile,LineNumberTable

View File

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

View File

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

View File

@ -18,6 +18,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices; package nodomain.freeyourgadget.gadgetbridge.devices;
import static nodomain.freeyourgadget.gadgetbridge.GBApplication.getPrefs;
import android.app.Activity; import android.app.Activity;
import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice; 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.SleepRespiratoryRateSample;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample; import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
import nodomain.freeyourgadget.gadgetbridge.model.StressSample; import nodomain.freeyourgadget.gadgetbridge.model.StressSample;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.ServiceDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.ServiceDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.GBApplication.getPrefs;
public abstract class AbstractDeviceCoordinator implements DeviceCoordinator { public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceCoordinator.class); private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceCoordinator.class);
@ -110,13 +109,13 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
} }
Prefs prefs = getPrefs(); Prefs prefs = getPrefs();
String lastDevice = prefs.getPreferences().getString("last_device_address",""); String lastDevice = prefs.getPreferences().getString("last_device_address", "");
if (gbDevice.getAddress().equals(lastDevice)) { if (gbDevice.getAddress().equals(lastDevice)) {
LOG.debug("#1605 removing last device"); LOG.debug("#1605 removing last device");
prefs.getPreferences().edit().remove("last_device_address").apply(); 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)) { if (gbDevice.getAddress().equals(macAddress)) {
LOG.debug("#1605 removing devel miband"); LOG.debug("#1605 removing devel miband");
prefs.getPreferences().edit().remove(MiBandConst.PREF_MIBAND_ADDRESS).apply(); prefs.getPreferences().edit().remove(MiBandConst.PREF_MIBAND_ADDRESS).apply();
@ -201,7 +200,13 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
} }
public boolean isHealthWearable(BluetoothDevice device) { 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) { if (bluetoothClass == null) {
LOG.warn("unable to determine bluetooth device class of " + device); LOG.warn("unable to determine bluetooth device class of " + device);
return false; 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.app.Activity;
import android.bluetooth.le.ScanFilter; 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)) { if (name != null && name.equalsIgnoreCase(HuamiConst.AMAZFIT_BAND5_NAME)) {
return DeviceType.AMAZFITBAND5; return DeviceType.AMAZFITBAND5;
} }
} catch (Exception ex) { } catch (SecurityException ex) {
LOG.error("unable to check device support", ex); LOG.error("unable to check device support", ex);
} }
return DeviceType.UNKNOWN; return DeviceType.UNKNOWN;

View File

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

View File

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

View File

@ -320,7 +320,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
protected void handleGBDeviceEvent(GBDeviceEventLEDColor colorEvent) { protected void handleGBDeviceEvent(GBDeviceEventLEDColor colorEvent) {
Context context = getContext(); 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) { if (gbDevice == null) {
return; return;
} }

View File

@ -17,6 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.util; package nodomain.freeyourgadget.gadgetbridge.util;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ContentUris; import android.content.ContentUris;
@ -124,6 +125,7 @@ public class AndroidUtils {
dynamicColorContext = DynamicColors.wrapContextIfAvailable(context, R.style.GadgetbridgeThemeDynamicLight); dynamicColorContext = DynamicColors.wrapContextIfAvailable(context, R.style.GadgetbridgeThemeDynamicLight);
} }
int[] attrsToResolve = {R.attr.colorOnSurface}; int[] attrsToResolve = {R.attr.colorOnSurface};
@SuppressLint("ResourceType")
TypedArray ta = dynamicColorContext.obtainStyledAttributes(attrsToResolve); TypedArray ta = dynamicColorContext.obtainStyledAttributes(attrsToResolve);
color = ta.getColor(0, 0); color = ta.getColor(0, 0);
ta.recycle(); ta.recycle();
@ -149,6 +151,7 @@ public class AndroidUtils {
dynamicColorContext = DynamicColors.wrapContextIfAvailable(context, R.style.GadgetbridgeThemeDynamicLight); dynamicColorContext = DynamicColors.wrapContextIfAvailable(context, R.style.GadgetbridgeThemeDynamicLight);
} }
int[] attrsToResolve = {R.attr.colorSurface}; int[] attrsToResolve = {R.attr.colorSurface};
@SuppressLint("ResourceType")
TypedArray ta = dynamicColorContext.obtainStyledAttributes(attrsToResolve); TypedArray ta = dynamicColorContext.obtainStyledAttributes(attrsToResolve);
color = ta.getColor(0, 0); color = ta.getColor(0, 0);
ta.recycle(); 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.sony.headphones.coordinators.SonyWH1000XM4Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.sonyswr12.SonySWR12DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.sonyswr12.SonySWR12DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.tlw64.TLW64Coordinator; 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.um25.Coordinator.UM25Coordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.vesc.VescCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.vesc.VescCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.vibratissimo.VibratissimoCoordinator;

View File

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

View File

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

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?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:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -87,10 +87,10 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
<android.support.constraint.Guideline <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline" android:id="@+id/guideline"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" /> 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"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout
android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"> android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<RelativeLayout <LinearLayout
android:layout_width="fill_parent" android:layout_width="wrap_content"
android:layout_height="fill_parent" android:layout_height="wrap_content"
android:gravity="center"> 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_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:text="@string/unknown"
android:gravity="center_horizontal"> android:textSize="50sp"
android:id="@+id/text_sensor_count"/>
<TextView </LinearLayout>
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"/>
<TextView </RelativeLayout>
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>

View File

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

View File

@ -1,76 +1,71 @@
<?xml version="1.0" encoding="utf-8"?> <?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_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="horizontal">
<LinearLayout <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:text="RPM: "
android:labelFor="@+id/vesc_control_input_rpm"/>
<TextView <EditText
android:layout_width="wrap_content" android:layout_width="100dp"
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"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:inputType="numberDecimal"
android:id="@+id/vesc_control_input_rpm"/>
<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> </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:padding="4dp"
android:scaleType="fitXY" android:scaleType="fitXY"
card_view:srcCompat="@drawable/ic_device_set_reminders" card_view:srcCompat="@drawable/ic_device_set_reminders"
android:tint="@color/secondarytext" /> app:tint="@color/secondarytext" />
<ImageView <ImageView
android:id="@+id/device_action_show_activity_graphs" android:id="@+id/device_action_show_activity_graphs"

View File

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

View File

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