mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 18:07:55 +00:00
Implemented notifications plugin (Android 4.3 required)
Now plugins are almost self-contained (PluginFactory still needs to know about them) Regression: Plugins settings page does not work Now plugins that fail to load can display a message to the user explaining the problem Clipboard plugin now compares if content has changed before sending it
This commit is contained in:
parent
92cbf99891
commit
b22d753410
@ -66,7 +66,7 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
|
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Android 4.2.2" jdkType="Android SDK" />
|
<orderEntry type="jdk" jdkName="Android 4.3 Platform" jdkType="Android SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" exported="" name="android-support-v4" level="project" />
|
<orderEntry type="library" exported="" name="android-support-v4" level="project" />
|
||||||
<orderEntry type="library" exported="" name="mina-core-2.0.7" level="project" />
|
<orderEntry type="library" exported="" name="mina-core-2.0.7" level="project" />
|
||||||
|
@ -16,8 +16,8 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 17
|
compileSdkVersion 18
|
||||||
buildToolsVersion "17.0.0"
|
buildToolsVersion "18.0.1"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 7
|
minSdkVersion 7
|
||||||
|
Binary file not shown.
@ -68,6 +68,13 @@
|
|||||||
android:name="org.kde.connect.BackgroundService">
|
android:name="org.kde.connect.BackgroundService">
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service android:name="org.kde.connect.NotificationReceiver"
|
||||||
|
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.service.notification.NotificationListenerService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
<receiver android:name="org.kde.connect.KdeConnectBroadcastReceiver">
|
<receiver android:name="org.kde.connect.KdeConnectBroadcastReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.PACKAGE_REPLACED"></action>
|
<action android:name="android.intent.action.PACKAGE_REPLACED"></action>
|
||||||
|
@ -32,7 +32,7 @@ public class BackgroundService extends Service {
|
|||||||
Set<String> trustedDevices = preferences.getStringSet("trusted", new HashSet<String>());
|
Set<String> trustedDevices = preferences.getStringSet("trusted", new HashSet<String>());
|
||||||
for(String deviceId : trustedDevices) {
|
for(String deviceId : trustedDevices) {
|
||||||
Log.e("loadRememberedDevicesFromSettings",deviceId);
|
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);
|
device.addLink(link);
|
||||||
} else {
|
} else {
|
||||||
Log.i("BackgroundService", "unknown device");
|
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);
|
devices.put(deviceId, device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,6 @@ public abstract class BaseComputerLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TO OVERRIDE
|
//TO OVERRIDE
|
||||||
public abstract boolean sendPackage(NetworkPackage np); //Should be async
|
public abstract boolean sendPackage(NetworkPackage np);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ public class Device implements BaseComputerLink.PackageReceiver {
|
|||||||
|
|
||||||
private ArrayList<BaseComputerLink> links = new ArrayList<BaseComputerLink>();
|
private ArrayList<BaseComputerLink> links = new ArrayList<BaseComputerLink>();
|
||||||
private HashMap<String, Plugin> plugins = new HashMap<String, Plugin>();
|
private HashMap<String, Plugin> plugins = new HashMap<String, Plugin>();
|
||||||
|
private HashMap<String, Plugin> failedPlugins = new HashMap<String, Plugin>();
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private String deviceId;
|
private String deviceId;
|
||||||
@ -184,7 +185,7 @@ public class Device implements BaseComputerLink.PackageReceiver {
|
|||||||
return plugins.get(name);
|
return plugins.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin addPlugin(String name) {
|
private Plugin addPlugin(String name) {
|
||||||
Plugin existing = plugins.get(name);
|
Plugin existing = plugins.get(name);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
Log.e("addPlugin","plugin already present:" + name);
|
Log.e("addPlugin","plugin already present:" + name);
|
||||||
@ -194,12 +195,18 @@ public class Device implements BaseComputerLink.PackageReceiver {
|
|||||||
Plugin plugin = PluginFactory.instantiatePluginForDevice(context, name, this);
|
Plugin plugin = PluginFactory.instantiatePluginForDevice(context, name, this);
|
||||||
if (plugin == null) {
|
if (plugin == null) {
|
||||||
Log.e("addPlugin","could not create plugin: "+name);
|
Log.e("addPlugin","could not create plugin: "+name);
|
||||||
|
failedPlugins.put(name, plugin);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
plugin.onCreate();
|
boolean success = plugin.onCreate();
|
||||||
|
if (!success) {
|
||||||
|
failedPlugins.put(name, plugin);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
failedPlugins.put(name, plugin);
|
||||||
Log.e("addPlugin","Exception calling onCreate for "+name);
|
Log.e("addPlugin","Exception calling onCreate for "+name);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
@ -207,14 +214,22 @@ public class Device implements BaseComputerLink.PackageReceiver {
|
|||||||
|
|
||||||
Log.e("addPlugin",name);
|
Log.e("addPlugin",name);
|
||||||
|
|
||||||
|
failedPlugins.remove(name);
|
||||||
plugins.put(name, plugin);
|
plugins.put(name, plugin);
|
||||||
|
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removePlugin(String name) {
|
private boolean removePlugin(String name) {
|
||||||
|
|
||||||
Plugin plugin = plugins.remove(name);
|
Plugin plugin = plugins.remove(name);
|
||||||
|
Plugin failedPlugin = failedPlugins.remove(name);
|
||||||
|
|
||||||
if (plugin == null) {
|
if (plugin == null) {
|
||||||
return false;
|
if (failedPlugin == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
plugin = failedPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -230,21 +245,32 @@ public class Device implements BaseComputerLink.PackageReceiver {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPluginEnabled(String key, boolean value) {
|
public void setPluginEnabled(String pluginName, boolean value) {
|
||||||
settings.edit().putBoolean(key,value).commit();
|
settings.edit().putBoolean(pluginName,value).commit();
|
||||||
if (value) addPlugin(key);
|
if (value) addPlugin(pluginName);
|
||||||
else removePlugin(key);
|
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() {
|
public void reloadPluginsFromSettings() {
|
||||||
|
|
||||||
|
failedPlugins.clear();
|
||||||
|
|
||||||
Set<String> availablePlugins = PluginFactory.getAvailablePlugins();
|
Set<String> availablePlugins = PluginFactory.getAvailablePlugins();
|
||||||
|
|
||||||
for(String pluginName : availablePlugins) {
|
for(String pluginName : availablePlugins) {
|
||||||
boolean enabled = false;
|
boolean enabled = false;
|
||||||
if (isTrusted() && isReachable()) {
|
if (isTrusted() && isReachable()) {
|
||||||
boolean enabledByDefault = PluginFactory.isPluginEnabledByDefault(pluginName);
|
enabled = isPluginEnabled(pluginName);
|
||||||
enabled = settings.getBoolean(pluginName, enabledByDefault);
|
|
||||||
}
|
}
|
||||||
//Log.e("reloadPluginsFromSettings",pluginName+"->"+enabled);
|
//Log.e("reloadPluginsFromSettings",pluginName+"->"+enabled);
|
||||||
if (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) {
|
public HashMap<String,Plugin> getFailedPlugins() {
|
||||||
SharedPreferences.Editor editor = outSettings.edit();
|
return failedPlugins;
|
||||||
|
}
|
||||||
|
|
||||||
Set<String> availablePlugins = PluginFactory.getAvailablePlugins();
|
interface PluginsChangedListener {
|
||||||
for(String pluginName : availablePlugins) {
|
void onPluginsChanged(Device device);
|
||||||
boolean enabledByDefault = PluginFactory.isPluginEnabledByDefault(pluginName);
|
}
|
||||||
boolean enabled = settings.getBoolean(pluginName, enabledByDefault);
|
|
||||||
editor.putBoolean(pluginName, enabled);
|
|
||||||
//Log.e("readPluginPreferences",pluginName+"->"+enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.commit();
|
ArrayList<PluginsChangedListener> pluginsChangedListeners = new ArrayList<PluginsChangedListener>();
|
||||||
|
|
||||||
|
public void addPluginsChangedListener(PluginsChangedListener listener) {
|
||||||
|
pluginsChangedListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePluginsChangedListener(PluginsChangedListener listener) {
|
||||||
|
pluginsChangedListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,71 @@ package org.kde.connect;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
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.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.ListView;
|
||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
|
|
||||||
import org.kde.connect.Plugins.PingPlugin;
|
import org.kde.connect.Plugins.PingPlugin;
|
||||||
|
import org.kde.connect.Plugins.Plugin;
|
||||||
import org.kde.kdeconnect.R;
|
import org.kde.kdeconnect.R;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class DeviceActivity extends Activity {
|
public class DeviceActivity extends Activity {
|
||||||
|
|
||||||
private String deviceId;
|
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<String, Plugin> 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<String>(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
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
@ -63,6 +113,8 @@ public class DeviceActivity extends Activity {
|
|||||||
public void onServiceStart(BackgroundService service) {
|
public void onServiceStart(BackgroundService service) {
|
||||||
Device device = service.getDevice(deviceId);
|
Device device = service.getDevice(deviceId);
|
||||||
setTitle(device.getName());
|
setTitle(device.getName());
|
||||||
|
device.addPluginsChangedListener(pluginsChangedListener);
|
||||||
|
pluginsChangedListener.onPluginsChanged(device);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,8 +135,7 @@ public class DeviceActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void onServiceStart(BackgroundService service) {
|
public void onServiceStart(BackgroundService service) {
|
||||||
Device device = service.getDevice(deviceId);
|
Device device = service.getDevice(deviceId);
|
||||||
PingPlugin pi = (PingPlugin) device.getPlugin("plugin_ping");
|
device.sendPackage(new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PING));
|
||||||
if (pi != null) pi.sendPing();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.kde.connect;
|
package org.kde.connect.Helpers;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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<ImageListElement> localList = new ArrayList<ImageListElement>();
|
||||||
|
|
||||||
|
public ImageListAdapter(ArrayList<ImageListElement> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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<NotificationListener> listeners = new ArrayList<NotificationListener>();
|
||||||
|
|
||||||
|
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<InstanceCallback> callbacks = new ArrayList<InstanceCallback>();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,12 +2,15 @@ package org.kde.connect;
|
|||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.preference.CheckBoxPreference;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.kde.connect.Plugins.BatteryPlugin;
|
import org.kde.connect.Plugins.BatteryPlugin;
|
||||||
import org.kde.connect.Plugins.ClipboardPlugin;
|
import org.kde.connect.Plugins.ClipboardPlugin;
|
||||||
import org.kde.connect.Plugins.MprisPlugin;
|
import org.kde.connect.Plugins.MprisPlugin;
|
||||||
|
import org.kde.connect.Plugins.NotificationsPlugin;
|
||||||
import org.kde.connect.Plugins.PingPlugin;
|
import org.kde.connect.Plugins.PingPlugin;
|
||||||
import org.kde.connect.Plugins.Plugin;
|
import org.kde.connect.Plugins.Plugin;
|
||||||
import org.kde.connect.Plugins.TelephonyPlugin;
|
import org.kde.connect.Plugins.TelephonyPlugin;
|
||||||
@ -18,33 +21,81 @@ import java.util.TreeMap;
|
|||||||
|
|
||||||
public class PluginFactory {
|
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<String, Class> availablePlugins = new TreeMap<String, Class>();
|
private static final Map<String, Class> availablePlugins = new TreeMap<String, Class>();
|
||||||
|
private static final Map<String, PluginInfo> availablePluginsInfo = new TreeMap<String, PluginInfo>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
//Note that settings to enable the plugins must have tha same names as keys than here
|
//TODO: Avoid this factory having to know every plugin
|
||||||
availablePlugins.put("plugin_battery", BatteryPlugin.class);
|
PluginFactory.registerPlugin(TelephonyPlugin.class);
|
||||||
availablePlugins.put("plugin_clipboard", ClipboardPlugin.class);
|
PluginFactory.registerPlugin(PingPlugin.class);
|
||||||
availablePlugins.put("plugin_mpris", MprisPlugin.class);
|
PluginFactory.registerPlugin(MprisPlugin.class);
|
||||||
availablePlugins.put("plugin_ping", PingPlugin.class);
|
PluginFactory.registerPlugin(ClipboardPlugin.class);
|
||||||
availablePlugins.put("plugin_telephony", TelephonyPlugin.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<String> getAvailablePlugins() {
|
public static Set<String> getAvailablePlugins() {
|
||||||
return availablePlugins.keySet();
|
return availablePlugins.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPluginEnabledByDefault(String pluginName) {
|
public static Plugin instantiatePluginForDevice(Context context, String pluginName, Device device) {
|
||||||
|
Class c = availablePlugins.get(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);
|
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
Log.e("PluginFactory", "Plugin not found: "+name);
|
Log.e("PluginFactory", "Plugin not found: "+pluginName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,10 +105,21 @@ public class PluginFactory {
|
|||||||
return plugin;
|
return plugin;
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Log.e("PluginFactory", "Could not instantiate plugin: "+name);
|
Log.e("PluginFactory", "Could not instantiate plugin: "+pluginName);
|
||||||
return null;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package org.kde.connect.Plugins;
|
package org.kde.connect.Plugins;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.kde.connect.NetworkPackage;
|
import org.kde.connect.NetworkPackage;
|
||||||
|
import org.kde.connect.PluginFactory;
|
||||||
|
import org.kde.kdeconnect.R;
|
||||||
|
|
||||||
public class BatteryPlugin extends Plugin {
|
public class BatteryPlugin extends Plugin {
|
||||||
|
|
||||||
@ -15,6 +19,36 @@ public class BatteryPlugin extends Plugin {
|
|||||||
|
|
||||||
private IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
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() {
|
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
@ -73,4 +107,9 @@ public class BatteryPlugin extends Plugin {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlertDialog getErrorDialog(Context baseContext) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,67 @@
|
|||||||
package org.kde.connect.Plugins;
|
package org.kde.connect.Plugins;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
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.NetworkPackage;
|
||||||
|
import org.kde.connect.PluginFactory;
|
||||||
|
import org.kde.kdeconnect.R;
|
||||||
|
|
||||||
public class ClipboardPlugin extends Plugin {
|
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 cm;
|
||||||
private ClipboardManager.OnPrimaryClipChangedListener listener = new ClipboardManager.OnPrimaryClipChangedListener() {
|
private ClipboardManager.OnPrimaryClipChangedListener listener = new ClipboardManager.OnPrimaryClipChangedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPrimaryClipChanged() {
|
public void onPrimaryClipChanged() {
|
||||||
try {
|
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);
|
ClipData.Item item = cm.getPrimaryClip().getItemAt(0);
|
||||||
np.set("content",item.coerceToText(context).toString());
|
String content = item.coerceToText(context).toString();
|
||||||
device.sendPackage(np);
|
|
||||||
|
if (!content.equals(currentContent)) {
|
||||||
|
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_CLIPBOARD);
|
||||||
|
np.set("content", content);
|
||||||
|
device.sendPackage(np);
|
||||||
|
currentContent = content;
|
||||||
|
}
|
||||||
|
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
//Probably clipboard was not text
|
//Probably clipboard was not text
|
||||||
}
|
}
|
||||||
@ -33,6 +72,11 @@ public class ClipboardPlugin extends Plugin {
|
|||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
|
|
||||||
cm = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
|
cm = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT == 18) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
cm.addPrimaryClipChangedListener(listener);
|
cm.addPrimaryClipChangedListener(listener);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -43,6 +87,7 @@ public class ClipboardPlugin extends Plugin {
|
|||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
|
||||||
cm.removePrimaryClipChangedListener(listener);
|
cm.removePrimaryClipChangedListener(listener);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -51,10 +96,24 @@ public class ClipboardPlugin extends Plugin {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ignore_next_clipboard_change = true;
|
currentContent = np.getString("content");
|
||||||
cm.setText(np.getString("content"));
|
cm.setText(currentContent);
|
||||||
return true;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
package org.kde.connect.Plugins;
|
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.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.kde.connect.NetworkPackage;
|
import org.kde.connect.NetworkPackage;
|
||||||
|
import org.kde.connect.PluginFactory;
|
||||||
|
import org.kde.kdeconnect.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -21,6 +26,34 @@ public class MprisPlugin extends Plugin {
|
|||||||
private String player = "";
|
private String player = "";
|
||||||
private boolean playing = false;
|
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
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
@ -158,5 +191,9 @@ public class MprisPlugin extends Plugin {
|
|||||||
device.sendPackage(np);
|
device.sendPackage(np);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlertDialog getErrorDialog(Context baseContext) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,16 +1,48 @@
|
|||||||
package org.kde.connect.Plugins;
|
package org.kde.connect.Plugins;
|
||||||
|
|
||||||
import android.R;
|
import android.R;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.kde.connect.NetworkPackage;
|
import org.kde.connect.NetworkPackage;
|
||||||
|
import org.kde.connect.PluginFactory;
|
||||||
|
|
||||||
|
|
||||||
public class PingPlugin extends Plugin {
|
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
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
return true;
|
return true;
|
||||||
@ -45,10 +77,9 @@ public class PingPlugin extends Plugin {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPing() {
|
@Override
|
||||||
Log.e("PingPlugin", "sendPing");
|
public AlertDialog getErrorDialog(Context baseContext) {
|
||||||
NetworkPackage lastPackage = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PING);
|
return null;
|
||||||
device.sendPackage(lastPackage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
package org.kde.connect.Plugins;
|
package org.kde.connect.Plugins;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
import org.kde.connect.Device;
|
import org.kde.connect.Device;
|
||||||
import org.kde.connect.NetworkPackage;
|
import org.kde.connect.NetworkPackage;
|
||||||
@ -15,9 +20,60 @@ public abstract class Plugin {
|
|||||||
this.context = context;
|
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();
|
public abstract boolean onCreate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish any ongoing operations, remove listeners... so
|
||||||
|
* this object could be garbage collected
|
||||||
|
*/
|
||||||
public abstract void onDestroy();
|
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);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,51 @@
|
|||||||
package org.kde.connect.Plugins;
|
package org.kde.connect.Plugins;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.telephony.SmsMessage;
|
import android.telephony.SmsMessage;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.kde.connect.ContactsHelper;
|
import org.kde.connect.Helpers.ContactsHelper;
|
||||||
import org.kde.connect.NetworkPackage;
|
import org.kde.connect.NetworkPackage;
|
||||||
|
import org.kde.connect.PluginFactory;
|
||||||
|
import org.kde.kdeconnect.R;
|
||||||
|
|
||||||
public class TelephonyPlugin extends Plugin {
|
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() {
|
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
@ -145,5 +177,9 @@ public class TelephonyPlugin extends Plugin {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlertDialog getErrorDialog(Context baseContext) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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<Preference> localList;
|
||||||
|
|
||||||
|
public PreferenceListAdapter(ArrayList<Preference> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,33 +1,25 @@
|
|||||||
package org.kde.connect;
|
package org.kde.connect;
|
||||||
|
|
||||||
|
import android.app.ListActivity;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.CheckBoxPreference;
|
import android.preference.CheckBoxPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.preference.PreferenceManager;
|
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;
|
import org.kde.kdeconnect.R;
|
||||||
|
|
||||||
public class SettingsActivity extends PreferenceActivity {
|
import java.util.AbstractCollection;
|
||||||
|
import java.util.ArrayList;
|
||||||
Device device = null;
|
import java.util.Set;
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
public class SettingsActivity extends ListActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -39,43 +31,56 @@ public class SettingsActivity extends PreferenceActivity {
|
|||||||
| ActionBar.DISPLAY_SHOW_TITLE);
|
| ActionBar.DISPLAY_SHOW_TITLE);
|
||||||
actionBar.setDisplayHomeAsUpEnabled(true);*/
|
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");
|
final String deviceId = getIntent().getStringExtra("deviceId");
|
||||||
BackgroundService.RunCommand(getApplicationContext(), new BackgroundService.InstanceCallback() {
|
BackgroundService.RunCommand(getApplicationContext(), new BackgroundService.InstanceCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onServiceStart(BackgroundService service) {
|
public void onServiceStart(BackgroundService service) {
|
||||||
device = service.getDevice(deviceId);
|
|
||||||
|
|
||||||
//This activity displays the DefaultSharedPreferences, so let's update them from our device
|
final Device device = service.getDevice(deviceId);
|
||||||
device.readPluginPreferences(preferences);
|
Set<String> plugins = PluginFactory.getAvailablePlugins();
|
||||||
addPreferencesFromResource(R.xml.settings);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < 11 || Build.VERSION.SDK_INT == 18) {
|
ArrayList<Preference> preferences = new ArrayList<Preference>();
|
||||||
CheckBoxPreference p = (CheckBoxPreference)findPreference("plugin_clipboard");
|
for (final String pluginName : plugins) {
|
||||||
p.setEnabled(false);
|
Log.e("SettingsActivity", pluginName);
|
||||||
p.setChecked(false);
|
CheckBoxPreference pref = new CheckBoxPreference(getBaseContext());
|
||||||
p.setSelectable(false);
|
PluginFactory.PluginInfo info = PluginFactory.getPluginInfo(getBaseContext(), pluginName);
|
||||||
p.setSummary(R.string.plugin_not_available);
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -13,4 +13,19 @@
|
|||||||
<Button android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send Ping"/>
|
<Button android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Send Ping"/>
|
||||||
<Button android:id="@+id/button3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Mpris controls"/>
|
<Button android:id="@+id/button3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Mpris controls"/>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:text="Plugins failed to load (tap for more info):"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/textView"/>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/listView1"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
10
KdeConnect/src/main/res/layout/imagelist_element.xml
Normal file
10
KdeConnect/src/main/res/layout/imagelist_element.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingTop="12px"
|
||||||
|
android:paddingBottom="12px"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<ImageView android:layout_marginLeft="6px" android:layout_marginRight="8px" android:layout_height="wrap_content" android:maxHeight="32px" android:minHeight="32px" android:maxWidth="32px" android:minWidth="32px" android:src="@drawable/icon" android:layout_width="wrap_content" android:id="@+id/img" android:layout_gravity="center_vertical"></ImageView>
|
||||||
|
<TextView android:gravity="left" android:id="@+id/txt" android:layout_width="wrap_content" android:textSize="8pt" android:textColor="#000000" android:layout_height="wrap_content" android:layout_gravity="center_vertical" ></TextView>
|
||||||
|
</LinearLayout>
|
@ -12,7 +12,8 @@
|
|||||||
<string name="pref_plugin_mpris_desc">Control audio/video from your phone</string>
|
<string name="pref_plugin_mpris_desc">Control audio/video from your phone</string>
|
||||||
<string name="pref_plugin_ping">Ping</string>
|
<string name="pref_plugin_ping">Ping</string>
|
||||||
<string name="pref_plugin_ping_desc">Send and receive pings</string>
|
<string name="pref_plugin_ping_desc">Send and receive pings</string>
|
||||||
|
<string name="pref_plugin_notifications">Notification sync</string>
|
||||||
|
<string name="pref_plugin_notifications_desc">Access your notifications from other devices</string>
|
||||||
<string name="plugin_not_available">This feature is not available in your Android version</string>
|
<string name="plugin_not_available">This feature is not available in your Android version</string>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<PreferenceScreen
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="plugin_telephony"
|
|
||||||
android:title="@string/pref_plugin_telephony"
|
|
||||||
android:summary="@string/pref_plugin_telephony_desc"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="plugin_battery"
|
|
||||||
android:title="@string/pref_plugin_battery"
|
|
||||||
android:summary="@string/pref_plugin_battery_desc"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="plugin_clipboard"
|
|
||||||
android:title="@string/pref_plugin_clipboard"
|
|
||||||
android:summary="@string/pref_plugin_clipboard_desc"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="plugin_mpris"
|
|
||||||
android:title="@string/pref_plugin_mpris"
|
|
||||||
android:summary="@string/pref_plugin_mpris_desc"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="plugin_ping"
|
|
||||||
android:title="@string/pref_plugin_ping"
|
|
||||||
android:summary="@string/pref_plugin_ping_desc"
|
|
||||||
android:defaultValue="true" />
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
|
Loading…
x
Reference in New Issue
Block a user