2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-09-01 14:45:08 +00:00

Compare commits

..

24 Commits
v1.4 ... v1.4.4

Author SHA1 Message Date
Albert Vaca
2e3fabb3e5 Bumped version to release 2016-09-24 20:28:05 +02:00
Albert Vaca
c7b754a36e Swapped branches in if statement caused settings to not be stored in db 2016-09-24 20:26:23 +02:00
l10n daemon script
347c34927d SVN_SILENT made messages (after extraction) 2016-09-23 10:40:27 +00:00
Albert Vaca
e9013e7995 Android Studio 2.2 complains if we use an old version of the gradle plugin 2016-09-20 12:46:59 +02:00
Albert Vaca
3b5a7deebe Rewritten the Notification Filter.
- Now we display every app in the phone.
- We show the app icon next to the name.
- Some apps can now be disabled by default.

Disabled notifications for the default Android messaging app, as SMS
notifications are already handled by the telephony plugin.

BUG: 367930
2016-09-20 12:46:28 +02:00
Albert Vaca
ac04f5a610 Oops 2016-09-20 11:08:59 +02:00
Albert Vaca
efce35366b Bumped version to release 2016-09-20 10:54:44 +02:00
Albert Vaca
1a32f8142d Do not unpair on every handshake error.
Sometimes we get stupid errors like "connection closed by peer".

BUG: 368812
2016-09-20 10:53:10 +02:00
Albert Vaca
103f24c140 Reduce logging 2016-09-20 10:51:37 +02:00
Albert Vaca
66cdb77bbd Fixed margins of notification filter activity 2016-09-20 10:48:06 +02:00
Albert Vaca
91eefcc65a Fixed margins in the settings activity 2016-09-19 16:16:30 +02:00
Albert Vaca
b25ec2d133 Added cipher list for Android versions between 11 and 21.
BUG: 368172
2016-09-19 16:16:30 +02:00
l10n daemon script
e2e78cb562 SVN_SILENT made messages (after extraction) 2016-09-19 10:16:29 +00:00
l10n daemon script
8b0b65178b SVN_SILENT made messages (after extraction) 2016-09-18 10:38:50 +00:00
l10n daemon script
34d8a771d7 SVN_SILENT made messages (after extraction) 2016-09-14 10:29:43 +00:00
Albert Vaca
7f3afd194b Trying to debug a "no shared ciphers" issue some users are experiencing. 2016-09-13 16:56:23 +02:00
Albert Vaca
ef79b04d1a Bumped version to release 2016-09-11 21:47:49 +02:00
Albert Vaca
62bf2ccab7 Fixed clipboard propagation loop bug
Now ClipboardListener is a singleton

BUG: 362596
2016-09-11 21:40:07 +02:00
Albert Vaca
901440f78a Don't return an empty list of supported plugins
If we don't know it yet return them all.
2016-09-06 10:53:24 +02:00
Albert Vaca
e9a64dc99a Don't show the Encryption Info menu if we are not connected with the device
We don't know the actual encryption used unless we have a device link.
2016-09-06 10:53:24 +02:00
l10n daemon script
23f7eb90ba SVN_SILENT made messages (after extraction) 2016-08-31 10:22:15 +00:00
Albert Vaca
a8838b57bb What XML file? 2016-08-29 11:49:25 +02:00
Albert Vaca
2989fe5ab3 Bump version to release 2016-08-29 11:49:04 +02:00
Albert Vaca
9c40374b00 Unpair only when there is no certificate
Unpairing on every error was a bit too aggressive.

BUG: 367937
2016-08-29 11:48:30 +02:00
19 changed files with 342 additions and 233 deletions

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kde.kdeconnect_tp"
android:versionCode="1400"
android:versionName="1.4">
android:versionCode="1440"
android:versionName="1.4.4">
<uses-sdk android:minSdkVersion="9"
android:targetSdkVersion="22" />
@@ -187,6 +187,7 @@
android:value="org.kde.kdeconnect.UserInterface.PluginSettingsActivity" />
</activity>
</application>
</manifest>

View File

@@ -3,7 +3,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'com.android.tools.build:gradle:2.2.0'
}
}

View File

@@ -1,22 +1,32 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity">
<TextView
android:text="@string/filter_apps_info"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:id="@+id/tFilter"/>
<ProgressBar
android:layout_marginTop="64dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/spinner" />
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/lvFilterApps"
android:layout_below="@id/tFilter"/>
android:visibility="gone"
/>
</RelativeLayout>
</LinearLayout>

