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 @@
+
+
+
+
+
diff --git a/KdeConnect/src/main/res/layout/imagelist_element.xml b/KdeConnect/src/main/res/layout/imagelist_element.xml
new file mode 100644
index 00000000..3cdd4466
--- /dev/null
+++ b/KdeConnect/src/main/res/layout/imagelist_element.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/KdeConnect/src/main/res/values/strings.xml b/KdeConnect/src/main/res/values/strings.xml
index 2262a285..54b583fb 100644
--- a/KdeConnect/src/main/res/values/strings.xml
+++ b/KdeConnect/src/main/res/values/strings.xml
@@ -12,7 +12,8 @@
Control audio/video from your phone
Ping
Send and receive pings
-
+ Notification sync
+ Access your notifications from other devices
This feature is not available in your Android version
diff --git a/KdeConnect/src/main/res/xml/settings.xml b/KdeConnect/src/main/res/xml/settings.xml
deleted file mode 100644
index ced52c78..00000000
--- a/KdeConnect/src/main/res/xml/settings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file