mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-30 05:37:43 +00:00
Use a prefences file per device/plugin combo
Cleanup global plugin preferences after migration to per device preferences
This commit is contained in:
parent
e7651ec9bc
commit
4d8e7cadde
@ -16,7 +16,7 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.kde.kdeconnect;
|
package org.kde.kdeconnect;
|
||||||
|
|
||||||
@ -24,7 +24,6 @@ import android.app.Notification;
|
|||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.bluetooth.BluetoothClass;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
@ -33,9 +32,12 @@ import android.net.ConnectivityManager;
|
|||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
import org.kde.kdeconnect.Backends.BaseLink;
|
import org.kde.kdeconnect.Backends.BaseLink;
|
||||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||||
@ -53,14 +55,12 @@ import org.kde.kdeconnect_tp.R;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
|
|
||||||
|
|
||||||
//import org.kde.kdeconnect.Backends.BluetoothBackend.BluetoothLinkProvider;
|
//import org.kde.kdeconnect.Backends.BluetoothBackend.BluetoothLinkProvider;
|
||||||
|
|
||||||
public class BackgroundService extends Service {
|
public class BackgroundService extends Service {
|
||||||
@ -280,6 +280,7 @@ public class BackgroundService extends Service {
|
|||||||
initializeSecurityParameters();
|
initializeSecurityParameters();
|
||||||
NotificationHelper.initializeChannels(this);
|
NotificationHelper.initializeChannels(this);
|
||||||
loadRememberedDevicesFromSettings();
|
loadRememberedDevicesFromSettings();
|
||||||
|
migratePluginSettings();
|
||||||
registerLinkProviders();
|
registerLinkProviders();
|
||||||
|
|
||||||
//Link Providers need to be already registered
|
//Link Providers need to be already registered
|
||||||
@ -290,6 +291,29 @@ public class BackgroundService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void migratePluginSettings() {
|
||||||
|
SharedPreferences globalPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
|
||||||
|
for (String pluginKey : PluginFactory.getAvailablePlugins()) {
|
||||||
|
if (PluginFactory.getPluginInfo(pluginKey).supportsDeviceSpecificSettings()) {
|
||||||
|
Iterator<Device> it = devices.values().iterator();
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Device device = it.next();
|
||||||
|
Plugin plugin = PluginFactory.instantiatePluginForDevice(getBaseContext(), pluginKey, device);
|
||||||
|
|
||||||
|
if (plugin == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.copyGlobalToDeviceSpecificSettings(globalPrefs);
|
||||||
|
if (!it.hasNext()) {
|
||||||
|
plugin.removeSettings(globalPrefs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void changePersistentNotificationVisibility(boolean visible) {
|
public void changePersistentNotificationVisibility(boolean visible) {
|
||||||
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
@ -33,6 +33,12 @@ import android.preference.PreferenceManager;
|
|||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.AnyThread;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.WorkerThread;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import org.kde.kdeconnect.Backends.BaseLink;
|
import org.kde.kdeconnect.Backends.BaseLink;
|
||||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||||
@ -57,11 +63,6 @@ import java.util.Vector;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import androidx.annotation.AnyThread;
|
|
||||||
import androidx.annotation.WorkerThread;
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
|
|
||||||
public class Device implements BaseLink.PacketReceiver {
|
public class Device implements BaseLink.PacketReceiver {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -712,11 +713,13 @@ public class Device implements BaseLink.PacketReceiver {
|
|||||||
// Plugin-related functions
|
// Plugin-related functions
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public <T extends Plugin> T getPlugin(Class<T> pluginClass) {
|
public <T extends Plugin> T getPlugin(Class<T> pluginClass) {
|
||||||
Plugin plugin = getPlugin(Plugin.getPluginKey(pluginClass));
|
Plugin plugin = getPlugin(Plugin.getPluginKey(pluginClass));
|
||||||
return (T) plugin;
|
return (T) plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public Plugin getPlugin(String pluginKey) {
|
public Plugin getPlugin(String pluginKey) {
|
||||||
return plugins.get(pluginKey);
|
return plugins.get(pluginKey);
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,17 @@ package org.kde.kdeconnect.Plugins;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
|
||||||
import org.kde.kdeconnect.Device;
|
import org.kde.kdeconnect.Device;
|
||||||
import org.kde.kdeconnect.NetworkPacket;
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
import org.kde.kdeconnect.UserInterface.AlertDialogFragment;
|
import org.kde.kdeconnect.UserInterface.AlertDialogFragment;
|
||||||
@ -34,19 +41,37 @@ import org.kde.kdeconnect.UserInterface.PermissionsAlertDialogFragment;
|
|||||||
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
|
|
||||||
public abstract class Plugin {
|
public abstract class Plugin {
|
||||||
protected Device device;
|
protected Device device;
|
||||||
protected Context context;
|
protected Context context;
|
||||||
protected int permissionExplanation = R.string.permission_explanation;
|
protected int permissionExplanation = R.string.permission_explanation;
|
||||||
protected int optionalPermissionExplanation = R.string.optional_permission_explanation;
|
protected int optionalPermissionExplanation = R.string.optional_permission_explanation;
|
||||||
|
@Nullable
|
||||||
|
protected SharedPreferences preferences;
|
||||||
|
|
||||||
public final void setContext(Context context, Device device) {
|
public final void setContext(@NonNull Context context, @Nullable Device device) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
|
if (device != null) {
|
||||||
|
this.preferences = this.context.getSharedPreferences(this.getSharedPreferencesName(), Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSharedPreferencesName() {
|
||||||
|
if (device == null) {
|
||||||
|
throw new RuntimeException("You have to call setContext() before you can call getSharedPreferencesName()");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.supportsDeviceSpecificSettings())
|
||||||
|
return this.device.getDeviceId() + "_" + this.getPluginKey() + "_preferences";
|
||||||
|
else
|
||||||
|
return this.getPluginKey() + "_preferences";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public SharedPreferences getPreferences() {
|
||||||
|
return this.preferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,6 +146,30 @@ public abstract class Plugin {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to find out if a plugin supports device specific settings.
|
||||||
|
* If you return true your PluginSettingsFragment will use the device
|
||||||
|
* specific SharedPreferences to store the settings.
|
||||||
|
*
|
||||||
|
* @return true if this plugin supports device specific settings
|
||||||
|
*/
|
||||||
|
public boolean supportsDeviceSpecificSettings() { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when it's time to move the plugin settings from the global preferences
|
||||||
|
* to device specific preferences
|
||||||
|
*
|
||||||
|
* @param globalSharedPreferences The global Preferences to copy the settings from
|
||||||
|
*/
|
||||||
|
public void copyGlobalToDeviceSpecificSettings(SharedPreferences globalSharedPreferences) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the plugin should remove it's settings from the provided ShardPreferences
|
||||||
|
*
|
||||||
|
* @param sharedPreferences The SharedPreferences to remove the settings from
|
||||||
|
*/
|
||||||
|
public void removeSettings(SharedPreferences sharedPreferences) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If hasSettings returns true, this will be called when the user
|
* If hasSettings returns true, this will be called when the user
|
||||||
* wants to access this plugin's preferences. The default implementation
|
* wants to access this plugin's preferences. The default implementation
|
||||||
@ -244,5 +293,4 @@ public abstract class Plugin {
|
|||||||
public int getMinSdk() {
|
public int getMinSdk() {
|
||||||
return Build.VERSION_CODES.BASE;
|
return Build.VERSION_CODES.BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,14 +42,15 @@ public class PluginFactory {
|
|||||||
public static class PluginInfo {
|
public static class PluginInfo {
|
||||||
|
|
||||||
PluginInfo(String displayName, String description, Drawable icon,
|
PluginInfo(String displayName, String description, Drawable icon,
|
||||||
boolean enabledByDefault, boolean hasSettings, boolean listenToUnpaired,
|
boolean enabledByDefault, boolean hasSettings, boolean supportsDeviceSpecificSettings,
|
||||||
String[] supportedPacketTypes, String[] outgoingPacketTypes,
|
boolean listenToUnpaired, String[] supportedPacketTypes, String[] outgoingPacketTypes,
|
||||||
Class<? extends Plugin> instantiableClass) {
|
Class<? extends Plugin> instantiableClass) {
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.enabledByDefault = enabledByDefault;
|
this.enabledByDefault = enabledByDefault;
|
||||||
this.hasSettings = hasSettings;
|
this.hasSettings = hasSettings;
|
||||||
|
this.supportsDeviceSpecificSettings = supportsDeviceSpecificSettings;
|
||||||
this.listenToUnpaired = listenToUnpaired;
|
this.listenToUnpaired = listenToUnpaired;
|
||||||
HashSet<String> incoming = new HashSet<>();
|
HashSet<String> incoming = new HashSet<>();
|
||||||
if (supportedPacketTypes != null) Collections.addAll(incoming, supportedPacketTypes);
|
if (supportedPacketTypes != null) Collections.addAll(incoming, supportedPacketTypes);
|
||||||
@ -76,6 +77,8 @@ public class PluginFactory {
|
|||||||
return hasSettings;
|
return hasSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsDeviceSpecificSettings() { return supportsDeviceSpecificSettings; }
|
||||||
|
|
||||||
public boolean isEnabledByDefault() {
|
public boolean isEnabledByDefault() {
|
||||||
return enabledByDefault;
|
return enabledByDefault;
|
||||||
}
|
}
|
||||||
@ -101,6 +104,7 @@ public class PluginFactory {
|
|||||||
private final Drawable icon;
|
private final Drawable icon;
|
||||||
private final boolean enabledByDefault;
|
private final boolean enabledByDefault;
|
||||||
private final boolean hasSettings;
|
private final boolean hasSettings;
|
||||||
|
private final boolean supportsDeviceSpecificSettings;
|
||||||
private final boolean listenToUnpaired;
|
private final boolean listenToUnpaired;
|
||||||
private final Set<String> supportedPacketTypes;
|
private final Set<String> supportedPacketTypes;
|
||||||
private final Set<String> outgoingPacketTypes;
|
private final Set<String> outgoingPacketTypes;
|
||||||
@ -120,8 +124,9 @@ public class PluginFactory {
|
|||||||
Plugin p = ((Plugin) pluginClass.newInstance());
|
Plugin p = ((Plugin) pluginClass.newInstance());
|
||||||
p.setContext(context, null);
|
p.setContext(context, null);
|
||||||
PluginInfo info = new PluginInfo(p.getDisplayName(), p.getDescription(), p.getIcon(),
|
PluginInfo info = new PluginInfo(p.getDisplayName(), p.getDescription(), p.getIcon(),
|
||||||
p.isEnabledByDefault(), p.hasSettings(), p.listensToUnpairedDevices(),
|
p.isEnabledByDefault(), p.hasSettings(), p.supportsDeviceSpecificSettings(),
|
||||||
p.getSupportedPacketTypes(), p.getOutgoingPacketTypes(), p.getClass());
|
p.listensToUnpairedDevices(), p.getSupportedPacketTypes(),
|
||||||
|
p.getOutgoingPacketTypes(), p.getClass());
|
||||||
pluginInfo.put(p.getPluginKey(), info);
|
pluginInfo.put(p.getPluginKey(), info);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -27,6 +27,8 @@ import android.net.Uri;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.kde.kdeconnect.NetworkPacket;
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
@ -43,19 +45,16 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
@PluginFactory.LoadablePlugin
|
@PluginFactory.LoadablePlugin
|
||||||
public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
private final static String PACKET_TYPE_SFTP = "kdeconnect.sftp";
|
private final static String PACKET_TYPE_SFTP = "kdeconnect.sftp";
|
||||||
private final static String PACKET_TYPE_SFTP_REQUEST = "kdeconnect.sftp.request";
|
private final static String PACKET_TYPE_SFTP_REQUEST = "kdeconnect.sftp.request";
|
||||||
|
|
||||||
private static final SimpleSftpServer server = new SimpleSftpServer();
|
static int PREFERENCE_KEY_STORAGE_INFO_LIST = R.string.sftp_preference_key_storage_info_list;
|
||||||
|
private static int PREFERENCE_KEY_ADD_CAMERA_SHORTCUT = R.string.sftp_preference_key_add_camera_shortcut;
|
||||||
|
|
||||||
private String KeyStorageInfoList;
|
private static final SimpleSftpServer server = new SimpleSftpServer();
|
||||||
private String KeyAddCameraShortcut;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDisplayName() {
|
public String getDisplayName() {
|
||||||
@ -69,14 +68,11 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
KeyStorageInfoList = context.getString(R.string.sftp_preference_key_storage_info_list);
|
|
||||||
KeyAddCameraShortcut = context.getString(R.string.sftp_preference_key_add_camera_shortcut);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
server.init(context, device);
|
server.init(context, device);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
|
||||||
return SftpSettingsFragment.getStorageInfoList(context).size() != 0;
|
return SftpSettingsFragment.getStorageInfoList(context, this).size() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -89,7 +85,7 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
@Override
|
@Override
|
||||||
public boolean checkOptionalPermissions() {
|
public boolean checkOptionalPermissions() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
return SftpSettingsFragment.getStorageInfoList(context).size() != 0;
|
return SftpSettingsFragment.getStorageInfoList(context, this).size() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -110,7 +106,9 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
server.stop();
|
server.stop();
|
||||||
PreferenceManager.getDefaultSharedPreferences(context).unregisterOnSharedPreferenceChangeListener(this);
|
if (preferences != null) {
|
||||||
|
preferences.unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -119,7 +117,7 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
ArrayList<String> paths = new ArrayList<>();
|
ArrayList<String> paths = new ArrayList<>();
|
||||||
ArrayList<String> pathNames = new ArrayList<>();
|
ArrayList<String> pathNames = new ArrayList<>();
|
||||||
|
|
||||||
List<StorageInfo> storageInfoList = SftpSettingsFragment.getStorageInfoList(context);
|
List<StorageInfo> storageInfoList = SftpSettingsFragment.getStorageInfoList(context, this);
|
||||||
Collections.sort(storageInfoList, new StorageInfo.UriNameComparator());
|
Collections.sort(storageInfoList, new StorageInfo.UriNameComparator());
|
||||||
|
|
||||||
if (storageInfoList.size() > 0) {
|
if (storageInfoList.size() > 0) {
|
||||||
@ -141,7 +139,9 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
removeChildren(storageInfoList);
|
removeChildren(storageInfoList);
|
||||||
|
|
||||||
if (server.start(storageInfoList)) {
|
if (server.start(storageInfoList)) {
|
||||||
PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(this);
|
if (preferences != null) {
|
||||||
|
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
NetworkPacket np2 = new NetworkPacket(PACKET_TYPE_SFTP);
|
NetworkPacket np2 = new NetworkPacket(PACKET_TYPE_SFTP);
|
||||||
|
|
||||||
@ -170,11 +170,13 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
private void getPathsAndNamesForStorageInfoList(List<String> paths, List<String> pathNames, List<StorageInfo> storageInfoList) {
|
private void getPathsAndNamesForStorageInfoList(List<String> paths, List<String> pathNames, List<StorageInfo> storageInfoList) {
|
||||||
StorageInfo prevInfo = null;
|
StorageInfo prevInfo = null;
|
||||||
StringBuilder pathBuilder = new StringBuilder();
|
StringBuilder pathBuilder = new StringBuilder();
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
boolean addCameraShortcuts = false;
|
boolean addCameraShortcuts = false;
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
|
||||||
addCameraShortcuts = prefs.getBoolean(context.getString(R.string.sftp_preference_key_add_camera_shortcut), true);
|
if (preferences != null) {
|
||||||
|
addCameraShortcuts = preferences.getBoolean(context.getString(PREFERENCE_KEY_ADD_CAMERA_SHORTCUT), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (StorageInfo curInfo : storageInfoList) {
|
for (StorageInfo curInfo : storageInfoList) {
|
||||||
@ -245,6 +247,33 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsDeviceSpecificSettings() { return true; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyGlobalToDeviceSpecificSettings(SharedPreferences globalSharedPreferences) {
|
||||||
|
String KeyStorageInfoList = context.getString(PREFERENCE_KEY_STORAGE_INFO_LIST);
|
||||||
|
String KeyAddCameraShortcut = context.getString(PREFERENCE_KEY_ADD_CAMERA_SHORTCUT);
|
||||||
|
|
||||||
|
if (this.preferences != null &&
|
||||||
|
(!this.preferences.contains(KeyStorageInfoList) || !this.preferences.contains(KeyAddCameraShortcut))) {
|
||||||
|
this.preferences
|
||||||
|
.edit()
|
||||||
|
.putString(KeyStorageInfoList, globalSharedPreferences.getString(KeyStorageInfoList, "[]"))
|
||||||
|
.putBoolean(KeyAddCameraShortcut, globalSharedPreferences.getBoolean(KeyAddCameraShortcut, true))
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeSettings(SharedPreferences sharedPreferences) {
|
||||||
|
sharedPreferences
|
||||||
|
.edit()
|
||||||
|
.remove(context.getString(PREFERENCE_KEY_STORAGE_INFO_LIST))
|
||||||
|
.remove(context.getString(PREFERENCE_KEY_ADD_CAMERA_SHORTCUT))
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PluginSettingsFragment getSettingsFragment(Activity activity) {
|
public PluginSettingsFragment getSettingsFragment(Activity activity) {
|
||||||
return SftpSettingsFragment.newInstance(getPluginKey());
|
return SftpSettingsFragment.newInstance(getPluginKey());
|
||||||
@ -252,7 +281,8 @@ public class SftpPlugin extends Plugin implements SharedPreferences.OnSharedPref
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
if (key.equals(KeyStorageInfoList) || key.equals(KeyAddCameraShortcut)) {
|
if (key.equals(context.getString(PREFERENCE_KEY_STORAGE_INFO_LIST)) ||
|
||||||
|
key.equals(context.getString(PREFERENCE_KEY_ADD_CAMERA_SHORTCUT))) {
|
||||||
//TODO: There used to be a way to request an un-mount (see desktop SftpPlugin's Mounter::onPackageReceived) but that is not handled anymore by the SftpPlugin on KDE.
|
//TODO: There used to be a way to request an un-mount (see desktop SftpPlugin's Mounter::onPackageReceived) but that is not handled anymore by the SftpPlugin on KDE.
|
||||||
if (server.isStarted()) {
|
if (server.isStarted()) {
|
||||||
server.stop();
|
server.stop();
|
||||||
|
@ -36,12 +36,21 @@ import android.view.Menu;
|
|||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.view.ActionMode;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceCategory;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.kde.kdeconnect.BackgroundService;
|
import org.kde.kdeconnect.BackgroundService;
|
||||||
import org.kde.kdeconnect.Device;
|
import org.kde.kdeconnect.Device;
|
||||||
import org.kde.kdeconnect.Helpers.StorageHelper;
|
import org.kde.kdeconnect.Helpers.StorageHelper;
|
||||||
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
||||||
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
@ -52,15 +61,6 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.view.ActionMode;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceCategory;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import androidx.preference.PreferenceScreen;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
//TODO: Is it possible on API 19 to select a directory and then have write permission for everything beneath it
|
//TODO: Is it possible on API 19 to select a directory and then have write permission for everything beneath it
|
||||||
//TODO: Is it necessary to check if uri permissions are still in place? If it is make the user aware of the fact (red text or something)
|
//TODO: Is it necessary to check if uri permissions are still in place? If it is make the user aware of the fact (red text or something)
|
||||||
public class SftpSettingsFragment
|
public class SftpSettingsFragment
|
||||||
@ -116,10 +116,10 @@ public class SftpSettingsFragment
|
|||||||
|
|
||||||
int sdkInt = Build.VERSION.SDK_INT;
|
int sdkInt = Build.VERSION.SDK_INT;
|
||||||
|
|
||||||
storageInfoList = getStorageInfoList(requireContext());
|
storageInfoList = getStorageInfoList(requireContext(), plugin);
|
||||||
|
|
||||||
PreferenceScreen preferenceScreen = getPreferenceScreen();
|
PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||||
preferenceCategory = (PreferenceCategory) preferenceScreen
|
preferenceCategory = preferenceScreen
|
||||||
.findPreference(getString(R.string.sftp_preference_key_preference_category));
|
.findPreference(getString(R.string.sftp_preference_key_preference_category));
|
||||||
|
|
||||||
if (sdkInt <= 19) {
|
if (sdkInt <= 19) {
|
||||||
@ -245,30 +245,30 @@ public class SftpSettingsFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveStorageInfoList() {
|
private void saveStorageInfoList() {
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
SharedPreferences preferences = this.plugin.getPreferences();
|
||||||
|
|
||||||
JSONArray jsonArray = new JSONArray();
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (SftpPlugin.StorageInfo storageInfo : storageInfoList) {
|
for (SftpPlugin.StorageInfo storageInfo : this.storageInfoList) {
|
||||||
jsonArray.put(storageInfo.toJSON());
|
jsonArray.put(storageInfo.toJSON());
|
||||||
}
|
}
|
||||||
} catch (JSONException ignored) {}
|
} catch (JSONException ignored) {}
|
||||||
|
|
||||||
preferences
|
preferences
|
||||||
.edit()
|
.edit()
|
||||||
.putString(requireContext().getString(R.string.sftp_preference_key_storage_info_list), jsonArray.toString())
|
.putString(requireContext().getString(SftpPlugin.PREFERENCE_KEY_STORAGE_INFO_LIST), jsonArray.toString())
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
static List<SftpPlugin.StorageInfo> getStorageInfoList(@NonNull Context context) {
|
static List<SftpPlugin.StorageInfo> getStorageInfoList(@NonNull Context context, @NonNull Plugin plugin) {
|
||||||
ArrayList<SftpPlugin.StorageInfo> storageInfoList = new ArrayList<>();
|
ArrayList<SftpPlugin.StorageInfo> storageInfoList = new ArrayList<>();
|
||||||
|
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences deviceSettings = plugin.getPreferences();
|
||||||
|
|
||||||
String jsonString = preferences
|
String jsonString = deviceSettings
|
||||||
.getString(context.getString(R.string.sftp_preference_key_storage_info_list), "[]");
|
.getString(context.getString(SftpPlugin.PREFERENCE_KEY_STORAGE_INFO_LIST), "[]");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JSONArray jsonArray = new JSONArray(jsonString);
|
JSONArray jsonArray = new JSONArray(jsonString);
|
||||||
@ -414,11 +414,19 @@ public class SftpSettingsFragment
|
|||||||
|
|
||||||
addStoragePreferences(preferenceCategory);
|
addStoragePreferences(preferenceCategory);
|
||||||
|
|
||||||
Device device = BackgroundService.getInstance().getDevice(getDeviceId());
|
Device device = getDeviceOrThrow();
|
||||||
|
|
||||||
if (device != null) {
|
|
||||||
device.reloadPluginsFromSettings();
|
device.reloadPluginsFromSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Device getDeviceOrThrow() {
|
||||||
|
Device device = BackgroundService.getInstance().getDevice(getDeviceId());
|
||||||
|
|
||||||
|
if (device == null) {
|
||||||
|
throw new RuntimeException("SftpSettingsFragment.getDeviceOrThrow(): No device with id: " + getDeviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,20 +20,27 @@
|
|||||||
|
|
||||||
package org.kde.kdeconnect.UserInterface;
|
package org.kde.kdeconnect.UserInterface;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import org.kde.kdeconnect.BackgroundService;
|
||||||
|
import org.kde.kdeconnect.Device;
|
||||||
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
import org.kde.kdeconnect.Plugins.PluginFactory;
|
import org.kde.kdeconnect.Plugins.PluginFactory;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
|
||||||
|
|
||||||
public class PluginSettingsFragment extends PreferenceFragmentCompat {
|
public class PluginSettingsFragment extends PreferenceFragmentCompat {
|
||||||
private static final String ARG_PLUGIN_KEY = "plugin_key";
|
private static final String ARG_PLUGIN_KEY = "plugin_key";
|
||||||
|
|
||||||
private String pluginKey;
|
private String pluginKey;
|
||||||
|
protected Device device;
|
||||||
|
protected Plugin plugin;
|
||||||
|
|
||||||
public static PluginSettingsFragment newInstance(@NonNull String pluginKey) {
|
public static PluginSettingsFragment newInstance(@NonNull String pluginKey) {
|
||||||
PluginSettingsFragment fragment = new PluginSettingsFragment();
|
PluginSettingsFragment fragment = new PluginSettingsFragment();
|
||||||
@ -60,12 +67,20 @@ public class PluginSettingsFragment extends PreferenceFragmentCompat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pluginKey = getArguments().getString(ARG_PLUGIN_KEY);
|
pluginKey = getArguments().getString(ARG_PLUGIN_KEY);
|
||||||
|
this.device = getDeviceOrThrow(getDeviceId());
|
||||||
|
this.plugin = device.getPlugin(pluginKey);
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
if (this.plugin != null && this.plugin.supportsDeviceSpecificSettings()) {
|
||||||
|
PreferenceManager prefsManager = getPreferenceManager();
|
||||||
|
prefsManager.setSharedPreferencesName(this.plugin.getSharedPreferencesName());
|
||||||
|
prefsManager.setSharedPreferencesMode(Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
int resFile = getResources().getIdentifier(pluginKey.toLowerCase(Locale.ENGLISH) + "_preferences", "xml",
|
int resFile = getResources().getIdentifier(pluginKey.toLowerCase(Locale.ENGLISH) + "_preferences", "xml",
|
||||||
requireContext().getPackageName());
|
requireContext().getPackageName());
|
||||||
addPreferencesFromResource(resFile);
|
addPreferencesFromResource(resFile);
|
||||||
@ -82,4 +97,14 @@ public class PluginSettingsFragment extends PreferenceFragmentCompat {
|
|||||||
public String getDeviceId() {
|
public String getDeviceId() {
|
||||||
return ((PluginSettingsActivity)requireActivity()).getDeviceId();
|
return ((PluginSettingsActivity)requireActivity()).getDeviceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Device getDeviceOrThrow(String deviceId) {
|
||||||
|
Device device = BackgroundService.getInstance().getDevice(deviceId);
|
||||||
|
|
||||||
|
if (device == null) {
|
||||||
|
throw new RuntimeException("PluginSettingsFragment.onCreatePreferences() - No device with id " + getDeviceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return device;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,6 @@ import android.os.Build;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
|
||||||
|
|
||||||
import org.kde.kdeconnect.BackgroundService;
|
|
||||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
|
||||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
|
||||||
import org.kde.kdeconnect_tp.R;
|
|
||||||
|
|
||||||
import androidx.preference.EditTextPreference;
|
import androidx.preference.EditTextPreference;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@ -24,6 +16,13 @@ import androidx.preference.PreferenceScreen;
|
|||||||
import androidx.preference.SwitchPreferenceCompat;
|
import androidx.preference.SwitchPreferenceCompat;
|
||||||
import androidx.preference.TwoStatePreference;
|
import androidx.preference.TwoStatePreference;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
|
import org.kde.kdeconnect.BackgroundService;
|
||||||
|
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||||
|
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||||
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
public class SettingsFragment extends PreferenceFragmentCompat {
|
public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
private MainActivity mainActivity;
|
private MainActivity mainActivity;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user