View File

@@ -24,28 +24,23 @@
android:gravity="center_vertical"
android:paddingEnd="?android:attr/scrollbarSize"
android:paddingRight="?android:attr/scrollbarSize"
android:paddingStart="12dip"
android:paddingLeft="12dip"
android:background="?attr/selectableItemBackground">
<!-- Preference should place its actual preference widget here. -->
<!-- Preference will place its actual preference widget here. -->
<LinearLayout android:id="@+android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical" />
<ImageView
android:id="@+android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dip"
android:layout_marginLeft="15dip"
android:layout_marginEnd="15dip"
android:layout_marginStart="12dip"
android:layout_marginLeft="12dip"
android:layout_marginEnd="4dip"
android:layout_marginRight="4dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Notificador de telefonia</string>
<string name="pref_plugin_telephony">Notificador de la telefonia</string>
<string name="pref_plugin_telephony_desc">Envia notificacions pels SMS i les trucades</string>
<string name="pref_plugin_battery">Informe de la bateria</string>
<string name="pref_plugin_battery_desc">Informa periòdicament sobre l\'estat de la bateria</string>
@@ -68,7 +68,7 @@
<string name="error_canceled_by_user">Cancel·lat per l\'usuari</string>
<string name="error_canceled_by_other_peer">Cancel·lat per l\'altre parell</string>
<string name="error_invalid_key">S\'ha rebut una clau no vàlida</string>
<string name="encryption_info_title">Informació d\'encriptatge</string>
<string name="encryption_info_title">Informació de l\'encriptatge</string>
<string name="encryption_info_msg_no_ssl">L\'altre dispositiu no usa una versió recent del KDE Connect, s\'utilitzarà el mètode d\'encriptatge antic.</string>
<string name="my_device_fingerprint">L\'empremta digital SHA1 del certificat del vostre dispositiu és:</string>
<string name="remote_device_fingerprint">L\'empremta digital SHA1 del certificat del dispositiu remot és:</string>

View File

@@ -5,15 +5,19 @@
<string name="pref_plugin_battery">Akkubericht</string>
<string name="pref_plugin_battery_desc">Akkustatus periodisch berichten</string>
<string name="pref_plugin_sftp">Dateisystem zeigen</string>
<string name="pref_plugin_sftp_desc">Erlaubt das Browsen des Dateisystems auf diesem Gerät aus der Ferne</string>
<string name="pref_plugin_clipboard">Abgleich der Zwischenablage</string>
<string name="pref_plugin_clipboard_desc">Inhalt der Zwischenablage freigeben</string>
<string name="pref_plugin_mousepad">Ferneingabe</string>
<string name="pref_plugin_mousepad_desc">Verwendet Ihr Handy als Tablett, Touchpad und Tastatur</string>
<string name="pref_plugin_mpris">Multimedia-Bedienung</string>
<string name="pref_plugin_runcommand">Befehl ausführen</string>
<string name="pref_plugin_runcommand_desc">Von Ihrem Telefon oder Tablett Befehle auf anderen Geräten ausführen</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Senden und Empfangen von Pings</string>
<string name="pref_plugin_notifications">Benachrichtigungs-Abgleich</string>
<string name="pref_plugin_notifications_desc">Zugriff auf Ihre Benachrichtigungen von anderen Geräten</string>
<string name="pref_plugin_receive_notifications">Benachrichtigungen empfangen</string>
<string name="pref_plugin_sharereceiver">Veröffentlichen und Empfangen</string>
<string name="pref_plugin_sharereceiver_desc">Dateien und Adressen (URLs) zwischen Geräten teilen</string>
<string name="plugin_not_available">Diese Funktion ist in Ihrer Android-Version nicht verfügbar</string>
@@ -27,6 +31,8 @@
<string name="open_mousepad">Ferneingabe</string>
<string name="mousepad_double_tap_settings_title">Aktionsausführung bei Berührung mit zwei Fingern einstellen</string>
<string name="mousepad_triple_tap_settings_title">Aktionsausführung bei Berührung mit drei Fingern einstellen</string>
<string name="mousepad_sensitivity_settings_title">Empfindlichkeit des Touchpads einstellen</string>
<string name="mousepad_scroll_direction_title">Bildlaufrichtung umkehren</string>
<string-array name="mousepad_tap_entries">
<item>Rechtsklick</item>
<item>Mittelklick</item>
@@ -34,12 +40,13 @@
</string-array>
<string name="mousepad_double_default">Rechts</string>
<string name="mousepad_triple_default">Mitte</string>
<string name="mousepad_sensitivity_default">Standard</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Langsamste</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Standard</item>
<item>Above Default</item>
<item>Fastest</item>
<item>Schnellste</item>
</string-array>
<string name="category_connected_devices">Verbundene Geräte</string>
<string name="category_not_paired_devices">Verfügbare Gerät</string>
@@ -58,6 +65,9 @@
<string name="error_canceled_by_user">Abbruch durch Benutzer</string>
<string name="error_canceled_by_other_peer">Abbruch durch Gegenstelle</string>
<string name="error_invalid_key">Ungültiger Schlüssel empfangen</string>
<string name="encryption_info_title">Verschlüsselungsinformationen</string>
<string name="my_device_fingerprint">Der SHA1-Fingerabdruck Ihres Gerätezertifikats lautet:</string>
<string name="remote_device_fingerprint">Der SHA1-Fingerabdruck des Gerätezertifikats der Gegenstelle lautet:</string>
<string name="pair_requested">Verbindung angefordert</string>
<string name="pairing_request_from">Verbindungsanfrage von %1s</string>
<string name="received_url_title">Verknüpfung von %1s erhalten</string>
@@ -138,6 +148,9 @@
<string name="pref_plugin_telepathy">SMS senden</string>
<string name="pref_plugin_telepathy_desc">Text-Nachrichten von Ihrer Arbeitsfläche senden</string>
<string name="plugin_not_supported">Dieses Modul wird durch das Gerät nicht unterstützt</string>
<string name="findmyphone_title">Mein Telefon suchen</string>
<string name="findmyphone_title_tablet">Mein Tablett suchen</string>
<string name="findmyphone_description">Ruft dieses Gerät an, um es zu suchen.</string>
<string name="findmyphone_found">Gefunden</string>
<string name="open">Öffnen</string>
<string name="close">Schließen</string>

