diff --git a/KdeConnect/KdeConnect.iml b/KdeConnect/KdeConnect.iml index db686fa1..fa5ccc82 100644 --- a/KdeConnect/KdeConnect.iml +++ b/KdeConnect/KdeConnect.iml @@ -66,7 +66,7 @@ - + diff --git a/KdeConnect/build.gradle b/KdeConnect/build.gradle index c4e52ae5..876cc0c2 100644 --- a/KdeConnect/build.gradle +++ b/KdeConnect/build.gradle @@ -16,8 +16,8 @@ dependencies { } android { - compileSdkVersion 17 - buildToolsVersion "17.0.0" + compileSdkVersion 18 + buildToolsVersion "18.0.1" defaultConfig { minSdkVersion 7 diff --git a/KdeConnect/libs/android-support-v4.jar b/KdeConnect/libs/android-support-v4.jar deleted file mode 100644 index 428bdbc0..00000000 Binary files a/KdeConnect/libs/android-support-v4.jar and /dev/null differ diff --git a/KdeConnect/src/main/AndroidManifest.xml b/KdeConnect/src/main/AndroidManifest.xml index 03f20dd9..4ae06c14 100644 --- a/KdeConnect/src/main/AndroidManifest.xml +++ b/KdeConnect/src/main/AndroidManifest.xml @@ -68,6 +68,13 @@ android:name="org.kde.connect.BackgroundService"> + + + + + + diff --git a/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java b/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java index deb9507d..c2afcee8 100644 --- a/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java +++ b/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java @@ -32,7 +32,7 @@ public class BackgroundService extends Service { Set trustedDevices = preferences.getStringSet("trusted", new HashSet()); for(String deviceId : trustedDevices) { Log.e("loadRememberedDevicesFromSettings",deviceId); - devices.put(deviceId,new Device(getApplicationContext(), deviceId)); + devices.put(deviceId,new Device(getBaseContext(), deviceId)); } } @@ -74,7 +74,7 @@ public class BackgroundService extends Service { device.addLink(link); } else { Log.i("BackgroundService", "unknown device"); - Device device = new Device(getApplicationContext(), deviceId, name, link); + Device device = new Device(getBaseContext(), deviceId, name, link); devices.put(deviceId, device); } } diff --git a/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/BaseComputerLink.java b/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/BaseComputerLink.java index 777715b1..3a00e1ce 100644 --- a/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/BaseComputerLink.java +++ b/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/BaseComputerLink.java @@ -49,6 +49,6 @@ public abstract class BaseComputerLink { } //TO OVERRIDE - public abstract boolean sendPackage(NetworkPackage np); //Should be async + public abstract boolean sendPackage(NetworkPackage np); } diff --git a/KdeConnect/src/main/java/org/kde/connect/Device.java b/KdeConnect/src/main/java/org/kde/connect/Device.java index 596e05ac..cb3e60f7 100644 --- a/KdeConnect/src/main/java/org/kde/connect/Device.java +++ b/KdeConnect/src/main/java/org/kde/connect/Device.java @@ -20,6 +20,7 @@ public class Device implements BaseComputerLink.PackageReceiver { private ArrayList links = new ArrayList(); private HashMap plugins = new HashMap(); + private HashMap failedPlugins = new HashMap(); private Context context; private String deviceId; @@ -184,7 +185,7 @@ public class Device implements BaseComputerLink.PackageReceiver { return plugins.get(name); } - public Plugin addPlugin(String name) { + private Plugin addPlugin(String name) { Plugin existing = plugins.get(name); if (existing != null) { Log.e("addPlugin","plugin already present:" + name); @@ -194,12 +195,18 @@ public class Device implements BaseComputerLink.PackageReceiver { Plugin plugin = PluginFactory.instantiatePluginForDevice(context, name, this); if (plugin == null) { Log.e("addPlugin","could not create plugin: "+name); + failedPlugins.put(name, plugin); return null; } try { - plugin.onCreate(); + boolean success = plugin.onCreate(); + if (!success) { + failedPlugins.put(name, plugin); + return null; + } } catch (Exception e) { + failedPlugins.put(name, plugin); Log.e("addPlugin","Exception calling onCreate for "+name); e.printStackTrace(); return null; @@ -207,14 +214,22 @@ public class Device implements BaseComputerLink.PackageReceiver { Log.e("addPlugin",name); + failedPlugins.remove(name); plugins.put(name, plugin); + return plugin; } - public boolean removePlugin(String name) { + private boolean removePlugin(String name) { + Plugin plugin = plugins.remove(name); + Plugin failedPlugin = failedPlugins.remove(name); + if (plugin == null) { - return false; + if (failedPlugin == null) { + return false; + } + plugin = failedPlugin; } try { @@ -230,21 +245,32 @@ public class Device implements BaseComputerLink.PackageReceiver { return true; } - public void setPluginEnabled(String key, boolean value) { - settings.edit().putBoolean(key,value).commit(); - if (value) addPlugin(key); - else removePlugin(key); + public void setPluginEnabled(String pluginName, boolean value) { + settings.edit().putBoolean(pluginName,value).commit(); + if (value) addPlugin(pluginName); + else removePlugin(pluginName); + for (PluginsChangedListener listener : pluginsChangedListeners) { + listener.onPluginsChanged(this); + } } + public boolean isPluginEnabled(String pluginName) { + boolean enabledByDefault = PluginFactory.getPluginInfo(context, pluginName).isEnabledByDefault(); + boolean enabled = settings.getBoolean(pluginName, enabledByDefault); + return enabled; + } + + public void reloadPluginsFromSettings() { + failedPlugins.clear(); + Set availablePlugins = PluginFactory.getAvailablePlugins(); for(String pluginName : availablePlugins) { boolean enabled = false; if (isTrusted() && isReachable()) { - boolean enabledByDefault = PluginFactory.isPluginEnabledByDefault(pluginName); - enabled = settings.getBoolean(pluginName, enabledByDefault); + enabled = isPluginEnabled(pluginName); } //Log.e("reloadPluginsFromSettings",pluginName+"->"+enabled); if (enabled) { @@ -254,20 +280,27 @@ public class Device implements BaseComputerLink.PackageReceiver { } } + for (PluginsChangedListener listener : pluginsChangedListeners) { + listener.onPluginsChanged(this); + } } - public void readPluginPreferences(SharedPreferences outSettings) { - SharedPreferences.Editor editor = outSettings.edit(); + public HashMap getFailedPlugins() { + return failedPlugins; + } - Set availablePlugins = PluginFactory.getAvailablePlugins(); - for(String pluginName : availablePlugins) { - boolean enabledByDefault = PluginFactory.isPluginEnabledByDefault(pluginName); - boolean enabled = settings.getBoolean(pluginName, enabledByDefault); - editor.putBoolean(pluginName, enabled); - //Log.e("readPluginPreferences",pluginName+"->"+enabled); - } + interface PluginsChangedListener { + void onPluginsChanged(Device device); + } - editor.commit(); + ArrayList pluginsChangedListeners = new ArrayList(); + + public void addPluginsChangedListener(PluginsChangedListener listener) { + pluginsChangedListeners.add(listener); + } + + public void removePluginsChangedListener(PluginsChangedListener listener) { + pluginsChangedListeners.remove(listener); } } diff --git a/KdeConnect/src/main/java/org/kde/connect/DeviceActivity.java b/KdeConnect/src/main/java/org/kde/connect/DeviceActivity.java index da4947c3..e9d0ef47 100644 --- a/KdeConnect/src/main/java/org/kde/connect/DeviceActivity.java +++ b/KdeConnect/src/main/java/org/kde/connect/DeviceActivity.java @@ -2,21 +2,71 @@ package org.kde.connect; import android.app.Activity; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceManager; +import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.CompoundButton; +import android.widget.ListView; import android.widget.Switch; import org.kde.connect.Plugins.PingPlugin; +import org.kde.connect.Plugins.Plugin; import org.kde.kdeconnect.R; +import java.util.HashMap; +import java.util.Map; + public class DeviceActivity extends Activity { private String deviceId; + private Device.PluginsChangedListener pluginsChangedListener = new Device.PluginsChangedListener() { + @Override + public void onPluginsChanged(final Device device) { + + runOnUiThread(new Runnable() { + @Override + public void run() { + Log.e("MainActivity", "updateComputerList"); + + final HashMap plugins = device.getFailedPlugins(); + final String[] ids = plugins.keySet().toArray(new String[plugins.size()]); + String[] names = new String[plugins.size()]; + for(int i = 0; i < ids.length; i++) { + Plugin p = plugins.get(ids[i]); + names[i] = p.getDisplayName(); + } + + ListView list = (ListView)findViewById(R.id.listView1); + + list.setAdapter(new ArrayAdapter(DeviceActivity.this, android.R.layout.simple_list_item_1, names)); + + list.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int position, long id) { + Plugin p = plugins.get(ids[position]); + p.getErrorDialog(DeviceActivity.this).show(); + } + }); + + findViewById(R.id.textView).setVisibility(plugins.size() > 0? View.VISIBLE : View.GONE); + + } + }); + + + + } + }; @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -63,6 +113,8 @@ public class DeviceActivity extends Activity { public void onServiceStart(BackgroundService service) { Device device = service.getDevice(deviceId); setTitle(device.getName()); + device.addPluginsChangedListener(pluginsChangedListener); + pluginsChangedListener.onPluginsChanged(device); } }); @@ -83,8 +135,7 @@ public class DeviceActivity extends Activity { @Override public void onServiceStart(BackgroundService service) { Device device = service.getDevice(deviceId); - PingPlugin pi = (PingPlugin) device.getPlugin("plugin_ping"); - if (pi != null) pi.sendPing(); + device.sendPackage(new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PING)); } }); @@ -105,6 +156,19 @@ public class DeviceActivity extends Activity { } }); + + } + @Override + protected void onDestroy() { + BackgroundService.RunCommand(DeviceActivity.this, new BackgroundService.InstanceCallback() { + @Override + public void onServiceStart(BackgroundService service) { + Device device = service.getDevice(deviceId); + device.removePluginsChangedListener(pluginsChangedListener); + } + }); + super.onDestroy(); + } } diff --git a/KdeConnect/src/main/java/org/kde/connect/Helpers/AppsHelper.java b/KdeConnect/src/main/java/org/kde/connect/Helpers/AppsHelper.java new file mode 100644 index 00000000..aabf2c8a --- /dev/null +++ b/KdeConnect/src/main/java/org/kde/connect/Helpers/AppsHelper.java @@ -0,0 +1,61 @@ +package org.kde.connect.Helpers; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.provider.ContactsContract.PhoneLookup; +import android.util.Log; + +public class AppsHelper { + + public static String appNameLookup(Context context, String packageName) { + + try { + + PackageManager pm = context.getPackageManager(); + ApplicationInfo ai = pm.getApplicationInfo( packageName, 0); + + return pm.getApplicationLabel(ai).toString(); + + } catch (final PackageManager.NameNotFoundException e) { + + e.printStackTrace(); + Log.e("AppsHelper","Could not resolve name "+packageName); + + return null; + + } + + } + + public static Drawable appIconLookup(Context context, String packageName) { + + try { + + PackageManager pm = context.getPackageManager(); + ApplicationInfo ai = pm.getApplicationInfo( packageName, 0); + Drawable drawable = pm.getApplicationIcon(ai); + + return drawable; + + } catch (final PackageManager.NameNotFoundException e) { + + e.printStackTrace(); + Log.e("AppsHelper","Could not find icon for "+packageName); + + return null; + + } + + } + + + +} \ No newline at end of file diff --git a/KdeConnect/src/main/java/org/kde/connect/ContactsHelper.java b/KdeConnect/src/main/java/org/kde/connect/Helpers/ContactsHelper.java similarity index 97% rename from KdeConnect/src/main/java/org/kde/connect/ContactsHelper.java rename to KdeConnect/src/main/java/org/kde/connect/Helpers/ContactsHelper.java index 2ff3b87a..3f784dae 100644 --- a/KdeConnect/src/main/java/org/kde/connect/ContactsHelper.java +++ b/KdeConnect/src/main/java/org/kde/connect/Helpers/ContactsHelper.java @@ -1,4 +1,4 @@ -package org.kde.connect; +package org.kde.connect.Helpers; import android.content.Context; import android.database.Cursor; diff --git a/KdeConnect/src/main/java/org/kde/connect/Helpers/ImagesHelper.java b/KdeConnect/src/main/java/org/kde/connect/Helpers/ImagesHelper.java new file mode 100644 index 00000000..10d5068f --- /dev/null +++ b/KdeConnect/src/main/java/org/kde/connect/Helpers/ImagesHelper.java @@ -0,0 +1,23 @@ +package org.kde.connect.Helpers; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; + +public class ImagesHelper { + + public static Bitmap drawableToBitmap (Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable)drawable).getBitmap(); + } + + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } + +} diff --git a/KdeConnect/src/main/java/org/kde/connect/ImageListAdapter.java b/KdeConnect/src/main/java/org/kde/connect/ImageListAdapter.java new file mode 100644 index 00000000..4dbdd96f --- /dev/null +++ b/KdeConnect/src/main/java/org/kde/connect/ImageListAdapter.java @@ -0,0 +1,95 @@ +package org.kde.connect; + +import android.content.Context; +import android.database.DataSetObserver; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ListAdapter; +import android.widget.TextView; + +import org.kde.kdeconnect.R; + +import java.util.ArrayList; + +public class ImageListAdapter implements ListAdapter { + + static class ImageListElement { + String text; + Drawable icon; + } + + private ArrayList localList = new ArrayList(); + + public ImageListAdapter(ArrayList list) { + super(); + localList = list; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE ); + convertView = inflater.inflate(R.layout.imagelist_element, null); + } + ImageListElement data = localList.get(position); + ((TextView) convertView.findViewById(R.id.txt)).setText(data.text); + ((ImageView) convertView.findViewById(R.id.img)).setImageDrawable(data.icon); + return convertView; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + } // Empty + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + } // Empty + + @Override + public boolean isEmpty() { + return localList.size() == 0; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public int getViewTypeCount() { + return localList.size(); + } + + @Override + public int getItemViewType(int position) { + return 0; + } // Empty + + @Override + public Object getItem(int position) { + return localList.get(position); + } // Empty + + @Override + public int getCount() { + return localList.size(); + } + + @Override + public boolean isEnabled(int i) { + return false; + } + + @Override + public boolean areAllItemsEnabled() { + return false; + } + } diff --git a/KdeConnect/src/main/java/org/kde/connect/NotificationReceiver.java b/KdeConnect/src/main/java/org/kde/connect/NotificationReceiver.java new file mode 100644 index 00000000..f016a37a --- /dev/null +++ b/KdeConnect/src/main/java/org/kde/connect/NotificationReceiver.java @@ -0,0 +1,76 @@ +package org.kde.connect; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.service.notification.NotificationListenerService; +import android.service.notification.StatusBarNotification; +import android.util.Log; + +import java.util.ArrayList; + +public class NotificationReceiver extends NotificationListenerService { + + public interface NotificationListener { + void onNotificationPosted(StatusBarNotification statusBarNotification); + void onNotificationRemoved(StatusBarNotification statusBarNotification); + } + + private ArrayList listeners = new ArrayList(); + + public void addListener(NotificationListener listener) { + listeners.add(listener); + } + public void removeListener(NotificationListener listener) { + listeners.remove(listener); + } + + @Override + public void onNotificationPosted(StatusBarNotification statusBarNotification) { + Log.e("NotificationReceiver.onNotificationPosted","listeners: " + listeners.size()); + for(NotificationListener listener : listeners) { + listener.onNotificationPosted(statusBarNotification); + } + } + + @Override + public void onNotificationRemoved(StatusBarNotification statusBarNotification) { + for(NotificationListener listener : listeners) { + listener.onNotificationRemoved(statusBarNotification); + } + } + + + + + + //To use the service from the outer (name)space + + //This will be called for each intent launch, even if the service is already started and is reused + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.e("NotificationReceiver", "onStartCommand"); + for (InstanceCallback c : callbacks) { + c.onServiceStart(this); + } + callbacks.clear(); + return Service.START_STICKY; + } + + public interface InstanceCallback { + void onServiceStart(NotificationReceiver service); + } + + private static ArrayList callbacks = new ArrayList(); + + public static void Start(Context c) { + RunCommand(c, null); + } + + public static void RunCommand(Context c, final InstanceCallback callback) { + if (callback != null) callbacks.add(callback); + Intent serviceIntent = new Intent(c, NotificationReceiver.class); + c.startService(serviceIntent); + } + +} diff --git a/KdeConnect/src/main/java/org/kde/connect/PluginFactory.java b/KdeConnect/src/main/java/org/kde/connect/PluginFactory.java index cb1d0489..d13ffedf 100644 --- a/KdeConnect/src/main/java/org/kde/connect/PluginFactory.java +++ b/KdeConnect/src/main/java/org/kde/connect/PluginFactory.java @@ -2,12 +2,15 @@ package org.kde.connect; import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Build; +import android.preference.CheckBoxPreference; import android.util.Log; import org.kde.connect.Plugins.BatteryPlugin; import org.kde.connect.Plugins.ClipboardPlugin; import org.kde.connect.Plugins.MprisPlugin; +import org.kde.connect.Plugins.NotificationsPlugin; import org.kde.connect.Plugins.PingPlugin; import org.kde.connect.Plugins.Plugin; import org.kde.connect.Plugins.TelephonyPlugin; @@ -18,33 +21,81 @@ import java.util.TreeMap; public class PluginFactory { + public static class PluginInfo { + + public PluginInfo(String pluginName, String displayName, String description, Drawable icon, boolean enabledByDefault) { + this.pluginName = pluginName; + this.displayName = displayName; + this.description = description; + this.icon = icon; + this.enabledByDefault = enabledByDefault; + } + + public String getPluginName() { + return pluginName; + } + + public String getDisplayName() { + return displayName; + } + + public String getDescription() { + return description; + } + + public Drawable getIcon() { + return icon; + } + + public boolean isEnabledByDefault() { + return enabledByDefault; + } + + private String pluginName; + private String displayName; + private String description; + private final Drawable icon; + private boolean enabledByDefault; + + } + private static final Map availablePlugins = new TreeMap(); + private static final Map availablePluginsInfo = new TreeMap(); + static { - //Note that settings to enable the plugins must have tha same names as keys than here - availablePlugins.put("plugin_battery", BatteryPlugin.class); - availablePlugins.put("plugin_clipboard", ClipboardPlugin.class); - availablePlugins.put("plugin_mpris", MprisPlugin.class); - availablePlugins.put("plugin_ping", PingPlugin.class); - availablePlugins.put("plugin_telephony", TelephonyPlugin.class); + //TODO: Avoid this factory having to know every plugin + PluginFactory.registerPlugin(TelephonyPlugin.class); + PluginFactory.registerPlugin(PingPlugin.class); + PluginFactory.registerPlugin(MprisPlugin.class); + PluginFactory.registerPlugin(ClipboardPlugin.class); + PluginFactory.registerPlugin(BatteryPlugin.class); + PluginFactory.registerPlugin(NotificationsPlugin.class); + } + + public static PluginInfo getPluginInfo(Context context, String pluginName) { + PluginInfo info = availablePluginsInfo.get(pluginName); //Is it cached? + if (info != null) return info; + try { + Plugin p = ((Plugin)availablePlugins.get(pluginName).newInstance()); + p.setContext(context, null); + info = new PluginInfo(pluginName, p.getDisplayName(), p.getDescription(), p.getIcon(), p.isEnabledByDefault()); + availablePluginsInfo.put(pluginName, info); //Cache it + return info; + } catch(Exception e) { + e.printStackTrace(); + Log.e("PluginFactory","getPluginInfo exception"); + return null; + } } public static Set getAvailablePlugins() { return availablePlugins.keySet(); } - public static boolean isPluginEnabledByDefault(String pluginName) { - - if (pluginName.equals("plugin_clibpoard")) - return (Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT != 18); - else - return true; - - } - - public static Plugin instantiatePluginForDevice(Context context, String name, Device device) { - Class c = availablePlugins.get(name); + public static Plugin instantiatePluginForDevice(Context context, String pluginName, Device device) { + Class c = availablePlugins.get(pluginName); if (c == null) { - Log.e("PluginFactory", "Plugin not found: "+name); + Log.e("PluginFactory", "Plugin not found: "+pluginName); return null; } @@ -54,10 +105,21 @@ public class PluginFactory { return plugin; } catch(Exception e) { e.printStackTrace(); - Log.e("PluginFactory", "Could not instantiate plugin: "+name); + Log.e("PluginFactory", "Could not instantiate plugin: "+pluginName); return null; } } + public static void registerPlugin(Class pluginClass) { + try { + //I hate this but I need to create an instance because abstract static functions can't be declared + String pluginName = ((Plugin)pluginClass.newInstance()).getPluginName(); + availablePlugins.put(pluginName, pluginClass); + } catch(Exception e) { + Log.e("PluginFactory","addPlugin exception"); + e.printStackTrace(); + } + } + } diff --git a/KdeConnect/src/main/java/org/kde/connect/Plugins/BatteryPlugin.java b/KdeConnect/src/main/java/org/kde/connect/Plugins/BatteryPlugin.java index d342ffb7..a21519da 100644 --- a/KdeConnect/src/main/java/org/kde/connect/Plugins/BatteryPlugin.java +++ b/KdeConnect/src/main/java/org/kde/connect/Plugins/BatteryPlugin.java @@ -1,13 +1,17 @@ package org.kde.connect.Plugins; +import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.drawable.Drawable; import android.os.BatteryManager; import android.util.Log; import org.kde.connect.NetworkPackage; +import org.kde.connect.PluginFactory; +import org.kde.kdeconnect.R; public class BatteryPlugin extends Plugin { @@ -15,6 +19,36 @@ public class BatteryPlugin extends Plugin { private IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + /*static { + PluginFactory.registerPlugin(BatteryPlugin.class); + }*/ + + @Override + public String getPluginName() { + return "plugin_battery"; + } + + @Override + public String getDisplayName() { + return context.getResources().getString(R.string.pref_plugin_battery); + } + + @Override + public String getDescription() { + return context.getResources().getString(R.string.pref_plugin_battery_desc); + } + + @Override + public Drawable getIcon() { + return context.getResources().getDrawable(R.drawable.icon); + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + + private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -73,4 +107,9 @@ public class BatteryPlugin extends Plugin { return true; } + @Override + public AlertDialog getErrorDialog(Context baseContext) { + return null; + } + } diff --git a/KdeConnect/src/main/java/org/kde/connect/Plugins/ClipboardPlugin.java b/KdeConnect/src/main/java/org/kde/connect/Plugins/ClipboardPlugin.java index bdb46924..7c150faf 100644 --- a/KdeConnect/src/main/java/org/kde/connect/Plugins/ClipboardPlugin.java +++ b/KdeConnect/src/main/java/org/kde/connect/Plugins/ClipboardPlugin.java @@ -1,28 +1,67 @@ package org.kde.connect.Plugins; +import android.app.AlertDialog; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; +import android.content.DialogInterface; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.Log; import org.kde.connect.NetworkPackage; +import org.kde.connect.PluginFactory; +import org.kde.kdeconnect.R; public class ClipboardPlugin extends Plugin { - private boolean ignore_next_clipboard_change = false; + private String currentContent; + + /*static { + PluginFactory.registerPlugin(ClipboardPlugin.class); + }*/ + + @Override + public String getPluginName() { + return "plugin_clipboard"; + } + @Override + public String getDisplayName() { + return context.getResources().getString(R.string.pref_plugin_clipboard); + } + + @Override + public String getDescription() { + return context.getResources().getString(R.string.pref_plugin_clipboard_desc); + } + + @Override + public Drawable getIcon() { + return context.getResources().getDrawable(R.drawable.icon); + } + + @Override + public boolean isEnabledByDefault() { + return true; + } private ClipboardManager cm; private ClipboardManager.OnPrimaryClipChangedListener listener = new ClipboardManager.OnPrimaryClipChangedListener() { @Override public void onPrimaryClipChanged() { try { - if (ignore_next_clipboard_change) { - ignore_next_clipboard_change = false; - return; - } - NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_CLIPBOARD); + ClipData.Item item = cm.getPrimaryClip().getItemAt(0); - np.set("content",item.coerceToText(context).toString()); - device.sendPackage(np); + String content = item.coerceToText(context).toString(); + + if (!content.equals(currentContent)) { + NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_CLIPBOARD); + np.set("content", content); + device.sendPackage(np); + currentContent = content; + } + } catch(Exception e) { //Probably clipboard was not text } @@ -33,6 +72,11 @@ public class ClipboardPlugin extends Plugin { public boolean onCreate() { cm = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE); + + if (Build.VERSION.SDK_INT == 18) { + return false; + } + cm.addPrimaryClipChangedListener(listener); return true; @@ -43,6 +87,7 @@ public class ClipboardPlugin extends Plugin { public void onDestroy() { cm.removePrimaryClipChangedListener(listener); + } @Override @@ -51,10 +96,24 @@ public class ClipboardPlugin extends Plugin { return false; } - ignore_next_clipboard_change = true; - cm.setText(np.getString("content")); + currentContent = np.getString("content"); + cm.setText(currentContent); return true; } + @Override + public AlertDialog getErrorDialog(Context baseContext) { + return new AlertDialog.Builder(baseContext) + .setTitle("ClipBoard Plugin") + .setMessage("This plugin is not compatible with Android 4.3") + .setPositiveButton("Ok",new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + + } + }) + .create(); + } + } diff --git a/KdeConnect/src/main/java/org/kde/connect/Plugins/MprisPlugin.java b/KdeConnect/src/main/java/org/kde/connect/Plugins/MprisPlugin.java index 3a39e0fa..b5d44c59 100644 --- a/KdeConnect/src/main/java/org/kde/connect/Plugins/MprisPlugin.java +++ b/KdeConnect/src/main/java/org/kde/connect/Plugins/MprisPlugin.java @@ -1,10 +1,15 @@ package org.kde.connect.Plugins; +import android.app.AlertDialog; +import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.util.Log; import org.kde.connect.NetworkPackage; +import org.kde.connect.PluginFactory; +import org.kde.kdeconnect.R; import java.util.ArrayList; @@ -21,6 +26,34 @@ public class MprisPlugin extends Plugin { private String player = ""; private boolean playing = false; + /*static { + PluginFactory.registerPlugin(MprisPlugin.class); + }*/ + + @Override + public String getPluginName() { + return "plugin_mpris"; + } + + @Override + public String getDisplayName() { + return context.getResources().getString(R.string.pref_plugin_mpris); + } + + @Override + public String getDescription() { + return context.getResources().getString(R.string.pref_plugin_mpris_desc); + } + + @Override + public Drawable getIcon() { + return context.getResources().getDrawable(R.drawable.icon); + } + + @Override + public boolean isEnabledByDefault() { + return true; + } @Override public boolean onCreate() { @@ -158,5 +191,9 @@ public class MprisPlugin extends Plugin { device.sendPackage(np); } + @Override + public AlertDialog getErrorDialog(Context baseContext) { + return null; + } } diff --git a/KdeConnect/src/main/java/org/kde/connect/Plugins/NotificationsPlugin.java b/KdeConnect/src/main/java/org/kde/connect/Plugins/NotificationsPlugin.java new file mode 100644 index 00000000..eb056854 --- /dev/null +++ b/KdeConnect/src/main/java/org/kde/connect/Plugins/NotificationsPlugin.java @@ -0,0 +1,285 @@ +package org.kde.connect.Plugins; + +import android.Manifest; +import android.app.AlertDialog; +import android.app.Notification; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.provider.Settings; +import android.service.notification.StatusBarNotification; +import android.util.Base64; +import android.util.Log; + +import org.kde.connect.Helpers.AppsHelper; +import org.kde.connect.Helpers.ImagesHelper; +import org.kde.connect.NetworkPackage; +import org.kde.connect.NotificationReceiver; +import org.kde.connect.PluginFactory; +import org.kde.kdeconnect.R; + +import java.io.ByteArrayOutputStream; +import java.nio.charset.Charset; + +public class NotificationsPlugin extends Plugin implements NotificationReceiver.NotificationListener { + + private NotificationId lastId; + + /*static { + PluginFactory.registerPlugin(NotificationsPlugin.class); + }*/ + + @Override + public String getPluginName() { + return "plugin_notifications"; + } + + @Override + public String getDisplayName() { + return context.getResources().getString(R.string.pref_plugin_notifications); + } + + @Override + public String getDescription() { + return context.getResources().getString(R.string.pref_plugin_notifications_desc); + } + + @Override + public Drawable getIcon() { + return context.getResources().getDrawable(R.drawable.icon); + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + + static class NotificationId { + String packageName; + String tag; + int id; + + public static NotificationId fromNotification(StatusBarNotification statusBarNotification) { + NotificationId nid = new NotificationId(); + nid.packageName = statusBarNotification.getPackageName(); + nid.tag = statusBarNotification.getTag(); + nid.id = statusBarNotification.getId(); + return nid; + } + public static NotificationId unserialize(String s) { + NotificationId nid = new NotificationId(); + int first = s.indexOf(':'); + int last = s.lastIndexOf(':'); + nid.packageName = s.substring(0, first); + nid.tag = s.substring(first, last); + if (nid.tag.length() == 0) nid.tag = null; + nid.id = Integer.parseInt(s.substring(last)); + return nid; + } + public String serialize() { + String safePackageName = (packageName == null)? "" : packageName; + String safeTag = (tag == null)? "" : tag; + return safePackageName+":"+safeTag+":"+id; + } + public String getPackageName() { + return packageName; + } + public String getTag() { + return tag; + } + public int getId() { + return id; + } + @Override + public boolean equals(Object o) { + if (!(o instanceof NotificationId)) return false; + NotificationId other = (NotificationId)o; + return other.getTag().equals(tag) && other.getId() == id && other.getPackageName().equals(packageName); + } + } + + + + + private boolean hasPermissions; + + @Override + public boolean onCreate() { + Log.e("NotificationsPlugin", "onCreate"); + + if (Build.VERSION.SDK_INT < 18) return false; + + //Check for permissions + String notificationListenerList = Settings.Secure.getString(context.getContentResolver(), "enabled_notification_listeners"); + if (notificationListenerList != null && notificationListenerList.contains(context.getPackageName())) { + NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { + @Override + public void onServiceStart(NotificationReceiver service) { + try { + service.addListener(NotificationsPlugin.this); + /* + StatusBarNotification[] notifications = service.getActiveNotifications(); + for (StatusBarNotification notification : notifications) { + onNotificationPosted(notification); + } + */ + } catch(Exception e) { + e.printStackTrace(); + Log.e("NotificationsPlugin","Exception"); +} + } + }); + return true; + } else { + return false; + } + + } + + + @Override + public void onDestroy() { + NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { + @Override + public void onServiceStart(NotificationReceiver service) { + service.removeListener(NotificationsPlugin.this); + } + }); + } + + + + + + + @Override + public void onNotificationRemoved(StatusBarNotification statusBarNotification) { + NotificationId id = NotificationId.fromNotification(statusBarNotification); + + if (!id.equals(lastId)) { + NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_NOTIFICATION); + + np.set("id", id.serialize()); + np.set("isCancel", true); + + device.sendPackage(np); + } + } + + @Override + public void onNotificationPosted(StatusBarNotification statusBarNotification) { + + Notification notification = statusBarNotification.getNotification(); + NotificationId id = NotificationId.fromNotification(statusBarNotification); + PackageManager packageManager = context.getPackageManager(); + + NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_NOTIFICATION); + + String packageName = statusBarNotification.getPackageName(); + String appName = AppsHelper.appNameLookup(context, packageName); + + try { + Drawable drawableAppIcon = AppsHelper.appIconLookup(context, packageName); + Bitmap appIcon = ImagesHelper.drawableToBitmap(drawableAppIcon); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + appIcon.compress(Bitmap.CompressFormat.PNG, 90, outStream); + byte[] bitmapData = outStream.toByteArray(); + byte[] serializedBitmapData = Base64.encode(bitmapData, Base64.NO_WRAP); + String stringBitmapData = new String(serializedBitmapData, Charset.defaultCharset()); + //Es super gran lol, millor ho fem quan puguem enviar arxius + //np.set("base64icon", stringBitmapData); + } catch(Exception e) { + e.printStackTrace(); + Log.e("NotificationsPlugin","Error retrieveing icon"); + } + + np.set("id", id.serialize()); + np.set("appName", appName == null? packageName : appName); + np.set("isClearable", statusBarNotification.isClearable()); + np.set("ticker", notification.tickerText.toString()); + np.set("time", new Long(statusBarNotification.getPostTime()).toString()); + + device.sendPackage(np); + } + + + + + + @Override + public boolean onPackageReceived(NetworkPackage np) { + if (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_NOTIFICATION)) return false; + + if (np.getBoolean("request")) { + + NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { + @Override + public void onServiceStart(NotificationReceiver service) { + StatusBarNotification[] notifications = service.getActiveNotifications(); + for (StatusBarNotification notification : notifications) { + onNotificationPosted(notification); + } + } + }); + + } else if (np.getBoolean("isCancel")) { + + lastId = NotificationId.unserialize(np.getString("id")); + NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { + @Override + public void onServiceStart(NotificationReceiver service) { + service.cancelNotification(lastId.getPackageName(), lastId.getTag(), lastId.getId()); + } + }); + + } else { + + Log.e("NotificationsPlugin","Nothing to do"); + + } + + return true; + } + + + @Override + public AlertDialog getErrorDialog(final Context baseContext) { + + if (Build.VERSION.SDK_INT < 18) { + return new AlertDialog.Builder(baseContext) + .setTitle("Notifications Plugin") + .setMessage("This plugin is not compatible with Android 4.3") + .setPositiveButton("Ok",new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + + } + }) + .create(); + } else { + return new AlertDialog.Builder(baseContext) + .setTitle("Notifications Plugin") + .setMessage("You need to grant permission to access notifications") + .setPositiveButton("Open settings",new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent=new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"); + baseContext.startActivity(intent); + } + }) + .setNegativeButton("Cancel",new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + //Do nothing + } + }) + .create(); + } + } + + +} diff --git a/KdeConnect/src/main/java/org/kde/connect/Plugins/PingPlugin.java b/KdeConnect/src/main/java/org/kde/connect/Plugins/PingPlugin.java index 18e7d051..e382d123 100644 --- a/KdeConnect/src/main/java/org/kde/connect/Plugins/PingPlugin.java +++ b/KdeConnect/src/main/java/org/kde/connect/Plugins/PingPlugin.java @@ -1,16 +1,48 @@ package org.kde.connect.Plugins; import android.R; +import android.app.AlertDialog; import android.app.Notification; import android.app.NotificationManager; import android.content.Context; +import android.graphics.drawable.Drawable; import android.util.Log; import org.kde.connect.NetworkPackage; +import org.kde.connect.PluginFactory; public class PingPlugin extends Plugin { + /*static { + PluginFactory.registerPlugin(PingPlugin.class); + }*/ + + @Override + public String getPluginName() { + return "plugin_ping"; + } + + @Override + public String getDisplayName() { + return context.getResources().getString(org.kde.kdeconnect.R.string.pref_plugin_ping); + } + + @Override + public String getDescription() { + return context.getResources().getString(org.kde.kdeconnect.R.string.pref_plugin_ping_desc); + } + + @Override + public Drawable getIcon() { + return context.getResources().getDrawable(org.kde.kdeconnect.R.drawable.icon); + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + @Override public boolean onCreate() { return true; @@ -45,10 +77,9 @@ public class PingPlugin extends Plugin { return false; } - public void sendPing() { - Log.e("PingPlugin", "sendPing"); - NetworkPackage lastPackage = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PING); - device.sendPackage(lastPackage); + @Override + public AlertDialog getErrorDialog(Context baseContext) { + return null; } } diff --git a/KdeConnect/src/main/java/org/kde/connect/Plugins/Plugin.java b/KdeConnect/src/main/java/org/kde/connect/Plugins/Plugin.java index 3bd8bd34..a42031ea 100644 --- a/KdeConnect/src/main/java/org/kde/connect/Plugins/Plugin.java +++ b/KdeConnect/src/main/java/org/kde/connect/Plugins/Plugin.java @@ -1,6 +1,11 @@ package org.kde.connect.Plugins; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Application; import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Bundle; import org.kde.connect.Device; import org.kde.connect.NetworkPackage; @@ -15,9 +20,60 @@ public abstract class Plugin { this.context = context; } - //Functions to override + /** + * Return the internal plugin name, that will be used as a + * unique key to distinguish it. This function can not access + * this.context nor this.device. + */ + public abstract String getPluginName(); + + /** + * Return the human-readable plugin name. This function can + * access this.context to provide translated text. + */ + public abstract String getDisplayName(); + + /** + * Return the human-readable description of this plugin. This + * function can access this.context to provide translated text. + */ + public abstract String getDescription(); + + /** + * Return an icon associated to this plugin. This function can + * access this.context to load the image from resources. + */ + public abstract Drawable getIcon(); + + /** + * Return true if this plugin should be enabled on new devices. + * This function can access this.context and perform compatibility + * checks with the Android version, but can not access this.device. + */ + public abstract boolean isEnabledByDefault(); + + /** + * Initialize the listeners and structures in your plugin. + * Should return true if initialization was successful. + */ public abstract boolean onCreate(); + + /** + * Finish any ongoing operations, remove listeners... so + * this object could be garbage collected + */ public abstract void onDestroy(); + + /** + * If onCreate returns false, should create a dialog explaining + * the problem (and how to fix it, if possible) to the user + */ public abstract boolean onPackageReceived(NetworkPackage np); + /** + * If onCreate returns false, should create a dialog explaining + * the problem (and how to fix it, if possible) to the user + */ + public abstract AlertDialog getErrorDialog(Context baseContext); + } diff --git a/KdeConnect/src/main/java/org/kde/connect/Plugins/TelephonyPlugin.java b/KdeConnect/src/main/java/org/kde/connect/Plugins/TelephonyPlugin.java index 92f189a4..175bde16 100644 --- a/KdeConnect/src/main/java/org/kde/connect/Plugins/TelephonyPlugin.java +++ b/KdeConnect/src/main/java/org/kde/connect/Plugins/TelephonyPlugin.java @@ -1,19 +1,51 @@ package org.kde.connect.Plugins; +import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.telephony.SmsMessage; import android.telephony.TelephonyManager; import android.util.Log; -import org.kde.connect.ContactsHelper; +import org.kde.connect.Helpers.ContactsHelper; import org.kde.connect.NetworkPackage; +import org.kde.connect.PluginFactory; +import org.kde.kdeconnect.R; public class TelephonyPlugin extends Plugin { + /*static { + PluginFactory.registerPlugin(TelephonyPlugin.class); + }*/ + + @Override + public String getPluginName() { + return "plugin_telephony"; + } + + @Override + public String getDisplayName() { + return context.getResources().getString(R.string.pref_plugin_telephony); + } + + @Override + public String getDescription() { + return context.getResources().getString(R.string.pref_plugin_telephony_desc); + } + + @Override + public Drawable getIcon() { + return context.getResources().getDrawable(R.drawable.icon); + } + + @Override + public boolean isEnabledByDefault() { + return true; + } private BroadcastReceiver receiver = new BroadcastReceiver() { @Override @@ -145,5 +177,9 @@ public class TelephonyPlugin extends Plugin { return false; } + @Override + public AlertDialog getErrorDialog(Context baseContext) { + return null; + } } diff --git a/KdeConnect/src/main/java/org/kde/connect/PreferenceListAdapter.java b/KdeConnect/src/main/java/org/kde/connect/PreferenceListAdapter.java new file mode 100644 index 00000000..4efbc956 --- /dev/null +++ b/KdeConnect/src/main/java/org/kde/connect/PreferenceListAdapter.java @@ -0,0 +1,90 @@ +package org.kde.connect; + +import android.content.Context; +import android.database.DataSetObserver; +import android.graphics.drawable.Drawable; +import android.preference.Preference; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ListAdapter; +import android.widget.TextView; + +import org.kde.kdeconnect.R; + +import java.util.ArrayList; + +public class PreferenceListAdapter implements ListAdapter { + + + private ArrayList localList; + + public PreferenceListAdapter(ArrayList list) { + super(); + Log.e("PreferenceListAdapter", ""+list.size()); + localList = list; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View v = localList.get(position).getView(convertView, parent); + v.setEnabled(true); + v.setFocusable(true); + return v; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + } // Empty + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + } // Empty + + @Override + public boolean isEmpty() { + return localList.size() == 0; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public int getViewTypeCount() { + return localList.size(); + } + + @Override + public int getItemViewType(int position) { + return 0; + } // Empty + + @Override + public Object getItem(int position) { + return localList.get(position); + } // Empty + + @Override + public int getCount() { + return localList.size(); + } + + @Override + public boolean isEnabled(int i) { + return false; + } + + @Override + public boolean areAllItemsEnabled() { + return false; + } + } diff --git a/KdeConnect/src/main/java/org/kde/connect/SettingsActivity.java b/KdeConnect/src/main/java/org/kde/connect/SettingsActivity.java index 7d724722..f1b6d992 100644 --- a/KdeConnect/src/main/java/org/kde/connect/SettingsActivity.java +++ b/KdeConnect/src/main/java/org/kde/connect/SettingsActivity.java @@ -1,33 +1,25 @@ package org.kde.connect; +import android.app.ListActivity; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; +import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; import org.kde.kdeconnect.R; -public class SettingsActivity extends PreferenceActivity { - - Device device = null; - SharedPreferences preferences; - - private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, final String key) { - final boolean value = sharedPreferences.getBoolean(key,true); - BackgroundService.RunCommand(getApplicationContext(), new BackgroundService.InstanceCallback() { - @Override - public void onServiceStart(BackgroundService service) { - device.setPluginEnabled(key,value); - } - }); - - } - }; +import java.util.AbstractCollection; +import java.util.ArrayList; +import java.util.Set; +public class SettingsActivity extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { @@ -39,43 +31,56 @@ public class SettingsActivity extends PreferenceActivity { | ActionBar.DISPLAY_SHOW_TITLE); actionBar.setDisplayHomeAsUpEnabled(true);*/ - preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + getListView().setItemsCanFocus(true); + getListView().setFocusable(false); + getListView().setEnabled(true); + getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); + getListView().setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); + getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); final String deviceId = getIntent().getStringExtra("deviceId"); BackgroundService.RunCommand(getApplicationContext(), new BackgroundService.InstanceCallback() { @Override public void onServiceStart(BackgroundService service) { - device = service.getDevice(deviceId); - //This activity displays the DefaultSharedPreferences, so let's update them from our device - device.readPluginPreferences(preferences); - addPreferencesFromResource(R.xml.settings); + final Device device = service.getDevice(deviceId); + Set plugins = PluginFactory.getAvailablePlugins(); - if (Build.VERSION.SDK_INT < 11 || Build.VERSION.SDK_INT == 18) { - CheckBoxPreference p = (CheckBoxPreference)findPreference("plugin_clipboard"); - p.setEnabled(false); - p.setChecked(false); - p.setSelectable(false); - p.setSummary(R.string.plugin_not_available); + ArrayList preferences = new ArrayList(); + for (final String pluginName : plugins) { + Log.e("SettingsActivity", pluginName); + CheckBoxPreference pref = new CheckBoxPreference(getBaseContext()); + PluginFactory.PluginInfo info = PluginFactory.getPluginInfo(getBaseContext(), pluginName); + pref.setKey(pluginName); + pref.setTitle(info.getDisplayName()); + pref.setSummary(info.getDescription()); + pref.setSelectable(true); + pref.setEnabled(true); + pref.setChecked(device.isPluginEnabled(pluginName)); + pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + Log.e("CLICK","CLICK"); + return false; + } + }); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + device.setPluginEnabled(pluginName, (Boolean)newValue); + return true; + } + }); + preferences.add(pref); } - preferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener); + setListAdapter(new PreferenceListAdapter(preferences)); } }); - } - @Override - public void onResume() { - super.onResume(); - if (preferences != null) preferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener); } - @Override - public void onPause() { - if (preferences != null) preferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener); - super.onPause(); - } } \ No newline at end of file diff --git a/KdeConnect/src/main/res/layout/activity_device.xml b/KdeConnect/src/main/res/layout/activity_device.xml index bc536712..f2d589dd 100644 --- a/KdeConnect/src/main/res/layout/activity_device.xml +++ b/KdeConnect/src/main/res/layout/activity_device.xml @@ -13,4 +13,19 @@