From cd6c4b60a6898bcbaa3db2d912d0d6bedf4d5067 Mon Sep 17 00:00:00 2001 From: Fabian Wiesel Date: Sun, 18 Feb 2024 21:57:29 +0100 Subject: [PATCH] WIP: Modernize the Stack Kotlin Edition --- app/build.gradle | 21 +- app/src/main/AndroidManifest.xml | 6 + ...CodecDefines.java => AudioCodecDefines.kt} | 25 +- .../childmonitor/DiscoverActivity.java | 297 ----------------- .../childmonitor/DiscoverActivity.kt | 247 ++++++++++++++ .../childmonitor/ListenActivity.java | 127 ------- .../rochefort/childmonitor/ListenActivity.kt | 122 +++++++ .../rochefort/childmonitor/ListenService.java | 246 -------------- .../rochefort/childmonitor/ListenService.kt | 212 ++++++++++++ .../childmonitor/MonitorActivity.java | 143 -------- .../rochefort/childmonitor/MonitorActivity.kt | 134 ++++++++ .../childmonitor/MonitorService.java | 313 ------------------ .../rochefort/childmonitor/MonitorService.kt | 273 +++++++++++++++ .../rochefort/childmonitor/StartActivity.java | 96 ------ .../rochefort/childmonitor/StartActivity.kt | 87 +++++ .../rochefort/childmonitor/VolumeHistory.java | 77 ----- .../rochefort/childmonitor/VolumeHistory.kt | 63 ++++ .../de/rochefort/childmonitor/VolumeView.java | 104 ------ .../de/rochefort/childmonitor/VolumeView.kt | 92 +++++ .../childmonitor/audio/G711UCodec.java | 71 ---- .../childmonitor/audio/G711UCodec.kt | 103 ++++++ build.gradle | 27 ++ gradle.properties | 2 + gradle/wrapper/gradle-wrapper.properties | 6 +- 24 files changed, 1398 insertions(+), 1496 deletions(-) rename app/src/main/java/de/rochefort/childmonitor/{AudioCodecDefines.java => AudioCodecDefines.kt} (54%) delete mode 100644 app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/ListenActivity.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/ListenActivity.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/ListenService.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/ListenService.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/MonitorActivity.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/MonitorActivity.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/MonitorService.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/MonitorService.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/StartActivity.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/StartActivity.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/VolumeHistory.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/VolumeHistory.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/VolumeView.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/VolumeView.kt delete mode 100644 app/src/main/java/de/rochefort/childmonitor/audio/G711UCodec.java create mode 100644 app/src/main/java/de/rochefort/childmonitor/audio/G711UCodec.kt diff --git a/app/build.gradle b/app/build.gradle index c8b4b59..95fa2e3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' +apply plugin: 'org.jetbrains.kotlin.android' android { - compileSdk 26 + compileSdk 34 defaultConfig { applicationId "de.rochefort.childmonitor" minSdkVersion 21 - //noinspection ExpiredTargetSdkVersion - targetSdkVersion 26 + targetSdkVersion 34 versionCode 11 versionName "1.1" } @@ -19,9 +19,7 @@ android { } } - dependencies { - implementation "com.android.support:support-compat:26.1.0" } namespace 'de.rochefort.childmonitor' lint { @@ -29,7 +27,16 @@ android { warning 'MissingTranslation' } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + // Sets Java compatibility to Java 17 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } + kotlin { + jvmToolchain(17) + } +} + +dependencies { + implementation 'androidx.core:core:1.12.0' + implementation 'androidx.core:core-ktx:1.12.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6c0b841..6725f91 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,6 +20,10 @@ android:required="true" /> + + . */ -package de.rochefort.childmonitor; +package de.rochefort.childmonitor -import android.media.AudioFormat; +import android.media.AudioFormat +import de.rochefort.childmonitor.audio.G711UCodec -import de.rochefort.childmonitor.audio.G711UCodec; +class AudioCodecDefines private constructor() { + init { + throw IllegalStateException("Do not instantiate!") + } -public class AudioCodecDefines { - public static final int FREQUENCY = 8000; - public static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT; - public static final G711UCodec CODEC = new G711UCodec(); - public static final int CHANNEL_CONFIGURATION_IN = AudioFormat.CHANNEL_IN_MONO; - public static final int CHANNEL_CONFIGURATION_OUT = AudioFormat.CHANNEL_OUT_MONO; - - private AudioCodecDefines() { - throw new IllegalStateException("Do not instantiate!"); + companion object { + const val FREQUENCY = 8000 + const val ENCODING = AudioFormat.ENCODING_PCM_16BIT + val CODEC = G711UCodec() + const val CHANNEL_CONFIGURATION_IN = AudioFormat.CHANNEL_IN_MONO + const val CHANNEL_CONFIGURATION_OUT = AudioFormat.CHANNEL_OUT_MONO } } diff --git a/app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.java b/app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.java deleted file mode 100644 index d260cd3..0000000 --- a/app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * This file is part of Child Monitor. - * - * Child Monitor is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Child Monitor is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Child Monitor. If not, see . - */ -package de.rochefort.childmonitor; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.nsd.NsdManager; -import android.net.nsd.NsdServiceInfo; -import android.net.wifi.WifiManager; -import android.os.Bundle; -import android.util.Log; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ListView; -import android.widget.Toast; - -import java.util.Objects; - - -public class DiscoverActivity extends Activity { - private static final String PREF_KEY_CHILD_DEVICE_ADDRESS = "childDeviceAddress"; - private static final String PREF_KEY_CHILD_DEVICE_PORT = "childDevicePort"; - final String TAG = "ChildMonitor"; - - private NsdManager nsdManager; - - private NsdManager.DiscoveryListener discoveryListener; - - @Override - protected void onCreate(Bundle savedInstanceState) { - Log.i(TAG, "ChildMonitor start"); - - nsdManager = (NsdManager)this.getSystemService(Context.NSD_SERVICE); - - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_discover); - - final Button discoverChildButton = findViewById(R.id.discoverChildButton); - discoverChildButton.setOnClickListener(v -> loadDiscoveryViaMdns()); - - final Button enterChildAddressButton = findViewById(R.id.enterChildAddressButton); - enterChildAddressButton.setOnClickListener(v -> loadDiscoveryViaAddress()); - } - - private void loadDiscoveryViaMdns() { - setContentView(R.layout.activity_discover_mdns); - startServiceDiscovery("_childmonitor._tcp."); - } - - private void loadDiscoveryViaAddress() { - setContentView(R.layout.activity_discover_address); - - final Button connectButton = findViewById(R.id.connectViaAddressButton); - final EditText addressField = findViewById(R.id.ipAddressField); - final EditText portField = findViewById(R.id.portField); - String preferredAddress = getPreferences(MODE_PRIVATE).getString(PREF_KEY_CHILD_DEVICE_ADDRESS, null); - if (preferredAddress != null && !preferredAddress.isEmpty()) { - addressField.setText(preferredAddress); - } - int preferredPort = getPreferences(MODE_PRIVATE).getInt(PREF_KEY_CHILD_DEVICE_PORT, -1); - if (preferredPort > 0) { - portField.setText(String.valueOf(preferredPort)); - } else { - portField.setText("10000"); - } - - connectButton.setOnClickListener(v -> { - Log.i(TAG, "Connecting to child device via address"); - final String addressString = addressField.getText().toString(); - final String portString = portField.getText().toString(); - - if(addressString.length() == 0) - { - Toast.makeText(DiscoverActivity.this, R.string.invalidAddress, Toast.LENGTH_LONG).show(); - return; - } - - int port; - - try { - port = Integer.parseInt(portString); - } - catch(NumberFormatException e) - { - Toast.makeText(DiscoverActivity.this, R.string.invalidPort, Toast.LENGTH_LONG).show(); - return; - } - SharedPreferences.Editor preferencesEditor = getPreferences(MODE_PRIVATE).edit(); - preferencesEditor.putString(PREF_KEY_CHILD_DEVICE_ADDRESS, addressString); - preferencesEditor.putInt(PREF_KEY_CHILD_DEVICE_PORT, port); - preferencesEditor.apply(); - connectToChild(addressString, port, addressString); - }); - } - - @Override - protected void onDestroy() { - Log.i(TAG, "ChildMonitoring stop"); - - if(discoveryListener != null) { - Log.i(TAG, "Unregistering monitoring service"); - - nsdManager.stopServiceDiscovery(discoveryListener); - discoveryListener = null; - } - - super.onDestroy(); - } - - public void startServiceDiscovery(final String serviceType) { - final NsdManager nsdManager = (NsdManager)this.getSystemService(Context.NSD_SERVICE); - if (nsdManager == null) { - Log.e(TAG, "Could not obtain nsdManager"); - return; - } - - WifiManager wifi = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - final Runnable multicastReleaser; - if (wifi != null) { - final WifiManager.MulticastLock multicastLock = wifi.createMulticastLock("multicastLock"); - multicastLock.setReferenceCounted(true); - multicastLock.acquire(); - multicastReleaser = () -> { - try { - multicastLock.release(); - } catch (Exception ignored) { - //dont really care - } - }; - } else { - multicastReleaser = () -> { - }; - } - - - final ListView serviceTable = findViewById(R.id.ServiceTable); - - final ArrayAdapter availableServicesAdapter = new ArrayAdapter<>(this, - R.layout.available_children_list); - serviceTable.setAdapter(availableServicesAdapter); - - serviceTable.setOnItemClickListener((parent, view, position, id) -> { - final ServiceInfoWrapper info = (ServiceInfoWrapper) parent.getItemAtPosition(position); - connectToChild(info.getAddress(), info.getPort(), info.getName()); - }); - - // Instantiate a new DiscoveryListener - discoveryListener = new NsdManager.DiscoveryListener() { - // Called as soon as service discovery begins. - @Override - public void onDiscoveryStarted(String regType) - { - Log.d(TAG, "Service discovery started"); - } - - @Override - public void onServiceFound(NsdServiceInfo service) { - // A service was found! Do something with it. - Log.d(TAG, "Service discovery success: " + service); - - if (!service.getServiceType().equals(serviceType)) { - // Service type is the string containing the protocol and - // transport layer for this service. - Log.d(TAG, "Unknown Service Type: " + service.getServiceType()); - } else if (service.getServiceName().contains("ChildMonitor")) { - NsdManager.ResolveListener resolver = new NsdManager.ResolveListener() { - @Override - public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) { - // Called when the resolve fails. Use the error code to debug. - Log.e(TAG, "Resolve failed: error " + errorCode + " for service: " + serviceInfo); - } - - @Override - public void onServiceResolved(final NsdServiceInfo serviceInfo) { - Log.i(TAG, "Resolve Succeeded: " + serviceInfo); - - DiscoverActivity.this.runOnUiThread(() -> { - for (int index=0; index < availableServicesAdapter.getCount(); index++) { - ServiceInfoWrapper item = availableServicesAdapter.getItem(index); - if (item != null && item.matches(serviceInfo)) { - // Prevent inserting duplicates - return; - } - } - availableServicesAdapter.add(new ServiceInfoWrapper(serviceInfo)); - }); - } - }; - - DiscoverActivity.this.nsdManager.resolveService(service, resolver); - } else { - Log.d(TAG, "Unknown Service name: " + service.getServiceName()); - } - } - - @Override - public void onServiceLost(NsdServiceInfo service) { - // When the network service is no longer available. - // Internal bookkeeping code goes here. - Log.e(TAG, "Service lost: " + service); - multicastReleaser.run(); - } - - @Override - public void onDiscoveryStopped(String serviceType) { - Log.i(TAG, "Discovery stopped: " + serviceType); - multicastReleaser.run(); - } - - @Override - public void onStartDiscoveryFailed(String serviceType, int errorCode) { - Log.e(TAG, "Discovery failed: Error code: " + errorCode); - nsdManager.stopServiceDiscovery(this); - multicastReleaser.run(); - } - - @Override - public void onStopDiscoveryFailed(String serviceType, int errorCode) { - Log.e(TAG, "Discovery failed: Error code: " + errorCode); - nsdManager.stopServiceDiscovery(this); - multicastReleaser.run(); - } - }; - - nsdManager.discoverServices( - serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryListener - ); - } - - private void connectToChild(final String address, final int port, final String name) { - final Intent i = new Intent(getApplicationContext(), ListenActivity.class); - final Bundle b = new Bundle(); - b.putString("address", address); - b.putInt("port", port); - b.putString("name", name); - i.putExtras(b); - startActivity(i); - } -} - -class ServiceInfoWrapper { - private final NsdServiceInfo info; - public ServiceInfoWrapper(NsdServiceInfo info) - { - this.info = info; - } - - public boolean matches(NsdServiceInfo other) { - return Objects.equals(this.info.getHost(), other.getHost()) && this.info.getPort() == other.getPort(); - } - - public String getAddress() - { - return info.getHost().getHostAddress(); - } - - public int getPort() - { - return info.getPort(); - } - - public String getName() { - // If there is more than one service with the same name on the network, it will - // have a number at the end, but will appear as the following: - // "ChildMonitor\\032(number) - // or - // "ChildMonitor\032(number) - // Replace \\032 and \032 with a " " - String serviceName = info.getServiceName(); - serviceName = serviceName.replace("\\\\032", " "); - serviceName = serviceName.replace("\\032", " "); - return serviceName; - } - - @Override - public String toString() - { - return getName(); - } -} diff --git a/app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.kt b/app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.kt new file mode 100644 index 0000000..0cd56ad --- /dev/null +++ b/app/src/main/java/de/rochefort/childmonitor/DiscoverActivity.kt @@ -0,0 +1,247 @@ +/* + * This file is part of Child Monitor. + * + * Child Monitor is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Child Monitor is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Child Monitor. If not, see . + */ +package de.rochefort.childmonitor + +import android.app.Activity +import android.content.Intent +import android.net.nsd.NsdManager +import android.net.nsd.NsdManager.DiscoveryListener +import android.net.nsd.NsdServiceInfo +import android.net.wifi.WifiManager +import android.os.Bundle +import android.util.Log +import android.view.View +import android.widget.AdapterView +import android.widget.AdapterView.OnItemClickListener +import android.widget.ArrayAdapter +import android.widget.Button +import android.widget.EditText +import android.widget.ListView +import android.widget.Toast + +val TAG = "ChildMonitor" + +class DiscoverActivity : Activity() { + private var nsdManager: NsdManager? = null + private var discoveryListener: DiscoveryListener? = null + override fun onCreate(savedInstanceState: Bundle?) { + Log.i(TAG, "ChildMonitor start") + nsdManager = this.getSystemService(NSD_SERVICE) as NsdManager + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_discover) + val discoverChildButton = findViewById