View File

@@ -5,15 +5,19 @@
<string name="pref_plugin_battery">Relatório da bateria</string>
<string name="pref_plugin_battery_desc">Informação periódica do status da bateria</string>
<string name="pref_plugin_sftp">Exposição do sistema de arquivos</string>
<string name="pref_plugin_sftp_desc">Permite navegar no sistema de arquivos deste telefone remotamente</string>
<string name="pref_plugin_clipboard">Sincronização da área de transferência</string>
<string name="pref_plugin_clipboard_desc">Compartilha o conteúdo da área de transferência</string>
<string name="pref_plugin_mousepad">Introdução de dados remota</string>
<string name="pref_plugin_mousepad_desc">Use seu telefone ou tablet como mouse e teclado</string>
<string name="pref_plugin_mpris">Controle multimídia</string>
<string name="pref_plugin_mpris_desc">Fornece um controle remoto de seu reprodutor de mídia</string>
<string name="pref_plugin_runcommand">Executar comando</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Envia e recebe pings</string>
<string name="pref_plugin_notifications">Sincronização de notificações</string>
<string name="pref_plugin_notifications_desc">Acesse suas notificações a partir de outros dispositivos</string>
<string name="pref_plugin_receive_notifications">Receber notificações</string>
<string name="pref_plugin_sharereceiver">Compartilhar e receber</string>
<string name="pref_plugin_sharereceiver_desc">Compartilha arquivos e URLs entre os dispositivos</string>
<string name="plugin_not_available">Esta funcionalidade não está disponível na sua versão do Android</string>
@@ -28,6 +32,8 @@
<string name="mousepad_info">Mova um dedo pela tela para mover o ponteiro do mouse. Dê um toque para clicar e use dois/três dedos para os botões da direita e do meio. Use uma pressão longa para arrastar e soltar.</string>
<string name="mousepad_double_tap_settings_title">Definir a ação do toque com dois dedos</string>
<string name="mousepad_triple_tap_settings_title">Definir a ação do toque com três dedos</string>
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do touchpad</string>
<string name="mousepad_scroll_direction_title">Direção de rolagem inversa</string>
<string-array name="mousepad_tap_entries">
<item>Botão direito</item>
<item>Botão do meio</item>
@@ -35,12 +41,13 @@
</string-array>
<string name="mousepad_double_default">direita</string>
<string name="mousepad_triple_default">meio</string>
<string name="mousepad_sensitivity_default">padrão</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
<item>Mais lento</item>
<item>Ainda mais lento</item>
<item>Padrão</item>
<item>Acima do padrão</item>
<item>Mais rápido</item>
</string-array>
<string name="category_connected_devices">Dispositivos conectados</string>
<string name="category_not_paired_devices">Dispositivos disponíveis</string>
@@ -59,6 +66,7 @@
<string name="error_canceled_by_user">Cancelado pelo usuário</string>
<string name="error_canceled_by_other_peer">Cancelado pelo outro dispositivo</string>
<string name="error_invalid_key">Chave inválida recebida</string>
<string name="encryption_info_title">Informação da criptografia</string>
<string name="pair_requested">Solicitação de emparelhamento</string>
<string name="pairing_request_from">Emparelhamento solicitado por %1s</string>
<string name="received_url_title">Link recebido de %1s</string>
@@ -144,5 +152,9 @@
<string name="pref_plugin_telepathy">Enviar SMS</string>
<string name="pref_plugin_telepathy_desc">Enviar mensagens de texto do seu Desktop</string>
<string name="plugin_not_supported">Este plugin não é suportado pelo dispositivo</string>
<string name="findmyphone_title">Encontrar meu telefone</string>
<string name="findmyphone_title_tablet">Encontrar meu tablet</string>
<string name="findmyphone_found">Encontrado</string>
<string name="open">Abrir</string>
<string name="close">Fechar</string>
</resources>

