diff --git a/src/org/kde/kdeconnect/KdeConnect.java b/src/org/kde/kdeconnect/KdeConnect.java deleted file mode 100644 index 8a21f751..00000000 --- a/src/org/kde/kdeconnect/KdeConnect.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Albert Vaca Cintora - * - * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL - */ - -package org.kde.kdeconnect; - -import android.Manifest; -import android.app.Application; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.os.Build; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; - -import org.kde.kdeconnect.Backends.BaseLink; -import org.kde.kdeconnect.Backends.BaseLinkProvider; -import org.kde.kdeconnect.Helpers.DeviceHelper; -import org.kde.kdeconnect.Helpers.LifecycleHelper; -import org.kde.kdeconnect.Helpers.NotificationHelper; -import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper; -import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper; -import org.kde.kdeconnect.Plugins.Plugin; -import org.kde.kdeconnect.Plugins.PluginFactory; -import org.kde.kdeconnect.UserInterface.MainActivity; -import org.kde.kdeconnect.UserInterface.ThemeUtil; -import org.kde.kdeconnect_tp.BuildConfig; -import org.slf4j.impl.HandroidLoggerAdapter; - -import java.security.cert.CertificateException; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/* - * This class holds all the active devices and makes them accessible from every other class. - * It also takes care of initializing all classes that need so when the app boots. - * It provides a ConnectionReceiver that the BackgroundService uses to ping this class every time a new DeviceLink is created. - */ -public class KdeConnect extends Application { - - public interface DeviceListChangedCallback { - void onDeviceListChanged(); - } - - private static KdeConnect instance = null; - - private final ConcurrentHashMap devices = new ConcurrentHashMap<>(); - - private final ConcurrentHashMap deviceListChangedCallbacks = new ConcurrentHashMap<>(); - - @Override - public void onCreate() { - super.onCreate(); - instance = this; - setupSL4JLogging(); - Log.d("KdeConnect/Application", "onCreate"); - ThemeUtil.setUserPreferredTheme(this); - DeviceHelper.initializeDeviceId(this); - RsaHelper.initialiseRsaKeys(this); - SslHelper.initialiseCertificate(this); - PluginFactory.initPluginInfo(this); - NotificationHelper.initializeChannels(this); - LifecycleHelper.initializeObserver(); - loadRememberedDevicesFromSettings(); - - } - - private void setupSL4JLogging() { - HandroidLoggerAdapter.DEBUG = BuildConfig.DEBUG; - HandroidLoggerAdapter.ANDROID_API_LEVEL = Build.VERSION.SDK_INT; - HandroidLoggerAdapter.APP_NAME = "KDEConnect"; - } - - @Override - public void onTerminate() { - Log.d("KdeConnect/Application", "onTerminate"); - super.onTerminate(); - } - - public void addDeviceListChangedCallback(String key, DeviceListChangedCallback callback) { - deviceListChangedCallbacks.put(key, callback); - } - - public void removeDeviceListChangedCallback(String key) { - deviceListChangedCallbacks.remove(key); - } - - private void onDeviceListChanged() { - Log.i("MainActivity","Device list changed, notifying "+ deviceListChangedCallbacks.size() +" observers."); - for (DeviceListChangedCallback callback : deviceListChangedCallbacks.values()) { - callback.onDeviceListChanged(); - } - } - - public ConcurrentHashMap getDevices() { - return devices; - } - - public Device getDevice(String id) { - if (id == null) { - return null; - } - return devices.get(id); - } - - public T getDevicePlugin(String deviceId, Class pluginClass) { - if (deviceId == null) { - return null; - } - Device device = devices.get(deviceId); - if (device == null) { - return null; - } - return device.getPlugin(pluginClass); - } - - public static KdeConnect getInstance() { - return instance; - } - - private void loadRememberedDevicesFromSettings() { - //Log.e("BackgroundService", "Loading remembered trusted devices"); - SharedPreferences preferences = getSharedPreferences("trusted_devices", Context.MODE_PRIVATE); - Set trustedDevices = preferences.getAll().keySet(); - for (String deviceId : trustedDevices) { - //Log.e("BackgroundService", "Loading device "+deviceId); - if (preferences.getBoolean(deviceId, false)) { - try { - Device device = new Device(this, deviceId); - devices.put(deviceId, device); - device.addPairingCallback(devicePairingCallback); - } catch (CertificateException e) { - Log.w("KdeConnect", "Couldn't load the certificate for a remembered device. Removing from trusted list."); - e.printStackTrace(); - preferences.edit().remove(deviceId).apply(); - } - } - } - } - - private final PairingHandler.PairingCallback devicePairingCallback = new PairingHandler.PairingCallback() { - @Override - public void incomingPairRequest() { - onDeviceListChanged(); - } - - @Override - public void pairingSuccessful() { - onDeviceListChanged(); - } - - @Override - public void pairingFailed(String error) { - onDeviceListChanged(); - } - - @Override - public void unpaired() { - onDeviceListChanged(); - } - }; - - private final BaseLinkProvider.ConnectionReceiver connectionListener = new BaseLinkProvider.ConnectionReceiver() { - @Override - public void onConnectionReceived(@NonNull final BaseLink link) { - Device device = devices.get(link.getDeviceId()); - if (device != null) { - device.addLink(link); - } else { - device = new Device(KdeConnect.this, link); - devices.put(link.getDeviceId(), device); - device.addPairingCallback(devicePairingCallback); - } - onDeviceListChanged(); - } - - @Override - public void onConnectionLost(BaseLink link) { - Device device = devices.get(link.getDeviceId()); - Log.i("KDE/onConnectionLost", "removeLink, deviceId: " + link.getDeviceId()); - if (device != null) { - device.removeLink(link); - if (!device.isReachable() && !device.isPaired()) { - //Log.e("onConnectionLost","Removing connection device because it was not paired"); - devices.remove(link.getDeviceId()); - device.removePairingCallback(devicePairingCallback); - } - } else { - Log.d("KDE/onConnectionLost","Removing connection to unknown device"); - } - onDeviceListChanged(); - } - }; - - public BaseLinkProvider.ConnectionReceiver getConnectionListener() { - return connectionListener; - } - -} diff --git a/src/org/kde/kdeconnect/KdeConnect.kt b/src/org/kde/kdeconnect/KdeConnect.kt new file mode 100644 index 00000000..54003548 --- /dev/null +++ b/src/org/kde/kdeconnect/KdeConnect.kt @@ -0,0 +1,169 @@ +/* + * SPDX-FileCopyrightText: 2023 Albert Vaca Cintora + * + * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL + */ +package org.kde.kdeconnect + +import android.app.Application +import android.os.Build +import android.util.Log +import org.kde.kdeconnect.Backends.BaseLink +import org.kde.kdeconnect.Backends.BaseLinkProvider.ConnectionReceiver +import org.kde.kdeconnect.Helpers.DeviceHelper +import org.kde.kdeconnect.Helpers.LifecycleHelper +import org.kde.kdeconnect.Helpers.NotificationHelper +import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper +import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper +import org.kde.kdeconnect.PairingHandler.PairingCallback +import org.kde.kdeconnect.Plugins.Plugin +import org.kde.kdeconnect.Plugins.PluginFactory +import org.kde.kdeconnect.UserInterface.ThemeUtil +import org.kde.kdeconnect_tp.BuildConfig +import org.slf4j.impl.HandroidLoggerAdapter +import java.security.cert.CertificateException +import java.util.concurrent.ConcurrentHashMap + +/* + * This class holds all the active devices and makes them accessible from every other class. + * It also takes care of initializing all classes that need so when the app boots. + * It provides a ConnectionReceiver that the BackgroundService uses to ping this class every time a new DeviceLink is created. + */ +class KdeConnect : Application() { + fun interface DeviceListChangedCallback { + fun onDeviceListChanged() + } + + val devices: ConcurrentHashMap = ConcurrentHashMap() + + private val deviceListChangedCallbacks = ConcurrentHashMap() + + override fun onCreate() { + super.onCreate() + _instance = this + setupSL4JLogging() + Log.d("KdeConnect/Application", "onCreate") + ThemeUtil.setUserPreferredTheme(this) + DeviceHelper.initializeDeviceId(this) + RsaHelper.initialiseRsaKeys(this) + SslHelper.initialiseCertificate(this) + PluginFactory.initPluginInfo(this) + NotificationHelper.initializeChannels(this) + LifecycleHelper.initializeObserver() + loadRememberedDevicesFromSettings() + } + + private fun setupSL4JLogging() { + HandroidLoggerAdapter.DEBUG = BuildConfig.DEBUG + HandroidLoggerAdapter.ANDROID_API_LEVEL = Build.VERSION.SDK_INT + HandroidLoggerAdapter.APP_NAME = "KDEConnect" + } + + override fun onTerminate() { + Log.d("KdeConnect/Application", "onTerminate") + super.onTerminate() + } + + fun addDeviceListChangedCallback(key: String, callback: DeviceListChangedCallback) { + deviceListChangedCallbacks[key] = callback + } + + fun removeDeviceListChangedCallback(key: String) { + deviceListChangedCallbacks.remove(key) + } + + private fun onDeviceListChanged() { + Log.i("MainActivity", "Device list changed, notifying ${deviceListChangedCallbacks.size} observers.") + deviceListChangedCallbacks.values.forEach(DeviceListChangedCallback::onDeviceListChanged) + } + + fun getDevice(id: String?): Device? { + if (id == null) { + return null + } + return devices[id] + } + + fun getDevicePlugin(deviceId: String?, pluginClass: Class): T? { + val device = getDevice(deviceId) + return device?.getPlugin(pluginClass) + } + + private fun loadRememberedDevicesFromSettings() { + // Log.e("BackgroundService", "Loading remembered trusted devices"); + val preferences = getSharedPreferences("trusted_devices", MODE_PRIVATE) + val trustedDevices: Set = preferences.all.keys + trustedDevices.map { id -> + Log.d("KdeConnect", "Loading device $id") + id + }.filter { preferences.getBoolean(it, false) }.forEach { + try { + val device = Device(this, it) + devices[it] = device + device.addPairingCallback(devicePairingCallback) + } catch (e: CertificateException) { + Log.w( + "KdeConnect", + "Couldn't load the certificate for a remembered device. Removing from trusted list.", e + ) + preferences.edit().remove(it).apply() + } + } + } + + private val devicePairingCallback: PairingCallback = object : PairingCallback { + override fun incomingPairRequest() { + onDeviceListChanged() + } + + override fun pairingSuccessful() { + onDeviceListChanged() + } + + override fun pairingFailed(error: String) { + onDeviceListChanged() + } + + override fun unpaired() { + onDeviceListChanged() + } + } + + val connectionListener: ConnectionReceiver = object : ConnectionReceiver { + override fun onConnectionReceived(link: BaseLink) { + var device = devices[link.deviceId] + if (device != null) { + device.addLink(link) + } else { + device = Device(this@KdeConnect, link) + devices[link.deviceId] = device + device.addPairingCallback(devicePairingCallback) + } + onDeviceListChanged() + } + + override fun onConnectionLost(link: BaseLink) { + val device = devices[link.deviceId] + Log.i("KDE/onConnectionLost", "removeLink, deviceId: ${link.deviceId}") + if (device != null) { + device.removeLink(link) + if (!device.isReachable && !device.isPaired) { + // Log.e("onConnectionLost","Removing connection device because it was not paired"); + devices.remove(link.deviceId) + device.removePairingCallback(devicePairingCallback) + } + } else { + Log.d("KDE/onConnectionLost", "Removing connection to unknown device") + } + onDeviceListChanged() + } + } + + companion object { + @JvmStatic + private lateinit var _instance: KdeConnect + + @JvmStatic + fun getInstance(): KdeConnect = _instance + } +} diff --git a/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt b/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt index 9f0449fb..bc115b0e 100644 --- a/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt +++ b/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt @@ -50,7 +50,7 @@ class PresenterActivity : AppCompatActivity(), SensorEventListener { } private val powerManager by lazy { getSystemService(POWER_SERVICE) as PowerManager } private val plugin: PresenterPlugin by lazy { - KdeConnect.getInstance().getDevicePlugin(intent.getStringExtra("deviceId"), PresenterPlugin::class.java) + KdeConnect.getInstance().getDevicePlugin(intent.getStringExtra("deviceId"), PresenterPlugin::class.java)!! } //TODO: make configurable diff --git a/src/org/kde/kdeconnect/UserInterface/MainActivity.kt b/src/org/kde/kdeconnect/UserInterface/MainActivity.kt index b871e922..19edaddd 100644 --- a/src/org/kde/kdeconnect/UserInterface/MainActivity.kt +++ b/src/org/kde/kdeconnect/UserInterface/MainActivity.kt @@ -286,7 +286,7 @@ class MainActivity : AppCompatActivity(), OnSharedPreferenceChangeListener { override fun onStart() { super.onStart() BackgroundService.Start(applicationContext) - KdeConnect.getInstance().addDeviceListChangedCallback(this::class.simpleName) { runOnUiThread { updateDeviceList() } } + KdeConnect.getInstance().addDeviceListChangedCallback(this::class.simpleName!!) { runOnUiThread { updateDeviceList() } } updateDeviceList() onBackPressedDispatcher.addCallback(mainFragmentCallback) onBackPressedDispatcher.addCallback(closeDrawerCallback) @@ -294,7 +294,7 @@ class MainActivity : AppCompatActivity(), OnSharedPreferenceChangeListener { } override fun onStop() { - KdeConnect.getInstance().removeDeviceListChangedCallback(this::class.simpleName) + KdeConnect.getInstance().removeDeviceListChangedCallback(this::class.simpleName!!) mainFragmentCallback.remove() closeDrawerCallback.remove() super.onStop()