Skip to content

Commit

Permalink
Merge branch 'release/1.9.7'
Browse files Browse the repository at this point in the history
  • Loading branch information
Florianisme committed Mar 23, 2024
2 parents 91cd61c + 92b35f0 commit 91fa511
Show file tree
Hide file tree
Showing 46 changed files with 1,078 additions and 286 deletions.
16 changes: 8 additions & 8 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apply from: "$rootProject.projectDir/shared-build.gradle"

android {
defaultConfig {
versionCode 97
versionCode 105
wearAppUnbundled true
}
buildFeatures {
Expand All @@ -13,19 +13,19 @@ android {

dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment:2.7.3'
implementation 'androidx.navigation:navigation-ui:2.7.3'
implementation 'androidx.navigation:navigation-fragment:2.7.5'
implementation 'androidx.navigation:navigation-ui:2.7.5'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'org.reactivestreams:reactive-streams:1.0.3'
implementation 'io.reactivex.rxjava2:rxjava:2.2.9'
implementation 'org.reactivestreams:reactive-streams:1.0.4'
implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
implementation 'android.arch.lifecycle:livedata:1.1.1'

implementation "androidx.core:core:1.12.0"
implementation 'androidx.core:core-google-shortcuts:1.1.0'

def room_version = "2.5.2"
def room_version = "2.6.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

Expand All @@ -34,8 +34,8 @@ dependencies {
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'

implementation files('libs/android-ping.aar')
implementation project(path: ':shared-models')
implementation project(path: ':ping')

// Fix Duplicate class
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
Expand Down
Binary file removed app/libs/android-ping.aar
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package de.florianisme.wakeonlan.persistence.models;

public class Device {
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;

public class Device implements Parcelable {

public int id;

Expand Down Expand Up @@ -48,4 +53,53 @@ public Device(int id, String name, String macAddress, String broadcastAddress, i

public Device() {
}

public static final Parcelable.Creator<Device> CREATOR
= new Parcelable.Creator<>() {
public Device createFromParcel(Parcel in) {
return new Device(in);
}

public Device[] newArray(int size) {
return new Device[size];
}
};

private Device(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
this.macAddress = in.readString();
this.broadcastAddress = in.readString();
this.port = in.readInt();
this.statusIp = in.readString();
this.secureOnPassword = in.readString();
this.remoteShutdownEnabled = in.readInt() >= 1;
this.sshAddress = in.readString();
this.sshPort = in.readInt();
this.sshUsername = in.readString();
this.sshPassword = in.readString();
this.sshCommand = in.readString();
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeString(macAddress);
dest.writeString(broadcastAddress);
dest.writeInt(port);
dest.writeString(statusIp);
dest.writeString(secureOnPassword);
dest.writeInt(remoteShutdownEnabled ? 1 : 0);
dest.writeString(sshAddress);
dest.writeInt(sshPort == null ? -1 : sshPort);
dest.writeString(sshUsername);
dest.writeString(sshPassword);
dest.writeString(sshCommand);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public Flow.Publisher<Control> createPublisherFor(@NonNull List<String> controlI

@Override
public void onDestroy() {
StatefulControlService.unscheduleStatusTester();
StatefulControlService.stopAllStatusTesters();
super.onDestroy();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,22 @@
import androidx.annotation.RequiresApi;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import de.florianisme.wakeonlan.R;
import de.florianisme.wakeonlan.persistence.models.Device;
import de.florianisme.wakeonlan.persistence.models.DeviceStatus;
import de.florianisme.wakeonlan.persistence.repository.DeviceRepository;
import de.florianisme.wakeonlan.ui.list.status.DeviceStatusTester;
import de.florianisme.wakeonlan.ui.list.status.PingDeviceStatusTester;
import de.florianisme.wakeonlan.ui.list.status.pool.PingStatusTesterPool;
import de.florianisme.wakeonlan.ui.list.status.pool.StatusTestType;
import de.florianisme.wakeonlan.ui.list.status.pool.StatusTesterPool;
import io.reactivex.processors.ReplayProcessor;

@RequiresApi(api = Build.VERSION_CODES.R)
public class StatefulControlService {

private static final Map<Integer, DeviceStatusTester> statusTesterMap = new HashMap<>();

static void unscheduleStatusTester() {
statusTesterMap.forEach((id, tester) -> tester.stopDeviceStatusPings());
statusTesterMap.clear();
}
private static final StatusTesterPool STATUS_TESTER_POOL = PingStatusTesterPool.getInstance();

static void createAndUpdateStatefulControls(List<String> deviceIds, ReplayProcessor<Control> processor, Context context) {
DeviceRepository deviceRepository = DeviceRepository.getInstance(context);
Expand All @@ -42,12 +36,10 @@ static void createAndUpdateStatefulControls(List<String> deviceIds, ReplayProces
.collect(Collectors.toList());

for (Device device : filteredDevices) {
DeviceStatusTester deviceStatusTester = statusTesterMap.getOrDefault(device.id, new PingDeviceStatusTester());
statusTesterMap.putIfAbsent(device.id, deviceStatusTester);
deviceStatusTester.scheduleDeviceStatusPings(device, deviceStatus -> {
STATUS_TESTER_POOL.scheduleStatusTest(device, deviceStatus -> {
Control control = mapDeviceToStatefulControl(device, deviceStatus == DeviceStatus.ONLINE, context);
processor.onNext(control);
});
}, StatusTestType.QUICK_ACCESS);
}
}

Expand All @@ -67,4 +59,7 @@ private static Control mapDeviceToStatefulControl(Device device, boolean toggleO
.build();
}

public static void stopAllStatusTesters() {
STATUS_TESTER_POOL.stopAllStatusTesters(StatusTestType.QUICK_ACCESS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import android.os.Build;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.util.Log;
import android.widget.Toast;

import java.util.List;
Expand All @@ -13,18 +12,22 @@
import de.florianisme.wakeonlan.persistence.models.Device;
import de.florianisme.wakeonlan.persistence.models.DeviceStatus;
import de.florianisme.wakeonlan.persistence.repository.DeviceRepository;
import de.florianisme.wakeonlan.shutdown.ShutdownExecutor;
import de.florianisme.wakeonlan.ui.list.status.DeviceStatusListener;
import de.florianisme.wakeonlan.ui.list.status.DeviceStatusTester;
import de.florianisme.wakeonlan.ui.list.status.PingDeviceStatusTester;
import de.florianisme.wakeonlan.ui.list.status.pool.PingStatusTesterPool;
import de.florianisme.wakeonlan.ui.list.status.pool.StatusTestType;
import de.florianisme.wakeonlan.ui.list.status.pool.StatusTesterPool;
import de.florianisme.wakeonlan.wol.WolSender;

public abstract class DeviceTileService extends TileService implements DeviceStatusListener {

private final DeviceStatusTester deviceStatusTester = new PingDeviceStatusTester();
private final StatusTesterPool statusTesterPool = PingStatusTesterPool.getInstance();

private DeviceRepository deviceRepository;
private Device device;

private DeviceStatus lastDeviceStatus = DeviceStatus.UNKNOWN;


@Override
public void onTileAdded() {
Expand All @@ -41,7 +44,7 @@ private void updateTileState() {
if (optionalMachine.isPresent()) {
Device device = optionalMachine.get();
this.device = device;
deviceStatusTester.scheduleDeviceStatusPings(device, this);
statusTesterPool.scheduleStatusTest(device, this, StatusTestType.TILE);

tile.setLabel(device.name);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Expand All @@ -67,15 +70,20 @@ public void onStatusAvailable(DeviceStatus deviceStatus) {
Tile tile = getQsTile();
tile.setState(deviceStatus == DeviceStatus.ONLINE ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.updateTile();

lastDeviceStatus = deviceStatus;
}

@Override
public void onClick() {
try {
if (lastDeviceStatus == DeviceStatus.ONLINE) {
if (device.remoteShutdownEnabled) {
ShutdownExecutor.shutdownDevice(device);
Toast.makeText(this, getString(R.string.remote_shutdown_send_command, device.name), Toast.LENGTH_LONG).show();
}
} else {
WolSender.sendWolPacket(device);
Toast.makeText(this, getString(R.string.wol_toast_sending_packet, device.name), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e(this.getClass().getName(), "Error while sending WOL Packet", e);
}
}

Expand All @@ -88,7 +96,7 @@ public void onStartListening() {
@Override
public void onStopListening() {
super.onStopListening();
deviceStatusTester.stopDeviceStatusPings();
statusTesterPool.stopStatusTest(device, StatusTestType.TILE);
}

abstract int machineAtIndex();
Expand Down
36 changes: 36 additions & 0 deletions app/src/main/java/de/florianisme/wakeonlan/ui/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package de.florianisme.wakeonlan.ui;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.GravityCompat;
Expand All @@ -14,6 +18,7 @@

import java.util.Set;

import de.florianisme.wakeonlan.BuildConfig;
import de.florianisme.wakeonlan.R;
import de.florianisme.wakeonlan.databinding.ActivityMainBinding;
import de.florianisme.wakeonlan.persistence.repository.DeviceRepository;
Expand All @@ -34,13 +39,33 @@ protected void onCreate(Bundle savedInstanceState) {
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());

setVersionInformation();

setSupportActionBar(binding.toolbar);

initializeNavController();
initializeWearClient();
initializeShortcuts();
}

private void setVersionInformation() {
View headerView = binding.navigationView.getHeaderView(0);

TextView versionView = headerView.findViewById(R.id.navigation_header_version);
TextView headerTitleView = headerView.findViewById(R.id.navigation_header_title);

headerTitleView.setOnApplyWindowInsetsListener((v, insets) -> {
int calculatedTopPadding = Math.round(insets.getSystemWindowInsetTop() +
getResources().getDimension(R.dimen.navigation_header_top_padding));

headerTitleView.setPadding(versionView.getPaddingStart(), calculatedTopPadding,
versionView.getPaddingEnd(), 0);
return insets;
});

versionView.setText(getString(R.string.drawer_menu_header_version, BuildConfig.VERSION_NAME));
}

private void initializeWearClient() {
wearClient = new WearClient(this);
DeviceRepository.getInstance(this)
Expand All @@ -53,6 +78,17 @@ private void initializeNavController() {
appBarConfiguration = new AppBarConfiguration.Builder(getMenuIds()).setOpenableLayout(binding.drawerLayout).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(binding.navigationView, navController);

setGithubShortcut();
}

private void setGithubShortcut() {
binding.navigationView.getMenu().findItem(R.id.githubShortcut).setOnMenuItemClickListener(item -> {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/Florianisme/WakeOnLan"));
startActivity(browserIntent);

return false;
});
}

private void initializeShortcuts() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
import androidx.activity.result.ActivityResultLauncher;
import androidx.fragment.app.Fragment;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -49,7 +50,7 @@ public void onActivityResult(Uri uri) {
.stream().map(DeviceBackupModel::new)
.collect(Collectors.toList());

byte[] content = new ObjectMapper().writeValueAsBytes(devices);
byte[] content = new Gson().toJson(devices).getBytes(StandardCharsets.UTF_8);
writeDevicesToFile(uri, content, context);

Toast.makeText(context, context.getString(R.string.backup_message_export_success, devices.size()), Toast.LENGTH_SHORT).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
import androidx.activity.result.ActivityResultLauncher;
import androidx.fragment.app.Fragment;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.ByteStreams;
import com.google.gson.Gson;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.Arrays;

Expand Down Expand Up @@ -46,7 +48,8 @@ public void onActivityResult(Uri uri) {

try {
byte[] bytes = readContentFromFile(uri, context);
Device[] devices = Arrays.stream(new ObjectMapper().readValue(bytes, DeviceBackupModel[].class))
InputStreamReader inputStreamReader = new InputStreamReader(new ByteArrayInputStream(bytes));
Device[] devices = Arrays.stream(new Gson().fromJson(inputStreamReader, DeviceBackupModel[].class))
.map(DeviceBackupModel::toModel)
.toArray(Device[]::new);

Expand Down
Loading

0 comments on commit 91fa511

Please sign in to comment.