View File

@@ -5,16 +5,21 @@
<string name="pref_plugin_battery">Oznam o batérii</string>
<string name="pref_plugin_battery_desc">Periodicky oznamovať stav batérie</string>
<string name="pref_plugin_sftp">Odhaliť súborový systém</string>
<string name="pref_plugin_sftp_desc">Umožní prehliadač súborový systém zariadenia vzdialene</string>
<string name="pref_plugin_clipboard">Synchronizácia schránky</string>
<string name="pref_plugin_clipboard_desc">Zdieľať obsah schránky</string>
<string name="pref_plugin_mousepad">Vzdialený vstup</string>
<string name="pref_plugin_mousepad_desc">Použiť váš telefón alebo tablet ako touchpad a klávesnicu</string>
<string name="pref_plugin_mpris">Multimediálne ovládače</string>
<string name="pref_plugin_mpris_desc">Poskytuje vzdialené ovládanie pre váš prehrávač médií</string>
<string name="pref_plugin_runcommand">Spustiť príkaz</string>
<string name="pref_plugin_runcommand_desc">Vyvolať vzdialené príkazy z vášho mobilu alebo tabletu</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Poslať a prijať pingy</string>
<string name="pref_plugin_notifications">Synchronizácia pripomienok</string>
<string name="pref_plugin_notifications_desc">Prístup k vašim pripomienkam z iných zariadení</string>
<string name="pref_plugin_receive_notifications">Prijať upozornenia</string>
<string name="pref_plugin_receive_notifications_desc">Prístup k pripomienkam z iných zariadení a zobrazenie ich na Androide</string>
<string name="pref_plugin_sharereceiver">Zdieľať a prijať</string>
<string name="pref_plugin_sharereceiver_desc">Zdieľať súbory a medzi zariadeniami</string>
<string name="plugin_not_available">Táto funkcia nie je dostupná vo vašej verzii Androidu</string>
@@ -153,6 +158,8 @@
<string name="pref_plugin_telepathy_desc">Posielať textové správy z vášho počítača</string>
<string name="plugin_not_supported">Tento plugin nie je podporovaný zariadením</string>
<string name="findmyphone_title">Nájsť môj telefón</string>
<string name="findmyphone_title_tablet">Nájsť môj tablet</string>
<string name="findmyphone_description">Prezvoní vaše zariadenie, aby ste ho našli</string>
<string name="findmyphone_found">Nájdené</string>
<string name="open">Otvoriť</string>
<string name="close">Zavrieť</string>

View File

@@ -0,0 +1,22 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string-array name="mousepad_tap_entries">
<item>Right click</item>
<item>Middle click</item>
<item>Nothing</item>
</string-array>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
</string-array>
<string-array name="mpris_time_entries">
<item>10 seconds</item>
<item>20 seconds</item>
<item>30 seconds</item>
<item>1 minute</item>
<item>2 minutes</item>
</string-array>
</resources>

