From 5f232456a629b0285b4c8f400a3d5d2f8eb415cf Mon Sep 17 00:00:00 2001 From: Joshua Date: Mon, 30 Aug 2021 21:16:00 +0200 Subject: [PATCH 1/8] Removed usages of MainContext --- .../ch/virt/smartphonemouse/MainActivity.java | 94 ++++--------------- .../customization/SamplingRateCalibrator.java | 14 +-- .../smartphonemouse/helper/MainContext.java | 20 ---- .../smartphonemouse/mouse/MouseInputs.java | 13 ++- .../mouse/MovementHandler.java | 16 ++-- .../transmission/BluetoothDiscoverer.java | 16 +--- .../transmission/BluetoothHandler.java | 36 +++---- .../transmission/DeviceStorage.java | 17 ++-- .../transmission/hid/HidDevice.java | 17 ++-- .../smartphonemouse/ui/ConnectFragment.java | 3 +- .../virt/smartphonemouse/ui/HomeFragment.java | 9 +- .../smartphonemouse/ui/MouseFragment.java | 12 +-- .../smartphonemouse/ui/SettingsFragment.java | 6 +- .../connect/ConnectConnectedSubfragment.java | 3 +- .../ui/connect/ConnectFailedSubfragment.java | 13 ++- .../ui/connect/dialog/AddDialog.java | 13 +-- .../ui/home/HomeConnectedSubfragment.java | 10 +- .../ui/mouse/MouseCalibrateDialog.java | 4 +- .../ui/mouse/MouseUsageDialog.java | 2 +- .../ui/mouse/MouseUsageFinishedSubdialog.java | 6 +- .../SettingsCommunicationSubfragment.java | 8 +- .../dialog/CalibrateFinishedSubdialog.java | 4 +- .../dialog/SamplingRateSubdialog.java | 4 +- app/src/main/res/values/strings.xml | 4 +- 24 files changed, 125 insertions(+), 219 deletions(-) diff --git a/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java b/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java index 1614377..8f4f3ba 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java +++ b/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java @@ -1,17 +1,9 @@ package ch.virt.smartphonemouse; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.res.Resources; import android.os.Bundle; import android.view.View; import android.widget.Toast; -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -24,11 +16,9 @@ import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.navigation.NavigationView; -import com.google.android.material.snackbar.Snackbar; import ch.virt.smartphonemouse.customization.DefaultSettings; import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.helper.ResultListener; import ch.virt.smartphonemouse.mouse.MouseInputs; import ch.virt.smartphonemouse.mouse.MovementHandler; import ch.virt.smartphonemouse.transmission.BluetoothHandler; @@ -91,71 +81,26 @@ protected void onStart() { */ private void loadContent() { mainContext = new MainContext() { - @Override - public void exitApp() { - finish(); - } - - @Override - public void navigate(int element) { - MainActivity.this.navigate(element); - } - - @Override - public ActivityResultLauncher registerActivityForResult(ResultListener listener) { - return registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> listener.result(result.getResultCode())); - } - - @Override - public void toast(String content, int duration) { - Toast.makeText(MainActivity.this, content, duration).show(); - } - @Override - public void snack(String content, int duration) { - Snackbar.make(MainActivity.this, MainActivity.this.findViewById(R.id.container), content, duration).show(); - } - - @Override - public Resources getResources() { - return MainActivity.this.getResources(); - } - - @Override - public Context getContext() { - return MainActivity.this; - } - - @Override - public void refresh() { - reRender(); - } - - @Override - public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { - MainActivity.this.registerReceiver(receiver, filter); - } - - @Override - public void unregisterReceiver(BroadcastReceiver receiver) { - MainActivity.this.unregisterReceiver(receiver); - } - - @Override - public SharedPreferences getPreferences() { - return PreferenceManager.getDefaultSharedPreferences(MainActivity.this); - } }; - bluetooth = new BluetoothHandler(mainContext); + bluetooth = new BluetoothHandler(this); - inputs = new MouseInputs(bluetooth, mainContext); + inputs = new MouseInputs(bluetooth, this); - movement = new MovementHandler(mainContext, inputs); + movement = new MovementHandler(this, inputs); checkNavItems(); } + public void updateBluetoothStatus(){ + reRender(); + } + + public MainContext getMainContext() { + return mainContext; + } + /** * Switches the Fragment displayed on the app * @@ -202,9 +147,7 @@ private void setupNavigation() { drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() { @Override - public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { - - } + public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { } @Override public void onDrawerOpened(@NonNull View drawerView) { @@ -212,14 +155,9 @@ public void onDrawerOpened(@NonNull View drawerView) { } @Override - public void onDrawerClosed(@NonNull View drawerView) { - - } - + public void onDrawerClosed(@NonNull View drawerView) { } @Override - public void onDrawerStateChanged(int newState) { - - } + public void onDrawerStateChanged(int newState) { } }); } @@ -277,10 +215,10 @@ private void setNavItemEnable(int item, boolean enable){ * @param entry entry to navigate to * @return whether that entry is navigated */ - private boolean navigate(int entry) { + public boolean navigate(int entry) { if (entry == R.id.drawer_mouse){ - if (!mainContext.getPreferences().getBoolean("movementSamplingCalibrated", false)) { // Make sure that the sampling rate is calibrated + if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean("movementSamplingCalibrated", false)) { // Make sure that the sampling rate is calibrated MouseCalibrateDialog dialog = new MouseCalibrateDialog(this.mainContext); dialog.show(getSupportFragmentManager(), null); diff --git a/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java b/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java index 267b235..b6e0773 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java +++ b/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java @@ -6,13 +6,13 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; -import android.os.Handler; + +import androidx.preference.PreferenceManager; import java.util.Timer; import java.util.TimerTask; import ch.virt.smartphonemouse.helper.Listener; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.mouse.MovementHandler; public class SamplingRateCalibrator implements SensorEventListener { @@ -29,16 +29,16 @@ public class SamplingRateCalibrator implements SensorEventListener { private long delays; private int amount; - private final MainContext main; + private final Context context; - public SamplingRateCalibrator(MainContext main) { - this.main = main; + public SamplingRateCalibrator(Context context) { + this.context = context; fetchSensor(); } public void fetchSensor(){ - manager = (SensorManager) main.getContext().getSystemService(Context.SENSOR_SERVICE); + manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); sensor = manager.getDefaultSensor(MovementHandler.SENSOR_TYPE); } @@ -87,7 +87,7 @@ public void finishTest(){ int samplesPerSecond = Math.round(1f / averageDelaySecond); - SharedPreferences.Editor edit = main.getPreferences().edit(); + SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(context).edit(); edit.putBoolean("movementSamplingCalibrated", true); edit.putInt("movementSamplingRealRate", samplesPerSecond); edit.apply(); diff --git a/app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java b/app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java index 99aff42..f15a4d8 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java +++ b/app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java @@ -1,25 +1,5 @@ package ch.virt.smartphonemouse.helper; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.res.Resources; - -import androidx.activity.result.ActivityResultLauncher; - public interface MainContext { - void exitApp(); - void navigate(int element); - ActivityResultLauncher registerActivityForResult(ResultListener result); - void toast(String content, int duration); - void snack(String content, int duration); - Resources getResources(); - Context getContext(); - void refresh(); - void registerReceiver(BroadcastReceiver receiver, IntentFilter filter); - void unregisterReceiver(BroadcastReceiver receiver); - SharedPreferences getPreferences(); } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java index 06adb32..366b56a 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java @@ -1,6 +1,9 @@ package ch.virt.smartphonemouse.mouse; -import ch.virt.smartphonemouse.helper.MainContext; +import android.content.Context; + +import androidx.preference.PreferenceManager; + import ch.virt.smartphonemouse.transmission.BluetoothHandler; public class MouseInputs { @@ -13,15 +16,15 @@ public class MouseInputs { private int transmissionRate = 0; private BluetoothHandler bluetoothHandler; - private MainContext main; + private Context context; private Thread thread; private boolean running; private long lastTime; - public MouseInputs(BluetoothHandler bluetoothHandler, MainContext main) { + public MouseInputs(BluetoothHandler bluetoothHandler, Context context) { this.bluetoothHandler = bluetoothHandler; - this.main = main; + this.context = context; } public void start(){ @@ -29,7 +32,7 @@ public void start(){ thread = new Thread(this::run); - transmissionRate = main.getPreferences().getInt("communicationTransmissionRate", 100); + transmissionRate = PreferenceManager.getDefaultSharedPreferences(context).getInt("communicationTransmissionRate", 100); running = true; thread.start(); diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java index 1424a25..febe0f0 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java @@ -6,7 +6,7 @@ import android.hardware.SensorEventListener; import android.hardware.SensorManager; -import ch.virt.smartphonemouse.helper.MainContext; +import androidx.preference.PreferenceManager; public class MovementHandler implements SensorEventListener { @@ -18,7 +18,7 @@ public class MovementHandler implements SensorEventListener { private SensorManager manager; private Sensor sensor; - private MainContext main; + private Context context; private MouseInputs inputs; private boolean registered; @@ -26,8 +26,8 @@ public class MovementHandler implements SensorEventListener { private long lastSample = 0; private Pipeline xLine, yLine; - public MovementHandler(MainContext main, MouseInputs inputs) { - this.main = main; + public MovementHandler(Context context, MouseInputs inputs) { + this.context = context; this.inputs = inputs; fetchSensor(); @@ -35,14 +35,14 @@ public MovementHandler(MainContext main, MouseInputs inputs) { } public void create(){ - int sampleRate = main.getPreferences().getInt("communicationTransmissionRate", 200); + int sampleRate = PreferenceManager.getDefaultSharedPreferences(context).getInt("communicationTransmissionRate", 200); - xLine = new Pipeline(sampleRate, new PipelineConfig(main.getPreferences())); - yLine = new Pipeline(sampleRate, new PipelineConfig(main.getPreferences())); + xLine = new Pipeline(sampleRate, new PipelineConfig(PreferenceManager.getDefaultSharedPreferences(context))); + yLine = new Pipeline(sampleRate, new PipelineConfig(PreferenceManager.getDefaultSharedPreferences(context))); } public void fetchSensor(){ - manager = (SensorManager) main.getContext().getSystemService(Context.SENSOR_SERVICE); + manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); sensor = manager.getDefaultSensor(SENSOR_TYPE); } diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java index 404c8b2..be9effb 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java @@ -1,26 +1,21 @@ package ch.virt.smartphonemouse.transmission; -import android.Manifest; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.PackageManager; import androidx.annotation.Nullable; -import androidx.core.app.ActivityCompat; import java.util.ArrayList; import java.util.List; import ch.virt.smartphonemouse.helper.Listener; -import ch.virt.smartphonemouse.helper.MainContext; public class BluetoothDiscoverer extends BroadcastReceiver { - MainContext context; BluetoothAdapter adapter; boolean isScanning; @@ -29,8 +24,7 @@ public class BluetoothDiscoverer extends BroadcastReceiver { Listener updateListener; Listener scanListener; - public BluetoothDiscoverer(MainContext context, BluetoothAdapter adapter) { - this.context = context; + public BluetoothDiscoverer(Context context, BluetoothAdapter adapter) { this.adapter = adapter; devices = new ArrayList<>(); @@ -44,13 +38,7 @@ public BluetoothDiscoverer(MainContext context, BluetoothAdapter adapter) { } public void startDiscovery() { - System.out.println(ActivityCompat.checkSelfPermission(context.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED); - System.out.println(ActivityCompat.checkSelfPermission(context.getContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED); - System.out.println(ActivityCompat.checkSelfPermission(context.getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED); - System.out.println(ActivityCompat.checkSelfPermission(context.getContext(), Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED); - System.out.println(adapter.getState() == BluetoothAdapter.STATE_ON); - System.out.println("Started: " + adapter.startDiscovery()); - + adapter.startDiscovery(); } public void stopDiscovery() { diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java index d428965..bf87cab 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java @@ -6,13 +6,13 @@ import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.util.Log; +import android.widget.Toast; +import androidx.activity.ComponentActivity; import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; -import com.google.android.material.snackbar.Snackbar; - -import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; +import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.transmission.hid.HidDevice; public class BluetoothHandler implements BluetoothProfile.ServiceListener { @@ -24,7 +24,7 @@ public class BluetoothHandler implements BluetoothProfile.ServiceListener { private DeviceStorage devices; - private final MainContext context; + private final ComponentActivity main; private HidDevice device; @@ -35,12 +35,12 @@ public class BluetoothHandler implements BluetoothProfile.ServiceListener { private ActivityResultLauncher enableBluetoothLauncher; - public BluetoothHandler(MainContext context) { - this.context = context; - discoverer = new BluetoothDiscoverer(context, adapter); - devices = new DeviceStorage(context); + public BluetoothHandler(ComponentActivity context) { + this.main = context; + discoverer = new BluetoothDiscoverer(main, adapter); + devices = new DeviceStorage(main); - enableBluetoothLauncher = context.registerActivityForResult(result -> reInit()); + enableBluetoothLauncher = main.registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> reInit()); } public boolean reInitRequired(){ @@ -77,7 +77,7 @@ private void init() { initialized = true; supported = false; - context.refresh(); + ((MainActivity)main).updateBluetoothStatus(); return; } @@ -87,7 +87,7 @@ private void init() { enabled = false; initialized = true; - context.refresh(); + ((MainActivity)main).updateBluetoothStatus(); return; }else enabled = true; @@ -96,12 +96,12 @@ private void init() { } private void open(){ - if(!adapter.getProfileProxy(context.getContext(), this, BluetoothProfile.HID_DEVICE)){ + if(!adapter.getProfileProxy(main, this, BluetoothProfile.HID_DEVICE)){ Log.i(TAG, "Bluetooth HID profile is not supported"); initialized = true; supported = false; - context.refresh(); + ((MainActivity)main).updateBluetoothStatus(); return; } @@ -112,13 +112,13 @@ private void start(){ Log.i(TAG, "Opened HID Profile successfully"); initialized = true; - discoverer = new BluetoothDiscoverer(context, adapter); - device = new HidDevice(service, this, context); + discoverer = new BluetoothDiscoverer(main, adapter); + device = new HidDevice(service, this, main); Log.d(TAG, "Registering with a HID Device!"); device.register(); - context.refresh(); + ((MainActivity)main).updateBluetoothStatus(); } @Override @@ -137,7 +137,7 @@ public void onServiceDisconnected(int profile) { opened = false; Log.i(TAG, "Reconnecting to Service"); - context.snack(context.getResources().getString(R.string.snack_bluetooth_closed), Snackbar.LENGTH_SHORT); + Toast.makeText(main, "Reloading Bluetooth", Toast.LENGTH_SHORT).show(); open(); } diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java index c2aeac8..5c38be6 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java @@ -1,37 +1,36 @@ package ch.virt.smartphonemouse.transmission; -import android.bluetooth.BluetoothClass; +import android.content.Context; + +import androidx.preference.PreferenceManager; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; -import ch.virt.smartphonemouse.helper.MainContext; - public class DeviceStorage { public static final String DEVICES_KEY = "devices"; - MainContext context; + Context context; List devices; - public DeviceStorage(MainContext context) { + public DeviceStorage(Context context) { this.context = context; load(); } public void load(){ - String src = context.getPreferences().getString(DEVICES_KEY, "[]"); + String src = PreferenceManager.getDefaultSharedPreferences(context).getString(DEVICES_KEY, "[]"); devices = new Gson().fromJson(src, new TypeToken>(){}.getType()); } public void save(){ - devices.sort((o1, o2) -> Long.compare(o1.getLastConnected(), o2.getLastConnected())); + devices.sort((o1, o2) -> -Long.compare(o1.getLastConnected(), o2.getLastConnected())); String src = new Gson().toJson(devices); - context.getPreferences().edit().putString(DEVICES_KEY, src).apply(); + PreferenceManager.getDefaultSharedPreferences(context).edit().putString(DEVICES_KEY, src).apply(); } public List getDevices() { diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java index 605a693..d7eec04 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java @@ -2,15 +2,14 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHidDevice; -import android.bluetooth.BluetoothHidDeviceAppQosSettings; import android.bluetooth.BluetoothHidDeviceAppSdpSettings; +import android.content.Context; import android.os.SystemClock; import android.util.Log; -import ch.virt.smartphonemouse.helper.MainContext; +import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.transmission.HostDevice; -import ch.virt.smartphonemouse.transmission.hid.HidDescriptor; public class HidDevice extends BluetoothHidDevice.Callback { private static final String TAG = "HidDevice"; @@ -20,7 +19,7 @@ public class HidDevice extends BluetoothHidDevice.Callback { private static final String PROVIDER = "Virt"; BluetoothHidDevice service; - MainContext context; + Context context; BluetoothDevice device; long connectedSince; @@ -33,7 +32,7 @@ public class HidDevice extends BluetoothHidDevice.Callback { BluetoothHandler bluetooth; - public HidDevice(BluetoothHidDevice device, BluetoothHandler bluetooth, MainContext context) { + public HidDevice(BluetoothHidDevice device, BluetoothHandler bluetooth, Context context) { this.service = device; this.context = context; this.bluetooth = bluetooth; @@ -44,7 +43,7 @@ private BluetoothHidDeviceAppSdpSettings createSDP(){ } public void register(){ - if (!registered) service.registerApp(createSDP(), null, null, context.getContext().getMainExecutor(), this); + if (!registered) service.registerApp(createSDP(), null, null, context.getMainExecutor(), this); else Log.d(TAG, "The Device is already registered!"); } @@ -67,7 +66,7 @@ public void onConnectionStateChanged(BluetoothDevice device, int state) { bluetooth.getDevices().getDevice(device.getAddress()).setLastConnected(System.currentTimeMillis()); bluetooth.getDevices().save(); - context.refresh(); + ((MainActivity)context).updateBluetoothStatus(); Log.d(TAG, "HID Host connected!"); break; @@ -78,7 +77,7 @@ public void onConnectionStateChanged(BluetoothDevice device, int state) { connecting = false; connected = false; - context.refresh(); + ((MainActivity)context).updateBluetoothStatus(); Log.d(TAG, "HID Host disconnected!"); break; @@ -95,7 +94,7 @@ public void connect(HostDevice deviceH){ service.connect(device); connecting = true; - context.refresh(); + ((MainActivity)context).updateBluetoothStatus(); Log.d(TAG, "connect: Refreshed"); } else Log.d(TAG, "Cannot connect to host whilst connecting or being connected and must be registered"); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java index 55ddc7a..39172b4 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java @@ -14,7 +14,6 @@ import ch.virt.smartphonemouse.ui.connect.ConnectConnectingSubfragment; import ch.virt.smartphonemouse.ui.connect.ConnectFailedSubfragment; import ch.virt.smartphonemouse.ui.connect.ConnectSelectSubfragment; -import ch.virt.smartphonemouse.ui.home.HomeConnectedSubfragment; public class ConnectFragment extends CustomFragment { @@ -37,7 +36,7 @@ public void render() { setStatus(R.color.status_connecting, R.string.connect_status_connecting); } else if (!bluetooth.isConnected()){ - if (bluetooth.getHost().hasFailed()) loadFragment(new ConnectFailedSubfragment(main, bluetooth)); + if (bluetooth.getHost().hasFailed()) loadFragment(new ConnectFailedSubfragment(main, bluetooth, this::render)); else loadFragment(new ConnectSelectSubfragment(main, bluetooth)); setStatus(R.color.status_disconnected, R.string.connect_status_disconnected); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java index 1a4c16c..e47ecd1 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java @@ -8,9 +8,10 @@ import androidx.fragment.app.Fragment; +import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.helper.MainContext; +import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.ui.home.HomeConnectedSubfragment; import ch.virt.smartphonemouse.ui.home.HomeDisabledSubfragment; import ch.virt.smartphonemouse.ui.home.HomeDisconnectedSubfragment; @@ -39,13 +40,13 @@ public void render() { setStatus(R.color.status_init, R.string.home_status_disabled, R.string.home_button_disabled, v -> bluetooth.enableBluetooth(), new HomeDisabledSubfragment(bluetooth)); else if (!bluetooth.isSupported()) - setStatus(R.color.status_unsupported, R.string.home_status_unsupported, R.string.home_button_unsupported, v -> main.exitApp(), new HomeUnsupportedSubfragment()); + setStatus(R.color.status_unsupported, R.string.home_status_unsupported, R.string.home_button_unsupported, v -> getActivity().finish(), new HomeUnsupportedSubfragment()); else if (bluetooth.isConnected()) - setStatus(R.color.status_connected, R.string.home_status_connected, R.string.home_button_connected, v -> main.navigate(R.id.drawer_mouse), new HomeConnectedSubfragment(bluetooth, main)); + setStatus(R.color.status_connected, R.string.home_status_connected, R.string.home_button_connected, v -> ((MainActivity) getActivity()).navigate(R.id.drawer_mouse), new HomeConnectedSubfragment(bluetooth, main)); else - setStatus(R.color.status_disconnected, R.string.home_status_disconnected, R.string.home_button_disconnected, v -> main.navigate(R.id.drawer_connect), new HomeDisconnectedSubfragment()); + setStatus(R.color.status_disconnected, R.string.home_status_disconnected, R.string.home_button_disconnected, v -> ((MainActivity) getActivity()).navigate(R.id.drawer_connect), new HomeDisconnectedSubfragment()); } protected void loadComponents(View view){ diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java index e3134d0..ed76917 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java @@ -1,5 +1,7 @@ package ch.virt.smartphonemouse.ui; +import static android.content.Context.VIBRATOR_SERVICE; + import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.os.Build; @@ -12,16 +14,14 @@ import android.widget.FrameLayout; import android.widget.RelativeLayout; +import androidx.preference.PreferenceManager; + import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.mouse.MouseInputs; import ch.virt.smartphonemouse.mouse.MovementHandler; -import ch.virt.smartphonemouse.ui.mouse.MouseCalibrateDialog; import ch.virt.smartphonemouse.ui.mouse.MouseUsageDialog; -import static android.content.Context.VIBRATOR_SERVICE; - /** * This fragment represents the mouse interface the user uses to input button strokes */ @@ -86,7 +86,7 @@ public MouseFragment(MainContext context, MouseInputs mouse, MovementHandler mov * Reads the settings for the fragment from the preferences */ private void readSettings(){ - SharedPreferences prefs = main.getPreferences(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); theme = prefs.getString("interfaceTheme", "dark").equals("dark"); @@ -162,7 +162,7 @@ protected void initComponents() { if (vibrations) vibrator = (Vibrator) getContext().getSystemService(VIBRATOR_SERVICE); - if (main.getPreferences().getBoolean("showUsage", true)){ + if (PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("showUsage", true)){ movement.unregister(); mouse.stop(); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java index b8676a6..d3bcd41 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java @@ -2,11 +2,11 @@ import android.app.AlertDialog; import android.app.Dialog; -import android.content.DialogInterface; import android.os.Bundle; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceManager; import com.google.android.material.snackbar.Snackbar; @@ -33,9 +33,9 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { builder.setMessage(R.string.settings_reset_dialog_message) .setPositiveButton(R.string.settings_reset_dialog_reset, (dialog, id) -> { - DefaultSettings.set(main.getPreferences()); + DefaultSettings.set(PreferenceManager.getDefaultSharedPreferences(getContext())); - main.snack(main.getResources().getString(R.string.settings_reset_confirmation), Snackbar.LENGTH_SHORT); + Snackbar.make(getView(), getResources().getString(R.string.settings_reset_confirmation), Snackbar.LENGTH_SHORT); }) .setNegativeButton(R.string.settings_reset_dialog_cancel, (dialog, id) -> {}); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java index f5f7f41..f126139 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java @@ -5,6 +5,7 @@ import android.widget.Chronometer; import android.widget.TextView; +import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; @@ -38,7 +39,7 @@ public void render() { disconnect.setOnClickListener(v -> bluetooth.getHost().disconnect()); mouse.setOnClickListener(v -> { bluetooth.getHost().sendReport(false, false, false, 0, 20, 0); - main.navigate(R.id.drawer_mouse); + ((MainActivity) getActivity()).navigate(R.id.drawer_mouse); }); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java index b3e222b..32f7deb 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java @@ -17,9 +17,12 @@ public class ConnectFailedSubfragment extends CustomFragment { Button back; Button remove; - public ConnectFailedSubfragment(MainContext context, BluetoothHandler bluetooth) { + ReturnListener listener; + + public ConnectFailedSubfragment(MainContext context, BluetoothHandler bluetooth, ReturnListener listener) { super(R.layout.subfragment_connect_failed, context); this.bluetooth = bluetooth; + this.listener = listener; } @Override @@ -29,11 +32,11 @@ public void render() { remove.setOnClickListener(v -> { bluetooth.getDevices().removeDevice(bluetooth.getHost().getDevice().getAddress()); bluetooth.getHost().markFailedAsRead(); - main.refresh(); + listener.called(); }); back.setOnClickListener(v -> { bluetooth.getHost().markFailedAsRead(); - main.refresh(); + listener.called(); }); } @@ -44,4 +47,8 @@ protected void loadComponents(View view) { back = view.findViewById(R.id.connect_failed_back); remove = view.findViewById(R.id.connect_failed_remove); } + + public interface ReturnListener { + void called(); + } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java index a56a888..aa1aaad 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java @@ -14,7 +14,6 @@ import android.view.View; import android.view.WindowManager; import android.widget.Button; -import android.widget.Toast; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; @@ -24,8 +23,6 @@ import androidx.core.location.LocationManagerCompat; import androidx.fragment.app.DialogFragment; -import com.google.android.material.snackbar.Snackbar; - import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.helper.Listener; import ch.virt.smartphonemouse.helper.MainContext; @@ -73,8 +70,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) { requestLocation = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { - mainContext.snack(mainContext.getResources().getString(R.string.add_request_permission_success), Snackbar.LENGTH_SHORT); - showRequestSetting(); } else ((AddRequestPermissionSubdialog) currentSub).showError(); @@ -97,7 +92,7 @@ private void setFragment(CustomFragment fragment){ public void showRequestPermission(){ state = REQUEST_PERMISSION_STATE; - if (ActivityCompat.checkSelfPermission(mainContext.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){ + if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){ showRequestSetting(); // Get on if already granted return; } @@ -113,7 +108,7 @@ public void showRequestPermission(){ public void showRequestSetting(){ state = REQUEST_SETTING_STATE; - if (LocationManagerCompat.isLocationEnabled((LocationManager) mainContext.getContext().getSystemService(Context.LOCATION_SERVICE))){ + if (LocationManagerCompat.isLocationEnabled((LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE))){ showSelect(); // Get on if already granted return; } @@ -263,7 +258,7 @@ public void requestPermission(){ } public void requestSetting(){ - if (LocationManagerCompat.isLocationEnabled((LocationManager) mainContext.getContext().getSystemService(Context.LOCATION_SERVICE))){ + if (LocationManagerCompat.isLocationEnabled((LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE))){ showSelect(); } else { enableLocation.launch(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); @@ -271,7 +266,7 @@ public void requestSetting(){ } public void checkSetting(){ - if (LocationManagerCompat.isLocationEnabled((LocationManager) mainContext.getContext().getSystemService(Context.LOCATION_SERVICE))){ + if (LocationManagerCompat.isLocationEnabled((LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE))){ showSelect(); } else { ((AddRequestSettingSubdialog) currentSub).showError(); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java index 29cc082..1e7f672 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java @@ -1,17 +1,11 @@ package ch.virt.smartphonemouse.ui.home; -import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Chronometer; import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; - -import org.w3c.dom.Text; - +import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; @@ -39,7 +33,7 @@ public void render() { device.setText(handler.getHost().getDevice().getName()); - more.setOnClickListener(v -> main.navigate(R.id.drawer_connect)); + more.setOnClickListener(v -> ((MainActivity) getActivity()).navigate(R.id.drawer_connect)); } @Override diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java index 308d130..5a50e6d 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java @@ -36,7 +36,7 @@ private void created(){ positiveButton.setEnabled(true); negativeButton.setVisibility(View.VISIBLE); - setFragment(new MouseMessageSubdialog(main.getResources().getString(R.string.mouse_message_calibrate), main)); + setFragment(new MouseMessageSubdialog(getResources().getString(R.string.mouse_message_calibrate), main)); } private void next(){ @@ -63,7 +63,7 @@ private void finished(){ dialog.setCanceledOnTouchOutside(true); positiveButton.setEnabled(true); - setFragment(new MouseMessageSubdialog(main.getResources().getString(R.string.dialog_mouse_calibrate_finished), main)); + setFragment(new MouseMessageSubdialog(getResources().getString(R.string.dialog_mouse_calibrate_finished), main)); } private void setFragment(CustomFragment fragment){ diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java index 19972eb..6693084 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java @@ -56,7 +56,7 @@ private void next(){ } private void showFragment(){ - setFragment(new MouseMessageSubdialog(main.getResources().getString(getCurrentMessage(index)), main)); + setFragment(new MouseMessageSubdialog(getResources().getString(getCurrentMessage(index)), main)); } public int getCurrentMessage(int index){ diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java index c8c1419..611e9d3 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java @@ -3,6 +3,8 @@ import android.view.View; import android.widget.CheckBox; +import androidx.preference.PreferenceManager; + import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.ui.CustomFragment; @@ -23,10 +25,10 @@ public void render() { @Override protected void initComponents() { - notAgain.setChecked(!main.getPreferences().getBoolean("showUsage", true)); + notAgain.setChecked(!PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("showUsage", true)); notAgain.setOnCheckedChangeListener((buttonView, isChecked) -> { - main.getPreferences().edit().putBoolean("showUsage", !isChecked).apply(); + PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putBoolean("showUsage", !isChecked).apply(); }); } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java index c084c17..6448d37 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java @@ -6,14 +6,12 @@ import android.os.Bundle; import androidx.preference.Preference; -import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceManager; import com.google.android.material.snackbar.Snackbar; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.customization.DefaultSettings; import ch.virt.smartphonemouse.transmission.DeviceStorage; -import ch.virt.smartphonemouse.ui.settings.custom.EditIntegerPreference; public class SettingsCommunicationSubfragment extends CustomSettingsFragment { @Override @@ -28,13 +26,13 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { builder.setMessage(R.string.settings_communication_removeall_dialog_message) .setPositiveButton(R.string.settings_communication_removeall_dialog_remove, (dialog, id) -> { - SharedPreferences.Editor editor = main.getPreferences().edit(); + SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(getContext()).edit(); editor.putString(DeviceStorage.DEVICES_KEY, "[]"); // Reset to an empty json array editor.apply(); - main.snack(main.getResources().getString(R.string.settings_communication_removeall_confirmation), Snackbar.LENGTH_SHORT); + Snackbar.make(getView(), getResources().getString(R.string.settings_communication_removeall_confirmation), Snackbar.LENGTH_SHORT).show(); }) .setNegativeButton(R.string.settings_communication_removeall_dialog_cancel, (dialog, id) -> {}); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java index 8b66506..ab9264c 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java @@ -3,6 +3,8 @@ import android.view.View; import android.widget.TextView; +import androidx.preference.PreferenceManager; + import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.ui.CustomFragment; @@ -22,7 +24,7 @@ public void render() { @Override protected void initComponents() { - rate.setText(main.getResources().getString(R.string.dialog_calibrate_finished_rate, main.getPreferences().getInt("movementSamplingRealRate", 0))); + rate.setText(getResources().getString(R.string.dialog_calibrate_finished_rate, PreferenceManager.getDefaultSharedPreferences(getContext()).getInt("movementSamplingRealRate", 0))); } @Override diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java index fc751e2..bbb5556 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java @@ -21,7 +21,7 @@ public SamplingRateSubdialog(MainContext context, Listener doneListener) { super(R.layout.subdialog_calibrate_samplingrate, context); this.doneListener = doneListener; - calibrator = new SamplingRateCalibrator(main); + calibrator = new SamplingRateCalibrator(getContext()); //TODO: Will probably produce nullpointer } @Override @@ -32,7 +32,7 @@ public void render() { @Override protected void initComponents() { - time.setText(main.getResources().getString(R.string.dialog_calibrate_samplingrate_time, calibrator.getTestLength() / 1000 * 2)); // Double the time, so it is always shorter + time.setText(getResources().getString(R.string.dialog_calibrate_samplingrate_time, calibrator.getTestLength() / 1000 * 2)); // Double the time, so it is always shorter calibrator.calibrate(doneListener); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fe47fbd..698b6cc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -133,10 +133,10 @@ In order to see nearby devices, you must have location turn on. If you don\'t want to enable location, you can still add a device manually. Enable Location About - 1.0.0 + 1.1.0 Version:  Last Updated at:  - 16.08.21 + 30.08.21 This app is a feasibility study about whether it is possible to use a smartphone as a normal computer mouse. As a result, the app should not be treated as a finished product. This app is also part of a Matura Paper by Joshua Stalder. Developed by Joshua Stalder From e2b8f021113a822317975e1c4c3d144fa7f72e05 Mon Sep 17 00:00:00 2001 From: Joshua Date: Mon, 30 Aug 2021 22:15:44 +0200 Subject: [PATCH 2/8] Javadoc and minor refactoring --- .../customization/DefaultSettings.java | 42 ++++++++++-- .../customization/SamplingRateCalibrator.java | 65 ++++++++++++++++--- .../mouse/elements/Freezer.java | 33 ++++++++-- .../mouse/elements/Integration.java | 17 ++++- .../mouse/elements/LowPassFilter.java | 10 +++ .../mouse/elements/NoiseCancelling.java | 32 +++++++-- .../mouse/elements/PersistentIntegration.java | 3 + .../mouse/elements/Scaler.java | 20 +++++- .../mouse/elements/Sensitivity.java | 34 ++++++++-- .../mouse/elements/SignCache.java | 58 ++++++++++++----- .../ui/mouse/MouseCalibrateDialog.java | 2 +- .../ui/settings/dialog/CalibrateDialog.java | 2 +- .../dialog/SamplingRateSubdialog.java | 5 +- 13 files changed, 263 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/ch/virt/smartphonemouse/customization/DefaultSettings.java b/app/src/main/java/ch/virt/smartphonemouse/customization/DefaultSettings.java index cae294a..146ccca 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/customization/DefaultSettings.java +++ b/app/src/main/java/ch/virt/smartphonemouse/customization/DefaultSettings.java @@ -2,13 +2,27 @@ import android.content.SharedPreferences; +/** + * This class is used for restoring the settings to their factory defaults. + */ public class DefaultSettings { - public static void check(SharedPreferences preferences){ + /** + * Checks whether the preferences have once been populated. + * If not, they get initialized to the default settings. + * + * @param preferences preferences to check in + */ + public static void check(SharedPreferences preferences) { if (!preferences.getBoolean("populated", false)) set(preferences); } - public static void set(SharedPreferences preferences){ + /** + * Overwrites the settings to the defaults + * + * @param preferences preferences to write in + */ + public static void set(SharedPreferences preferences) { SharedPreferences.Editor edit = preferences.edit(); edit.putBoolean("populated", true); @@ -22,7 +36,12 @@ public static void set(SharedPreferences preferences){ defaultCommunication(preferences); } - private static void defaultInterface(SharedPreferences preferences){ + /** + * Writes the default interface settings + * + * @param preferences preferences to write in + */ + private static void defaultInterface(SharedPreferences preferences) { SharedPreferences.Editor edit = preferences.edit(); edit.putString("interfaceTheme", "dark"); @@ -48,7 +67,12 @@ private static void defaultInterface(SharedPreferences preferences){ edit.apply(); } - private static void defaultMovement(SharedPreferences preferences){ + /** + * Writes the default movement settings + * + * @param preferences preferences to write in + */ + private static void defaultMovement(SharedPreferences preferences) { SharedPreferences.Editor edit = preferences.edit(); edit.putFloat("movementSensitivity", 13); @@ -59,7 +83,7 @@ private static void defaultMovement(SharedPreferences preferences){ edit.putInt("movementSamplingRealRate", 200); edit.putInt("movementLowPassOrder", 1); - edit.putFloat("movementLowPassCutoff", 0.1f); + edit.putFloat("movementLowPassCutoff", 0.05f); edit.putFloat("movementFreezerFreezingThreshold", 0.1f); edit.putFloat("movementFreezerUnfreezingThreshold", 0.04f); @@ -78,12 +102,16 @@ private static void defaultMovement(SharedPreferences preferences){ edit.apply(); } - private static void defaultCommunication(SharedPreferences preferences){ + /** + * Writes the default communication settings + * + * @param preferences preferences to write in + */ + private static void defaultCommunication(SharedPreferences preferences) { SharedPreferences.Editor edit = preferences.edit(); edit.putInt("communicationTransmissionRate", 100); edit.apply(); } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java b/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java index b6e0773..df75a03 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java +++ b/app/src/main/java/ch/virt/smartphonemouse/customization/SamplingRateCalibrator.java @@ -12,9 +12,11 @@ import java.util.Timer; import java.util.TimerTask; -import ch.virt.smartphonemouse.helper.Listener; import ch.virt.smartphonemouse.mouse.MovementHandler; +/** + * This class is used to measure and save the sampling rate of the inbuilt accelerometer. + */ public class SamplingRateCalibrator implements SensorEventListener { private static final int TEST_LENGTH = 5000; @@ -31,32 +33,51 @@ public class SamplingRateCalibrator implements SensorEventListener { private final Context context; + /** + * Creates the calibrator. + * + * @param context context to use + */ public SamplingRateCalibrator(Context context) { this.context = context; fetchSensor(); } - public void fetchSensor(){ + /** + * Fetches the sensor from the system. + */ + private void fetchSensor() { manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); sensor = manager.getDefaultSensor(MovementHandler.SENSOR_TYPE); } - public void register(){ + /** + * Registers itself as a listener. + */ + private void register() { if (registered) return; manager.registerListener(this, sensor, MovementHandler.SAMPLING_RATE); registered = true; } - public void unregister(){ + /** + * Unregisters itself as a listener. + */ + private void unregister() { if (!registered) return; manager.unregisterListener(this, sensor); registered = false; } - public void calibrate(Listener doneListener){ + /** + * Starts the measuring process. + * + * @param doneListener listener that is executed once the process has finished + */ + public void calibrate(DoneListener doneListener) { register(); prepareTest(); running = true; @@ -67,21 +88,27 @@ public void run() { running = false; unregister(); - finishTest(); + int rate = finishTest(); - doneListener.called(); + doneListener.done(rate); } }, TEST_LENGTH); } - public void prepareTest(){ + /** + * Initializes the variables for the process. + */ + private void prepareTest() { lastTime = 0; delays = 0; amount = 0; } - public void finishTest(){ + /** + * Finishes the measuring process by processing the results and saving it into the preferences. + */ + private int finishTest() { long averageDelay = delays / amount; float averageDelaySecond = averageDelay * NANO_FULL_FACTOR; @@ -92,9 +119,15 @@ public void finishTest(){ edit.putInt("movementSamplingRealRate", samplesPerSecond); edit.apply(); + return samplesPerSecond; } - public int getTestLength(){ + /** + * Returns how long the measuring process approximately will go. + * + * @return length of the process in milliseconds + */ + public int getTestLength() { return TEST_LENGTH; } @@ -116,6 +149,18 @@ public void onSensorChanged(SensorEvent event) { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + /** + * This interface is a listener used for when the measuring process is done. + */ + public interface DoneListener { + + /** + * Called when the process is done. + * + * @param samplingRate sampling rate that was measured + */ + void done(int samplingRate); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Freezer.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Freezer.java index becd8ed..d0d6684 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Freezer.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Freezer.java @@ -1,5 +1,9 @@ package ch.virt.smartphonemouse.mouse.elements; +/** + * This class holds the freezer component of the signal processing pipeline. + * The freezer ensures that the subtracted gravity gets occasionally frozen so that it is not affected by the movement of the smartphone. + */ public class Freezer { private final float freezingThreshold; @@ -10,27 +14,42 @@ public class Freezer { private int unfreezing; private float subtract; + /** + * Creates a freezer component. + * + * @param freezingThreshold how much acceleration is required for the freezer to kick in + * @param unfreezingThreshold how less acceleration is required for the freezing process to end + * @param unfreezingSamples how many samples in a row must be below said threshold + */ public Freezer(float freezingThreshold, float unfreezingThreshold, int unfreezingSamples) { this.freezingThreshold = freezingThreshold; this.unfreezingThreshold = unfreezingThreshold; this.unfreezingSamples = unfreezingSamples; } - public float next(float lowPassed, float acceleration){ - if (frozen){ - - if (Math.abs(acceleration - lowPassed) < unfreezingThreshold) unfreezing++; // Count up if it may be unfrozen + /** + * Calculates the next sample + * + * @param lowPassed acceleration after the low pass filter (gravity) + * @param acceleration unfiltered acceleration + * @return new gravity value, that may be frozen + */ + public float next(float lowPassed, float acceleration) { + if (frozen) { + + if (Math.abs(acceleration - lowPassed) < unfreezingThreshold) + unfreezing++; // Count up if it may be unfrozen else unfreezing = 0; - if (unfreezing == unfreezingSamples){ // Unfreeze if enough samples in a row + if (unfreezing == unfreezingSamples) { // Unfreeze if enough samples in a row frozen = false; subtract = lowPassed; } - }else { + } else { subtract = lowPassed; - if (Math.abs(acceleration - subtract) > freezingThreshold){ // Freeze if below threshold + if (Math.abs(acceleration - subtract) > freezingThreshold) { // Freeze if below threshold frozen = true; unfreezing = 0; } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Integration.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Integration.java index 092f69d..a688524 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Integration.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Integration.java @@ -1,14 +1,27 @@ package ch.virt.smartphonemouse.mouse.elements; +/** + * This class handles basic integration that is not persistent and can is used for the signal processing. + */ public class Integration { private float last; - public float integrate(float delta, float value){ + /** + * Integrates with the newly given sample. + * + * @param delta time delta since the last sample + * @param value new sample + * @return integrated delta + */ + public float integrate(float delta, float value) { return ((last + (last = value)) / 2) * delta; } - public void reset(){ + /** + * Resets previously stored variables. + */ + public void reset() { last = 0; } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/LowPassFilter.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/LowPassFilter.java index 83bfd3f..0f4cb91 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/LowPassFilter.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/LowPassFilter.java @@ -2,8 +2,18 @@ import uk.me.berndporr.iirj.Bessel; +/** + * This class wraps a bessel filter from the iirj library as a low pass filter and provides it for the signal processing. + */ public class LowPassFilter extends Bessel { + /** + * Creates a low pass filter. + * + * @param order order of the filter + * @param sampleRate sample rate with which samples are expected + * @param cutoff cutoff frequency of the filter + */ public LowPassFilter(int order, int sampleRate, float cutoff) { super(); lowPass(order, sampleRate, cutoff); diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/NoiseCancelling.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/NoiseCancelling.java index b82d0b5..78320bc 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/NoiseCancelling.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/NoiseCancelling.java @@ -1,5 +1,9 @@ package ch.virt.smartphonemouse.mouse.elements; +/** + * This class holds the noise cancelling component for the signal processing. + * The noise cancelling removes all amplitudes below a certain value. It also does support clearing the velocity if there has been only noise for a certain amount of time. + */ public class NoiseCancelling { private final float cancellingThreshold; @@ -9,28 +13,46 @@ public class NoiseCancelling { private int noise; + /** + * Creates a noise cancelling component + * + * @param cancellingThreshold all signal below this threshold is regarded as noise + * @param finalCancellingSamples how many samples in a row must be noise in order to reset the velocity + * @param velocityIntegration integration of the velocity that may be reset + */ public NoiseCancelling(float cancellingThreshold, int finalCancellingSamples, Integration velocityIntegration) { this.cancellingThreshold = cancellingThreshold; this.finalCancellingSamples = finalCancellingSamples; this.velocityIntegration = velocityIntegration; } - public float cancel(float value){ + /** + * Process the values that may be cancelled, presumably the acceleration + * + * @param value current acceleration value + * @return possibly canceled value + */ + public float cancel(float value) { if (Math.abs(value) <= cancellingThreshold) { // Below Threshold noise++; return 0; - }else noise = 0; + } else noise = 0; return value; } - public float velocity(float value){ - if (noise > finalCancellingSamples){ + /** + * Process the velocity to potentially reset it + * + * @param value current velocity value + * @return possibly reset velocity + */ + public float velocity(float value) { + if (noise > finalCancellingSamples) { velocityIntegration.reset(); return 0; // Cancel if much noise } return value; } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/PersistentIntegration.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/PersistentIntegration.java index f939908..2f024cb 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/PersistentIntegration.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/PersistentIntegration.java @@ -1,5 +1,8 @@ package ch.virt.smartphonemouse.mouse.elements; +/** + * This class handles integration that is persistent (just like normal integration) + */ public class PersistentIntegration extends Integration { private float whole; diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Scaler.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Scaler.java index a822747..871f192 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Scaler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Scaler.java @@ -1,21 +1,37 @@ package ch.virt.smartphonemouse.mouse.elements; +/** + * This class is a component for the signal processing that scales the signal. + * The signal gets scaled so that low values get even lower, and high values even higher. + */ public class Scaler { private final boolean enabled; private final int power; private final float split; + /** + * Creates a scaler. + * + * @param enabled whether the scaler is enabled + * @param power the power of the function that is used for scaling + * @param split values over this value get higher, values lower than it get lower + */ public Scaler(boolean enabled, int power, float split) { this.enabled = enabled; this.power = power; this.split = split; } - public float scale(float value){ + /** + * Scales a value with the function. + * + * @param value value that is scaled + * @return the scaled value + */ + public float scale(float value) { if (!enabled) return value; return (float) (Math.pow(Math.abs(value), power) * (split / Math.pow(split, power))) * (value > 0 ? 1 : -1); } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Sensitivity.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Sensitivity.java index 4ea261c..a28b8aa 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Sensitivity.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/Sensitivity.java @@ -1,23 +1,45 @@ package ch.virt.smartphonemouse.mouse.elements; +/** + * This component of the signal processing is used to scale the signal by a fixed factor. + * The factor of this scaling is made up of a base and a power, because (i think) humans do only feel exponential increase. + */ public class Sensitivity { private final int base; private final float power; + private float factor; + + /** + * Creates a sensitivity component. + * + * @param base base of the factor + * @param power power of the factor + */ public Sensitivity(int base, float power) { this.base = base; this.power = power; + + factor = (float) Math.pow(base, power); // Factor can be pre calculated since the base and power do not change } + /** + * Creates a sensitivity component with the base of two. + * + * @param power power of the factor + */ public Sensitivity(float power) { - this.power = power; - base = 2; // Two, so one unit is double - - System.out.println("Power " + Math.pow(base, power)); + this(2, power); // Two, so one unit is double } - public float scale(float value){ - return (float) (value * Math.pow(base, power)); + /** + * Scales the value by the factor. + * + * @param value value to be scaled + * @return scaled value + */ + public float scale(float value) { + return value * factor; } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/SignCache.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/SignCache.java index 6885cb6..fbc6999 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/SignCache.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/elements/SignCache.java @@ -1,5 +1,9 @@ package ch.virt.smartphonemouse.mouse.elements; +/** + * The sign cache component caches the velocity after the sign switches. If quickly after that, the acceleration rises drastically, the cached values get used again. + * This component is used to remove invalid movements that occur after a sign change. + */ public class SignCache { private final int minimalDuration; @@ -9,6 +13,21 @@ public class SignCache { private final Integration velocityIntegration; private final Integration distanceIntegration; + private boolean caching; + private boolean latelyChanged; + private float lastValue; + private int duration; + private float cachedDistance; + + /** + * Creates a sign cache. + * + * @param minimalDuration minimal duration the signal gets cached + * @param maximalDuration maximal duration the signal gets cached + * @param releasingThreshold how high the acceleration has to be in order for the values in the cache to get used again + * @param velocityIntegration integration for the velocity that may be cleared + * @param distanceIntegration integration for the distance so the distance loss can be compensated + */ public SignCache(int minimalDuration, int maximalDuration, float releasingThreshold, Integration velocityIntegration, Integration distanceIntegration) { this.minimalDuration = minimalDuration; this.maximalDuration = maximalDuration; @@ -17,14 +36,15 @@ public SignCache(int minimalDuration, int maximalDuration, float releasingThresh this.distanceIntegration = distanceIntegration; } - private boolean caching; - private boolean latelyChanged; - private float lastValue; - private int duration; - private float cachedDistance; - - public float velocity(float value, float acceleration){ - if (value != 0 && lastValue != 0 && (lastValue > 0 != value > 0)){ // If sign switched start caching + /** + * Potentially caches the velocity. + * + * @param value current velocity value + * @param acceleration current acceleration value + * @return possibly canceled velocity + */ + public float velocity(float value, float acceleration) { + if (value != 0 && lastValue != 0 && (lastValue > 0 != value > 0)) { // If sign switched start caching caching = true; duration = 0; cachedDistance = 0; @@ -32,17 +52,17 @@ public float velocity(float value, float acceleration){ lastValue = value; - if (caching){ + if (caching) { if (duration >= minimalDuration) { - if (Math.abs(acceleration) >= releasingThreshold){ // If releasing soon enough, just return to normal + if (Math.abs(acceleration) >= releasingThreshold) { // If releasing soon enough, just return to normal caching = false; latelyChanged = true; return value; } - if (duration >= maximalDuration){ // If not released, reset velocity + if (duration >= maximalDuration) { // If not released, reset velocity velocityIntegration.reset(); caching = false; return 0; @@ -56,18 +76,24 @@ public float velocity(float value, float acceleration){ return value; } - public float distance(float value, float delta){ - if (caching){ // If caching, add values up + /** + * Potentially caches the moved distance. + * + * @param value current distance value + * @param delta time delta since the last value + * @return possibly cached distance + */ + public float distance(float value, float delta) { + if (caching) { // If caching, add values up cachedDistance += distanceIntegration.integrate(delta, lastValue); return 0; - }else if (latelyChanged) { // If changed to non caching, release distance Cache + } else if (latelyChanged) { // If changed to non caching, release distance Cache latelyChanged = false; return value + cachedDistance; - }else return value; + } else return value; } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java index 5a50e6d..ec9870d 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java @@ -52,7 +52,7 @@ private void next(){ introduction = false; - setFragment(new SamplingRateSubdialog(main, () -> positiveButton.post(this::finished))); + setFragment(new SamplingRateSubdialog(main, (r) -> positiveButton.post(this::finished))); }else dismiss(); } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java index 2aab63b..2c369f4 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java @@ -36,7 +36,7 @@ private void created(){ positiveButton.setEnabled(false); dialog.setCanceledOnTouchOutside(false); - setFragment(new SamplingRateSubdialog(main, () -> positiveButton.post(this::finished))); + setFragment(new SamplingRateSubdialog(main, (r) -> positiveButton.post(this::finished))); } private void finished(){ diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java index bbb5556..515fa2d 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java @@ -5,7 +5,6 @@ import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.customization.SamplingRateCalibrator; -import ch.virt.smartphonemouse.helper.Listener; import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.ui.CustomFragment; @@ -15,9 +14,9 @@ public class SamplingRateSubdialog extends CustomFragment { private SamplingRateCalibrator calibrator; - private final Listener doneListener; + private final SamplingRateCalibrator.DoneListener doneListener; - public SamplingRateSubdialog(MainContext context, Listener doneListener) { + public SamplingRateSubdialog(MainContext context, SamplingRateCalibrator.DoneListener doneListener) { super(R.layout.subdialog_calibrate_samplingrate, context); this.doneListener = doneListener; From eb71a84c2ae80ec399c9d40ed9934ba74ec02224 Mon Sep 17 00:00:00 2001 From: Joshua Date: Thu, 2 Sep 2021 11:26:38 +0200 Subject: [PATCH 3/8] Javadoc and minor improvement on general structure --- .../smartphonemouse/mouse/MouseInputs.java | 72 ++++++++-- .../mouse/MovementHandler.java | 32 ++++- .../virt/smartphonemouse/mouse/Pipeline.java | 46 ++++-- .../smartphonemouse/mouse/PipelineConfig.java | 32 ++--- .../transmission/BluetoothDiscoverer.java | 124 ++++++++++++++-- .../transmission/BluetoothHandler.java | 128 +++++++++++++---- .../transmission/DeviceStorage.java | 82 +++++++++-- .../transmission/HostDevice.java | 29 ++++ .../transmission/hid/HidDescriptor.java | 5 +- .../transmission/hid/HidDevice.java | 134 ++++++++++++++---- .../ui/connect/dialog/AddSelectSubdialog.java | 8 +- .../ui/debug/handling/DebugDataHandler.java | 2 +- 12 files changed, 556 insertions(+), 138 deletions(-) diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java index 366b56a..813ba05 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/MouseInputs.java @@ -6,6 +6,9 @@ import ch.virt.smartphonemouse.transmission.BluetoothHandler; +/** + * This class collects the calculated inputs and transmits them to the computer when needed. + */ public class MouseInputs { private final float NANO_TO_FULL = 1e9f; @@ -22,12 +25,21 @@ public class MouseInputs { private boolean running; private long lastTime; + /** + * Creates this class. + * + * @param bluetoothHandler bluetooth handler to send the signals to + * @param context context to fetch settings from + */ public MouseInputs(BluetoothHandler bluetoothHandler, Context context) { this.bluetoothHandler = bluetoothHandler; this.context = context; } - public void start(){ + /** + * Starts the transmission to the pc. + */ + public void start() { if (running) return; thread = new Thread(this::run); @@ -38,28 +50,39 @@ public void start(){ thread.start(); } - public void run(){ + /** + * Starts the sending loop. + * Should be executed on a separate thread. + */ + private void run() { lastTime = System.nanoTime(); while (running) { long current = System.nanoTime(); - if (current - lastTime >= NANO_TO_FULL / transmissionRate){ + if (current - lastTime >= NANO_TO_FULL / transmissionRate) { sendUpdate(); lastTime = current; } } } - public void stop(){ + /** + * Stops the transmission to the pc. + */ + public void stop() { running = false; } - private void sendUpdate(){ + /** + * Sends an update to the pc. + */ + private void sendUpdate() { int x = (int) xPosition; int y = (int) yPosition; - if (bluetoothHandler.getHost().isConnected()) bluetoothHandler.getHost().sendReport(leftButton, middleButton, rightButton, wheelPosition, x, y); + if (bluetoothHandler.getHost().isConnected()) + bluetoothHandler.getHost().sendReport(leftButton, middleButton, rightButton, wheelPosition, x, y); // Reset Deltas xPosition -= x; @@ -68,28 +91,57 @@ private void sendUpdate(){ } - public void changeWheelPosition(int delta){ + /** + * Changes the current wheel position. + * + * @param delta change in wheel steps + */ + public void changeWheelPosition(int delta) { wheelPosition += delta; } + /** + * Sets the current state of the left button. + * + * @param leftButton whether the left button is pressed + */ public void setLeftButton(boolean leftButton) { this.leftButton = leftButton; } + /** + * Sets the current state of the middle button. + * + * @param middleButton whether the middle button is pressed + */ public void setMiddleButton(boolean middleButton) { this.middleButton = middleButton; } + /** + * Sets the current state of the right button. + * + * @param rightButton whether the right button is pressed + */ public void setRightButton(boolean rightButton) { this.rightButton = rightButton; } - public void changeXPosition(float x){ + /** + * Changes the x position of the mouse + * + * @param x change of the position + */ + public void changeXPosition(float x) { xPosition += x; } - public void changeYPosition(float y){ + /** + * Changes the y position of the mouse + * + * @param y change of the position + */ + public void changeYPosition(float y) { yPosition += y; } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java index febe0f0..ef13718 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/MovementHandler.java @@ -8,6 +8,9 @@ import androidx.preference.PreferenceManager; +/** + * This class handles and calculates the movement of the mouse + */ public class MovementHandler implements SensorEventListener { private static final float NANO_FULL_FACTOR = 1e-9f; @@ -26,6 +29,12 @@ public class MovementHandler implements SensorEventListener { private long lastSample = 0; private Pipeline xLine, yLine; + /** + * Creates a movement handler. + * + * @param context context to get the sensor from + * @param inputs inputs to send the movement to + */ public MovementHandler(Context context, MouseInputs inputs) { this.context = context; this.inputs = inputs; @@ -34,19 +43,28 @@ public MovementHandler(Context context, MouseInputs inputs) { create(); } - public void create(){ + /** + * Creates the signal processing pipelines. + */ + public void create() { int sampleRate = PreferenceManager.getDefaultSharedPreferences(context).getInt("communicationTransmissionRate", 200); xLine = new Pipeline(sampleRate, new PipelineConfig(PreferenceManager.getDefaultSharedPreferences(context))); yLine = new Pipeline(sampleRate, new PipelineConfig(PreferenceManager.getDefaultSharedPreferences(context))); } - public void fetchSensor(){ + /** + * Fetches the sensor from the context. + */ + private void fetchSensor() { manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); sensor = manager.getDefaultSensor(SENSOR_TYPE); } - public void register(){ + /** + * Registers the sensor for this handler. + */ + public void register() { if (registered) return; manager.registerListener(this, sensor, SAMPLING_RATE); @@ -54,7 +72,10 @@ public void register(){ registered = true; } - public void unregister(){ + /** + * Unregisters the sensor for this handler. + */ + public void unregister() { if (!registered) return; manager.unregisterListener(this, sensor); @@ -79,5 +100,6 @@ public void onSensorChanged(SensorEvent event) { } @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { } + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/Pipeline.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/Pipeline.java index b66508c..c7bd3d1 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/Pipeline.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/Pipeline.java @@ -9,6 +9,10 @@ import ch.virt.smartphonemouse.mouse.elements.Sensitivity; import ch.virt.smartphonemouse.mouse.elements.SignCache; +/** + * This class handles all calculation to get from the raw sensor data to the distance output. + * In order to do the calculation it uses various different components. + */ public class Pipeline { private int sampleRate; @@ -26,13 +30,22 @@ public class Pipeline { private boolean debugging; private float[] debuggingValues; + /** + * Creates a signal processing pipeline. + * + * @param sampleRate sample rate at which the new samples will be provided + * @param config configuration for all different components of this pipeline + */ public Pipeline(int sampleRate, PipelineConfig config) { this.config = config; this.sampleRate = sampleRate; create(); } - public void create(){ + /** + * Initializes all components. + */ + private void create() { velocityIntegration = new PersistentIntegration(); distanceIntegration = new Integration(); @@ -52,7 +65,14 @@ public void create(){ debuggingValues = new float[12]; } - public float nextForDistance(float delta, float unfiltered){ + /** + * Calculates the current distance delta from a new acceleration sample + * + * @param delta time passed since the last sample (in seconds) + * @param unfiltered new acceleration sample from the accelerometer + * @return new distance delta + */ + public float nextForDistance(float delta, float unfiltered) { int i = 0; if (debugging) debuggingValues[i++] = unfiltered; @@ -85,22 +105,30 @@ public float nextForDistance(float delta, float unfiltered){ return distance; } - public void enableDebugging(){ + /** + * Enables debugging for this pipeline. + * This will place the values in between the acceleration and distance into an array for every sample. + */ + public void enableDebugging() { debugging = true; } + /** + * Returns all values in between the acceleration and distance in an array. + * Make sure to enable debugging to get content in this array. + * + * @return values in between + */ public float[] getDebuggingValues() { return debuggingValues; } - public void reset(){ + /** + * Resets the pipeline to its initial state + */ + public void reset() { velocityIntegration.reset(); distanceIntegration.reset(); lowPass.reset(); } - - public void clear(){ - - } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/mouse/PipelineConfig.java b/app/src/main/java/ch/virt/smartphonemouse/mouse/PipelineConfig.java index 30cd063..3f614b4 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/mouse/PipelineConfig.java +++ b/app/src/main/java/ch/virt/smartphonemouse/mouse/PipelineConfig.java @@ -2,6 +2,9 @@ import android.content.SharedPreferences; +/** + * This class loads and contains all configuration data needed to configure a single pipeline. + */ public class PipelineConfig { // Acceleration Low Pass @@ -26,32 +29,15 @@ public class PipelineConfig { private boolean scalerEnabled; private int scalerPower; private float scalerSplit; - + // Sensitivity private float sensitivityFactor; - public PipelineConfig() { - this.lowPassOrder = 1; - this.lowPassCutoff = 0.1f; - - this.freezerFreezingThreshold = 0.1f; - this.freezerUnfreezingThreshold = 0.04f; - this.freezerUnfreezingSamples = 10; - - this.noiseCancellingThreshold = 0.04f; - this.noiseFinalSamples = 20; - - this.cacheMinimalDuration = 5; - this.cacheMaximalDuration = 10; - this.cacheReleasingThreshold = 0.05f; - - this.scalerEnabled = true; - this.scalerPower = 2; - this.scalerSplit = 0.1f; - - this.sensitivityFactor = 13; - } - + /** + * Loads all config entries into this class. + * + * @param preferences preferences to load from. + */ public PipelineConfig(SharedPreferences preferences) { lowPassOrder = preferences.getInt("movementLowPassOrder", 1); lowPassCutoff = preferences.getFloat("movementLowPassCutoff", 0.1f); diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java index be9effb..b7cd863 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothDiscoverer.java @@ -12,18 +12,25 @@ import java.util.ArrayList; import java.util.List; -import ch.virt.smartphonemouse.helper.Listener; - +/** + * This class handles the discovery of new bluetooth devices to connect to. + */ public class BluetoothDiscoverer extends BroadcastReceiver { - BluetoothAdapter adapter; + private BluetoothAdapter adapter; - boolean isScanning; - List devices; + private boolean isScanning; + private List devices; - Listener updateListener; - Listener scanListener; + private UpdateListener updateListener; + private ScanListener scanListener; + /** + * Creates a bluetooth discoverer. + * + * @param context context to get events from + * @param adapter bluetooth adapter to use + */ public BluetoothDiscoverer(Context context, BluetoothAdapter adapter) { this.adapter = adapter; @@ -37,14 +44,23 @@ public BluetoothDiscoverer(Context context, BluetoothAdapter adapter) { context.registerReceiver(this, intents); } + /** + * Starts the discovery for new devices. + */ public void startDiscovery() { adapter.startDiscovery(); } + /** + * Stops the discovery + */ public void stopDiscovery() { adapter.cancelDiscovery(); } + /** + * Removes the already found devices. + */ public void reset() { devices.clear(); } @@ -59,45 +75,105 @@ public void onReceive(Context context, Intent intent) { if (!devices.contains(discovered)) { // Ignore duplicates devices.add(discovered); - if (updateListener != null) updateListener.called(); + if (updateListener != null) updateListener.update(devices); } - }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action) || BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){ + } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action) || BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { isScanning = BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action); - if (scanListener != null) scanListener.called(); + if (scanListener != null) scanListener.changed(isScanning); } } + /** + * Returns the already found devices. + * + * @return list of already found devices + */ public List getDevices() { return devices; } + /** + * Returns whether the listener is still scanning for devices. + * + * @return is scanning + */ public boolean isScanning() { return isScanning; } + /** + * Sets the update listener. + * This listener gets called when a new device is discovered. + * + * @param updateListener update listener + */ + public void setUpdateListener(UpdateListener updateListener) { + this.updateListener = updateListener; + } + + /** + * Sets the scan listener. + * This listener is called when the scan status changes. + * + * @param scanListener scan listener + */ + public void setScanListener(ScanListener scanListener) { + this.scanListener = scanListener; + } + + /** + * This subclass contains the basic information for a discovered bluetooth device. + */ public static class DiscoveredDevice { private String name; private String address; private int majorClass; - public DiscoveredDevice(BluetoothDevice device){ + /** + * Creates a discovered device from a bluetooth device. + * + * @param device bluetooth device that is the discovered device + */ + public DiscoveredDevice(BluetoothDevice device) { this((device.getName() == null || device.getName().equals("")) ? "Unknown" : device.getName(), device.getAddress(), device.getBluetoothClass().getMajorDeviceClass()); } + /** + * Creates a discovered device from a set of information. + * + * @param name name of the device + * @param address bluetooth mac address of the device + * @param majorClass major device class of the device + */ public DiscoveredDevice(String name, String address, int majorClass) { this.name = name; this.address = address; this.majorClass = majorClass; } + /** + * Returns the name of the device. + * + * @return name + */ public String getName() { return name; } + /** + * Returns the bluetooth mac address of the device. + * + * @return bluetooth mac address + */ public String getAddress() { return address; } + /** + * Returns the major device class of the device. + * + * @return major device class + */ public int getMajorClass() { return majorClass; } @@ -108,11 +184,29 @@ public boolean equals(@Nullable Object obj) { } } - public void setUpdateListener(Listener updateListener) { - this.updateListener = updateListener; + /** + * This interface is a basic listener for updates on the discovered device list. + */ + public interface UpdateListener { + + /** + * Device list got updated. + * + * @param devices currently discovered devices + */ + void update(List devices); } - public void setScanListener(Listener scanListener) { - this.scanListener = scanListener; + /** + * This interface is a basic listener when the scanning starts / stops + */ + public interface ScanListener { + + /** + * Scan status got changed. + * + * @param scanning whether it is currently scanning + */ + void changed(boolean scanning); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java index bf87cab..c482aa8 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/BluetoothHandler.java @@ -15,6 +15,9 @@ import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.transmission.hid.HidDevice; +/** + * This class handles everything related to bluetooth. + */ public class BluetoothHandler implements BluetoothProfile.ServiceListener { private static final String TAG = "BluetoothHandler"; @@ -31,10 +34,14 @@ public class BluetoothHandler implements BluetoothProfile.ServiceListener { private boolean initialized = false; private boolean enabled = false; private boolean supported = false; - private boolean opened = false; private ActivityResultLauncher enableBluetoothLauncher; + /** + * Creates a bluetooth handler + * + * @param context activity to use for various things + */ public BluetoothHandler(ComponentActivity context) { this.main = context; discoverer = new BluetoothDiscoverer(main, adapter); @@ -43,8 +50,13 @@ public BluetoothHandler(ComponentActivity context) { enableBluetoothLauncher = main.registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> reInit()); } - public boolean reInitRequired(){ - if (!adapter.isEnabled()){ + /** + * Checks whether bluetooth is still turned on and if not, reinitializes + * + * @return whether a reinitialization is required + */ + public boolean reInitRequired() { + if (!adapter.isEnabled()) { reInit(); return true; } @@ -52,12 +64,18 @@ public boolean reInitRequired(){ return false; } - public void reInit(){ + /** + * Reinitializes the bluetooth things. + */ + public void reInit() { initialized = false; init(); } - public void enableBluetooth(){ + /** + * Enables bluetooth by prompting the user. + */ + public void enableBluetooth() { if (!adapter.isEnabled()) { Log.i(TAG, "Enabling Bluetooth"); @@ -66,6 +84,9 @@ public void enableBluetooth(){ } } + /** + * Intitializes the bluetooth things. + */ private void init() { supported = false; enabled = false; @@ -77,7 +98,7 @@ private void init() { initialized = true; supported = false; - ((MainActivity)main).updateBluetoothStatus(); + ((MainActivity) main).updateBluetoothStatus(); return; } @@ -87,28 +108,34 @@ private void init() { enabled = false; initialized = true; - ((MainActivity)main).updateBluetoothStatus(); + ((MainActivity) main).updateBluetoothStatus(); return; - }else enabled = true; + } else enabled = true; open(); } - private void open(){ - if(!adapter.getProfileProxy(main, this, BluetoothProfile.HID_DEVICE)){ + /** + * Opens the bluetooth hid profile. + */ + private void open() { + if (!adapter.getProfileProxy(main, this, BluetoothProfile.HID_DEVICE)) { Log.i(TAG, "Bluetooth HID profile is not supported"); initialized = true; supported = false; - ((MainActivity)main).updateBluetoothStatus(); + ((MainActivity) main).updateBluetoothStatus(); return; } supported = true; } - private void start(){ + /** + * Registers the app as a hid device. + */ + private void start() { Log.i(TAG, "Opened HID Profile successfully"); initialized = true; @@ -118,23 +145,21 @@ private void start(){ Log.d(TAG, "Registering with a HID Device!"); device.register(); - ((MainActivity)main).updateBluetoothStatus(); + ((MainActivity) main).updateBluetoothStatus(); } @Override public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.HID_DEVICE){ + if (profile == BluetoothProfile.HID_DEVICE) { this.service = (BluetoothHidDevice) proxy; - opened = true; start(); } } @Override public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.HID_DEVICE){ - opened = false; + if (profile == BluetoothProfile.HID_DEVICE) { Log.i(TAG, "Reconnecting to Service"); Toast.makeText(main, "Reloading Bluetooth", Toast.LENGTH_SHORT).show(); @@ -143,47 +168,102 @@ public void onServiceDisconnected(int profile) { } } + /** + * Returns whether the bluetooth hid profile is supported by this device. + * + * @return is supported + */ public boolean isSupported() { return supported; } + + /** + * Returns whether the app is connected to a host device. + * + * @return is connected + */ public boolean isConnected() { if (!initialized || !supported) return false; return getHost().isConnected(); } - public boolean isConnecting(){ + + /** + * Returns whether the app is currently connecting to a host device + * + * @return is connecting + */ + public boolean isConnecting() { if (!initialized || !supported) return false; return getHost().isConnecting(); } + + /** + * Returns whether bluetooth is enabled + * + * @return is enabled + */ public boolean isEnabled() { return enabled; } + + /** + * Returns whether bluetooth has ben initialized. + * + * @return is initialized + */ public boolean isInitialized() { return initialized; } + /** + * Returns the class responsible for discovering new bluetooth devices. + * + * @return bluetooth discoverer + */ public BluetoothDiscoverer getDiscoverer() { return discoverer; } + /** + * Returns a storage of all known devices. + * + * @return known devices + */ public DeviceStorage getDevices() { return devices; } + /** + * Returns the hid interface. + * + * @return hid device to interact with the hid profile + */ public HidDevice getHost() { return device; } - public BluetoothDevice fromHostDevice(HostDevice device){ + /** + * Gets a real bluetooth device from a host device that can be saved. + * + * @param device saved host device + * @return fetched bluetooth device + */ + public BluetoothDevice fromHostDevice(HostDevice device) { return adapter.getRemoteDevice(device.getAddress()); } - public boolean isBonded(String address){ - boolean result = false; + /** + * Returns whether the smartphone is already bonded to a certain device. + * + * @param address address of that device + * @return whether it is bonded + */ + public boolean isBonded(String address) { - for (BluetoothDevice device : adapter.getBondedDevices()){ - if (device.getAddress().equals(address)) result = true; + for (BluetoothDevice device : adapter.getBondedDevices()) { + if (device.getAddress().equals(address)) return true; } - return result; + return false; } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java index 5c38be6..5b8b0b5 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/DeviceStorage.java @@ -10,38 +10,68 @@ import java.util.ArrayList; import java.util.List; +/** + * This class stores already known bluetooth devices. + */ public class DeviceStorage { public static final String DEVICES_KEY = "devices"; - Context context; - - List devices; + private Context context; + private List devices; + /** + * Creates and loads the device storage. + * + * @param context context to access preferences + */ public DeviceStorage(Context context) { this.context = context; load(); } - public void load(){ + /** + * Loads the devices from the preferences. + */ + public void load() { String src = PreferenceManager.getDefaultSharedPreferences(context).getString(DEVICES_KEY, "[]"); - devices = new Gson().fromJson(src, new TypeToken>(){}.getType()); + devices = new Gson().fromJson(src, new TypeToken>() { }.getType()); } - public void save(){ + /** + * Saves the devices to the preferences. + */ + public void save() { devices.sort((o1, o2) -> -Long.compare(o1.getLastConnected(), o2.getLastConnected())); String src = new Gson().toJson(devices); PreferenceManager.getDefaultSharedPreferences(context).edit().putString(DEVICES_KEY, src).apply(); } + /** + * Returns all known devices. + * + * @return list of known host devices. + */ public List getDevices() { return devices; } - public HostDevice getDevice(int i){ + /** + * Returns a specific host device at a certain index. + * + * @param i index of the device. + * @return known device + */ + public HostDevice getDevice(int i) { return devices.get(i); } - public HostDevice getDevice(String address){ + /** + * Returns a specific host device with a certain bluetooth mac address. + * + * @param address bluetooth mac address + * @return known device + */ + public HostDevice getDevice(String address) { for (HostDevice device : devices) { if (device.getAddress().equals(address)) return device; } @@ -49,12 +79,22 @@ public HostDevice getDevice(String address){ return null; } - public void addDevice(HostDevice device){ + /** + * Adds a device to the storage. + * + * @param device known device to add + */ + public void addDevice(HostDevice device) { devices.add(device); save(); } - public void removeDevice(int i){ + /** + * Removes a device at an index from the known devices. + * + * @param i index of that device + */ + public void removeDevice(int i) { HostDevice device = getDevice(i); if (device != null) { @@ -62,7 +102,12 @@ public void removeDevice(int i){ } } - public void removeDevice(String address){ + /** + * Removes a device with a specific bluetooth mac address. + * + * @param address bluetooth mac address of that device + */ + public void removeDevice(String address) { HostDevice device = getDevice(address); if (device != null) { @@ -70,12 +115,23 @@ public void removeDevice(String address){ } } - public void removeDevice(HostDevice device){ + /** + * Removes a known device. + * + * @param device device to remove + */ + public void removeDevice(HostDevice device) { devices.remove(device); save(); } - public boolean hasDevice(String address){ + /** + * Returns whether a certain device is present in the known devices. + * + * @param address bluetooth mac address of said device + * @return whether it is present + */ + public boolean hasDevice(String address) { return getDevice(address) != null; } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/HostDevice.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/HostDevice.java index 8448da9..2da4066 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/HostDevice.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/HostDevice.java @@ -1,29 +1,58 @@ package ch.virt.smartphonemouse.transmission; +/** + * This class represents a known host device. + */ public class HostDevice { private String address; private String name; private long lastConnected; + /** + * Creates a host device. + * + * @param address bluetooth mac address of the device + * @param name name of the device + */ public HostDevice(String address, String name) { this.address = address; this.name = name; this.lastConnected = -1; } + /** + * Sets when the device has last connected. + * + * @param lastConnected unix timestamp when last connected + */ public void setLastConnected(long lastConnected) { this.lastConnected = lastConnected; } + /** + * Returns the bluetooth mac address of the device. + * + * @return bluetooth mac address + */ public String getAddress() { return address; } + /** + * Returns the name of the device. + * + * @return name + */ public String getName() { return name; } + /** + * Returns when the device was last connected to. + * + * @return unix timestamp of when it was last connected + */ public long getLastConnected() { return lastConnected; } diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDescriptor.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDescriptor.java index 55445bc..adc2819 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDescriptor.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDescriptor.java @@ -1,5 +1,8 @@ package ch.virt.smartphonemouse.transmission.hid; +/** + * This class holds the Hid Descriptor used for this app. + */ public class HidDescriptor { // Tag IDs @@ -73,6 +76,4 @@ public class HidDescriptor { TAG_END_COLLECTION }; - - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java b/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java index d7eec04..4773f64 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java +++ b/app/src/main/java/ch/virt/smartphonemouse/transmission/hid/HidDevice.java @@ -11,39 +11,58 @@ import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.transmission.HostDevice; +/** + * This class is used to interact and use the bluetooth hid profile. + */ public class HidDevice extends BluetoothHidDevice.Callback { private static final String TAG = "HidDevice"; - + private static final String NAME = "Smartphone Mouse"; private static final String DESCRIPTION = "Acceleration based Smartphone Mouse"; private static final String PROVIDER = "Virt"; - BluetoothHidDevice service; - Context context; + private BluetoothHidDevice service; + private Context context; - BluetoothDevice device; - long connectedSince; + private BluetoothDevice device; + private long connectedSince; - boolean registered; - boolean connected; - boolean connecting; + private boolean registered; + private boolean connected; + private boolean connecting; - boolean lastFailed; + private boolean lastFailed; - BluetoothHandler bluetooth; + private BluetoothHandler bluetooth; + /** + * Creates this class. + * + * @param device device from android to interact with + * @param bluetooth bluetooth handler to perform bluetooth actions + * @param context context, presumably the main activity used for refreshing the ui + */ public HidDevice(BluetoothHidDevice device, BluetoothHandler bluetooth, Context context) { this.service = device; this.context = context; this.bluetooth = bluetooth; } - private BluetoothHidDeviceAppSdpSettings createSDP(){ + /** + * Creates the Service Discovery Protocol records. + * + * @return Service Discovery Protocol records + */ + private BluetoothHidDeviceAppSdpSettings createSDP() { return new BluetoothHidDeviceAppSdpSettings(NAME, DESCRIPTION, PROVIDER, BluetoothHidDevice.SUBCLASS1_MOUSE, HidDescriptor.DESCRIPTOR); } - public void register(){ - if (!registered) service.registerApp(createSDP(), null, null, context.getMainExecutor(), this); + /** + * Registers the app as a hid. + */ + public void register() { + if (!registered) + service.registerApp(createSDP(), null, null, context.getMainExecutor(), this); else Log.d(TAG, "The Device is already registered!"); } @@ -57,7 +76,7 @@ public void onAppStatusChanged(BluetoothDevice pluggedDevice, boolean registered @Override public void onConnectionStateChanged(BluetoothDevice device, int state) { - switch (state){ + switch (state) { case BluetoothHidDevice.STATE_CONNECTED: connecting = false; connected = true; @@ -66,7 +85,7 @@ public void onConnectionStateChanged(BluetoothDevice device, int state) { bluetooth.getDevices().getDevice(device.getAddress()).setLastConnected(System.currentTimeMillis()); bluetooth.getDevices().save(); - ((MainActivity)context).updateBluetoothStatus(); + ((MainActivity) context).updateBluetoothStatus(); Log.d(TAG, "HID Host connected!"); break; @@ -77,40 +96,60 @@ public void onConnectionStateChanged(BluetoothDevice device, int state) { connecting = false; connected = false; - ((MainActivity)context).updateBluetoothStatus(); + ((MainActivity) context).updateBluetoothStatus(); Log.d(TAG, "HID Host disconnected!"); break; - default: super.onConnectionStateChanged(device, state); + default: + super.onConnectionStateChanged(device, state); } } - public void connect(HostDevice deviceH){ + /** + * Connects as a HID to the provided host device + * + * @param deviceH host device to connect to + */ + public void connect(HostDevice deviceH) { if (bluetooth.reInitRequired()) return; - if (registered && !connected && !connecting){ + + if (registered && !connected && !connecting) { this.device = bluetooth.fromHostDevice(deviceH); service.connect(device); connecting = true; - ((MainActivity)context).updateBluetoothStatus(); - Log.d(TAG, "connect: Refreshed"); + ((MainActivity) context).updateBluetoothStatus(); - } else Log.d(TAG, "Cannot connect to host whilst connecting or being connected and must be registered"); + } else + Log.d(TAG, "Cannot connect to host whilst connecting or being connected and must be registered"); } - - public void disconnect(){ - if (registered && connected && !connecting){ + + /** + * Disconnects from the host device. + */ + public void disconnect() { + if (registered && connected && !connecting) { service.disconnect(device); - } else Log.d(TAG, "Cannot connect to host whilst connecting or being connected"); + } else Log.d(TAG, "Cannot connect to host whilst connecting or not being connected"); } - public void sendReport(boolean left, boolean middle, boolean right, int wheel, int x, int y){ - if (!registered || !connected || connecting){ - Log.d(TAG, "Cannot send a to the host report when no device is connected successfully!"); + /** + * Sends a report to the host device. + * + * @param left whether the left mouse button is pressed + * @param middle whether the middle mouse button is pressed + * @param right whether the right mouse button is pressed + * @param wheel change of position of the mouse wheel + * @param x change of x position + * @param y change of y position + */ + public void sendReport(boolean left, boolean middle, boolean right, int wheel, int x, int y) { + if (!registered || !connected || connecting) { + Log.d(TAG, "Cannot send a report to the host when no device is connected successfully!"); return; } @@ -124,30 +163,63 @@ public void sendReport(boolean left, boolean middle, boolean right, int wheel, i service.sendReport(device, 1, report); // Id 1 because of the descriptor } + /** + * Returns the currently connected host device. + * + * @return connected device + */ public BluetoothDevice getDevice() { return device; } + /** + * Returns whether the app is registered. + * + * @return is registered + */ public boolean isRegistered() { return registered; } + /** + * Returns whether the app is connected to a host device. + * + * @return is connected + */ public boolean isConnected() { return connected; } + /** + * Returns whether the app is currently connecting to a host device. + * + * @return is connecting + */ public boolean isConnecting() { return connecting; } - public boolean hasFailed(){ + /** + * Returns whether the last connection to a host device has failed. + * + * @return has last failed + */ + public boolean hasFailed() { return lastFailed; } - public void markFailedAsRead(){ + /** + * Marks the last failed status as read. + */ + public void markFailedAsRead() { lastFailed = false; } + /** + * Returns the timestamp when the host device has connected. + * + * @return timestamp in milliseconds since the device booted + */ public long getConnectedSince() { return connectedSince; } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java index c24710a..df695d1 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java @@ -1,6 +1,5 @@ package ch.virt.smartphonemouse.ui.connect.dialog; -import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.view.LayoutInflater; import android.view.View; @@ -13,7 +12,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import java.util.ArrayList; import java.util.List; import ch.virt.smartphonemouse.R; @@ -46,7 +44,7 @@ public void render() { scanning.setOnClickListener(v -> startDiscovery()); - bluetooth.getDiscoverer().setUpdateListener(adapter::notifyDataSetChanged); + bluetooth.getDiscoverer().setUpdateListener(devices -> adapter.notifyDataSetChanged()); bluetooth.getDiscoverer().setScanListener(this::discoveryUpdated); bluetooth.getDiscoverer().startDiscovery(); @@ -58,8 +56,8 @@ public void startDiscovery(){ bluetooth.getDiscoverer().startDiscovery(); } - public void discoveryUpdated(){ - if (bluetooth.getDiscoverer().isScanning()) { + public void discoveryUpdated(boolean status){ + if (status) { scanning.setEnabled(false); scanning.setText(R.string.dialog_add_select_scanning); }else { diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java index 4b9bfab..f0b5439 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java @@ -97,6 +97,6 @@ public void setAxis(int axis) { } public void renew(){ - pipeline.clear(); + pipeline.reset(); } } From 11f6a4ff49c0717b50cabfed2b16f7ca80722dd5 Mon Sep 17 00:00:00 2001 From: Joshua Date: Thu, 2 Sep 2021 14:24:34 +0200 Subject: [PATCH 4/8] Connect dialogs improved and refactored --- .../ui/connect/ConnectSelectSubfragment.java | 7 +- .../connect/dialog/AddAlreadySubdialog.java | 26 +- .../ui/connect/dialog/AddBondedSubdialog.java | 41 ++- .../ui/connect/dialog/AddDialog.java | 250 +++++++++++------- .../ui/connect/dialog/AddManualSubdialog.java | 47 ++-- .../dialog/AddRequestPermissionSubdialog.java | 35 +-- .../dialog/AddRequestSettingSubdialog.java | 31 ++- .../ui/connect/dialog/AddSelectSubdialog.java | 179 ++++++++----- .../connect/dialog/AddSuccessSubdialog.java | 31 ++- .../ui/connect/dialog/InfoDialog.java | 39 ++- 10 files changed, 438 insertions(+), 248 deletions(-) diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java index 10b6f7f..b1e5d34 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java @@ -6,7 +6,6 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; @@ -47,7 +46,8 @@ public void render() { } public void info(){ - InfoDialog dialog = new InfoDialog(bluetooth, adapter.getSelected(), () -> adapter.notifyDataSetChanged()); + InfoDialog dialog = new InfoDialog(bluetooth, adapter.getSelected()); + dialog.setOnDismissListener((d) -> adapter.notifyDataSetChanged()); dialog.show(this.getParentFragmentManager(), null); } @@ -67,7 +67,8 @@ protected void initComponents() { } private void add(){ - AddDialog dialog = new AddDialog(bluetooth, main, () -> adapter.notifyDataSetChanged()); + AddDialog dialog = new AddDialog(bluetooth); + dialog.setOnDismissListener((d) -> adapter.notifyDataSetChanged()); dialog.show(this.getParentFragmentManager(), null); } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddAlreadySubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddAlreadySubdialog.java index 27b6b55..aa5bcba 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddAlreadySubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddAlreadySubdialog.java @@ -1,23 +1,17 @@ package ch.virt.smartphonemouse.ui.connect.dialog; -import android.view.View; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; - -public class AddAlreadySubdialog extends CustomFragment { - public AddAlreadySubdialog(MainContext context) { - super(R.layout.subdialog_add_already, context); - } - - @Override - public void render() { - - } - - @Override - protected void loadComponents(View view) { +/** + * This class displays the sub page of the add dialog when a device has already been added. + */ +public class AddAlreadySubdialog extends Fragment { + /** + * Initializes the sub dialog. + */ + public AddAlreadySubdialog() { + super(R.layout.subdialog_add_already); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddBondedSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddBondedSubdialog.java index 2955dd4..f3ce6d9 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddBondedSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddBondedSubdialog.java @@ -1,45 +1,60 @@ package ch.virt.smartphonemouse.ui.connect.dialog; +import android.os.Bundle; import android.view.View; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothDiscoverer; import ch.virt.smartphonemouse.transmission.BluetoothHandler; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class AddBondedSubdialog extends CustomFragment { +/** + * This class contains the sub page of the add dialog, which is displayed when a device is bonded with the smartphone. + */ +public class AddBondedSubdialog extends Fragment { private BluetoothHandler handler; private TextView error; private BluetoothDiscoverer.DiscoveredDevice target; + /** + * Creates the sub dialog. + * + * @param handler handler to check whether still bonded + * @param target target device to check for + */ + public AddBondedSubdialog(BluetoothHandler handler, BluetoothDiscoverer.DiscoveredDevice target) { + super(R.layout.subdialog_add_bonded); - public AddBondedSubdialog(MainContext context, BluetoothHandler handler, BluetoothDiscoverer.DiscoveredDevice target) { - super(R.layout.subdialog_add_bonded, context); this.handler = handler; this.target = target; } - public boolean check(){ - if (handler.isBonded(target.getAddress())){ + /** + * Checks if the device is still bonded. + * If it is still bonded, an error message will be displayed. + * + * @return whether it is NOT bonded + */ + public boolean check() { + if (handler.isBonded(target.getAddress())) { error.setVisibility(View.VISIBLE); return false; - }else { + } else { error.setVisibility(View.GONE); return true; } } @Override - public void render() { - - } + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - @Override - protected void loadComponents(View view) { error = view.findViewById(R.id.add_bonded_error); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java index aa1aaad..8db6a77 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddDialog.java @@ -22,15 +22,16 @@ import androidx.core.app.ActivityCompat; import androidx.core.location.LocationManagerCompat; import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothDiscoverer; import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.transmission.HostDevice; -import ch.virt.smartphonemouse.ui.CustomFragment; +/** + * This dialog is shown when the user wants to add a device. + */ public class AddDialog extends DialogFragment { private static final int SELECT_STATE = 0; private static final int MANUAL_STATE = 1; @@ -41,150 +42,216 @@ public class AddDialog extends DialogFragment { private static final int REQUEST_SETTING_STATE = 6; private final BluetoothHandler bluetoothHandler; - private final MainContext mainContext; - private final Listener closed; private Button positiveButton, negativeButton, neutralButton; + private DialogInterface.OnDismissListener dismissListener; private AlertDialog dialog; - private CustomFragment currentSub; private int state; - + private Fragment currentFragment; private BluetoothDiscoverer.DiscoveredDevice target; - ActivityResultLauncher requestLocation; - ActivityResultLauncher enableLocation; - + private ActivityResultLauncher requestLocation; + private ActivityResultLauncher enableLocation; - public AddDialog(BluetoothHandler bluetoothHandler, MainContext mainContext, Listener closed) { + /** + * Creates an add dialog. + * @param bluetoothHandler bluetooth handler to use + */ + public AddDialog(BluetoothHandler bluetoothHandler) { this.bluetoothHandler = bluetoothHandler; - this.mainContext = mainContext; - this.closed = closed; } + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize Location requests - requestLocation = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { + requestLocation = registerForActivityResult(new ActivityResultContracts.RequestPermission(), this::checkPermission); + enableLocation = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> positiveButton.post(this::checkSetting)); + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + LayoutInflater inflater = requireActivity().getLayoutInflater(); + + builder.setView(inflater.inflate(R.layout.dialog_add, null)) + .setPositiveButton(R.string.dialog_add_next, null) + .setNegativeButton(R.string.dialog_add_cancel, null) + .setNeutralButton("-", null); + - if (isGranted) { - showRequestSetting(); - } else ((AddRequestPermissionSubdialog) currentSub).showError(); + dialog = builder.create(); + dialog.setTitle("-"); // Add default title so it is shown + dialog.setOnShowListener(dialogInterface -> { + positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); + negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE); + neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL); + positiveButton.setOnClickListener((v) -> onNext()); + neutralButton.setOnClickListener((v) -> onNeutral()); + + created(); }); + dialog.setOnDismissListener(dismissListener); - enableLocation = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> positiveButton.post(this::checkSetting)); + return dialog; } - public void created(){ + @Override + public void onDismiss(@NonNull DialogInterface dialog) { + if (bluetoothHandler.getDiscoverer().isScanning()) bluetoothHandler.getDiscoverer().stopDiscovery(); + + super.onDismiss(dialog); + } + + + /** + * This method gets called when the dialog is shown. + */ + private void created(){ neutralButton.setVisibility(View.GONE); dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); // Enable keyboard to be working showRequestPermission(); } - private void setFragment(CustomFragment fragment){ - currentSub = fragment; - getChildFragmentManager().beginTransaction().setReorderingAllowed(true).replace(R.id.add_container, currentSub).commit(); + /** + * This method sets a sub fragment. + * @param fragment fragment to be set + */ + private void setFragment(Fragment fragment){ + currentFragment = fragment; + getChildFragmentManager().beginTransaction().setReorderingAllowed(true).replace(R.id.add_container, currentFragment).commit(); } + + /** + * This method shows the fragment that requests the permission to discover devices. + */ public void showRequestPermission(){ state = REQUEST_PERMISSION_STATE; + if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){ showRequestSetting(); // Get on if already granted return; } - setFragment(new AddRequestPermissionSubdialog(mainContext)); - dialog.setTitle(R.string.dialog_add_request_permission_title); + setFragment(new AddRequestPermissionSubdialog()); + dialog.setTitle(R.string.dialog_add_request_permission_title); positiveButton.setVisibility(View.VISIBLE); - neutralButton.setVisibility(View.VISIBLE); neutralButton.setText(R.string.dialog_add_select_manual); } + /** + * This method shows the fragment that requests the user to turn on location in order to discover devices. + */ public void showRequestSetting(){ state = REQUEST_SETTING_STATE; + if (LocationManagerCompat.isLocationEnabled((LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE))){ - showSelect(); // Get on if already granted + showSelect(); // Get on if already enabled return; } - setFragment(new AddRequestSettingSubdialog(mainContext)); - dialog.setTitle(R.string.dialog_add_request_setting_title); + setFragment(new AddRequestSettingSubdialog()); + dialog.setTitle(R.string.dialog_add_request_setting_title); positiveButton.setVisibility(View.VISIBLE); - neutralButton.setVisibility(View.VISIBLE); neutralButton.setText(R.string.dialog_add_select_manual); } + /** + * This method shows the fragment where the user can select form nearby devices. + */ public void showSelect(){ state = SELECT_STATE; - setFragment(new AddSelectSubdialog(mainContext, bluetoothHandler, () -> { - selected(((AddSelectSubdialog) currentSub).getSelected()); - })); + AddSelectSubdialog fragment = new AddSelectSubdialog(bluetoothHandler); + fragment.setSelectListener(this::selected); + setFragment(fragment); + + dialog.setTitle(R.string.dialog_add_select_title); positiveButton.setVisibility(View.GONE); neutralButton.setVisibility(View.VISIBLE); - neutralButton.setText(R.string.dialog_add_select_manual); - dialog.setTitle(R.string.dialog_add_select_title); - } + /** + * This method shows the fragment where the user can enter their device details manually. + */ public void showManual(){ state = MANUAL_STATE; - setFragment(new AddManualSubdialog(mainContext)); - positiveButton.setVisibility(View.VISIBLE); - neutralButton.setVisibility(View.GONE); + setFragment(new AddManualSubdialog()); dialog.setTitle(getString(R.string.dialog_add_manual_title)); + positiveButton.setVisibility(View.VISIBLE); + neutralButton.setVisibility(View.GONE); } + /** + * This method shows the fragment which tells the user that they have to remove the target device from their bonded devices. + */ public void showBonded(){ state = BONDED_STATE; - setFragment(new AddBondedSubdialog(mainContext, bluetoothHandler, target)); - positiveButton.setVisibility(View.VISIBLE); - neutralButton.setVisibility(View.GONE); + setFragment(new AddBondedSubdialog(bluetoothHandler, target)); dialog.setTitle(getString(R.string.dialog_add_bonded_title)); + positiveButton.setVisibility(View.VISIBLE); + neutralButton.setVisibility(View.GONE); } - public void showSuccess(){ - state = SUCCESS_STATE; - setFragment(new AddSuccessSubdialog(mainContext, target)); + /** + * This method shows the fragment which tells the user that the device is already added. + */ + public void showAlready(){ + state = ALREADY_STATE; + setFragment(new AddAlreadySubdialog()); + + dialog.setTitle(getString(R.string.dialog_add_already_title)); neutralButton.setVisibility(View.GONE); negativeButton.setVisibility(View.GONE); positiveButton.setVisibility(View.VISIBLE); - positiveButton.setText(R.string.dialog_add_success_positive); - - dialog.setTitle(getString(R.string.dialog_add_success_title)); + positiveButton.setText(R.string.dialog_add_already_positive); } - public void showAlready(){ - state = ALREADY_STATE; - setFragment(new AddAlreadySubdialog(mainContext)); + /** + * This method shows the fragment which tells the user that the device was added successfully. + */ + public void showSuccess(){ + state = SUCCESS_STATE; + + setFragment(new AddSuccessSubdialog(target)); + dialog.setTitle(getString(R.string.dialog_add_success_title)); neutralButton.setVisibility(View.GONE); negativeButton.setVisibility(View.GONE); positiveButton.setVisibility(View.VISIBLE); - positiveButton.setText(R.string.dialog_add_already_positive); - - dialog.setTitle(getString(R.string.dialog_add_already_title)); + positiveButton.setText(R.string.dialog_add_success_positive); } + + /** + * Adds the target device to the device storage and displays the success message. + */ public void finished(){ bluetoothHandler.getDevices().addDevice(new HostDevice(target.getAddress(), target.getName())); showSuccess(); } + /** + * Proceeds after a device has been selected. + * @param device selected device. + */ public void selected(BluetoothDiscoverer.DiscoveredDevice device){ target = device; @@ -193,6 +260,10 @@ public void selected(BluetoothDiscoverer.DiscoveredDevice device){ else finished(); } + + /** + * This method is called when the positive button is clicked. + */ public void onNext(){ switch (state){ case REQUEST_PERMISSION_STATE: @@ -202,10 +273,10 @@ public void onNext(){ requestSetting(); break; case MANUAL_STATE: - if (((AddManualSubdialog) currentSub).check()) selected(((AddManualSubdialog) currentSub).createDevice()); + if (((AddManualSubdialog) currentFragment).check()) selected(((AddManualSubdialog) currentFragment).createDevice()); break; case BONDED_STATE: - if (((AddBondedSubdialog) currentSub).check()) finished(); + if (((AddBondedSubdialog) currentFragment).check()) finished(); break; case SUCCESS_STATE: case ALREADY_STATE: @@ -213,50 +284,34 @@ public void onNext(){ } } + /** + * This method is called when the neutral button is clicked. + */ public void onNeutral(){ if (state == SELECT_STATE || state == REQUEST_PERMISSION_STATE || state == REQUEST_SETTING_STATE) showManual(); } - @Override - public void onDismiss(@NonNull DialogInterface dialog) { - super.onDismiss(dialog); - if (bluetoothHandler.getDiscoverer().isScanning()) bluetoothHandler.getDiscoverer().stopDiscovery(); - - closed.called(); - } - - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - LayoutInflater inflater = requireActivity().getLayoutInflater(); - - builder.setView(inflater.inflate(R.layout.dialog_add, null)) - .setPositiveButton(R.string.dialog_add_next, null) - .setNegativeButton(R.string.dialog_add_cancel, null) - .setNeutralButton("-", null); - - - dialog = builder.create(); - dialog.setTitle("-"); // Add default title so it is shown - dialog.setOnShowListener(dialogInterface -> { - positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); - negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE); - neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL); - - positiveButton.setOnClickListener((v) -> onNext()); - neutralButton.setOnClickListener((v) -> onNeutral()); - - created(); - }); - - return dialog; - } + /** + * Launches the request permission intent to request location permissions. + */ public void requestPermission(){ requestLocation.launch(Manifest.permission.ACCESS_FINE_LOCATION); } + /** + * Proceeds after the permission may have been granted. + * @param isGranted whether it was granted + */ + public void checkPermission(boolean isGranted){ + if (isGranted) { + showRequestSetting(); + } else ((AddRequestPermissionSubdialog) currentFragment).showError(); + } + + /** + * Launches the request intent to request to turn on location. + */ public void requestSetting(){ if (LocationManagerCompat.isLocationEnabled((LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE))){ showSelect(); @@ -265,13 +320,26 @@ public void requestSetting(){ } } + /** + * Checks whether the location setting was turned on. + */ public void checkSetting(){ if (LocationManagerCompat.isLocationEnabled((LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE))){ showSelect(); } else { - ((AddRequestSettingSubdialog) currentSub).showError(); + ((AddRequestSettingSubdialog) currentFragment).showError(); } } + /** + * Sets the dismiss listener. + * The listener should be set before the dialog is shown. + * + * @param dismissListener dismiss listener that will be passed to the dialog + * @see Dialog#setOnDismissListener(DialogInterface.OnDismissListener) + */ + public void setOnDismissListener(DialogInterface.OnDismissListener dismissListener) { + this.dismissListener = dismissListener; + } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddManualSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddManualSubdialog.java index b3e7ff4..47a53b5 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddManualSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddManualSubdialog.java @@ -1,31 +1,38 @@ package ch.virt.smartphonemouse.ui.connect.dialog; import android.bluetooth.BluetoothClass; +import android.os.Bundle; import android.view.View; -import android.view.WindowManager; -import com.google.android.material.textfield.TextInputEditText; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import com.google.android.material.textfield.TextInputLayout; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothDiscoverer; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class AddManualSubdialog extends CustomFragment { +/** + * This class contains the sub page of the add dialog that lets the user add their own custom device by their bluetooth mac address. + */ +public class AddManualSubdialog extends Fragment { TextInputLayout nameLayout, macLayout; - public AddManualSubdialog(MainContext context) { - super(R.layout.subdialog_add_manual, context); + /** + * Creates the sub dialog. + */ + public AddManualSubdialog() { + super(R.layout.subdialog_add_manual); } - @Override - public void render() { - - } - - public boolean check(){ + /** + * Checks whether the current entered name and mac bluetooth address are correct. + * + * @return whether the inputs are correct + */ + public boolean check() { boolean valid = true; if (nameLayout.getEditText().getText() == null || nameLayout.getEditText().getText().toString().equals("")) { @@ -36,7 +43,7 @@ public boolean check(){ nameLayout.setErrorEnabled(false); } - if (macLayout.getEditText().getText() == null || !macLayout.getEditText().getText().toString().matches("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")){ + if (macLayout.getEditText().getText() == null || !macLayout.getEditText().getText().toString().matches("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")) { macLayout.setErrorEnabled(true); macLayout.setError(getString(R.string.dialog_add_manual_mac_error)); valid = false; @@ -48,14 +55,20 @@ public boolean check(){ return valid; } - public BluetoothDiscoverer.DiscoveredDevice createDevice(){ + /** + * Returns a discovered device, created from the entered details. + * + * @return discovered device + */ + public BluetoothDiscoverer.DiscoveredDevice createDevice() { return new BluetoothDiscoverer.DiscoveredDevice(nameLayout.getEditText().getText().toString(), macLayout.getEditText().getText().toString(), BluetoothClass.Device.Major.UNCATEGORIZED); } @Override - protected void loadComponents(View view) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + nameLayout = view.findViewById(R.id.add_manual_name); macLayout = view.findViewById(R.id.add_manual_mac); - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestPermissionSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestPermissionSubdialog.java index 471c250..c9d89d6 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestPermissionSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestPermissionSubdialog.java @@ -1,35 +1,40 @@ package ch.virt.smartphonemouse.ui.connect.dialog; -import android.Manifest; -import android.content.pm.PackageManager; +import android.os.Bundle; import android.view.View; import android.widget.TextView; -import androidx.core.app.ActivityCompat; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class AddRequestPermissionSubdialog extends CustomFragment { +/** + * This class holds a sub page for the add dialog when the user must grant the app permissions to discover new devices. + */ +public class AddRequestPermissionSubdialog extends Fragment { - TextView error; + private TextView error; - public AddRequestPermissionSubdialog(MainContext context) { - super(R.layout.subdialog_add_requestpermission, context); + /** + * Creates the sub dialog. + */ + public AddRequestPermissionSubdialog() { + super(R.layout.subdialog_add_requestpermission); } - public void showError(){ + /** + * Displays the error on the screen. + */ + public void showError() { error.post(() -> error.setVisibility(View.VISIBLE)); } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - } - - @Override - protected void loadComponents(View view) { error = view.findViewById(R.id.add_request_permission_error); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestSettingSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestSettingSubdialog.java index 0c48486..5fc64fb 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestSettingSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddRequestSettingSubdialog.java @@ -1,31 +1,40 @@ package ch.virt.smartphonemouse.ui.connect.dialog; +import android.os.Bundle; import android.view.View; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class AddRequestSettingSubdialog extends CustomFragment { +/** + * This class holds the sub page of the add dialog that is displayed when the user should enable location in order to be able to discover near devices. + */ +public class AddRequestSettingSubdialog extends Fragment { - TextView error; + private TextView error; - public AddRequestSettingSubdialog(MainContext context) { - super(R.layout.subdialog_add_requestsetting, context); + /** + * Creates the sub dialog. + */ + public AddRequestSettingSubdialog() { + super(R.layout.subdialog_add_requestsetting); } + /** + * Shows the error on the screen. + */ public void showError(){ error.post(() -> error.setVisibility(View.VISIBLE)); } @Override - public void render() { - - } + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - @Override - protected void loadComponents(View view) { error = view.findViewById(R.id.add_request_setting_error); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java index df695d1..8d0c0cc 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSelectSubdialog.java @@ -1,6 +1,7 @@ package ch.virt.smartphonemouse.ui.connect.dialog; import android.bluetooth.BluetoothClass; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -9,86 +10,121 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.List; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothDiscoverer; import ch.virt.smartphonemouse.transmission.BluetoothHandler; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class AddSelectSubdialog extends CustomFragment { - - BluetoothHandler bluetooth; - RecyclerView list; - Button scanning; - - ListAdapter adapter; - Listener selectListener; - - public AddSelectSubdialog(MainContext context, BluetoothHandler bluetoothAdapter, Listener selected) { - super(R.layout.subdialog_add_select, context); +/** + * This class holds a sub page for the add dialog that is used to display discovered devices and to select them. + */ +public class AddSelectSubdialog extends Fragment { + + private final BluetoothHandler bluetooth; + + private Button scanning; + private RecyclerView list; + private ListAdapter adapter; + private ListAdapter.SelectListener selectListener; + + /** + * Creates the sub dialog. + * + * @param bluetoothAdapter bluetooth handler to use + */ + public AddSelectSubdialog(BluetoothHandler bluetoothAdapter) { + super(R.layout.subdialog_add_select); this.bluetooth = bluetoothAdapter; - selectListener = selected; } - @Override - public void render() { - adapter = new ListAdapter(bluetooth.getDiscoverer().getDevices(), selectListener); - list.setAdapter(adapter); - list.setLayoutManager(new LinearLayoutManager(getContext())); - - scanning.setOnClickListener(v -> startDiscovery()); - - bluetooth.getDiscoverer().setUpdateListener(devices -> adapter.notifyDataSetChanged()); - bluetooth.getDiscoverer().setScanListener(this::discoveryUpdated); - - bluetooth.getDiscoverer().startDiscovery(); - bluetooth.getDiscoverer().reset(); - } - - public void startDiscovery(){ + /** + * Starts the discovery. + */ + private void startDiscovery() { bluetooth.getDiscoverer().reset(); bluetooth.getDiscoverer().startDiscovery(); } - public void discoveryUpdated(boolean status){ + /** + * This method updates the scan button. + * + * @param status current scanning status + */ + private void discoveryUpdated(boolean status) { + if (status) { scanning.setEnabled(false); scanning.setText(R.string.dialog_add_select_scanning); - }else { + } else { scanning.setEnabled(true); scanning.setText(R.string.dialog_add_select_rescan); } } - public BluetoothDiscoverer.DiscoveredDevice getSelected(){ - return adapter.getSelected(); + /** + * Sets the listener for when a device has been selected. + * This method has to be called before the dialog is shown. + * + * @param selectListener select listener + */ + public void setSelectListener(ListAdapter.SelectListener selectListener) { + this.selectListener = selectListener; } @Override - protected void loadComponents(View view) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + list = view.findViewById(R.id.add_select_list); scanning = view.findViewById(R.id.add_select_scanning); + + + adapter = new ListAdapter(bluetooth.getDiscoverer().getDevices()); + adapter.setSelectListener(selectListener); + + list.setAdapter(adapter); + list.setLayoutManager(new LinearLayoutManager(getContext())); + + scanning.setOnClickListener(v -> startDiscovery()); + + bluetooth.getDiscoverer().setUpdateListener(devices -> adapter.notifyDataSetChanged()); + bluetooth.getDiscoverer().setScanListener(this::discoveryUpdated); + + startDiscovery(); } + + /** + * This list adapter handles the recycler view that shows all the discovered devices. + */ private static class ListAdapter extends RecyclerView.Adapter { private List devices; - private int selectedDevice; - private Listener selectListener; - - public ListAdapter(List devices, Listener listener) { - selectListener = listener; + private SelectListener selectListener; + + /** + * Creates the list adapter. + * + * @param devices devices to show + */ + public ListAdapter(List devices) { this.devices = devices; } - public BluetoothDiscoverer.DiscoveredDevice getSelected(){ - return devices.get(selectedDevice); + /** + * Sets the listener that is called when a device is selected. + * + * @param selectListener select listener + */ + public void setSelectListener(SelectListener selectListener) { + this.selectListener = selectListener; } @NonNull @@ -102,12 +138,7 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { @Override public void onBindViewHolder(@NonNull AddSelectSubdialog.ListAdapter.ViewHolder holder, int position) { - holder.getLabel().setText(devices.get(position).getName()); - - // Only covers the three major types - if (devices.get(position).getMajorClass() == BluetoothClass.Device.Major.PHONE) holder.getIcon().setImageResource(R.drawable.device_add_smartphone); - else if (devices.get(position).getMajorClass() == BluetoothClass.Device.Major.COMPUTER) holder.getIcon().setImageResource(R.drawable.device_add_computer); - else holder.getIcon().setImageResource(R.drawable.device_add_other); + holder.populate(devices.get(position)); } @Override @@ -115,32 +146,60 @@ public int getItemCount() { return devices.size(); } + /** + * This class is the view holder for the recycler view that shows the discovered devices. + */ public class ViewHolder extends RecyclerView.ViewHolder { private final TextView label; private final ImageView icon; + private BluetoothDiscoverer.DiscoveredDevice device; + + /** + * Creates the view holder. + * + * @param view view that the holder holds + */ public ViewHolder(View view) { super(view); - view.setOnClickListener(v -> { - selectedDevice = getLayoutPosition(); - selectListener.called(); - }); + view.setOnClickListener(v -> selectListener.called(device)); label = view.findViewById(R.id.add_select_list_item_text); icon = view.findViewById(R.id.add_select_list_item_icon); } - public TextView getLabel() { - return label; - } - - public ImageView getIcon() { - return icon; + /** + * Populates the view with the data about one device. + * + * @param device device to populate with + */ + public void populate(BluetoothDiscoverer.DiscoveredDevice device) { + this.device = device; + + label.setText(device.getName()); + + // Only covers the three major types + if (device.getMajorClass() == BluetoothClass.Device.Major.PHONE) + icon.setImageResource(R.drawable.device_add_smartphone); + else if (device.getMajorClass() == BluetoothClass.Device.Major.COMPUTER) + icon.setImageResource(R.drawable.device_add_computer); + else icon.setImageResource(R.drawable.device_add_other); } } - + /** + * This interface is a basic listener for when a list entry is selected. + */ + public interface SelectListener { + + /** + * Called when a list entry is selected. + * + * @param device device that is selected + */ + void called(BluetoothDiscoverer.DiscoveredDevice device); + } } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSuccessSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSuccessSubdialog.java index e58f132..f072ab8 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSuccessSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/AddSuccessSubdialog.java @@ -1,32 +1,41 @@ package ch.virt.smartphonemouse.ui.connect.dialog; +import android.os.Bundle; import android.view.View; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothDiscoverer; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class AddSuccessSubdialog extends CustomFragment { +/** + * This class holds the sub page for the add dialog that informs the user that they have successfully added a device. + */ +public class AddSuccessSubdialog extends Fragment { private TextView name; - private BluetoothDiscoverer.DiscoveredDevice target; + private final BluetoothDiscoverer.DiscoveredDevice target; - public AddSuccessSubdialog(MainContext context, BluetoothDiscoverer.DiscoveredDevice target) { - super(R.layout.subdialog_add_success, context); + /** + * Creates the sub dialog. + * + * @param target device which was added, used to display its name + */ + public AddSuccessSubdialog(BluetoothDiscoverer.DiscoveredDevice target) { + super(R.layout.subdialog_add_success); this.target = target; } @Override - public void render() { - name.setText(target.getName()); - } + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - @Override - protected void loadComponents(View view) { name = view.findViewById(R.id.add_success_name); + name.setText(target.getName()); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/InfoDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/InfoDialog.java index 1090883..54e0b2d 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/InfoDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/dialog/InfoDialog.java @@ -16,34 +16,50 @@ import java.util.Date; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.transmission.HostDevice; +/** + * This dialog is shown when the user wants to see more information about a device. + */ public class InfoDialog extends DialogFragment { private final BluetoothHandler bluetooth; private final HostDevice device; - private final Listener closed; - public InfoDialog(BluetoothHandler bluetooth, HostDevice device, Listener closed) { + private DialogInterface.OnDismissListener dismissListener; + + /** + * Creates the info dialog. + * + * @param bluetooth bluetooth handler to remove device from + * @param device device that is viewed + */ + public InfoDialog(BluetoothHandler bluetooth, HostDevice device) { this.bluetooth = bluetooth; this.device = device; - this.closed = closed; } - public void populate(View view) { - + /** + * Populates the text views on the view with the data of the device. + * + * @param view view to populate + */ + private void populate(View view) { ((TextView) view.findViewById(R.id.info_address)).setText(device.getAddress()); ((TextView) view.findViewById(R.id.info_name)).setText(device.getName()); ((TextView) view.findViewById(R.id.info_last)).setText(device.getLastConnected() == -1 ? view.getResources().getString(R.string.dialog_info_last_never) : new SimpleDateFormat(view.getResources().getString(R.string.dialog_info_last_format)).format(new Date(device.getLastConnected()))); } - @Override - public void onDismiss(@NonNull DialogInterface dialog) { - super.onDismiss(dialog); - - closed.called(); + /** + * Sets the dismiss listener. + * The listener should be set before the dialog is shown. + * + * @param dismissListener dismiss listener that will be passed to the dialog + * @see Dialog#setOnDismissListener(DialogInterface.OnDismissListener) + */ + public void setOnDismissListener(DialogInterface.OnDismissListener dismissListener) { + this.dismissListener = dismissListener; } @NonNull @@ -62,6 +78,7 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { Dialog dialog = builder.create(); dialog.setTitle(R.string.dialog_info_title); + dialog.setOnDismissListener(dismissListener); return dialog; } From 29141b443506c99d137d86dda1058eb228c3804e Mon Sep 17 00:00:00 2001 From: Joshua Date: Thu, 2 Sep 2021 21:50:19 +0200 Subject: [PATCH 5/8] Much mor Javadoc and Refactoring --- .../smartphonemouse/ui/ConnectFragment.java | 12 +- .../virt/smartphonemouse/ui/HomeFragment.java | 2 +- .../connect/ConnectConnectedSubfragment.java | 56 ++++--- .../connect/ConnectConnectingSubfragment.java | 33 ++-- .../ui/connect/ConnectFailedSubfragment.java | 67 +++++--- .../ui/connect/ConnectSelectSubfragment.java | 144 ++++++++++++------ .../ui/debug/DebugChartSheet.java | 61 +++++--- .../ui/debug/OnDoubleClickListener.java | 8 + .../ui/debug/SideDialogFragment.java | 4 + .../ui/debug/handling/DebugChartHandler.java | 95 +++++++++--- .../ui/debug/handling/DebugCsvExporter.java | 39 ++++- .../ui/debug/handling/DebugDataHandler.java | 58 ++++++- .../ui/debug/handling/DebugSeries.java | 62 +++++++- .../ui/home/HomeConnectedSubfragment.java | 46 +++--- .../ui/home/HomeDisabledSubfragment.java | 14 +- .../ui/home/HomeDisconnectedSubfragment.java | 8 +- .../ui/home/HomeUnsupportedSubfragment.java | 11 +- 17 files changed, 526 insertions(+), 194 deletions(-) diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java index 39172b4..ddc1960 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java @@ -32,17 +32,21 @@ public void render() { if (bluetooth.isInitialized()){ if (bluetooth.isConnecting()) { - loadFragment(new ConnectConnectingSubfragment(main, bluetooth)); + loadFragment(new ConnectConnectingSubfragment()); setStatus(R.color.status_connecting, R.string.connect_status_connecting); } else if (!bluetooth.isConnected()){ - if (bluetooth.getHost().hasFailed()) loadFragment(new ConnectFailedSubfragment(main, bluetooth, this::render)); - else loadFragment(new ConnectSelectSubfragment(main, bluetooth)); + if (bluetooth.getHost().hasFailed()){ + ConnectFailedSubfragment fragment = new ConnectFailedSubfragment(bluetooth); + fragment.setReturnListener(this::render); + loadFragment(fragment); + } + else loadFragment(new ConnectSelectSubfragment(bluetooth)); setStatus(R.color.status_disconnected, R.string.connect_status_disconnected); } else{ - loadFragment(new ConnectConnectedSubfragment(main, bluetooth)); + loadFragment(new ConnectConnectedSubfragment(bluetooth)); setStatus(R.color.status_connected, R.string.connect_status_connected); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java index e47ecd1..4e2c63b 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java @@ -43,7 +43,7 @@ else if (!bluetooth.isSupported()) setStatus(R.color.status_unsupported, R.string.home_status_unsupported, R.string.home_button_unsupported, v -> getActivity().finish(), new HomeUnsupportedSubfragment()); else if (bluetooth.isConnected()) - setStatus(R.color.status_connected, R.string.home_status_connected, R.string.home_button_connected, v -> ((MainActivity) getActivity()).navigate(R.id.drawer_mouse), new HomeConnectedSubfragment(bluetooth, main)); + setStatus(R.color.status_connected, R.string.home_status_connected, R.string.home_button_connected, v -> ((MainActivity) getActivity()).navigate(R.id.drawer_mouse), new HomeConnectedSubfragment(bluetooth)); else setStatus(R.color.status_disconnected, R.string.home_status_disconnected, R.string.home_button_disconnected, v -> ((MainActivity) getActivity()).navigate(R.id.drawer_connect), new HomeDisconnectedSubfragment()); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java index f126139..5fc1b29 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectedSubfragment.java @@ -1,34 +1,53 @@ package ch.virt.smartphonemouse.ui.connect; +import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Chronometer; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class ConnectConnectedSubfragment extends CustomFragment { +/** + * This class is a sub fragment for the connect page. + * This fragment is displayed when the app has a successful connection. + */ +public class ConnectConnectedSubfragment extends Fragment { - Chronometer elapsed; - TextView name; + private Chronometer elapsed; + private TextView name; - Button disconnect; - Button mouse; + private Button disconnect; + private Button mouse; - BluetoothHandler bluetooth; + private final BluetoothHandler bluetooth; - public ConnectConnectedSubfragment(MainContext context, BluetoothHandler bluetooth) { - super(R.layout.subfragment_connect_connected, context); + /** + * Creates this sub fragment. + * + * @param bluetooth bluetooth handler to read status from + */ + public ConnectConnectedSubfragment(BluetoothHandler bluetooth) { + super(R.layout.subfragment_connect_connected); this.bluetooth = bluetooth; } @Override - public void render() { - if (bluetooth.isConnected()){ + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + elapsed = view.findViewById(R.id.connect_connected_device_elapsed); + name = view.findViewById(R.id.connect_connected_device_name); + disconnect = view.findViewById(R.id.connect_connected_disconnect); + mouse = view.findViewById(R.id.connect_connected_mouse); + + if (bluetooth.isConnected()) { name.setText(bluetooth.getHost().getDevice().getName()); @@ -37,18 +56,7 @@ public void render() { elapsed.start(); disconnect.setOnClickListener(v -> bluetooth.getHost().disconnect()); - mouse.setOnClickListener(v -> { - bluetooth.getHost().sendReport(false, false, false, 0, 20, 0); - ((MainActivity) getActivity()).navigate(R.id.drawer_mouse); - }); + mouse.setOnClickListener(v -> ((MainActivity) getActivity()).navigate(R.id.drawer_mouse)); } } - - @Override - protected void loadComponents(View view) { - elapsed = view.findViewById(R.id.connect_connected_device_elapsed); - name = view.findViewById(R.id.connect_connected_device_name); - disconnect = view.findViewById(R.id.connect_connected_disconnect); - mouse = view.findViewById(R.id.connect_connected_mouse); - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectingSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectingSubfragment.java index 739dd30..6b2548a 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectingSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectConnectingSubfragment.java @@ -1,28 +1,19 @@ package ch.virt.smartphonemouse.ui.connect; -import android.view.View; -import android.widget.TextView; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.transmission.BluetoothHandler; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class ConnectConnectingSubfragment extends CustomFragment { - - BluetoothHandler bluetooth; - - public ConnectConnectingSubfragment(MainContext context, BluetoothHandler bluetooth) { - super(R.layout.subfragment_connect_connecting, context); - - this.bluetooth = bluetooth; - } - - @Override - public void render() { - } - - @Override - protected void loadComponents(View view) { +/** + * This is a sub fragment for the connect page. + * This fragment gets displayed when the app is currently connecting to a device. + */ +public class ConnectConnectingSubfragment extends Fragment { + + /** + * Creates this sub fragment. + */ + public ConnectConnectingSubfragment() { + super(R.layout.subfragment_connect_connecting); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java index 32f7deb..ad37705 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectFailedSubfragment.java @@ -1,54 +1,79 @@ package ch.virt.smartphonemouse.ui.connect; +import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class ConnectFailedSubfragment extends CustomFragment { +/** + * This is a sub fragment for the connect page. + * This fragment is shown when a recent connection failed. + */ +public class ConnectFailedSubfragment extends Fragment { - BluetoothHandler bluetooth; + private final BluetoothHandler bluetooth; - TextView device; - Button back; - Button remove; + private TextView device; + private Button back; + private Button remove; - ReturnListener listener; + private ReturnListener listener; - public ConnectFailedSubfragment(MainContext context, BluetoothHandler bluetooth, ReturnListener listener) { - super(R.layout.subfragment_connect_failed, context); + /** + * Creates the sub fragment. + * @param bluetooth bluetooth handler to query information from + */ + public ConnectFailedSubfragment(BluetoothHandler bluetooth) { + super(R.layout.subfragment_connect_failed); this.bluetooth = bluetooth; - this.listener = listener; } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + device = view.findViewById(R.id.connect_failed_device); + + back = view.findViewById(R.id.connect_failed_back); + remove = view.findViewById(R.id.connect_failed_remove); + + device.setText(bluetooth.getHost().getDevice().getName()); remove.setOnClickListener(v -> { bluetooth.getDevices().removeDevice(bluetooth.getHost().getDevice().getAddress()); bluetooth.getHost().markFailedAsRead(); - listener.called(); + listener.returned(); }); back.setOnClickListener(v -> { bluetooth.getHost().markFailedAsRead(); - listener.called(); + listener.returned(); }); } - @Override - protected void loadComponents(View view) { - device = view.findViewById(R.id.connect_failed_device); - - back = view.findViewById(R.id.connect_failed_back); - remove = view.findViewById(R.id.connect_failed_remove); + /** + * Sets the return listener that is called when the user wants to return from this fragment + * @param listener return listener + */ + public void setReturnListener(ReturnListener listener) { + this.listener = listener; } + /** + * This interface is a basic listener that is called when the user returns from the failure message. + */ public interface ReturnListener { - void called(); + + /** + * Called when the user returns. + */ + void returned(); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java index b1e5d34..76338e4 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/connect/ConnectSelectSubfragment.java @@ -1,5 +1,6 @@ package ch.virt.smartphonemouse.ui.connect; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -8,6 +9,8 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -16,77 +19,109 @@ import java.util.List; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.transmission.HostDevice; -import ch.virt.smartphonemouse.ui.CustomFragment; import ch.virt.smartphonemouse.ui.connect.dialog.AddDialog; import ch.virt.smartphonemouse.ui.connect.dialog.InfoDialog; -public class ConnectSelectSubfragment extends CustomFragment { +/** + * This class is a sub fragment for the connect page. + * On this fragment, the user can select or add a device, which he then can connect to. + */ +public class ConnectSelectSubfragment extends Fragment { - private BluetoothHandler bluetooth; + private final BluetoothHandler bluetooth; - ListAdapter adapter; - RecyclerView list; - Button add; + private ListAdapter adapter; + private RecyclerView list; + private Button add; - public ConnectSelectSubfragment(MainContext context, BluetoothHandler bluetooth) { - super(R.layout.subfragment_connect_select, context); + /** + * Creates the sub fragment. + * @param bluetooth bluetooth handler to handle bluetooth + */ + public ConnectSelectSubfragment(BluetoothHandler bluetooth) { + super(R.layout.subfragment_connect_select); this.bluetooth = bluetooth; } @Override - public void render() { - adapter = new ListAdapter(bluetooth.getDevices().getDevices(), this::connect, this::info); + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + list = view.findViewById(R.id.connect_select_items); + add = view.findViewById(R.id.connect_select_add); + + + add.setOnClickListener(v -> add()); + + adapter = new ListAdapter(bluetooth.getDevices().getDevices()); + adapter.setConnectListener(this::connect); + adapter.setInfoListener(this::info); list.setAdapter(adapter); list.setLayoutManager(new LinearLayoutManager(getContext())); + } - public void info(){ - InfoDialog dialog = new InfoDialog(bluetooth, adapter.getSelected()); + /** + * Opens the information dialog for the specified device. + * @param device device + */ + public void info(HostDevice device){ + InfoDialog dialog = new InfoDialog(bluetooth, device); dialog.setOnDismissListener((d) -> adapter.notifyDataSetChanged()); dialog.show(this.getParentFragmentManager(), null); } - public void connect(){ - bluetooth.getHost().connect(adapter.getSelected()); - } - - @Override - protected void loadComponents(View view) { - list = view.findViewById(R.id.connect_select_items); - add = view.findViewById(R.id.connect_select_add); - } - - @Override - protected void initComponents() { - add.setOnClickListener(view -> add()); + /** + * Connects to the known device specified + * @param device device to connect to + */ + public void connect(HostDevice device){ + bluetooth.getHost().connect(device); } + /** + * Starts the dialog to add a device. + */ private void add(){ AddDialog dialog = new AddDialog(bluetooth); dialog.setOnDismissListener((d) -> adapter.notifyDataSetChanged()); dialog.show(this.getParentFragmentManager(), null); } + /** + * This class is the list adapter for the recycler view which shows the known devices. + */ private static class ListAdapter extends RecyclerView.Adapter { - private List devices; - private int selectedDevice; - private Listener selectListener; - private Listener settingsListener; + private final List devices; + private ListResultListener connectListener; + private ListResultListener infoListener; - public ListAdapter(List devices, Listener listener, Listener settingsListener) { - selectListener = listener; + /** + * Creates the list adapter. + * @param devices devices to show + */ + public ListAdapter(List devices) { this.devices = devices; - this.settingsListener = settingsListener; } - public HostDevice getSelected(){ - return devices.get(selectedDevice); + /** + * Sets the listener that gets called when the user clicks on an entry. + * @param connectListener connect listener + */ + public void setConnectListener(ListResultListener connectListener) { + this.connectListener = connectListener; + } + + /** + * Sets the listener that gets called when the user clicks on the info sign on an entry. + * @param infoListener info listener + */ + public void setInfoListener(ListResultListener infoListener) { + this.infoListener = infoListener; } @NonNull @@ -108,36 +143,55 @@ public int getItemCount() { return devices.size(); } + /** + * This is the view holder for that recyclerview. + */ public class ViewHolder extends RecyclerView.ViewHolder { private final TextView name; private final TextView last; private final ImageView settings; + private HostDevice device; + + /** + * Creates the view holder. + * @param view view to hold + */ public ViewHolder(View view) { super(view); - view.setOnClickListener(v -> { - selectedDevice = getLayoutPosition(); - selectListener.called(); - }); - name = view.findViewById(R.id.connect_select_list_item_name); last = view.findViewById(R.id.connect_select_list_item_last); settings = view.findViewById(R.id.connect_select_list_item_settings); - settings.setOnClickListener(v -> { - selectedDevice = getLayoutPosition(); - settingsListener.called(); - }); + view.setOnClickListener(v -> connectListener.result(device)); + settings.setOnClickListener(v -> infoListener.result(device)); } + /** + * Sets the device the holder does represent. + * @param device device + */ public void setDevice(HostDevice device){ + this.device = device; + name.setText(device.getName()); last.setText(itemView.getResources().getString(R.string.connect_select_item_last, device.getLastConnected() == -1 ? itemView.getResources().getString(R.string.connect_select_item_never) : new SimpleDateFormat(itemView.getResources().getString(R.string.connect_select_item_last_format)).format(new Date(device.getLastConnected())))); } } + /** + * This interface is a basic listener which is used for events regarding the recyclerview in this activity. + */ + public interface ListResultListener { + + /** + * Gets called when an entry is clicked. + * @param device device of that entry + */ + void result(HostDevice device); + } } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/DebugChartSheet.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/DebugChartSheet.java index 47bdb65..2ed7043 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/DebugChartSheet.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/DebugChartSheet.java @@ -25,26 +25,30 @@ import ch.virt.smartphonemouse.ui.debug.handling.DebugChartHandler; import ch.virt.smartphonemouse.ui.debug.handling.DebugDataHandler; +/** + * This class is the pseudo side sheet that is used to configure the chart in the debugging page. + */ public class DebugChartSheet extends SideDialogFragment { - Dialog dialog; - RecyclerView seriesView; - RadioGroup axis; + private Dialog dialog; + private RecyclerView seriesView; + private RadioGroup axis; + private EditText averageEdit; - DebugChartHandler chartHandler; - DebugDataHandler dataHandler; - EditText averageEdit; + private final DebugChartHandler chartHandler; + private final DebugDataHandler dataHandler; + /** + * Creates the chart sheet. + * + * @param chartHandler chart to manipulate + * @param dataHandler data handler to manipulate + */ public DebugChartSheet(DebugChartHandler chartHandler, DebugDataHandler dataHandler) { this.chartHandler = chartHandler; this.dataHandler = dataHandler; } - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { @@ -68,30 +72,37 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { averageEdit.setText("" + chartHandler.getAverageAmount()); averageEdit.setOnEditorActionListener((v, actionId, event) -> { - if (actionId == IME_ACTION_DONE || actionId == IME_ACTION_NEXT || actionId == IME_ACTION_PREVIOUS) chartHandler.setAverageAmount(Integer.parseInt(v.getText().toString())); + if (actionId == IME_ACTION_DONE || actionId == IME_ACTION_NEXT || actionId == IME_ACTION_PREVIOUS) + chartHandler.setAverageAmount(Integer.parseInt(v.getText().toString())); return false; }); return dialog; } + /** + * This list adapter is for the recycler view that is used to show the different series. + */ private static class ListAdapter extends RecyclerView.Adapter { DebugChartHandler handler; + /** + * Creates the list adapter. + * + * @param series handler to get series from that are displayed. + */ public ListAdapter(DebugChartHandler series) { - this.handler = series; } - @NonNull @Override public ListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_debug_chart_axis, parent, false); - return new ListAdapter.ViewHolder(view); + return new ViewHolder(view); } @Override @@ -104,12 +115,19 @@ public int getItemCount() { return handler.getSeries().size(); } - public class ViewHolder extends RecyclerView.ViewHolder { + /** + * This view holder does hold one entry for one series in the recycler view. + */ + public static class ViewHolder extends RecyclerView.ViewHolder { private final ImageView color; private final CheckBox checkbox; - + /** + * Creates the view holder. + * + * @param view view to hold + */ public ViewHolder(View view) { super(view); @@ -117,8 +135,15 @@ public ViewHolder(View view) { color = view.findViewById(R.id.debug_chart_series_item_color); } + /** + * Binds the view holder to a particular series. + * + * @param handler chart to get series from + * @param index index of the series + */ public void bind(DebugChartHandler handler, int index) { - ((GradientDrawable) color.getBackground()).setColor(handler.getSeries().get(index).getColor() | 0xFF000000); + ((GradientDrawable) color.getBackground()).setColor(handler.getSeries().get(index).getColor() | 0xFF000000); // Add alpha values + checkbox.setText(handler.getSeries().get(index).getName()); checkbox.setChecked(handler.getSeries().get(index).isVisible()); checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> handler.setSeriesVisibility(handler.getSeries().get(index), isChecked)); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/OnDoubleClickListener.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/OnDoubleClickListener.java index e2468e1..4d845ab 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/OnDoubleClickListener.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/OnDoubleClickListener.java @@ -2,6 +2,9 @@ import android.view.View; +/** + * This class is a further abstraction of the on click listener that listens to double clicks. + */ public abstract class OnDoubleClickListener implements View.OnClickListener { public static final long DOUBLE_CLICK_DELAY = 200; @@ -18,5 +21,10 @@ public void onClick(View v) { } + /** + * Gets called when a double click is performed. + * + * @param v view it was performed on + */ public abstract void onDoubleClick(View v); } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/SideDialogFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/SideDialogFragment.java index ba26c43..1091423 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/SideDialogFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/SideDialogFragment.java @@ -8,6 +8,10 @@ import androidx.fragment.app.DialogFragment; +/** + * This class configures a dialog fragment as a dialog that appears on the side of the screen. + * This dialog is similar to a side sheet from material design, but since it is not implemented by their library, this is used. + */ public class SideDialogFragment extends DialogFragment { @Override diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugChartHandler.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugChartHandler.java index 91ef2a4..1ce74d5 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugChartHandler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugChartHandler.java @@ -8,15 +8,19 @@ import java.util.ArrayList; import java.util.List; +import ch.virt.smartphonemouse.mouse.Pipeline; import ch.virt.smartphonemouse.ui.debug.OnDoubleClickListener; +/** + * This class handles the chart on the debug fragment. + */ public class DebugChartHandler { - private static final int[] COLORS = { 0xf44336, 0x9c27b0, 0x673ab7, 0x3f51b5, 0x2196f3, 0x009688, 0x4caf50, 0x8bc34a, 0xcddc39, 0xffeb3b, 0xffc107, 0xff9800, 0xff5722, 0x795548, 0x9e9e9e, 0x607d8b, 0x03a9f4, 0x00bcd4, 0xe91e63}; + private static final int[] COLORS = {0xf44336, 0x9c27b0, 0x673ab7, 0x3f51b5, 0x2196f3, 0x009688, 0x4caf50, 0x8bc34a, 0xcddc39, 0xffeb3b, 0xffc107, 0xff9800, 0xff5722, 0x795548, 0x9e9e9e, 0x607d8b, 0x03a9f4, 0x00bcd4, 0xe91e63}; private final GraphView chart; - private List series; - private SharedPreferences preferences; + private final List series; + private final SharedPreferences preferences; private int highestIndex; private int colorIndex; @@ -26,7 +30,13 @@ public class DebugChartHandler { private List timeStamps; - public DebugChartHandler(GraphView chart, SharedPreferences preferences){ + /** + * Creates the chart handler. + * + * @param chart chart to handle + * @param preferences preferences to read certain config entries from + */ + public DebugChartHandler(GraphView chart, SharedPreferences preferences) { timeStamps = new ArrayList<>(); series = new ArrayList<>(); this.preferences = preferences; @@ -38,7 +48,10 @@ public DebugChartHandler(GraphView chart, SharedPreferences preferences){ styleChart(); } - private void styleChart(){ + /** + * Styles the chart in order to look good. + */ + private void styleChart() { chart.getViewport().setYAxisBoundsManual(true); chart.getViewport().setMinY(-10); chart.getViewport().setMaxY(10); @@ -64,7 +77,13 @@ public void onDoubleClick(View v) { }); } - public void addSeries(String name, int index){ + /** + * Adds a series to the graph. + * + * @param name name of that series + * @param index source index of that data + */ + public void addSeries(String name, int index) { if (index > highestIndex) highestIndex = index; DebugSeries series = new DebugSeries(selectColor(), name, averageAmount); @@ -72,7 +91,14 @@ public void addSeries(String name, int index){ this.series.add(index, series); } - public void newData(long timestamp, float[] data){ + /** + * Adds a new line of samples to the graph. + * + * @param timestamp timestamp of the samples + * @param data debugging data from the pipeline + * @see Pipeline#getDebuggingValues() + */ + public void newData(long timestamp, float[] data) { timeStamps.add(timestamp); for (int i = 0; i < data.length; i++) { @@ -87,41 +113,57 @@ public void newData(long timestamp, float[] data){ } } - private int selectColor(){ + /** + * Selects a colour for the next series. The colours are selected from the material colors. + * + * @return selected color as an integer + * @see DebugChartHandler#COLORS + */ + private int selectColor() { if (colorIndex == COLORS.length) colorIndex = 0; return COLORS[colorIndex++]; } - public void setAverageAmount(int amount){ + /** + * Sets the amount of samples needed to form one point on the chart. + * + * @param amount amount of samples + */ + public void setAverageAmount(int amount) { if (amount == averageAmount) return; this.averageAmount = amount; currentAverageAmount = 0; timeStamps.clear(); - for (DebugSeries series : this.series){ + for (DebugSeries series : this.series) { series.setAverageAmount(averageAmount); } preferences.edit().putInt("debugChartAverageAmount", amount).apply(); } - public void clear(){ + /** + * Clears the chart. + */ + public void clear() { timeStamps.clear(); currentAverageAmount = 0; - for (DebugSeries series : this.series){ + for (DebugSeries series : this.series) { series.clear(); } } - public List getTimeStamps() { - return timeStamps; - } - + /** + * Sets the visibility of a series. + * + * @param series series to set visibility for + * @param visibility visibility of that series + */ public void setSeriesVisibility(DebugSeries series, boolean visibility) { - if (series.isVisible() != visibility){ + if (series.isVisible() != visibility) { if (visibility) chart.addSeries(series.getDataSet()); else chart.removeSeries(series.getDataSet()); @@ -129,10 +171,29 @@ public void setSeriesVisibility(DebugSeries series, boolean visibility) { } } + /** + * Returns the list of timestamps present on the diagram. This method is used for exporting the shown data. + * + * @return list of timestamps + */ + public List getTimeStamps() { + return timeStamps; + } + + /** + * Returns all series of the diagram. + * + * @return list of series + */ public List getSeries() { return series; } + /** + * Returns how many samples are used for one point on the chart. + * + * @return amount + */ public int getAverageAmount() { return averageAmount; } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugCsvExporter.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugCsvExporter.java index fb29c47..9ce3829 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugCsvExporter.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugCsvExporter.java @@ -10,23 +10,42 @@ import java.io.FileWriter; import java.io.IOException; +/** + * This class is used to export the content of the chart as a csv file. + */ public class DebugCsvExporter { - DebugChartHandler chart; - Context context; + private final DebugChartHandler chart; + private final Context context; + /** + * Creates the exporter. + * + * @param chart chart to export + * @param context context to share with + */ public DebugCsvExporter(DebugChartHandler chart, Context context) { this.chart = chart; this.context = context; } + /** + * Exports the chart as a csv file. + * + * @throws IOException thrown if failed to write file to disk for cache + */ public void exportCsv() throws IOException { String csv = createCsv(); File file = cacheCsv(csv); shareCsv(file); } - public String createCsv(){ + /** + * Creates a string with the diagram data in csv format. + * + * @return string with csv data + */ + public String createCsv() { StringBuilder s = new StringBuilder(); // Write Header @@ -49,6 +68,13 @@ public String createCsv(){ return s.toString(); } + /** + * Writes the csv data to a cache file so it can be shared. + * + * @param s string with csv data + * @return file that it was written to + * @throws IOException thrown if failed to write file + */ public File cacheCsv(String s) throws IOException { new File(context.getExternalFilesDir(null), "exports").mkdir(); File file = new File(context.getExternalFilesDir(null), "exports/export.csv"); @@ -61,7 +87,12 @@ public File cacheCsv(String s) throws IOException { return file; } - public void shareCsv(File f){ + /** + * Shares the csv file through the android share dialog. + * + * @param f cache file to share + */ + public void shareCsv(File f) { Uri u = FileProvider.getUriForFile(context, "ch.virt.fileprovider", f); Intent intent = new Intent(Intent.ACTION_SEND); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java index f0b5439..5d35ca3 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugDataHandler.java @@ -10,22 +10,32 @@ import ch.virt.smartphonemouse.mouse.Pipeline; import ch.virt.smartphonemouse.mouse.PipelineConfig; +/** + * This class does handle the data from the accelerometer and does provide it to the chart. + */ public class DebugDataHandler implements SensorEventListener { private static final float NANO_FULL_FACTOR = 1e-9f; - DebugChartHandler chart; - SharedPreferences preferences; + private final DebugChartHandler chart; + private final SharedPreferences preferences; private long lastSample = 0; private boolean registered; private Pipeline pipeline; - private SensorManager manager; + private final SensorManager manager; private Sensor sensor; private int axis; + /** + * Create a debug data handler. + * + * @param manager sensor manager to get the sensor from + * @param chart chart to provide data to + * @param preferences preferences to fetch specific config + */ public DebugDataHandler(SensorManager manager, DebugChartHandler chart, SharedPreferences preferences) { this.manager = manager; this.chart = chart; @@ -37,16 +47,27 @@ public DebugDataHandler(SensorManager manager, DebugChartHandler chart, SharedPr fetchSensor(); } - public void create(SharedPreferences preferences){ + /** + * Creates the pipeline used for processing. + * + * @param preferences preferences to get pipeline config from + */ + public void create(SharedPreferences preferences) { pipeline = new Pipeline(preferences.getInt("communicationTransmissionRate", 200), new PipelineConfig(preferences)); pipeline.enableDebugging(); } - public void fetchSensor(){ + /** + * Fetches the sensor from the sensor manager. + */ + private void fetchSensor() { sensor = manager.getDefaultSensor(MovementHandler.SENSOR_TYPE); } - public void register(){ + /** + * Registers this handler as a handler for the accelerometer. + */ + public void register() { if (registered) return; manager.registerListener(this, sensor, MovementHandler.SAMPLING_RATE); @@ -54,7 +75,10 @@ public void register(){ registered = true; } - public void unregister(){ + /** + * Unregisters this handler as a handler for the accelerometer. + */ + public void unregister() { if (!registered) return; manager.unregisterListener(this, sensor); @@ -82,21 +106,39 @@ public void onAccuracyChanged(Sensor sensor, int accuracy) { } + /** + * Returns whether the handler is currently registered. + * + * @return is currently registered + */ public boolean isRegistered() { return registered; } + /** + * Returns the current axis data is used from. + * + * @return current axis, 0 = x, 1 = y, 2 = z + */ public int getAxis() { return axis; } + /** + * Sets the axis data is used form. + * + * @param axis current axis, 0 = x, 1 = y, 2 = z + */ public void setAxis(int axis) { this.axis = axis; preferences.edit().putInt("debugChartAxis", axis).apply(); } - public void renew(){ + /** + * Resets the algorithm to its initial state. + */ + public void renew() { pipeline.reset(); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugSeries.java b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugSeries.java index 209ab91..bfe5ef2 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugSeries.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/debug/handling/DebugSeries.java @@ -6,6 +6,9 @@ import java.util.ArrayList; import java.util.List; +/** + * This class holds a single series in the debugging chart. + */ public class DebugSeries { private final int color; @@ -21,7 +24,13 @@ public class DebugSeries { private LineGraphSeries dataSet; private int entryIndex; - + /** + * Creates a series. + * + * @param color color of that series + * @param name name of that series + * @param averageAmount amount of samples required for one point on the diagram + */ public DebugSeries(int color, String name, int averageAmount) { this.color = color; this.name = name; @@ -31,10 +40,15 @@ public DebugSeries(int color, String name, int averageAmount) { samples = new ArrayList<>(); dataSet = new LineGraphSeries<>(); - dataSet.setColor(color | 0xff000000); + dataSet.setColor(color | 0xff000000); // Add alpha values } - void newData(float sample){ + /** + * Adds a new sample to the series. + * + * @param sample new sample + */ + void newData(float sample) { samples.add(sample); currentAverage += sample; @@ -46,7 +60,10 @@ void newData(float sample){ } } - void clear(){ + /** + * Clears the series. + */ + void clear() { samples.clear(); dataSet.resetData(new DataPoint[0]); @@ -55,31 +72,66 @@ void clear(){ currentAverage = 0; } - void setAverageAmount(int amount){ + /** + * Sets how many samples are required for one datapoint on the chart. + * + * @param amount amount of samples + */ + void setAverageAmount(int amount) { averageAmount = amount; clear(); } + /** + * Returns the data set, one can add to a chart. + * + * @return dataset to be added + */ public LineGraphSeries getDataSet() { return dataSet; } + /** + * Returns all samples shown for this series. + * + * @return list of samples + */ public List getSamples() { return samples; } + /** + * Returns the color of this series. + * + * @return color as an integer + */ public int getColor() { return color; } + /** + * Returns the name of this series. + * + * @return name of the series + */ public String getName() { return name; } + /** + * Returns whether the series is currently visible on the chart. + * + * @return is visible + */ public boolean isVisible() { return visible; } + /** + * Sets whether the series should be visible. + * + * @param visible should be visible + */ void setVisible(boolean visible) { this.visible = visible; } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java index 1e7f672..5e54157 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeConnectedSubfragment.java @@ -1,32 +1,49 @@ package ch.virt.smartphonemouse.ui.home; +import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Chronometer; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; -import ch.virt.smartphonemouse.ui.CustomFragment; - -public class HomeConnectedSubfragment extends CustomFragment { - BluetoothHandler handler; +/** + * This sub fragment gets shown on the home screen when a device is currently connected. + */ +public class HomeConnectedSubfragment extends Fragment { - Chronometer chronometer; - TextView device; + private final BluetoothHandler handler; - Button more; + private Chronometer chronometer; + private TextView device; + private Button more; - public HomeConnectedSubfragment(BluetoothHandler handler, MainContext main) { - super(R.layout.subfragment_home_connected, main); + /** + * Creates the sub fragment. + * + * @param handler bluetooth handler to get connected information from + */ + public HomeConnectedSubfragment(BluetoothHandler handler) { + super(R.layout.subfragment_home_connected); this.handler = handler; } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + chronometer = view.findViewById(R.id.home_connected_device_elapsed); + device = view.findViewById(R.id.home_connected_device_name); + more = view.findViewById(R.id.home_connected_more); + + chronometer.setBase(handler.getHost().getConnectedSince()); chronometer.setFormat(getResources().getString(R.string.home_connected_elapsed)); chronometer.start(); @@ -35,11 +52,4 @@ public void render() { more.setOnClickListener(v -> ((MainActivity) getActivity()).navigate(R.id.drawer_connect)); } - - @Override - protected void loadComponents(View view) { - chronometer = view.findViewById(R.id.home_connected_device_elapsed); - device = view.findViewById(R.id.home_connected_device_name); - more = view.findViewById(R.id.home_connected_more); - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisabledSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisabledSubfragment.java index 028d5ce..21f5615 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisabledSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisabledSubfragment.java @@ -3,8 +3,6 @@ import android.os.Bundle; import android.view.View; import android.widget.Button; -import android.widget.Chronometer; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -13,12 +11,20 @@ import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.transmission.BluetoothHandler; +/** + * This sub fragment on the home page gets shown when bluetooth happens to be disabled. + */ public class HomeDisabledSubfragment extends Fragment { - BluetoothHandler handler; + private final BluetoothHandler handler; - Button refresh; + private Button refresh; + /** + * Creates the sub fragment. + * + * @param handler bluetooth handler to use to refresh + */ public HomeDisabledSubfragment(BluetoothHandler handler) { super(R.layout.subfragment_home_disabled); this.handler = handler; diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisconnectedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisconnectedSubfragment.java index 737d244..977a035 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisconnectedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeDisconnectedSubfragment.java @@ -4,9 +4,15 @@ import ch.virt.smartphonemouse.R; +/** + * This sub fragment of the home page is shown when the app is not connected. + */ public class HomeDisconnectedSubfragment extends Fragment { - public HomeDisconnectedSubfragment(){ + /** + * Creates this sub fragment. + */ + public HomeDisconnectedSubfragment() { super(R.layout.subfragment_home_disconnected); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeUnsupportedSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeUnsupportedSubfragment.java index 6cc1e9d..6f80d45 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeUnsupportedSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/home/HomeUnsupportedSubfragment.java @@ -3,7 +3,6 @@ import android.os.Bundle; import android.view.View; import android.widget.Button; -import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -12,11 +11,17 @@ import ch.virt.smartphonemouse.R; +/** + * This sub fragment of the home page is shown when the smartphone does not support the bluetooth id profile. + */ public class HomeUnsupportedSubfragment extends Fragment { private Button playstoreLink; - public HomeUnsupportedSubfragment(){ + /** + * Creates this sub fragment. + */ + public HomeUnsupportedSubfragment() { super(R.layout.subfragment_home_unsupported); } @@ -25,6 +30,6 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat super.onViewCreated(view, savedInstanceState); playstoreLink = view.findViewById(R.id.home_unsupported_playstore); - playstoreLink.setOnClickListener(v -> Toast.makeText(view.getContext(), "Not yet published", Toast.LENGTH_SHORT).show()); + playstoreLink.setOnClickListener(v -> Toast.makeText(view.getContext(), "Currently not published", Toast.LENGTH_SHORT).show()); } } From a18539dd6d4fb959440ba0a9c6fc30a2fefa214b Mon Sep 17 00:00:00 2001 From: Joshua Date: Tue, 7 Sep 2021 21:25:03 +0200 Subject: [PATCH 6/8] more refactoring --- .../ch/virt/smartphonemouse/MainActivity.java | 2 +- .../smartphonemouse/ui/MouseFragment.java | 2 +- .../ui/mouse/MouseCalibrateDialog.java | 45 ++++--- .../ui/mouse/MouseMessageSubdialog.java | 36 +++--- .../ui/mouse/MouseUsageDialog.java | 110 +++++++++++++----- .../ui/mouse/MouseUsageFinishedSubdialog.java | 35 +++--- .../dialog/SamplingRateSubdialog.java | 42 +++---- app/src/main/res/values/strings.xml | 2 +- 8 files changed, 163 insertions(+), 111 deletions(-) diff --git a/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java b/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java index 8f4f3ba..e744772 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java +++ b/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java @@ -220,7 +220,7 @@ public boolean navigate(int entry) { if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean("movementSamplingCalibrated", false)) { // Make sure that the sampling rate is calibrated - MouseCalibrateDialog dialog = new MouseCalibrateDialog(this.mainContext); + MouseCalibrateDialog dialog = new MouseCalibrateDialog(); dialog.show(getSupportFragmentManager(), null); return true; diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java index ed76917..2e34a8d 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java @@ -166,7 +166,7 @@ protected void initComponents() { movement.unregister(); mouse.stop(); - MouseUsageDialog dialog = new MouseUsageDialog(this.main, () -> { + MouseUsageDialog dialog = new MouseUsageDialog(() -> { mouse.start(); movement.register(); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java index ec9870d..4957918 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseCalibrateDialog.java @@ -7,14 +7,17 @@ import android.view.View; import android.widget.Button; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; import ch.virt.smartphonemouse.ui.settings.dialog.SamplingRateSubdialog; +/** + * This class is the dialog that is shown upon mouse calibration + */ public class MouseCalibrateDialog extends DialogFragment { private AlertDialog dialog; @@ -22,13 +25,10 @@ public class MouseCalibrateDialog extends DialogFragment { private boolean introduction; - private MainContext main; - - public MouseCalibrateDialog(MainContext main) { - this.main = main; - } - - private void created(){ + /** + * Is called when the dialog is created. + */ + private void created() { dialog.setTitle(R.string.dialog_mouse_calibrate_title_intro); introduction = true; @@ -36,10 +36,13 @@ private void created(){ positiveButton.setEnabled(true); negativeButton.setVisibility(View.VISIBLE); - setFragment(new MouseMessageSubdialog(getResources().getString(R.string.mouse_message_calibrate), main)); + setFragment(new MouseMessageSubdialog(getResources().getString(R.string.mouse_message_calibrate))); } - private void next(){ + /** + * Is called when the user wants to go to the next page. + */ + private void next() { dialog.setTitle(R.string.dialog_mouse_calibrate_title_calibrate); if (introduction) { @@ -52,24 +55,33 @@ private void next(){ introduction = false; - setFragment(new SamplingRateSubdialog(main, (r) -> positiveButton.post(this::finished))); - }else dismiss(); + setFragment(new SamplingRateSubdialog((r) -> positiveButton.post(this::finished))); + } else dismiss(); } - private void finished(){ + /** + * Is called when the calibration procedure is finished. + */ + private void finished() { dialog.setTitle(R.string.dialog_mouse_calibrate_title_finished); dialog.setCanceledOnTouchOutside(true); positiveButton.setEnabled(true); - setFragment(new MouseMessageSubdialog(getResources().getString(R.string.dialog_mouse_calibrate_finished), main)); + setFragment(new MouseMessageSubdialog(getResources().getString(R.string.dialog_mouse_calibrate_finished))); } - private void setFragment(CustomFragment fragment){ + /** + * Sets the current dialog fragment that should be displayed. + * + * @param fragment fragment to display + */ + private void setFragment(Fragment fragment) { getChildFragmentManager().beginTransaction().setReorderingAllowed(true).replace(R.id.mouse_container, fragment).commit(); } + @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); @@ -93,5 +105,4 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { return dialog; } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseMessageSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseMessageSubdialog.java index 59f1a4b..56dc026 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseMessageSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseMessageSubdialog.java @@ -1,46 +1,40 @@ package ch.virt.smartphonemouse.ui.mouse; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; import android.os.Bundle; -import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; -import ch.virt.smartphonemouse.ui.settings.dialog.CalibrateFinishedSubdialog; -import ch.virt.smartphonemouse.ui.settings.dialog.SamplingRateSubdialog; -public class MouseMessageSubdialog extends CustomFragment { +/** + * This sub dialog shows some basic information as text to the user. + */ +public class MouseMessageSubdialog extends Fragment { private String message; private TextView messageView; - public MouseMessageSubdialog(String message, MainContext context) { - super(R.layout.subdialog_mouse_message, context); + /** + * Creates the message sub dialog. + * + * @param message message that gets shown + */ + public MouseMessageSubdialog(String message) { + super(R.layout.subdialog_mouse_message); this.message = message; } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - } + messageView = view.findViewById(R.id.mouse_message_message); - @Override - protected void initComponents() { messageView.setText(message); } - - @Override - protected void loadComponents(View view) { - messageView = view.findViewById(R.id.mouse_message_message); - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java index 6693084..e71cd2d 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageDialog.java @@ -10,72 +10,106 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; +/** + * This dialog is shown when the user opens the mouse fragment. It tells the user how to use the mouse. + */ public class MouseUsageDialog extends DialogFragment { private AlertDialog dialog; private Button positiveButton; private int index; - private int maxIndex = 4; - private MainContext main; - private Listener finishedListener; + private UsageFinishedListener finishedListener; - public MouseUsageDialog(MainContext main, Listener finishedListener) { - this.main = main; + + public MouseUsageDialog(UsageFinishedListener finishedListener) { this.finishedListener = finishedListener; } - private void create(){ + /** + * Returns a message to show the user at the given index. + * + * @param index index of the message + * @return resource string id of the message + */ + private int getCurrentMessage(int index) { + + switch (index) { + case 0: + return R.string.dialog_mouse_usage_even; + case 1: + return R.string.dialog_mouse_usage_move; + case 2: + return R.string.dialog_mouse_usage_buttons; + case 3: + return R.string.dialog_mouse_usage_return; + default: + return 0; + } + } + + /** + * Returns how many messages can be displayed. + * + * @return amount of messages + */ + private int getMessageAmount() { + return 4; + } + + + /** + * Is called when the dialog is created. + */ + private void create() { showFragment(); dialog.setCanceledOnTouchOutside(false); } - private void next(){ - if (index == maxIndex) { + /** + * Is called when the user skips to the next page. + */ + private void next() { + if (index == getMessageAmount()) { dismiss(); return; } index++; - if (index == maxIndex) { + if (index == getMessageAmount()) { dialog.setCanceledOnTouchOutside(true); - setFragment(new MouseUsageFinishedSubdialog(main)); + setFragment(new MouseUsageFinishedSubdialog()); - }else showFragment(); + } else showFragment(); } - private void showFragment(){ - setFragment(new MouseMessageSubdialog(getResources().getString(getCurrentMessage(index)), main)); + /** + * Shows a message fragment with the current index. + */ + private void showFragment() { + setFragment(new MouseMessageSubdialog(getResources().getString(getCurrentMessage(index)))); } - public int getCurrentMessage(int index){ - - switch (index) { - case 0: return R.string.dialog_mouse_usage_even; - case 1: return R.string.dialog_mouse_usage_move; - case 2: return R.string.dialog_mouse_usage_buttons; - case 3: return R.string.dialog_mouse_usage_return; - } - - return 0; - - } - - private void setFragment(CustomFragment fragment){ + /** + * Displays a fragment in the respective fragment container. + * + * @param fragment fragment to display + */ + private void setFragment(Fragment fragment) { getChildFragmentManager().beginTransaction().setReorderingAllowed(true).replace(R.id.mouse_container, fragment).commit(); } + + @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); @@ -85,7 +119,7 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { .setPositiveButton(R.string.dialog_mouse_usage_next, null); dialog = builder.create(); - dialog.setTitle(R.string.dialog_mouse_usage_title); // Add default title so it is shown + dialog.setTitle(R.string.dialog_mouse_usage_title); dialog.setOnShowListener(dialogInterface -> { positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); positiveButton.setOnClickListener(view -> next()); @@ -98,8 +132,20 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { @Override public void onDismiss(@NonNull DialogInterface dialog) { - finishedListener.called(); + finishedListener.finished(); super.onDismiss(dialog); } + + + /** + * This interface is a basic listener for when the user has finished reading the instructions. + */ + public interface UsageFinishedListener { + + /** + * Called when the user is finished. + */ + void finished(); + } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java index 611e9d3..105c438 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/mouse/MouseUsageFinishedSubdialog.java @@ -1,40 +1,39 @@ package ch.virt.smartphonemouse.ui.mouse; +import android.os.Bundle; import android.view.View; import android.widget.CheckBox; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class MouseUsageFinishedSubdialog extends CustomFragment { +/** + * This sub dialog is the last page of the usage dialog. It gives the user the option to disable every further usage dialog. + */ +public class MouseUsageFinishedSubdialog extends Fragment { private CheckBox notAgain; - public MouseUsageFinishedSubdialog(MainContext context) { - super(R.layout.subdialog_mouse_usage_finished, context); + /** + * Creates the sub dialog. + */ + public MouseUsageFinishedSubdialog() { + super(R.layout.subdialog_mouse_usage_finished); } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - } + notAgain = view.findViewById(R.id.mouse_usage_finished_notagain); - @Override - protected void initComponents() { notAgain.setChecked(!PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("showUsage", true)); - notAgain.setOnCheckedChangeListener((buttonView, isChecked) -> { - PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putBoolean("showUsage", !isChecked).apply(); - }); - - } - - @Override - protected void loadComponents(View view) { - notAgain = view.findViewById(R.id.mouse_usage_finished_notagain); + notAgain.setOnCheckedChangeListener((buttonView, isChecked) -> PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putBoolean("showUsage", !isChecked).apply()); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java index 515fa2d..6136e16 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/SamplingRateSubdialog.java @@ -1,44 +1,46 @@ package ch.virt.smartphonemouse.ui.settings.dialog; +import android.os.Bundle; import android.view.View; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.customization.SamplingRateCalibrator; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class SamplingRateSubdialog extends CustomFragment { +/** + * This fragment for a dialog is used to handle the calibration of the sampling rate. + */ +public class SamplingRateSubdialog extends Fragment { private TextView time; private SamplingRateCalibrator calibrator; - private final SamplingRateCalibrator.DoneListener doneListener; - public SamplingRateSubdialog(MainContext context, SamplingRateCalibrator.DoneListener doneListener) { - super(R.layout.subdialog_calibrate_samplingrate, context); - this.doneListener = doneListener; + /** + * Creates the sub dialog fragment. + * + * @param doneListener listener that gets called when the calibration process is finished. + */ + public SamplingRateSubdialog(SamplingRateCalibrator.DoneListener doneListener) { + super(R.layout.subdialog_calibrate_samplingrate); - calibrator = new SamplingRateCalibrator(getContext()); //TODO: Will probably produce nullpointer + this.doneListener = doneListener; } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - } - - @Override - protected void initComponents() { + calibrator = new SamplingRateCalibrator(getContext()); - time.setText(getResources().getString(R.string.dialog_calibrate_samplingrate_time, calibrator.getTestLength() / 1000 * 2)); // Double the time, so it is always shorter + time = view.findViewById(R.id.calibrate_samplingrate_time); + time.setText(getResources().getString(R.string.dialog_calibrate_samplingrate_time, calibrator.getTestLength() / 1000)); calibrator.calibrate(doneListener); - - } - - @Override - protected void loadComponents(View view) { - time = view.findViewById(R.id.calibrate_samplingrate_time); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 698b6cc..56c88ef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -96,7 +96,7 @@ Please wait while the app is analyzing the sampling rate of your sensor. Analyzing Sampling Rate Done - This process can take up to %d seconds. + This process will take about %d seconds. The sampling rate for this app was calibrated successfully. Your sensor sampling rate for this device is: %d Samples per Second Finished From 16c87e004acaea998adfab2b50502cb079c8b290 Mon Sep 17 00:00:00 2001 From: Joshua Date: Wed, 8 Sep 2021 22:16:52 +0200 Subject: [PATCH 7/8] more refactoring and javadoc --- .../settings/custom/EditFloatPreference.java | 125 ++++++++++++--- .../custom/EditIntegerPreference.java | 142 ++++++++++++++---- .../settings/custom/SeekFloatPreference.java | 81 +++++++++- .../custom/SeekIntegerPreference.java | 80 +++++++++- 4 files changed, 359 insertions(+), 69 deletions(-) diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditFloatPreference.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditFloatPreference.java index d558cf1..0069e2c 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditFloatPreference.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditFloatPreference.java @@ -9,6 +9,9 @@ import ch.virt.smartphonemouse.R; +/** + * This preference is a preference that opens a dialog and allows you to edit a float. + */ public class EditFloatPreference extends EditTextPreference { private boolean showValueAsDescription; @@ -18,6 +21,14 @@ public class EditFloatPreference extends EditTextPreference { private float value; + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + * @param defStyleRes style resources + */ public EditFloatPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); @@ -30,40 +41,75 @@ public EditFloatPreference(Context context, AttributeSet attrs, int defStyleAttr if (valueUnit == null) valueUnit = ""; if (signed) minimumValue = -maximumValue; - if (showValueAsDescription) setSummaryProvider(preference -> EditFloatPreference.this.getSummary()); + if (showValueAsDescription) + setSummaryProvider(preference -> EditFloatPreference.this.getSummary()); setOnBindEditTextListener(editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | (signed ? InputType.TYPE_NUMBER_FLAG_SIGNED : 0x00))); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + */ public EditFloatPreference(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + */ public EditFloatPreference(Context context, AttributeSet attrs) { this(context, attrs, R.attr.editTextPreferenceStyle); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + */ public EditFloatPreference(Context context) { this(context, null); } - @Override - public CharSequence getSummary() { - return showValueAsDescription ? value + " " + valueUnit : super.getSummary(); - } + /** + * Returns the unit that is displayed to the user. + * + * @return unit of the value + */ public String getValueUnit() { return valueUnit; } + /** + * Sets the unit that is displayed to the user. + * + * @param valueUnit unit of the entered value + */ public void setValueUnit(String valueUnit) { this.valueUnit = valueUnit; } + /** + * Returns the value of the preference. + * + * @return value + */ public float getValue() { return value; } + /** + * Sets the value of the preference. + * + * @param value value + */ public void setValue(float value) { final boolean wasBlocking = shouldDisableDependents(); @@ -79,6 +125,55 @@ public void setValue(float value) { notifyChanged(); } + /** + * Returns the minimum value that may be entered. + * + * @return minimum value + */ + public float getMinimumValue() { + return minimumValue; + } + + /** + * Sets the minimum value that may be entered. + * + * @param minimumValue minimum value + */ + public void setMinimumValue(float minimumValue) { + this.minimumValue = minimumValue; + } + + /** + * Returns the maximum value may be entered. + * + * @return maximum value + */ + public float getMaximumValue() { + return maximumValue; + } + + /** + * Sets the maximum value that may be entered. + * + * @param maximumValue of the preference to be set + */ + public void setMaximumValue(float maximumValue) { + this.maximumValue = maximumValue; + } + + /** + * Updates the contained value from the preference storage. + */ + public void update() { + setValue(getPersistedFloat(minimumValue)); + } + + + @Override + public CharSequence getSummary() { + return showValueAsDescription ? value + " " + valueUnit : super.getSummary(); + } + @Override public String getText() { return Float.toString(getValue()); @@ -98,24 +193,4 @@ public boolean shouldDisableDependents() { protected void onSetInitialValue(Object defaultValue) { setValue(getPersistedFloat(defaultValue == null ? 0 : (Float) defaultValue)); } - - public float getMinimumValue() { - return minimumValue; - } - - public void setMinimumValue(float minimumValue) { - this.minimumValue = minimumValue; - } - - public float getMaximumValue() { - return maximumValue; - } - - public void setMaximumValue(float maximumValue) { - this.maximumValue = maximumValue; - } - - public void update(){ - setValue(getPersistedFloat(minimumValue)); - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditIntegerPreference.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditIntegerPreference.java index c384502..b9f7817 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditIntegerPreference.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/EditIntegerPreference.java @@ -4,16 +4,14 @@ import android.content.res.TypedArray; import android.text.InputType; import android.util.AttributeSet; -import android.widget.EditText; -import androidx.annotation.NonNull; -import androidx.core.content.res.TypedArrayUtils; -import androidx.preference.DialogPreference; import androidx.preference.EditTextPreference; -import androidx.preference.Preference; import ch.virt.smartphonemouse.R; +/** + * This is a preference that opens a dialog for the user to set a integer value. + */ public class EditIntegerPreference extends EditTextPreference { private boolean showValueAsDescription; @@ -23,6 +21,14 @@ public class EditIntegerPreference extends EditTextPreference { private int value; + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + * @param defStyleRes style resources + */ public EditIntegerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); @@ -35,48 +41,93 @@ public EditIntegerPreference(Context context, AttributeSet attrs, int defStyleAt if (valueUnit == null) valueUnit = ""; if (signed) minimumValue = -maximumValue; - if (showValueAsDescription) setSummaryProvider(preference -> EditIntegerPreference.this.getSummary()); + if (showValueAsDescription) + setSummaryProvider(preference -> EditIntegerPreference.this.getSummary()); setOnBindEditTextListener(editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER | (signed ? InputType.TYPE_NUMBER_FLAG_SIGNED : 0x00))); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + */ public EditIntegerPreference(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + */ public EditIntegerPreference(Context context, AttributeSet attrs) { this(context, attrs, R.attr.editTextPreferenceStyle); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + */ public EditIntegerPreference(Context context) { this(context, null); } + + /** + * Whether the value should be shown as description. + * + * @return is shown + */ public boolean isShowValueAsDescription() { return showValueAsDescription; } + /** + * Sets whether the value should be shown as the description of the preference. + * + * @param showValueAsDescription sets whether it should be shown as a description + */ public void setShowValueAsDescription(boolean showValueAsDescription) { this.showValueAsDescription = showValueAsDescription; } - @Override - public CharSequence getSummary() { - return showValueAsDescription ? value + " " + valueUnit : super.getSummary(); - } - + /** + * Returns the unit of the value of the preference. + * + * @return value unit + */ public String getValueUnit() { return valueUnit; } + /** + * Sets the unit of the value of the preference. + * + * @param valueUnit unit of the value + */ public void setValueUnit(String valueUnit) { this.valueUnit = valueUnit; } + /** + * Returns the value of the preference. + * + * @return value of the preference + */ public int getValue() { return value; } + /** + * Sets the value of the preference. + * + * @param value value of the preference + */ public void setValue(int value) { final boolean wasBlocking = shouldDisableDependents(); @@ -92,6 +143,55 @@ public void setValue(int value) { notifyChanged(); } + /** + * Returns the minimum value of the preference. + * + * @return minimum value + */ + public int getMinimumValue() { + return minimumValue; + } + + /** + * Sets the minimum value that may be entered to the preference. + * + * @param minimumValue minimum value + */ + public void setMinimumValue(int minimumValue) { + this.minimumValue = minimumValue; + } + + /** + * Returns the maximum value of the preference. + * + * @return maximum value + */ + public int getMaximumValue() { + return maximumValue; + } + + /** + * Sets the maximum value that may be entered to the preference. + * + * @param maximumValue maximum value + */ + public void setMaximumValue(int maximumValue) { + this.maximumValue = maximumValue; + } + + /** + * Updates the preference to the current stored value. + */ + public void update() { + setValue(getPersistedInt(minimumValue)); + } + + + @Override + public CharSequence getSummary() { + return showValueAsDescription ? value + " " + valueUnit : super.getSummary(); + } + @Override public String getText() { return Integer.toString(getValue()); @@ -111,24 +211,4 @@ public boolean shouldDisableDependents() { protected void onSetInitialValue(Object defaultValue) { setValue(getPersistedInt(defaultValue == null ? 0 : (Integer) defaultValue)); } - - public int getMinimumValue() { - return minimumValue; - } - - public void setMinimumValue(int minimumValue) { - this.minimumValue = minimumValue; - } - - public int getMaximumValue() { - return maximumValue; - } - - public void setMaximumValue(int maximumValue) { - this.maximumValue = maximumValue; - } - - public void update(){ - setValue(getPersistedInt(minimumValue)); - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekFloatPreference.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekFloatPreference.java index e1c2da0..a5ebdd3 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekFloatPreference.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekFloatPreference.java @@ -3,17 +3,27 @@ import android.content.Context; import android.util.AttributeSet; -import androidx.preference.Preference; import androidx.preference.SeekBarPreference; import ch.virt.smartphonemouse.R; +/** + * This is a Seek Bar preference that stores a float. + */ public class SeekFloatPreference extends SeekBarPreference { private float maximum; private float minimum; private int steps; + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + * @param defStyleRes style resources + */ public SeekFloatPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); @@ -23,38 +33,87 @@ public SeekFloatPreference(Context context, AttributeSet attrs, int defStyleAttr } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + */ public SeekFloatPreference(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + */ public SeekFloatPreference(Context context, AttributeSet attrs) { this(context, attrs, R.attr.seekBarPreferenceStyle); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + */ public SeekFloatPreference(Context context) { this(context, null); } + + /** + * Returns the maximum value of the preference. + * + * @return maximum value + */ public float getMaximum() { return maximum; } + /** + * Sets the maximum value of the preference. + * + * @param maximum maximum value + */ public void setMaximum(float maximum) { this.maximum = maximum; } + /** + * Returns the minimum value of the preference. + * + * @return minimum value + */ public float getMinimum() { return minimum; } + /** + * Sets the minimum value of the preference. + * + * @param minimum minimum value + */ public void setMinimum(float minimum) { this.minimum = minimum; } + /** + * Returns how many steps are present on the progress bar. + * + * @return steps on the bar + */ public int getSteps() { return steps; } + /** + * Sets the steps present on the progress bar. + * + * @param steps steps on the bar + */ public void setSteps(int steps) { this.steps = steps; @@ -62,10 +121,23 @@ public void setSteps(int steps) { setMax(steps); } - public float getRealValue(){ + /** + * Returns the real value that the preference holds. Use this instead of getValue. + * + * @return value + */ + public float getRealValue() { return (getValue() / ((float) steps) * (maximum - minimum) + minimum); } + /** + * Updates the preference to the values stored in the storage. + */ + public void update() { + onSetInitialValue(null); + } + + @Override protected boolean persistInt(int value) { // Have to use persistence methods, because otherwise, the variables are not accessible enough @@ -77,9 +149,4 @@ protected int getPersistedInt(int defaultReturnValue) { // Have to use persistence methods, because otherwise, the variables are not accessible enough return (int) ((super.getPersistedFloat(minimum) - minimum) / (maximum - minimum) * steps); } - - public void update(){ - onSetInitialValue(null); - } - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekIntegerPreference.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekIntegerPreference.java index 09423bc..8cfbcfa 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekIntegerPreference.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/custom/SeekIntegerPreference.java @@ -3,17 +3,27 @@ import android.content.Context; import android.util.AttributeSet; -import androidx.preference.Preference; import androidx.preference.SeekBarPreference; import ch.virt.smartphonemouse.R; +/** + * This preference is a seek bar preference that does seek for integers but is + */ public class SeekIntegerPreference extends SeekBarPreference { private int maximum; private int minimum; private int steps; + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + * @param defStyleRes style resources + */ public SeekIntegerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); @@ -23,38 +33,87 @@ public SeekIntegerPreference(Context context, AttributeSet attrs, int defStyleAt } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + * @param defStyleAttr style attributes + */ public SeekIntegerPreference(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } + /** + * Creates a preference. + * + * @param context context for the preference to be in + * @param attrs attributes + */ public SeekIntegerPreference(Context context, AttributeSet attrs) { this(context, attrs, R.attr.seekBarPreferenceStyle); } + + /** + * Creates a preference. + * + * @param context context for the preference to be in + */ public SeekIntegerPreference(Context context) { this(context, null); } + /** + * Returns the maximum value of the preference. + * + * @return maximum value + */ public int getMaximum() { return maximum; } + /** + * Sets the maximum value of the preference. + * + * @param maximum maximum value. + */ public void setMaximum(int maximum) { this.maximum = maximum; } + /** + * Returns the minimum value of the preference. + * + * @return minimum value + */ public int getMinimum() { return minimum; } + /** + * Sets the minimum value of the reference + * + * @param minimum minimum value + */ public void setMinimum(int minimum) { this.minimum = minimum; } + /** + * Returns the steps the seek bar can be in. + * + * @return amount of steps + */ public int getSteps() { return steps; } + /** + * Sets the steps the seek bar can be positioned in. + * + * @param steps amount of steps + */ public void setSteps(int steps) { this.steps = steps; @@ -62,10 +121,23 @@ public void setSteps(int steps) { setMax(steps); } - public int getRealValue(){ + /** + * Returns the real value of the preference. Use this instead of realValue. + * + * @return value of the preference + */ + public int getRealValue() { return (int) (getValue() / ((float) steps) * (maximum - minimum) + minimum); } + /** + * Updates the preference to the stored value. + */ + public void update() { + onSetInitialValue(null); + } + + @Override protected boolean persistInt(int value) { // Have to use persistence methods, because otherwise, the variables are not accessible enough @@ -77,8 +149,4 @@ protected int getPersistedInt(int defaultReturnValue) { // Have to use persistence methods, because otherwise, the variables are not accessible enough return (int) ((super.getPersistedInt(minimum) - minimum) / ((float) (maximum - minimum)) * steps); } - - public void update(){ - onSetInitialValue(null); - } } From 894331e434a65849dada0a7678b10f8719d48304 Mon Sep 17 00:00:00 2001 From: Joshua Date: Sun, 12 Sep 2021 20:51:02 +0200 Subject: [PATCH 8/8] Final Refactoring and Javadoc --- .../ch/virt/smartphonemouse/MainActivity.java | 244 +++++++++--------- .../virt/smartphonemouse/helper/Listener.java | 5 - .../smartphonemouse/helper/MainContext.java | 5 - .../helper/ResultListener.java | 5 - .../smartphonemouse/ui/AboutFragment.java | 35 +-- .../smartphonemouse/ui/ConnectFragment.java | 75 ++++-- .../smartphonemouse/ui/CustomFragment.java | 38 --- .../smartphonemouse/ui/DebugFragment.java | 57 ++-- .../virt/smartphonemouse/ui/HomeFragment.java | 50 +++- .../smartphonemouse/ui/MouseFragment.java | 147 ++++++----- .../smartphonemouse/ui/SettingsFragment.java | 39 +-- .../ui/settings/CustomSettingsFragment.java | 14 - .../SettingsCommunicationSubfragment.java | 40 +-- .../SettingsInterfaceSubfragment.java | 5 +- .../settings/SettingsMovementSubfragment.java | 15 +- .../ui/settings/dialog/CalibrateDialog.java | 54 ++-- .../dialog/CalibrateFinishedSubdialog.java | 33 +-- 17 files changed, 460 insertions(+), 401 deletions(-) delete mode 100644 app/src/main/java/ch/virt/smartphonemouse/helper/Listener.java delete mode 100644 app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java delete mode 100644 app/src/main/java/ch/virt/smartphonemouse/helper/ResultListener.java delete mode 100644 app/src/main/java/ch/virt/smartphonemouse/ui/CustomFragment.java delete mode 100644 app/src/main/java/ch/virt/smartphonemouse/ui/settings/CustomSettingsFragment.java diff --git a/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java b/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java index e744772..5d306c8 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java +++ b/app/src/main/java/ch/virt/smartphonemouse/MainActivity.java @@ -18,28 +18,26 @@ import com.google.android.material.navigation.NavigationView; import ch.virt.smartphonemouse.customization.DefaultSettings; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.mouse.MouseInputs; import ch.virt.smartphonemouse.mouse.MovementHandler; import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.ui.AboutFragment; import ch.virt.smartphonemouse.ui.ConnectFragment; -import ch.virt.smartphonemouse.ui.CustomFragment; import ch.virt.smartphonemouse.ui.DebugFragment; import ch.virt.smartphonemouse.ui.HomeFragment; import ch.virt.smartphonemouse.ui.MouseFragment; import ch.virt.smartphonemouse.ui.SettingsFragment; import ch.virt.smartphonemouse.ui.mouse.MouseCalibrateDialog; -import ch.virt.smartphonemouse.ui.settings.CustomSettingsFragment; +/** + * This class is the main activity of this app. + */ public class MainActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { private MaterialToolbar bar; private DrawerLayout drawerLayout; private NavigationView drawer; - private MainContext mainContext; - private BluetoothHandler bluetooth; private MovementHandler movement; @@ -47,14 +45,14 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen private boolean mouseActive; - private boolean instanceSaved = false; + private boolean instanceSaved = false; // Used to avoid ui changes if the activity is not rendered. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - DefaultSettings.check(PreferenceManager.getDefaultSharedPreferences(this)); + DefaultSettings.check(PreferenceManager.getDefaultSharedPreferences(this)); // Check whether new settings must be restored loadComponents(); setupNavigation(); @@ -63,66 +61,11 @@ protected void onCreate(Bundle savedInstanceState) { navigate(R.id.drawer_home); drawer.setCheckedItem(R.id.drawer_home); - } - @Override - protected void onStart() { - super.onStart(); - instanceSaved = false; - - bluetooth.reInit(); - reRender(); - } - - /** - * Loads the contents of the app - */ - private void loadContent() { - mainContext = new MainContext() { - - }; - - bluetooth = new BluetoothHandler(this); - - inputs = new MouseInputs(bluetooth, this); - - movement = new MovementHandler(this, inputs); - - checkNavItems(); - } - - public void updateBluetoothStatus(){ - reRender(); - } - - public MainContext getMainContext() { - return mainContext; - } - - /** - * Switches the Fragment displayed on the app - * - * @param fragment fragment that is displayed - * @param stack whether that fragment should be added to the back stack - */ - private void switchFragment(Fragment fragment, boolean stack) { - Fragment current = getCurrentFragment(); - if (current instanceof CustomFragment) ((CustomFragment) current).restore(); - - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - - if (stack) transaction.addToBackStack(null); - transaction.setReorderingAllowed(true); - transaction.replace(R.id.container, fragment); - - transaction.commit(); - - } - /** - * Loads the UI Components into their variables + * Loads the components into their variables. */ private void loadComponents() { drawerLayout = findViewById(R.id.drawer_layout); @@ -131,7 +74,7 @@ private void loadComponents() { } /** - * Sets the navigation up so it is ready to be used + * Sets the navigation up so it is ready to be used. */ private void setupNavigation() { bar.setNavigationOnClickListener(v -> drawerLayout.open()); @@ -147,7 +90,8 @@ private void setupNavigation() { drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() { @Override - public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { } + public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { + } @Override public void onDrawerOpened(@NonNull View drawerView) { @@ -155,31 +99,84 @@ public void onDrawerOpened(@NonNull View drawerView) { } @Override - public void onDrawerClosed(@NonNull View drawerView) { } + public void onDrawerClosed(@NonNull View drawerView) { + } + @Override - public void onDrawerStateChanged(int newState) { } + public void onDrawerStateChanged(int newState) { + } }); } /** - * Rerenders the current fragment + * Sets the correct state of the nav items in the nav drawer. */ - public void reRender() { - if (instanceSaved) return; // Do not re render if not saved - if (getCurrentFragment() != null) { - if (getCurrentFragment() instanceof CustomFragment) this.runOnUiThread(() -> ((CustomFragment) getCurrentFragment()).render()); + private void checkNavItems() { + if (bluetooth.isSupported()) { + setNavItemEnable(R.id.drawer_connect, true); + setNavItemEnable(R.id.drawer_mouse, bluetooth.isConnected()); + } else { + setNavItemEnable(R.id.drawer_connect, false); + setNavItemEnable(R.id.drawer_mouse, false); } - this.runOnUiThread(() -> { - if (!bluetooth.isSupported() && (getCurrentFragment() instanceof MouseFragment || getCurrentFragment() instanceof ConnectFragment)) { - navigate(R.id.drawer_home); - } - else if (!bluetooth.isConnected() && getCurrentFragment() instanceof MouseFragment) navigate(R.id.drawer_connect); + drawer.getMenu().findItem(R.id.drawer_debug).setVisible(PreferenceManager.getDefaultSharedPreferences(this).getBoolean("debugEnabled", false)); + } + + /** + * Enables / disables a certain nav item. + * + * @param item item to change + * @param enable enabled state + */ + private void setNavItemEnable(int item, boolean enable) { + drawer.getMenu().findItem(item).setEnabled(enable); + } + + + /** + * Loads the contents of the app + */ + private void loadContent() { + + bluetooth = new BluetoothHandler(this); + + inputs = new MouseInputs(bluetooth, this); - checkNavItems(); + movement = new MovementHandler(this, inputs); + } + + /** + * Updates the bluetooth status. + */ + public void updateBluetoothStatus() { + if (instanceSaved || getCurrentFragment() == null) return; + + if (getCurrentFragment() instanceof ConnectFragment || getCurrentFragment() instanceof MouseFragment) { + if (!bluetooth.isEnabled() || !bluetooth.isSupported()) navigate(R.id.drawer_home); + else if (!bluetooth.isConnected() && getCurrentFragment() instanceof MouseFragment) + navigate(R.id.drawer_connect); + } + + this.runOnUiThread(() -> { + if (getCurrentFragment() instanceof HomeFragment) + ((HomeFragment) getCurrentFragment()).update(); + else if (getCurrentFragment() instanceof ConnectFragment) + ((ConnectFragment) getCurrentFragment()).update(); }); } + + + @Override + protected void onStart() { + super.onStart(); + instanceSaved = false; + + bluetooth.reInit(); + updateBluetoothStatus(); // Current status is unknown + } + @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); @@ -190,33 +187,19 @@ protected void onSaveInstanceState(@NonNull Bundle outState) { protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); instanceSaved = false; - reRender(); + updateBluetoothStatus(); // Current status is unknown } - private void checkNavItems(){ - if (bluetooth.isSupported()) { - setNavItemEnable(R.id.drawer_connect, true); - setNavItemEnable(R.id.drawer_mouse, bluetooth.isConnected()); - } else { - setNavItemEnable(R.id.drawer_connect, false); - setNavItemEnable(R.id.drawer_mouse, false); - } - - drawer.getMenu().findItem(R.id.drawer_debug).setVisible(PreferenceManager.getDefaultSharedPreferences(this).getBoolean("debugEnabled", false)); - } - - private void setNavItemEnable(int item, boolean enable){ - drawer.getMenu().findItem(item).setEnabled(enable); - } + /** - * Navigates to the respective sites + * Navigates to the respective sites. * * @param entry entry to navigate to * @return whether that entry is navigated */ public boolean navigate(int entry) { - if (entry == R.id.drawer_mouse){ + if (entry == R.id.drawer_mouse) { if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean("movementSamplingCalibrated", false)) { // Make sure that the sampling rate is calibrated @@ -227,7 +210,7 @@ public boolean navigate(int entry) { } bar.setVisibility(View.GONE); - switchFragment(new MouseFragment(mainContext, inputs, movement), false); + switchFragment(new MouseFragment(inputs, movement), false); mouseActive = true; @@ -235,7 +218,7 @@ public boolean navigate(int entry) { movement.register(); inputs.start(); - }else { + } else { bar.setVisibility(View.VISIBLE); if (mouseActive) { @@ -247,34 +230,34 @@ public boolean navigate(int entry) { switch (entry) { case R.id.drawer_connect: - switchFragment(new ConnectFragment(mainContext, bluetooth), false); + switchFragment(new ConnectFragment(bluetooth), false); bar.setTitle(R.string.title_connect); break; case R.id.drawer_home: - switchFragment(new HomeFragment(bluetooth, mainContext), false); + switchFragment(new HomeFragment(bluetooth), false); bar.setTitle(R.string.title_home); break; case R.id.drawer_settings: - switchFragment(new SettingsFragment(mainContext), false); + switchFragment(new SettingsFragment(), false); bar.setTitle(R.string.title_settings); break; case R.id.drawer_about: - switchFragment(new AboutFragment(mainContext), false); + switchFragment(new AboutFragment(), false); bar.setTitle(R.string.title_about); break; case R.id.drawer_debug: - switchFragment(new DebugFragment(mainContext), false); + switchFragment(new DebugFragment(), false); bar.setTitle(R.string.title_debug); bar.setVisibility(View.GONE); break; @@ -289,37 +272,58 @@ public boolean navigate(int entry) { return true; } - @Override - public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) { - final Bundle args = pref.getExtras(); - final Fragment fragment = getSupportFragmentManager().getFragmentFactory().instantiate( - getClassLoader(), - pref.getFragment()); - fragment.setArguments(args); - fragment.setTargetFragment(caller, 0); + /** + * Switches the Fragment displayed on the app. + * + * @param fragment fragment that is displayed + * @param stack whether that fragment should be added to the back stack + */ + private void switchFragment(Fragment fragment, boolean stack) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - if (fragment instanceof CustomSettingsFragment) ((CustomSettingsFragment) fragment).setMain(mainContext); + if (stack) transaction.addToBackStack(null); + transaction.setReorderingAllowed(true); + transaction.replace(R.id.container, fragment); - switchFragment(fragment, true); + transaction.commit(); - return true; } + /** + * Returns the currently shown fragment. + * + * @return currently shown fragment + */ @Nullable - private Fragment getCurrentFragment(){ + private Fragment getCurrentFragment() { return getSupportFragmentManager().findFragmentById(R.id.container); } @Override public void onBackPressed() { - if (getSupportFragmentManager().getBackStackEntryCount() > 0) super.onBackPressed(); // If something is on the backstack proceed + if (getSupportFragmentManager().getBackStackEntryCount() > 0) + super.onBackPressed(); // If something is on the backstack proceed else { if (!(getCurrentFragment() instanceof HomeFragment)) { // Navigate to home if not in sub fragment and not in home - if (!(getCurrentFragment() instanceof MouseFragment)) navigate(R.id.drawer_home); // Make exception for mouse fragment - } - - else super.onBackPressed(); + if (!(getCurrentFragment() instanceof MouseFragment)) + navigate(R.id.drawer_home); // Make exception for mouse fragment + } else super.onBackPressed(); } } + + + @Override + public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) { + final Bundle args = pref.getExtras(); + final Fragment fragment = getSupportFragmentManager().getFragmentFactory().instantiate( + getClassLoader(), + pref.getFragment()); + fragment.setArguments(args); + fragment.setTargetFragment(caller, 0); + + switchFragment(fragment, true); + + return true; + } } \ No newline at end of file diff --git a/app/src/main/java/ch/virt/smartphonemouse/helper/Listener.java b/app/src/main/java/ch/virt/smartphonemouse/helper/Listener.java deleted file mode 100644 index 1100e0b..0000000 --- a/app/src/main/java/ch/virt/smartphonemouse/helper/Listener.java +++ /dev/null @@ -1,5 +0,0 @@ -package ch.virt.smartphonemouse.helper; - -public interface Listener { - void called(); -} diff --git a/app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java b/app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java deleted file mode 100644 index f15a4d8..0000000 --- a/app/src/main/java/ch/virt/smartphonemouse/helper/MainContext.java +++ /dev/null @@ -1,5 +0,0 @@ -package ch.virt.smartphonemouse.helper; - -public interface MainContext { - -} diff --git a/app/src/main/java/ch/virt/smartphonemouse/helper/ResultListener.java b/app/src/main/java/ch/virt/smartphonemouse/helper/ResultListener.java deleted file mode 100644 index 810b6e4..0000000 --- a/app/src/main/java/ch/virt/smartphonemouse/helper/ResultListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package ch.virt.smartphonemouse.helper; - -public interface ResultListener { - void result(int result); -} diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/AboutFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/AboutFragment.java index 0c0a889..547bbe3 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/AboutFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/AboutFragment.java @@ -1,34 +1,35 @@ package ch.virt.smartphonemouse.ui; -import android.text.Html; +import android.os.Bundle; import android.text.method.LinkMovementMethod; import android.view.View; -import android.widget.EditText; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -public class AboutFragment extends CustomFragment{ +/** + * This fragment shows information about the app in general. + */ +public class AboutFragment extends Fragment { - TextView aboutGithub; + private TextView aboutGithub; - public AboutFragment(MainContext context) { - super(R.layout.fragment_about, context); + /** + * Creates the fragment. + */ + public AboutFragment() { + super(R.layout.fragment_about); } @Override - public void render() { - - } + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - @Override - protected void initComponents() { - aboutGithub.setMovementMethod(LinkMovementMethod.getInstance()); - } - - @Override - protected void loadComponents(View view) { aboutGithub = view.findViewById(R.id.about_github); + aboutGithub.setMovementMethod(LinkMovementMethod.getInstance()); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java index ddc1960..2506269 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/ConnectFragment.java @@ -1,69 +1,100 @@ package ch.virt.smartphonemouse.ui; import android.graphics.drawable.GradientDrawable; +import android.os.Bundle; import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.ui.connect.ConnectConnectedSubfragment; import ch.virt.smartphonemouse.ui.connect.ConnectConnectingSubfragment; import ch.virt.smartphonemouse.ui.connect.ConnectFailedSubfragment; import ch.virt.smartphonemouse.ui.connect.ConnectSelectSubfragment; -public class ConnectFragment extends CustomFragment { +/** + * This fragment allows the user to see the current connection status and to change it. + */ +public class ConnectFragment extends Fragment { private ImageView status; private TextView statusText; private BluetoothHandler bluetooth; - public ConnectFragment(MainContext main, BluetoothHandler bluetooth){ - super(R.layout.fragment_connect, main); + /** + * Creates the fragment. + * + * @param bluetooth bluetooth handler used for bluetooth operations + */ + public ConnectFragment(BluetoothHandler bluetooth) { + super(R.layout.fragment_connect); this.bluetooth = bluetooth; } @Override - public void render() { - if (bluetooth.isInitialized()){ + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + status = view.findViewById(R.id.connect_status); + statusText = view.findViewById(R.id.connect_status_text); + + update(); + } + + /** + * Updates the content on the page according to the current status. + */ + public void update() { + if (bluetooth.isInitialized()) { if (bluetooth.isConnecting()) { + loadFragment(new ConnectConnectingSubfragment()); setStatus(R.color.status_connecting, R.string.connect_status_connecting); - } - else if (!bluetooth.isConnected()){ - if (bluetooth.getHost().hasFailed()){ + + } else if (!bluetooth.isConnected()) { + + if (bluetooth.getHost().hasFailed()) { + ConnectFailedSubfragment fragment = new ConnectFailedSubfragment(bluetooth); - fragment.setReturnListener(this::render); + fragment.setReturnListener(this::update); // Updates the fragment when going back loadFragment(fragment); - } - else loadFragment(new ConnectSelectSubfragment(bluetooth)); + + } else loadFragment(new ConnectSelectSubfragment(bluetooth)); setStatus(R.color.status_disconnected, R.string.connect_status_disconnected); - } - else{ + } else { + loadFragment(new ConnectConnectedSubfragment(bluetooth)); setStatus(R.color.status_connected, R.string.connect_status_connected); + } } } - @Override - protected void loadComponents(View view) { - status = view.findViewById(R.id.connect_status); - statusText = view.findViewById(R.id.connect_status_text); - } - - private void setStatus(int color, int text){ + /** + * Sets the status of the page. + * + * @param color color of the current status + * @param text name of the current status + */ + private void setStatus(int color, int text) { ((GradientDrawable) status.getBackground()).setColor(getResources().getColor(color, null)); statusText.setText(text); } - private void loadFragment(Fragment fragment){ + /** + * Sets the inner content to the requested fragment. + * + * @param fragment fragment to set to + */ + private void loadFragment(Fragment fragment) { getChildFragmentManager().beginTransaction().setReorderingAllowed(true).replace(R.id.connect_container, fragment).commit(); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/CustomFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/CustomFragment.java deleted file mode 100644 index 331d630..0000000 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/CustomFragment.java +++ /dev/null @@ -1,38 +0,0 @@ -package ch.virt.smartphonemouse.ui; - -import android.os.Bundle; -import android.view.View; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; - -import ch.virt.smartphonemouse.helper.MainContext; - -public abstract class CustomFragment extends Fragment { - - protected MainContext main; - - public CustomFragment(int contentLayoutId, MainContext context) { - super(contentLayoutId); - this.main = context; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - loadComponents(view); - initComponents(); - - render(); - } - - public abstract void render(); - - protected abstract void loadComponents(View view); - - protected void initComponents(){} - - public void restore(){} -} diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/DebugFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/DebugFragment.java index 77f8264..af8282e 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/DebugFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/DebugFragment.java @@ -12,6 +12,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; import com.jjoe64.graphview.GraphView; @@ -19,28 +20,35 @@ import java.io.IOException; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.ui.debug.DebugChartSheet; import ch.virt.smartphonemouse.ui.debug.handling.DebugChartHandler; import ch.virt.smartphonemouse.ui.debug.handling.DebugCsvExporter; import ch.virt.smartphonemouse.ui.debug.handling.DebugDataHandler; -public class DebugFragment extends CustomFragment{ +/** + * This fragment represents the debug page, which can be used to analyse the algorithms behaviour more closely. + */ +public class DebugFragment extends Fragment { - GraphView chart; + private GraphView chart; - ImageView buttonPlay, buttonClear, buttonRenew, buttonSeries, buttonExport; + private ImageView buttonPlay, buttonClear, buttonRenew, buttonSeries, buttonExport; - DebugChartHandler chartHandler; - DebugDataHandler dataHandler; + private DebugChartHandler chartHandler; + private DebugDataHandler dataHandler; - public DebugFragment(MainContext context) { - super(R.layout.fragment_debug, context); + /** + * Creates the fragment. + */ + public DebugFragment() { + super(R.layout.fragment_debug); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + // Sets the app in landscape mode if(getActivity().getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); if(getActivity().getWindow().getDecorView().getSystemUiVisibility() != View.SYSTEM_UI_FLAG_FULLSCREEN) getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); @@ -49,6 +57,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c @Override public void onDestroyView() { + + // Reverts the app back to portrait mode if(getActivity().getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); if(getActivity().getWindow().getDecorView().getSystemUiVisibility() != View.SYSTEM_UI_FLAG_VISIBLE) getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); @@ -56,13 +66,26 @@ public void onDestroyView() { } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + chart = view.findViewById(R.id.debug_chart); + buttonPlay = view.findViewById(R.id.debug_button_play); + buttonClear = view.findViewById(R.id.debug_button_clear); + buttonRenew = view.findViewById(R.id.debug_button_renew); + buttonSeries = view.findViewById(R.id.debug_button_series); + buttonExport = view.findViewById(R.id.debug_button_export); + + initialize(); } - @Override - protected void initComponents() { + /** + * Initializes everything. + */ + private void initialize(){ + // Initializes chart chartHandler = new DebugChartHandler(chart, PreferenceManager.getDefaultSharedPreferences(getContext())); dataHandler = new DebugDataHandler((SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE), chartHandler, PreferenceManager.getDefaultSharedPreferences(getContext())); @@ -79,6 +102,7 @@ protected void initComponents() { chartHandler.addSeries("Cached Distance", 10); chartHandler.addSeries("Final Distance", 11); + // Initializes buttons buttonSeries.setOnClickListener(v -> { DebugChartSheet chartSheet = new DebugChartSheet(chartHandler, dataHandler); chartSheet.show(getParentFragmentManager(), "debugChartSheet"); @@ -111,15 +135,4 @@ protected void initComponents() { } }); } - - @Override - protected void loadComponents(View view) { - chart = view.findViewById(R.id.debug_chart); - - buttonPlay = view.findViewById(R.id.debug_button_play); - buttonClear = view.findViewById(R.id.debug_button_clear); - buttonRenew = view.findViewById(R.id.debug_button_renew); - buttonSeries = view.findViewById(R.id.debug_button_series); - buttonExport = view.findViewById(R.id.debug_button_export); - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java index 4e2c63b..4593ab7 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/HomeFragment.java @@ -1,23 +1,28 @@ package ch.virt.smartphonemouse.ui; import android.graphics.drawable.GradientDrawable; +import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.MainActivity; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.transmission.BluetoothHandler; import ch.virt.smartphonemouse.ui.home.HomeConnectedSubfragment; import ch.virt.smartphonemouse.ui.home.HomeDisabledSubfragment; import ch.virt.smartphonemouse.ui.home.HomeDisconnectedSubfragment; import ch.virt.smartphonemouse.ui.home.HomeUnsupportedSubfragment; -public class HomeFragment extends CustomFragment { +/** + * This fragment contains the home page of the app, which shows basic information. + */ +public class HomeFragment extends Fragment { private BluetoothHandler bluetooth; @@ -26,14 +31,32 @@ public class HomeFragment extends CustomFragment { private Button button; - public HomeFragment(BluetoothHandler bluetooth, MainContext mainContext) { - super(R.layout.fragment_home, mainContext); + /** + * Creates the fragment. + * + * @param bluetooth bluetooth handler to use + */ + public HomeFragment(BluetoothHandler bluetooth) { + super(R.layout.fragment_home); this.bluetooth = bluetooth; } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + status = view.findViewById(R.id.home_status); + statusText = view.findViewById(R.id.home_status_text); + button = view.findViewById(R.id.home_button); + + update(); + } + + /** + * Updates the content of the page according to the current status. + */ + public void update() { if (bluetooth.isInitialized()) if (!bluetooth.isEnabled()) @@ -49,13 +72,16 @@ else if (bluetooth.isConnected()) setStatus(R.color.status_disconnected, R.string.home_status_disconnected, R.string.home_button_disconnected, v -> ((MainActivity) getActivity()).navigate(R.id.drawer_connect), new HomeDisconnectedSubfragment()); } - protected void loadComponents(View view){ - status = view.findViewById(R.id.home_status); - statusText = view.findViewById(R.id.home_status_text); - button = view.findViewById(R.id.home_button); - } - - private void setStatus(int statusColor, int statusText, int buttonText, View.OnClickListener buttonListener, Fragment fragment){ + /** + * Sets the status of the page. + * + * @param statusColor color of the status + * @param statusText name of the status + * @param buttonText text of the primary button of this status + * @param buttonListener action of the primary button of this status + * @param fragment fragment to be displayed + */ + private void setStatus(int statusColor, int statusText, int buttonText, View.OnClickListener buttonListener, Fragment fragment) { ((GradientDrawable) status.getBackground()).setColor(getResources().getColor(statusColor, null)); this.statusText.setText(statusText); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java index 2e34a8d..e5660f9 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/MouseFragment.java @@ -5,27 +5,32 @@ import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.os.Build; +import android.os.Bundle; import android.os.VibrationEffect; import android.os.Vibrator; +import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.RelativeLayout; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; import ch.virt.smartphonemouse.mouse.MouseInputs; import ch.virt.smartphonemouse.mouse.MovementHandler; import ch.virt.smartphonemouse.ui.mouse.MouseUsageDialog; /** - * This fragment represents the mouse interface the user uses to input button strokes + * This fragment represents the mouse interface the user uses to input button clicks. */ -public class MouseFragment extends CustomFragment { +public class MouseFragment extends Fragment { private RelativeLayout root; private int width, height; @@ -71,21 +76,21 @@ public class MouseFragment extends CustomFragment { private boolean middleScrolling; /** - * Creates a Mouse Fragment - * @param context main context - * @param mouse mouse to send the inputs to + * Creates a Mouse Fragment. + * + * @param mouse the movement to attach to */ - public MouseFragment(MainContext context, MouseInputs mouse, MovementHandler movement) { - super(R.layout.fragment_mouse, context); + public MouseFragment(MouseInputs mouse, MovementHandler movement) { + super(R.layout.fragment_mouse); this.mouse = mouse; this.movement = movement; } /** - * Reads the settings for the fragment from the preferences + * Reads the settings for the fragment from the preferences. */ - private void readSettings(){ + private void readSettings() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); theme = prefs.getString("interfaceTheme", "dark").equals("dark"); @@ -109,32 +114,40 @@ private void readSettings(){ buttonsMiddleWidth = prefs.getFloat("interfaceLayoutMiddleWidth", 0.2f); } + @Nullable @Override - public void render() { - root.setBackgroundResource(theme ? R.color.mouse_background_dark : R.color.mouse_background_light); + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + readSettings(); // Read settings first to determine whether visuals are turned on + + // Set system view visibility getActivity().getWindow().setStatusBarColor(getResources().getColor(theme ? R.color.mouse_background_dark : R.color.mouse_background_light)); getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (!visuals) getActivity().getWindow().getInsetsController().hide(WindowInsets.Type.statusBars()); + if (!visuals) + getActivity().getWindow().getInsetsController().hide(WindowInsets.Type.statusBars()); + getActivity().getWindow().getInsetsController().hide(WindowInsets.Type.mandatorySystemGestures()); getActivity().getWindow().getInsetsController().hide(WindowInsets.Type.systemGestures()); getActivity().getWindow().getInsetsController().hide(WindowInsets.Type.navigationBars()); } else { - if (!visuals) getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); + if (!visuals) + getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); } + return super.onCreateView(inflater, container, savedInstanceState); } @Override - public void restore() { + public void onDestroyView() { + + // Unset system view visibility getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.design_default_color_primary_dark)); getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (!visuals) getActivity().getWindow().getInsetsController().show(WindowInsets.Type.statusBars()); + if (!visuals) + getActivity().getWindow().getInsetsController().show(WindowInsets.Type.statusBars()); getActivity().getWindow().getInsetsController().show(WindowInsets.Type.mandatorySystemGestures()); getActivity().getWindow().getInsetsController().show(WindowInsets.Type.systemGestures()); @@ -143,15 +156,27 @@ public void restore() { getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); } + super.onDestroyView(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + root = view.findViewById(R.id.mouse_root); + root.setBackgroundResource(theme ? R.color.mouse_background_dark : R.color.mouse_background_light); + init(); } + + /** + * Initializes the fragment. + */ @SuppressLint("ClickableViewAccessibility") - @Override - protected void initComponents() { - readSettings(); + private void init() { - root.post(() -> { + root.post(() -> { // Wait for root view to get its size calculate(); if (visuals) createVisuals(); @@ -162,7 +187,7 @@ protected void initComponents() { if (vibrations) vibrator = (Vibrator) getContext().getSystemService(VIBRATOR_SERVICE); - if (PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("showUsage", true)){ + if (PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("showUsage", true)) { movement.unregister(); mouse.stop(); @@ -174,18 +199,12 @@ protected void initComponents() { }); dialog.show(getParentFragmentManager(), null); } - - } - - @Override - protected void loadComponents(View view) { - root = view.findViewById(R.id.mouse_root); } /** - * Calculates the buttons size + * Calculates the buttons size. */ - private void calculate(){ + private void calculate() { width = root.getWidth(); height = root.getHeight(); @@ -209,9 +228,9 @@ private void calculate(){ } /** - * Creates the visuals + * Creates the visuals. */ - private void createVisuals(){ + private void createVisuals() { View horizontal = new View(getContext()); horizontal.setBackgroundResource(theme ? R.color.mouse_stroke_dark : R.color.mouse_stroke_light); @@ -268,7 +287,8 @@ private void createVisuals(){ } /** - * Processes all touch events + * Processes all touch events. + * * @param event touch event * @return whether used */ @@ -278,22 +298,24 @@ private boolean viewTouched(MotionEvent event) { // Check whether a pointer is on a button, and if, check whether it is currently releasing or not for (int i = 0; i < event.getPointerCount(); i++) { - if (within(event.getX(i), event.getY(i), leftX, leftY, leftWidth, leftHeight)){ // Left Mouse Button - if ((event.getActionIndex() == i && event.getActionMasked() != MotionEvent.ACTION_POINTER_UP && event.getActionMasked() != MotionEvent.ACTION_UP) || event.getActionIndex() != i) left = true; + if (within(event.getX(i), event.getY(i), leftX, leftY, leftWidth, leftHeight)) { // Left Mouse Button + if ((event.getActionIndex() == i && event.getActionMasked() != MotionEvent.ACTION_POINTER_UP && event.getActionMasked() != MotionEvent.ACTION_UP) || event.getActionIndex() != i) + left = true; } - if (within(event.getX(i), event.getY(i), rightX, rightY, rightWidth, rightHeight)){ // Right Mouse Button - if ((event.getActionIndex() == i && event.getActionMasked() != MotionEvent.ACTION_POINTER_UP && event.getActionMasked() != MotionEvent.ACTION_UP) || event.getActionIndex() != i) right = true; + if (within(event.getX(i), event.getY(i), rightX, rightY, rightWidth, rightHeight)) { // Right Mouse Button + if ((event.getActionIndex() == i && event.getActionMasked() != MotionEvent.ACTION_POINTER_UP && event.getActionMasked() != MotionEvent.ACTION_UP) || event.getActionIndex() != i) + right = true; } - if (within(event.getX(i), event.getY(i), middleX, middleY, middleWidth, middleHeight)){ // Middle Mouse Button - if ((event.getActionIndex() == i && event.getActionMasked() != MotionEvent.ACTION_POINTER_UP && event.getActionMasked() != MotionEvent.ACTION_UP) || event.getActionIndex() != i) middle = true; + if (within(event.getX(i), event.getY(i), middleX, middleY, middleWidth, middleHeight)) { // Middle Mouse Button + if ((event.getActionIndex() == i && event.getActionMasked() != MotionEvent.ACTION_POINTER_UP && event.getActionMasked() != MotionEvent.ACTION_UP) || event.getActionIndex() != i) + middle = true; - if (!this.middle && middle){ + if (!this.middle && middle) { middleStart = (int) event.getY(i); middleStartTime = System.currentTimeMillis(); middleDecided = false; - } - else if (middle){ - if (middleStart - event.getY(i) > scrollThreshold && (!middleDecided || middleScrolling)){ // Scroll up + } else if (middle) { + if (middleStart - event.getY(i) > scrollThreshold && (!middleDecided || middleScrolling)) { // Scroll up mouse.changeWheelPosition(1); middleStart -= scrollThreshold; @@ -302,7 +324,7 @@ else if (middle){ setVisibility(middleView, true); vibrate(scrollLength, scrollIntensity); - }else if (middleStart - event.getY(i) < -scrollThreshold && (!middleDecided || middleScrolling)){ // Scroll down + } else if (middleStart - event.getY(i) < -scrollThreshold && (!middleDecided || middleScrolling)) { // Scroll down mouse.changeWheelPosition(-1); middleStart += scrollThreshold; @@ -311,7 +333,7 @@ else if (middle){ setVisibility(middleView, true); vibrate(scrollLength, scrollIntensity); - }else { // Click + } else { // Click if (System.currentTimeMillis() - middleStartTime > middleClickWait && !middleDecided) { mouse.setMiddleButton(true); @@ -335,13 +357,15 @@ else if (middle){ vibrate(buttonLength, buttonIntensity); setVisibility(rightView, right); } - if (this.middle != middle){ + if (this.middle != middle) { if (!middle) setVisibility(middleView, false); - if (!middle && middleDecided && !middleScrolling) vibrate(buttonLength, buttonIntensity); + if (!middle && middleDecided && !middleScrolling) + vibrate(buttonLength, buttonIntensity); } // Send Data - if (this.middle != middle && !middle && middleDecided && !middleScrolling) mouse.setMiddleButton(false); + if (this.middle != middle && !middle && middleDecided && !middleScrolling) + mouse.setMiddleButton(false); if (this.left != left) mouse.setLeftButton(left); if (this.right != right) mouse.setRightButton(right); @@ -354,20 +378,22 @@ else if (middle){ } /** - * Vibrates the device if the vibrations are enabled - * @param length length of the vibration + * Vibrates the device if the vibrations are enabled. + * + * @param length length of the vibration * @param intensity intensity of the vibration */ - private void vibrate(int length, int intensity){ + private void vibrate(int length, int intensity) { if (vibrations) vibrator.vibrate(VibrationEffect.createOneShot(length, intensity)); } /** - * Sets the visibility of a view if the visuals are enabled - * @param view view to set visibility for + * Sets the visibility of a view if the visuals are enabled. + * + * @param view view to set visibility for * @param visible whether the view is visible */ - private void setVisibility(View view, boolean visible){ + private void setVisibility(View view, boolean visible) { if (!visuals) return; if (visible) view.setVisibility(View.VISIBLE); @@ -375,16 +401,17 @@ private void setVisibility(View view, boolean visible){ } /** - * Checks whether certain coordinates are within a boundary + * Checks whether certain coordinates are within a boundary. + * * @param touchX x coordinate * @param touchY y coordinate - * @param x x coordinate of the boundary - * @param y y coordinate of the boundary - * @param width width of the boundary + * @param x x coordinate of the boundary + * @param y y coordinate of the boundary + * @param width width of the boundary * @param height height of the boundary * @return whether it is inside */ - private static boolean within(float touchX, float touchY, int x, int y, int width, int height){ + private static boolean within(float touchX, float touchY, int x, int y, int width, int height) { return touchX > x && touchX < x + width && touchY > y && touchY < y + height; } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java index d3bcd41..d14865b 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/SettingsFragment.java @@ -12,39 +12,40 @@ import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.customization.DefaultSettings; -import ch.virt.smartphonemouse.helper.MainContext; +/** + * This fragment contains the settings for the app. + */ public class SettingsFragment extends PreferenceFragmentCompat { - private final MainContext main; - - public SettingsFragment(MainContext main) { - this.main = main; - } - @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.settings, null); Preference reset = findPreference("reset"); reset.setOnPreferenceClickListener(preference -> { + resetSettings(); + return true; + }); + } - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setMessage(R.string.settings_reset_dialog_message) - .setPositiveButton(R.string.settings_reset_dialog_reset, (dialog, id) -> { - - DefaultSettings.set(PreferenceManager.getDefaultSharedPreferences(getContext())); + /** + * Shows the settings reset dialog, where the user can choose to restore their settings. + */ + private void resetSettings() { - Snackbar.make(getView(), getResources().getString(R.string.settings_reset_confirmation), Snackbar.LENGTH_SHORT); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(R.string.settings_reset_dialog_message) + .setPositiveButton(R.string.settings_reset_dialog_reset, (dialog, id) -> { - }) - .setNegativeButton(R.string.settings_reset_dialog_cancel, (dialog, id) -> {}); + DefaultSettings.set(PreferenceManager.getDefaultSharedPreferences(getContext())); - Dialog dialog = builder.create(); - dialog.show(); + Snackbar.make(getView(), getResources().getString(R.string.settings_reset_confirmation), Snackbar.LENGTH_SHORT).show(); - return true; + }) + .setNegativeButton(R.string.settings_reset_dialog_cancel, (dialog, id) -> { }); - }); + Dialog dialog = builder.create(); + dialog.show(); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/CustomSettingsFragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/CustomSettingsFragment.java deleted file mode 100644 index f5e30e1..0000000 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/CustomSettingsFragment.java +++ /dev/null @@ -1,14 +0,0 @@ -package ch.virt.smartphonemouse.ui.settings; - -import androidx.preference.PreferenceFragmentCompat; - -import ch.virt.smartphonemouse.helper.MainContext; - -public abstract class CustomSettingsFragment extends PreferenceFragmentCompat { - - protected MainContext main; - - public void setMain(MainContext main) { - this.main = main; - } -} diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java index 6448d37..414ad19 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsCommunicationSubfragment.java @@ -6,6 +6,7 @@ import android.os.Bundle; import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; import com.google.android.material.snackbar.Snackbar; @@ -13,7 +14,11 @@ import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.transmission.DeviceStorage; -public class SettingsCommunicationSubfragment extends CustomSettingsFragment { +/** + * This fragment shows the settings that are used to configure the settings regarding communication. + */ +public class SettingsCommunicationSubfragment extends PreferenceFragmentCompat { + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.settings_communication, null); @@ -21,27 +26,32 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { Preference communicationRemoveDevices = findPreference("communicationRemoveDevices"); communicationRemoveDevices.setOnPreferenceClickListener(preference -> { + removeDevices(); + return true; + }); + } - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setMessage(R.string.settings_communication_removeall_dialog_message) - .setPositiveButton(R.string.settings_communication_removeall_dialog_remove, (dialog, id) -> { - - SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(getContext()).edit(); + /** + * Shows the dialog where the user can choose to remove all known devices. + */ + private void removeDevices() { - editor.putString(DeviceStorage.DEVICES_KEY, "[]"); // Reset to an empty json array + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setMessage(R.string.settings_communication_removeall_dialog_message) + .setPositiveButton(R.string.settings_communication_removeall_dialog_remove, (dialog, id) -> { - editor.apply(); + SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(getContext()).edit(); - Snackbar.make(getView(), getResources().getString(R.string.settings_communication_removeall_confirmation), Snackbar.LENGTH_SHORT).show(); + editor.putString(DeviceStorage.DEVICES_KEY, "[]"); // Reset to an empty json array - }) - .setNegativeButton(R.string.settings_communication_removeall_dialog_cancel, (dialog, id) -> {}); + editor.apply(); - Dialog dialog = builder.create(); - dialog.show(); + Snackbar.make(getView(), getResources().getString(R.string.settings_communication_removeall_confirmation), Snackbar.LENGTH_SHORT).show(); - return true; + }) + .setNegativeButton(R.string.settings_communication_removeall_dialog_cancel, (dialog, id) -> { }); - }); + Dialog dialog = builder.create(); + dialog.show(); } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsInterfaceSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsInterfaceSubfragment.java index c8fe7b5..95d5470 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsInterfaceSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsInterfaceSubfragment.java @@ -2,14 +2,17 @@ import android.os.Bundle; -import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; import ch.virt.smartphonemouse.R; import ch.virt.smartphonemouse.ui.settings.custom.SeekFloatPreference; import ch.virt.smartphonemouse.ui.settings.custom.SeekIntegerPreference; +/** + * This fragment is the settings page, where the user can configure things regarding the interface. + */ public class SettingsInterfaceSubfragment extends PreferenceFragmentCompat { + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.settings_interface, null); diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsMovementSubfragment.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsMovementSubfragment.java index 8d5113a..e0bcd2e 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsMovementSubfragment.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/SettingsMovementSubfragment.java @@ -3,14 +3,18 @@ import android.os.Bundle; import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; import ch.virt.smartphonemouse.ui.settings.custom.EditIntegerPreference; import ch.virt.smartphonemouse.ui.settings.custom.SeekFloatPreference; import ch.virt.smartphonemouse.ui.settings.dialog.CalibrateDialog; -public class SettingsMovementSubfragment extends CustomSettingsFragment { +/** + * This fragment is the settings page, where the user can configure everything regarding the movement. + */ +public class SettingsMovementSubfragment extends PreferenceFragmentCompat { + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.settings_movement, null); @@ -24,14 +28,13 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { EditIntegerPreference movementSamplingRealRate = findPreference("movementSamplingRealRate"); Preference movementSamplingCalibrate = findPreference("movementSamplingCalibrate"); - movementSamplingCalibrate.setOnPreferenceClickListener((Preference.OnPreferenceClickListener) preference -> { + movementSamplingCalibrate.setOnPreferenceClickListener(preference -> { - CalibrateDialog dialog = new CalibrateDialog(main, movementSamplingRealRate::update); + CalibrateDialog dialog = new CalibrateDialog(); + dialog.setFinishedListener((v) -> movementSamplingRealRate.update()); dialog.show(SettingsMovementSubfragment.this.getParentFragmentManager(), null); return true; }); - - } } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java index 2c369f4..c209a7a 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateDialog.java @@ -7,58 +7,65 @@ import android.view.LayoutInflater; import android.widget.Button; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.Listener; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; +/** + * This dialog is used in the settings menu when the user requests to calibrate the sampling rate. + */ public class CalibrateDialog extends DialogFragment { AlertDialog dialog; Button positiveButton; - private final MainContext main; - private final Listener updateListener; + private DialogInterface.OnDismissListener finishedListener; - public CalibrateDialog(MainContext main, Listener updateListener) { - this.main = main; - this.updateListener = updateListener; + /** + * Sets the listener that should be used to update the setting once the dialog is done. + * + * @param finishedListener dialog dismiss listener that is executed + */ + public void setFinishedListener(DialogInterface.OnDismissListener finishedListener) { + this.finishedListener = finishedListener; } - private void created(){ + /** + * Is called when the dialog is created. + */ + private void created() { dialog.setTitle(R.string.dialog_calibrate_samplingrate_title); positiveButton.setEnabled(false); dialog.setCanceledOnTouchOutside(false); - setFragment(new SamplingRateSubdialog(main, (r) -> positiveButton.post(this::finished))); + setFragment(new SamplingRateSubdialog((r) -> positiveButton.post(this::finished))); } - private void finished(){ + /** + * Is called when the calibration process has finished. + */ + private void finished() { dialog.setTitle(R.string.dialog_calibrate_finished_title); dialog.setCanceledOnTouchOutside(true); positiveButton.setEnabled(true); - setFragment(new CalibrateFinishedSubdialog(main)); + setFragment(new CalibrateFinishedSubdialog()); } - private void setFragment(CustomFragment fragment){ + /** + * Sets the fragment of the dialog. + * + * @param fragment fragment to set + */ + private void setFragment(Fragment fragment) { getChildFragmentManager().beginTransaction().setReorderingAllowed(true).replace(R.id.calibrate_container, fragment).commit(); } - @Override - public void onDismiss(@NonNull DialogInterface dialog) { - super.onDismiss(dialog); - - updateListener.called(); - } - @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); @@ -76,9 +83,8 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { created(); }); + dialog.setOnDismissListener(finishedListener); + return dialog; } - - - } diff --git a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java index ab9264c..b2d887c 100644 --- a/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java +++ b/app/src/main/java/ch/virt/smartphonemouse/ui/settings/dialog/CalibrateFinishedSubdialog.java @@ -1,34 +1,35 @@ package ch.virt.smartphonemouse.ui.settings.dialog; +import android.os.Bundle; import android.view.View; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; import ch.virt.smartphonemouse.R; -import ch.virt.smartphonemouse.helper.MainContext; -import ch.virt.smartphonemouse.ui.CustomFragment; -public class CalibrateFinishedSubdialog extends CustomFragment { +/** + * This class is a sub fragment for the calibrate dialog, that is shown when the calibration process has finished. + */ +public class CalibrateFinishedSubdialog extends Fragment { - TextView rate; + private TextView rate; - public CalibrateFinishedSubdialog(MainContext context) { - super(R.layout.subdialog_calibrate_finished, context); + /** + * Creates the sub dialog. + */ + public CalibrateFinishedSubdialog() { + super(R.layout.subdialog_calibrate_finished); } @Override - public void render() { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); - } - - @Override - protected void initComponents() { - rate.setText(getResources().getString(R.string.dialog_calibrate_finished_rate, PreferenceManager.getDefaultSharedPreferences(getContext()).getInt("movementSamplingRealRate", 0))); - } - - @Override - protected void loadComponents(View view) { rate = view.findViewById(R.id.calibrate_finished_rate); + rate.setText(getResources().getString(R.string.dialog_calibrate_finished_rate, PreferenceManager.getDefaultSharedPreferences(getContext()).getInt("movementSamplingRealRate", 0))); } }