View File

@@ -198,6 +198,20 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
boolean isDeviceTrusted = preferences.getBoolean(deviceId, false);
if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
//Device paired with and old version, we can't use it as we lack the certificate
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
if (device == null) return;
device.unpair();
//Retry as unpaired
identityPackageReceived(identityPackage, socket, connectionStarted);
}
});
}
Log.i("KDE/LanLinkProvider","Starting SSL handshake with " + identityPackage.getString("deviceName") + " trusted:"+isDeviceTrusted);
final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
@@ -233,14 +247,11 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
} catch (Exception e) {
Log.e("KDE/LanLinkProvider","Handshake failed with " + identityPackage.getString("deviceName"));
e.printStackTrace();
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
if (device == null) return;
device.unpair();
}
});
//String[] ciphers = sslsocket.getSupportedCipherSuites();
//for (String cipher : ciphers) {
// Log.i("SupportedCiphers","cipher: " + cipher);
//}
}
}
}).start();
@@ -249,15 +260,6 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
}
} catch (Exception e) {
e.printStackTrace();
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
Log.e("LanLinkProvider", "Unpairing "+(device != null));
if (device == null) return;
device.unpair();
}
});
}
}

View File

@@ -146,6 +146,9 @@ public class Device implements BaseLink.PackageReceiver {
Log.e("KDE/Device","Exception deserializing stored public key for device");
}
//Assume every plugin is supported until addLink is called and we can get the actual list
m_supportedPlugins = new Vector<>(PluginFactory.getAvailablePlugins());
//Do not load plugins yet, the device is not present
//reloadPluginsFromSettings();
}
@@ -284,7 +287,6 @@ public class Device implements BaseLink.PackageReceiver {
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
preferences.edit().remove(deviceId).apply();
// FIXME : We delete all device info here, but the xml file still persists
SharedPreferences devicePreferences = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
devicePreferences.edit().clear().apply();

View File

@@ -131,6 +131,12 @@ public class SslHelper {
}
}
public static boolean isCertificateStored(Context context, String deviceId) {
SharedPreferences devicePreferences = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
String cert = devicePreferences.getString("certificate", "");
return !cert.isEmpty();
}
public static SSLContext getSslContext(Context context, String deviceId, boolean isDeviceTrusted) {
//TODO: Cache
try {
@@ -203,13 +209,17 @@ public class SslHelper {
// These cipher suites are most common of them that are accepted by kde and android during handshake
ArrayList<String> supportedCiphers = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
supportedCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"); // API 20+
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); // API 20+
supportedCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); // API 11+
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
supportedCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); // API 11+
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA"); // API 9+
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5"); // API 9+
} else {
// Following ciphers are for and due to old devices
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA");
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5");
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA"); // API 9+
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5"); // API 9+
}
socket.setEnabledCipherSuites(supportedCiphers.toArray(new String[supportedCiphers.size()]));

View File

@@ -6,4 +6,11 @@ public class StringsHelper {
public static final Charset UTF8 = Charset.forName("UTF-8");
public static int compare(String a, String b) {
if (a == b) return 0;
if (a == null) return -1;
if (b == null) return 1;
return a.compareToIgnoreCase(b);
}
}

View File

@@ -28,12 +28,15 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.NetworkPackage;
import java.util.HashSet;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class ClipboardListener {
public interface ClipboardObserver {
void clipboardChanged(String content);
}
private HashSet<ClipboardObserver> observers = new HashSet<>();
private final Context context;
private String currentContent;
@@ -41,9 +44,26 @@ public class ClipboardListener {
private ClipboardManager cm = null;
private ClipboardManager.OnPrimaryClipChangedListener listener;
ClipboardListener(final Context ctx, final Device device) {
private static ClipboardListener _instance = null;
public static ClipboardListener instance(Context context) {
if (_instance == null) {
_instance = new ClipboardListener(context);
}
return _instance;
}
public void registerObserver(ClipboardObserver observer) {
observers.add(observer);
}
public void removeObserver(ClipboardObserver observer) {
observers.remove(observer);
}
ClipboardListener(final Context ctx) {
context = ctx;
if(android.os.Build.VERSION.SDK_INT < 11) {
if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return;
}
@@ -59,11 +79,14 @@ public class ClipboardListener {
ClipData.Item item = cm.getPrimaryClip().getItemAt(0);
String content = item.coerceToText(context).toString();
if (!content.equals(currentContent)) {
NetworkPackage np = new NetworkPackage(ClipboardPlugin.PACKAGE_TYPE_CLIPBOARD);
np.set("content", content);
device.sendPackage(np);
currentContent = content;
if (content.equals(currentContent)) {
return;
}
currentContent = content;
for (ClipboardObserver observer : observers) {
observer.clipboardChanged(content);
}
} catch (Exception e) {
@@ -76,18 +99,10 @@ public class ClipboardListener {
});
}
public void stop() {
if(android.os.Build.VERSION.SDK_INT < 11) {
return;
}
cm.removePrimaryClipChangedListener(listener);
}
@SuppressWarnings("deprecation")
public void setText(String text) {
currentContent = text;
if(android.os.Build.VERSION.SDK_INT < 11) {
if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}

View File

@@ -20,6 +20,8 @@
package org.kde.kdeconnect.Plugins.ClibpoardPlugin;
import android.os.Build;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect_tp.R;
@@ -41,28 +43,34 @@ public class ClipboardPlugin extends Plugin {
@Override
public boolean isEnabledByDefault() {
//Disabled by default due to just one direction sync(incoming clipboard change) in early version of android.
return (android.os.Build.VERSION.SDK_INT >= 11);
return (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB);
}
private ClipboardListener listener;
@Override
public boolean onPackageReceived(NetworkPackage np) {
String content = np.getString("content");
ClipboardListener.instance(context).setText(content);
return true;
}
private ClipboardListener.ClipboardObserver observer = new ClipboardListener.ClipboardObserver() {
@Override
public void clipboardChanged(String content) {
NetworkPackage np = new NetworkPackage(ClipboardPlugin.PACKAGE_TYPE_CLIPBOARD);
np.set("content", content);
device.sendPackage(np);
}
};
@Override
public boolean onCreate() {
listener = new ClipboardListener(context, device);
ClipboardListener.instance(context).registerObserver(observer);
return true;
}
@Override
public void onDestroy() {
listener.stop();
}
@Override
public boolean onPackageReceived(NetworkPackage np) {
String content = np.getString("content");
listener.setText(content);
return true;
ClipboardListener.instance(context).removeObserver(observer);
}
@Override

View File

@@ -26,26 +26,32 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.HashSet;
public class AppDatabase {
public static final String KEY_ROW_ID = "id";
public static final String KEY_NAME = "app";
public static final String KEY_PACKAGE_NAME = "packageName";
public static final String KEY_IS_ENABLED = "isEnabled";
static final private HashSet<String> disabledByDefault = new HashSet<>();
static {
disabledByDefault.add("com.android.messaging"); //We already have sms notifications in the telephony plugin
disabledByDefault.add("com.google.android.googlequicksearchbox"); //Google Now notifications re-spawn every few minutes
}
private static final String DATABASE_NAME = "Applications";
private static final String DATABASE_TABLE = "Applications";
private static final int DATABASE_VERSION = 1;
static final String KEY_PACKAGE_NAME = "packageName";
static final String KEY_IS_ENABLED = "isEnabled";
private final Context ourContext;
private SQLiteDatabase ourDatabase;
private DbHelper ourHelper;
static final String DATABASE_NAME = "Applications";
static final String DATABASE_TABLE = "Applications";
static final int DATABASE_VERSION = 2;
final Context ourContext;
SQLiteDatabase ourDatabase;
DbHelper ourHelper;
public AppDatabase(Context c) {
ourContext = c;
}
private static class DbHelper extends SQLiteOpenHelper{
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -53,73 +59,57 @@ public class AppDatabase {
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DATABASE_TABLE + "(" + KEY_ROW_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ KEY_NAME + " TEXT NOT NULL, " + KEY_PACKAGE_NAME + " TEXT NOT NULL, " + KEY_IS_ENABLED + " TEXT NOT NULL); ");
db.execSQL("CREATE TABLE " + DATABASE_TABLE + "(" + KEY_PACKAGE_NAME + " TEXT PRIMARY KEY NOT NULL, " + KEY_IS_ENABLED + " TEXT NOT NULL); ");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i2) {
db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE);
onCreate(db);
}
}
public void open(){
public void open() {
ourHelper = new DbHelper(ourContext);
ourDatabase = ourHelper.getWritableDatabase();
}
public void close(){
public void close() {
ourHelper.close();
}
public Cursor getAllApplications()
{
String[] columns = new String []{KEY_ROW_ID,KEY_NAME,KEY_PACKAGE_NAME,KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,null,null,null,null,KEY_NAME);
return res;
}
public void setEnabled(String packageName, boolean isEnabled) {
String[] columns = new String []{KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
public long create(String appName, String packageName, boolean isEnabled) {
ContentValues cv = new ContentValues();
cv.put(KEY_NAME, appName);
cv.put(KEY_PACKAGE_NAME, packageName);
cv.put(KEY_IS_ENABLED, isEnabled?"true":"false");
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}
public long update(String packageName, boolean isEnabled) {
ContentValues cvUpdate = new ContentValues();
cvUpdate.put(KEY_IS_ENABLED, isEnabled?"true":"false");
return ourDatabase.update(DATABASE_TABLE,cvUpdate,KEY_PACKAGE_NAME + "=?",new String[]{packageName});
}
public boolean exists(String packageName) {
String[] columns = new String []{KEY_ROW_ID};
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
int count = res.getCount();
if (res.getCount() > 0) {
ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?",new String[]{packageName});
} else {
cv.put(KEY_PACKAGE_NAME, packageName);
ourDatabase.insert(DATABASE_TABLE, null, cv);
}
res.close();
return (count != 0);
}
public boolean isEnabled(String packageName){
public boolean isEnabled(String packageName) {
String[] columns = new String []{KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
boolean result = true; //Apps are enabled by default
boolean result;
if (res.getCount() > 0) {
res.moveToFirst();
result = (res.getString(res.getColumnIndex(KEY_IS_ENABLED))).equals("true");
} else {
result = getDefaultStatus(packageName);
}
res.close();
return result;
}
public void delete(String packageName){
ourDatabase.delete(DATABASE_TABLE,KEY_PACKAGE_NAME + " =? ",new String[]{packageName} );
private boolean getDefaultStatus(String packageName) {
return !disabledByDefault.contains(packageName);
}
}

View File

@@ -22,142 +22,144 @@ package org.kde.kdeconnect.Plugins.NotificationsPlugin;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Helpers.StringsHelper;
import org.kde.kdeconnect_tp.R;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class NotificationFilterActivity extends ActionBarActivity {
private AppDatabase appDatabase;
AppDatabase appDatabase;
static class AppListInfo {
String pkg;
String name;
Drawable icon;
boolean isEnabled;
}
AppListInfo[] apps;
class AppListAdapter extends BaseAdapter {
@Override
public int getCount() {
return apps.length;
}
@Override
public AppListInfo getItem(int position) {
return apps[position];
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = getLayoutInflater();
view = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null, true);
}
CheckedTextView checkedTextView = (CheckedTextView)view;
checkedTextView.setText(apps[position].name);
checkedTextView.setCompoundDrawablesWithIntrinsicBounds(apps[position].icon, null, null, null);
checkedTextView.setCompoundDrawablePadding((int)(8*getResources().getDisplayMetrics().density));
return view;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_filter);
final ListView listView = (ListView)findViewById(R.id.lvFilterApps);
appDatabase = new AppDatabase(this);
appDatabase = new AppDatabase(NotificationFilterActivity.this);
deleteUninstalledApps();
addNewlyInstalledApps();
new Thread(new Runnable() {
@Override
public void run() {
appDatabase.open();
Cursor res = appDatabase.getAllApplications();
res.moveToFirst();
PackageManager packageManager = getPackageManager();
List<ApplicationInfo> appList = packageManager.getInstalledApplications(0);
int count = appList.size();
String[] appName = new String[res.getCount()];
final String[] pkgName = new String[res.getCount()];
Boolean[] isFiltered = new Boolean[res.getCount()];
apps = new AppListInfo[count];
appDatabase.open();
for (int i = 0; i < count; i++) {
ApplicationInfo appInfo = appList.get(i);
apps[i] = new AppListInfo();
apps[i].pkg = appInfo.packageName;
apps[i].name = appInfo.loadLabel(packageManager).toString();
apps[i].icon = resizeIcon(appInfo.loadIcon(packageManager), 48);
apps[i].isEnabled = appDatabase.isEnabled(appInfo.packageName);
}
appDatabase.close();
int i = 0;
while(!res.isAfterLast()){
appName[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_NAME));
pkgName[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME));
isFiltered[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_IS_ENABLED)).equals("true");
res.moveToNext();
i++;
}
res.close();
appDatabase.close();
Arrays.sort(apps, new Comparator<AppListInfo>() {
@Override
public int compare(AppListInfo lhs, AppListInfo rhs) {
return StringsHelper.compare(lhs.name, rhs.name);
}
});
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_multiple_choice, android.R.id.text1, appName);
runOnUiThread(new Runnable() {
@Override
public void run() {
displayAppList();
}
});
}
}).start();
}
void displayAppList() {
final ListView listView = (ListView) findViewById(R.id.lvFilterApps);
AppListAdapter adapter = new AppListAdapter();
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
for (i = 0 ; i < isFiltered.length; i++){
if (isFiltered[i]) {
listView.setItemChecked(i, true);
}
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
boolean checked = listView.isItemChecked(i);
//Log.e("NotificationFilterActivity", pkgName[i] + ":" + checked);
appDatabase.open();
appDatabase.update(pkgName[i], checked);
appDatabase.setEnabled(apps[i].pkg, checked);
appDatabase.close();
apps[i].isEnabled = checked;
}
});
}
// Delete apps from database which are uninstalled
private void deleteUninstalledApps(){
Cursor res;
appDatabase.open();
res = appDatabase.getAllApplications();
if (res != null) {
res.moveToFirst();
while (!res.isAfterLast()) {
String packageName = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME));
if (!isPackageInstalled(packageName)) {
appDatabase.delete(packageName);
}
res.moveToNext();
}
res.close();
}
appDatabase.close();
}
// Adding newly installed apps in database
private void addNewlyInstalledApps() {
List<ApplicationInfo> PackList = getPackageManager().getInstalledApplications(0);
appDatabase.open();
for (int i=0; i < PackList.size(); i++)
{
ApplicationInfo PackInfo = PackList.get(i);
String appName = PackInfo.loadLabel(getPackageManager()).toString();
String packageName = PackInfo.packageName;
if ( (PackInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ) {
if (!appDatabase.exists(packageName)) {
appDatabase.create(appName, packageName, true);
}
//Log.e("App FLAG_UPDATED_SYSTEM_APP: " + Integer.toString(i), appName);
} else if ( (PackInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
//ignore these apps
} else {
if (!appDatabase.exists(packageName)) {
appDatabase.create(appName, packageName, true);
}
//Log.e("App : " + Integer.toString(i), appName);
}
for (int i = 0 ; i < apps.length; i++) {
listView.setItemChecked(i, apps[i].isEnabled);
}
appDatabase.close();
listView.setVisibility(View.VISIBLE);
findViewById(R.id.spinner).setVisibility(View.GONE);
}
private boolean isPackageInstalled(String packageName){
PackageManager pm = getPackageManager();
try {
pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
} catch (Exception e) {
return false;
}
return true;
}
@Override
protected void onStart() {
super.onStart();
@@ -170,4 +172,19 @@ public class NotificationFilterActivity extends ActionBarActivity {
BackgroundService.removeGuiInUseCounter(this);
}
Drawable resizeIcon(Drawable icon, int maxSize) {
Resources res = getResources();
//Convert to display pixels
maxSize = (int)(maxSize*res.getDisplayMetrics().density);
Bitmap bitmap = Bitmap.createBitmap(maxSize, maxSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
icon.draw(canvas);
return new BitmapDrawable(res, bitmap);
}
}

View File

@@ -170,11 +170,6 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
return;
}
if (packageName.equals("com.google.android.googlequicksearchbox")) {
//HACK: Hide Google Now notifications that keep constantly popping up (and without text because we don't know how to read them properly)
return;
}
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
if (packageName.equals("org.kde.kdeconnect_tp"))

View File

@@ -242,7 +242,7 @@ public class DeviceFragment extends Fragment {
}
});
if (device.isPaired()) {
if (device.isPaired() && device.isReachable()) {
menu.add(R.string.encryption_info_title).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
@@ -266,6 +266,9 @@ public class DeviceFragment extends Fragment {
return true;
}
});
}
if (device.isPaired()) {
menu.add(R.string.device_menu_unpair).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override