mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-09-01 14:45:08 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8b01db3c34 | ||
|
25728eae18 | ||
|
dc7fc46e62 | ||
|
2b1e4dcb23 | ||
|
97b7eb71cf | ||
|
bb0ab51d3b | ||
|
f503b18993 | ||
|
58e9a5d2b6 | ||
|
fd34e56675 | ||
|
4be79b52ae | ||
|
028a2992c9 | ||
|
bdfc21cf64 |
@@ -2,8 +2,8 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.kde.kdeconnect_tp"
|
||||
android:versionCode="12002"
|
||||
android:versionName="1.20.2">
|
||||
android:versionCode="12100"
|
||||
android:versionName="1.21.0">
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
@@ -40,6 +40,7 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||
@@ -362,7 +363,6 @@
|
||||
<action android:name="android.service.chooser.ChooserTargetService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<!--
|
||||
<service
|
||||
android:name="org.kde.kdeconnect.Plugins.MouseReceiverPlugin.MouseReceiverService"
|
||||
android:exported="true"
|
||||
@@ -374,7 +374,6 @@
|
||||
android:name="android.accessibilityservice"
|
||||
android:resource="@xml/mouse_receiver_service" />
|
||||
</service>
|
||||
-->
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity"
|
||||
|
12
build.gradle
12
build.gradle
@@ -4,9 +4,9 @@ import com.android.build.gradle.api.ApplicationVariant
|
||||
import com.github.jk1.license.render.TextReportRenderer
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.7.10'
|
||||
ext.kotlin_version = '1.7.20'
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||
classpath 'com.android.tools.build:gradle:7.3.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ dependencies {
|
||||
|
||||
implementation 'commons-io:commons-io:2.8.0' // newer versions don't work on Android 7: https://stackoverflow.com/questions/73604534/no-static-method-threadlocal-withinitial-commons-io-dependency
|
||||
implementation 'org.apache.commons:commons-collections4:4.4'
|
||||
implementation 'org.apache.commons:commons-lang3:3.11'
|
||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||
|
||||
// Kotlin
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
@@ -178,12 +178,12 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
|
||||
// Testing
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.powermock:powermock-core:2.0.0'
|
||||
testImplementation 'org.powermock:powermock-module-junit4:2.0.0'
|
||||
testImplementation 'org.powermock:powermock-api-mockito2:2.0.0'
|
||||
testImplementation 'org.mockito:mockito-core:2.23.0'
|
||||
testImplementation 'org.skyscreamer:jsonassert:1.3.0'
|
||||
testImplementation 'org.mockito:mockito-core:3.12.4' // powermock isn't compatible with mockito 4
|
||||
testImplementation 'org.skyscreamer:jsonassert:1.5.1'
|
||||
|
||||
// For device controls
|
||||
implementation 'org.reactivestreams:reactive-streams:1.0.4'
|
||||
|
@@ -52,6 +52,7 @@
|
||||
<string name="remotekeyboard_multiple_connections">Hi ha més d\'una connexió amb un teclat remot, seleccioneu el dispositiu per a configurar-lo</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_info">Moveu un dit per la pantalla per a moure el cursor del ratolí. Toqueu per a un clic, i empreu dos/tres dits per als botons dret i mig. Useu 2 dits per a desplaçar. Empreu un toc llarg per a arrossegar i deixar anar.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">El dispositiu aparellat no permet l\'entrada de teclat</string>
|
||||
<string name="mousepad_single_tap_settings_title">Estableix l\'acció de tocar amb un dit</string>
|
||||
<string name="mousepad_double_tap_settings_title">Estableix l\'acció de tocar amb dos dits</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Estableix l\'acció de tocar amb tres dits</string>
|
||||
|
@@ -52,6 +52,7 @@
|
||||
<string name="remotekeyboard_multiple_connections">There is more than one remote keyboard connection, select the device to configure</string>
|
||||
<string name="open_mousepad">Remote input</string>
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use 2 fingers to scroll. Use a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">Keyboard input not supported by the paired device</string>
|
||||
<string name="mousepad_single_tap_settings_title">Set one finger tap action</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
|
||||
@@ -275,6 +276,8 @@
|
||||
<string name="pref_plugin_mprisreceiver">Media Player Control</string>
|
||||
<string name="pref_plugin_mprisreceiver_desc">Control your phone\'s media players from another device</string>
|
||||
<string name="notification_channel_default">Other notifications</string>
|
||||
<string name="notification_channel_persistent_no_devices">Persistent indicator (no devices)</string>
|
||||
<string name="notification_channel_persistent_with_devices">Persistent indicator (with devices)</string>
|
||||
<string name="notification_channel_media_control">Media control</string>
|
||||
<string name="notification_channel_filetransfer">File transfer</string>
|
||||
<string name="notification_channel_high_priority">High priority</string>
|
||||
|
@@ -52,6 +52,7 @@
|
||||
<string name="remotekeyboard_multiple_connections">Urruneko teklatuekin konexio bat baino gehiago dago, hautatu konfiguratu beharreko gailua</string>
|
||||
<string name="open_mousepad">Urruneko sarrera</string>
|
||||
<string name="mousepad_info">Mugitu hatz bat pantailan zehar saguaren erakuslea mugitzeko. Egin tak klik baterako, eta erabili bi/hiru hatz eskuin eta erdiko botoietarako. Erabili 2 hatz labaintzeko. Erabili sakatze luze bat arrastatu eta jaregiteko.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">Parekatutako gailuak ez du teklatuko sarreraren euskarririk</string>
|
||||
<string name="mousepad_single_tap_settings_title">Ezarri hatz bakarrarekin tak egitearen ekintza</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ezarri bi hatzez tak egitearen ekintza</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ezarri hiru hatzez tak egitearen ekintza</string>
|
||||
|
@@ -52,6 +52,7 @@
|
||||
<string name="remotekeyboard_multiple_connections">Plusieurs connexions à des claviers sans fil sont disponibles, sélectionnez le périphérique à configurer</string>
|
||||
<string name="open_mousepad">Contrôle distant</string>
|
||||
<string name="mousepad_info">Faites glisser votre doigt sur l\'écran pour déplacer le pointeur de la souris. Appuyez pour cliquer et utilisez deux/trois doigts pour les clic droit et centre. Utilisez 2 doigts pour faire défiler. Appuyez longtemps pour faire un glisser-déposer.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">La saisie par le clavier n\'est pas pris en charge par le périphérique appairée.</string>
|
||||
<string name="mousepad_single_tap_settings_title">Définir une action pour tapotage avec un doigt</string>
|
||||
<string name="mousepad_double_tap_settings_title">Action pour l\'appui à deux doigts</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Action pour l\'appui à trois doigts</string>
|
||||
|
@@ -56,15 +56,19 @@
|
||||
<item>უსწრაფესი</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_acceleration_profile_entries">
|
||||
<item>No Acceleration</item>
|
||||
<item>Weakest</item>
|
||||
<item>Weaker</item>
|
||||
<item>ამაჩქარებლის გარეშე</item>
|
||||
<item>მინიმალური</item>
|
||||
<item>საშუალოზე დაბალი</item>
|
||||
<item>საშუალო</item>
|
||||
<item>Stronger</item>
|
||||
<item>Strongest</item>
|
||||
<item>ძლიერი</item>
|
||||
<item>უძლიერესი</item>
|
||||
</string-array>
|
||||
<string name="mouse_receiver_plugin_name">თაგუნას მიმღები</string>
|
||||
<string name="view_status_title">მდგომარეობა</string>
|
||||
<string name="battery_status_format">ელემენტი: %d%%</string>
|
||||
<string name="battery_status_low_format">ელემენტი: %d%% ელემენტი დასატენია</string>
|
||||
<string name="battery_status_charging_format">ელემენტი: %d%% იტენება</string>
|
||||
<string name="battery_status_unknown">ელემენტის ინფორმაცია ხელმიუწვდომელია</string>
|
||||
<string name="category_connected_devices">მიერთებული მოწყობილობები</string>
|
||||
<string name="category_not_paired_devices">ხელმისაწვდომი მოწყობილობები</string>
|
||||
<string name="category_remembered_devices">დამახსოვრებული მოწყობილობები</string>
|
||||
@@ -89,11 +93,14 @@
|
||||
<item quantity="other">(ფაილი %2$d of %3$d) : %1$s</item>
|
||||
</plurals>
|
||||
<string name="tap_to_open">გასახსნელად დაატყაპუნეთ</string>
|
||||
<string name="received_file_text">\'%1s\'-ის გასახსნელად დაატყაპუნეთ</string>
|
||||
<string name="cannot_create_file">ფაილის (%s) შექმნის შეცდომა</string>
|
||||
<string name="tap_to_answer">საპასუხოდ დაატყაპუნეთ</string>
|
||||
<string name="right_click">მარჯვენა წკაპის გაგზავნა</string>
|
||||
<string name="middle_click">შუა წკაპის გაგზავნა</string>
|
||||
<string name="show_keyboard">კლავიატურის ჩვენება</string>
|
||||
<string name="device_not_paired">მოწყობილოვა დაწყვილებული არაა</string>
|
||||
<string name="request_pairing">დაწყვილების მოთხოვნა</string>
|
||||
<string name="pairing_accept">დასტური</string>
|
||||
<string name="pairing_reject">უარყოფა</string>
|
||||
<string name="settings">პარამეტრები</string>
|
||||
@@ -105,6 +112,7 @@
|
||||
<string name="mpris_loop">მარყუჟი</string>
|
||||
<string name="mpris_shuffle">შემთხვევით</string>
|
||||
<string name="mpris_volume">ტომი</string>
|
||||
<string name="mpris_time_settings_title">წინ/გადახვევის ღილაკები</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 წამი</item>
|
||||
<item>20 წამი</item>
|
||||
@@ -124,6 +132,7 @@
|
||||
<string name="share_received_file">\"%s\"-ის გაზიარება</string>
|
||||
<string name="sftp_sdcard_num">SD ბარათი %d</string>
|
||||
<string name="sftp_sdcard">SD ბარათი</string>
|
||||
<string name="sftp_readonly">(მხოლოდ კითხვადი)</string>
|
||||
<string name="sftp_camera">კამერის სურათები</string>
|
||||
<string name="add_device_dialog_title">მოწყობილობის დამატება</string>
|
||||
<string name="add_device_hint">ჰოსტის სახელი ან IP მისამართი</string>
|
||||
@@ -133,11 +142,17 @@
|
||||
<string name="sftp_preference_add_storage_location_title">საცავის მდებარეობის დამატება</string>
|
||||
<string name="sftp_preference_edit_storage_location">საცავის მდებარეობის ჩასწორება</string>
|
||||
<string name="sftp_preference_add_camera_shortcut">კამერის საქაღალდის მალსახმობის დამატება</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_off">კამერის საქაღალდეს მალსახმობი არ დაემატება</string>
|
||||
<string name="sftp_storage_preference_storage_location">საცავის მდებარეობა</string>
|
||||
<string name="sftp_storage_preference_storage_location_already_configured">ეს მდებარეობა უკვე მორგებულია</string>
|
||||
<string name="sftp_storage_preference_click_to_select">მოსანიშნად დააწკაპუნეთ</string>
|
||||
<string name="sftp_storage_preference_display_name">ნაჩვენები სახელი</string>
|
||||
<string name="sftp_storage_preference_display_name_already_used">საჩვენებელი სახელი უკვე გამოიყენება</string>
|
||||
<string name="sftp_storage_preference_display_name_cannot_be_empty">საჩვენებელი სახელი ცარიელი არ შეიძლება იყოს</string>
|
||||
<string name="sftp_action_mode_menu_delete">წაშლა</string>
|
||||
<string name="sftp_no_sdcard_detected">SD ბარათი ვერ ვიპოვე</string>
|
||||
<string name="sftp_no_storage_locations_configured">საცავის მდებარეობები მითითებული არაა</string>
|
||||
<string name="no_players_connected">დამკვრელები ნაპოვნი არაა</string>
|
||||
<string name="send_files">ფაილების გაგზავნა</string>
|
||||
<string name="pairing_title">KDE Connect -ის მოწყობილობები</string>
|
||||
<string name="device_rename_title">მოწყობილობის სახელის გადარქმევა</string>
|
||||
|
@@ -52,6 +52,7 @@
|
||||
<string name="remotekeyboard_multiple_connections">Er is meer dan een verbinding met een toetsenbord op afstand, selecteer het te configureren apparaat</string>
|
||||
<string name="open_mousepad">Invoer op afstand</string>
|
||||
<string name="mousepad_info">Veeg met een vinger op het scherm om de muiscursor te verplaatsen. Tik om te klikken en gebruik twee/drie vingers voor rechter en middelste knop. Twee vingers gebruiken voor schuiven. Druk lang voor slepen en loslaten.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">Toetsenbordinvoer wordt niet ondersteund door het gepaarde apparaat</string>
|
||||
<string name="mousepad_single_tap_settings_title">Tikactie met één vinger instellen</string>
|
||||
<string name="mousepad_double_tap_settings_title">Tikactie met twee vingers instellen</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Tikactie met drie vingers instellen</string>
|
||||
|
@@ -52,6 +52,7 @@
|
||||
<string name="remotekeyboard_multiple_connections">Birden çok uzak klavye bağlantısı mevcut, yapılandırmak istediğiniz aygıtı seçin</string>
|
||||
<string name="open_mousepad">Girdi sil</string>
|
||||
<string name="mousepad_info">İmleç denetimi için parmağınızı ekranda hareket ettirin. Bir tıklama için hafifçe vurun, sağ ve orta düğmeler için iki/üç parmağınızı kullanın. Sarmak için 2 parmağınızı kullanın. Bırakıp sürüklemek için uzun basın.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">Klavye girişi, eşlenen aygıt tarafından desteklenmiyor</string>
|
||||
<string name="mousepad_single_tap_settings_title">Tek parmak dokunma eylemini ayarla</string>
|
||||
<string name="mousepad_double_tap_settings_title">İki parmak dokunma eylemini ayarla</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Üç parmak dokunma eylemini ayarla</string>
|
||||
|
@@ -52,6 +52,7 @@
|
||||
<string name="remotekeyboard_multiple_connections">Існує декілька з’єднань із віддаленою клавіатурою. Виберіть пристрій для налаштовування.</string>
|
||||
<string name="open_mousepad">Дистанційне введення</string>
|
||||
<string name="mousepad_info">Проведіть по екрану пальцем, щоб пересунути вказівник миші. Дотик одним пальцем означатиме клацання, дотиком двома або трьома пальцями можна імітувати праву і середню кнопки. Гортання відбувається за допомогою двох пальців. Для перетягування зі скиданням скористайтеся тривалим натисканням.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">Підтримки введення з клавіатури на пов\'язаному пристрої не передбачено</string>
|
||||
<string name="mousepad_single_tap_settings_title">Встановлення дії для торкання одним пальцем</string>
|
||||
<string name="mousepad_double_tap_settings_title">Встановлення дії для торкання двома пальцями</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Встановлення дії для торкання трьома пальцями</string>
|
||||
|
@@ -59,6 +59,7 @@
|
||||
<string name="remotekeyboard_multiple_connections" translatable="true">There is more than one remote keyboard connection, select the device to configure</string>
|
||||
<string name="open_mousepad">Remote input</string>
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use 2 fingers to scroll. Use a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_keyboard_input_not_supported">Keyboard input not supported by the paired device</string>
|
||||
<string name="mousepad_single_tap_settings_title">Set one finger tap action</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
|
||||
|
@@ -17,6 +17,8 @@ import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
@@ -262,11 +264,27 @@ public class BackgroundService extends Service {
|
||||
// Register screen on listener
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
||||
// See: https://developer.android.com/reference/android/net/ConnectivityManager.html#CONNECTIVITY_ACTION
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
}
|
||||
registerReceiver(new KdeConnectBroadcastReceiver(), filter);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkRequest.Builder builder = new NetworkRequest.Builder();
|
||||
cm.registerNetworkCallback(builder.build(), new ConnectivityManager.NetworkCallback() {
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
onDeviceListChanged();
|
||||
onNetworkChange();
|
||||
}
|
||||
@Override
|
||||
public void onLost(Network network) {
|
||||
onDeviceListChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Log.i("KDE/BackgroundService", "Service not started yet, initializing...");
|
||||
|
||||
PluginFactory.initPluginInfo(getBaseContext());
|
||||
|
@@ -19,6 +19,7 @@ import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
@@ -171,13 +172,6 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_mousepad, menu);
|
||||
|
||||
BackgroundService.RunWithPlugin(this, deviceId, MousePadPlugin.class, plugin -> {
|
||||
if (!plugin.isKeyboardEnabled()) {
|
||||
menu.removeItem(R.id.menu_show_keyboard);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -191,12 +185,24 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
|
||||
sendMiddleClick();
|
||||
return true;
|
||||
} else if (id == R.id.menu_show_keyboard) {
|
||||
showKeyboard();
|
||||
BackgroundService.RunWithPlugin(this, deviceId, MousePadPlugin.class, plugin -> {
|
||||
if (plugin.isKeyboardEnabled()) {
|
||||
showKeyboard();
|
||||
} else {
|
||||
Toast toast = Toast.makeText(this, R.string.mousepad_keyboard_input_not_supported, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else if (id == R.id.menu_open_compose_send) {
|
||||
Intent intent = new Intent(this, ComposeSendActivity.class);
|
||||
intent.putExtra("org.kde.kdeconnect.Plugins.MousePadPlugin.deviceId", deviceId);
|
||||
startActivity(intent);
|
||||
BackgroundService.RunWithPlugin(this, deviceId, MousePadPlugin.class, plugin -> {
|
||||
if (plugin.isKeyboardEnabled()) {
|
||||
showCompose();
|
||||
} else {
|
||||
Toast toast = Toast.makeText(this, R.string.mousepad_keyboard_input_not_supported, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
@@ -397,6 +403,12 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
|
||||
imm.toggleSoftInputFromWindow(keyListenerView.getWindowToken(), 0, 0);
|
||||
}
|
||||
|
||||
private void showCompose() {
|
||||
Intent intent = new Intent(this, ComposeSendActivity.class);
|
||||
intent.putExtra("org.kde.kdeconnect.Plugins.MousePadPlugin.deviceId", deviceId);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
super.onBackPressed();
|
||||
|
@@ -20,7 +20,7 @@ import org.kde.kdeconnect.UserInterface.MainActivity;
|
||||
import org.kde.kdeconnect.UserInterface.StartActivityAlertDialogFragment;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
//@PluginFactory.LoadablePlugin
|
||||
@PluginFactory.LoadablePlugin
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public class MouseReceiverPlugin extends Plugin {
|
||||
private final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
|
||||
|
@@ -165,6 +165,11 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
|
||||
actions.remove(id);
|
||||
|
||||
if (!appDatabase.isEnabled(statusBarNotification.getPackageName())) {
|
||||
currentNotifications.remove(id);
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkPacket np = new NetworkPacket(PACKET_TYPE_NOTIFICATION);
|
||||
np.set("id", id);
|
||||
np.set("isCancel", true);
|
||||
|
@@ -269,16 +269,17 @@ public class DeviceFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void refreshUI() {
|
||||
if (device == null || binding == null) {
|
||||
return;
|
||||
if (device != null) {
|
||||
//Once in-app, there is no point in keep displaying the notification if any
|
||||
device.hidePairingNotification();
|
||||
}
|
||||
|
||||
//Once in-app, there is no point in keep displaying the notification if any
|
||||
device.hidePairingNotification();
|
||||
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (device == null || binding == null) {
|
||||
return;
|
||||
}
|
||||
if (device.isPairRequestedByPeer()) {
|
||||
binding.pairMessage.setText(R.string.pair_requested);
|
||||
binding.pairVerification.setVisibility(View.VISIBLE);
|
||||
|
@@ -42,7 +42,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({Base64.class, Log.class, PreferenceManager.class, ContextCompat.class})
|
||||
|
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015 Vineet Garg <grg.vineet@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLink;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({DeviceHelper.class, Log.class})
|
||||
public class LanLinkProviderTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
PowerMockito.mockStatic(DeviceHelper.class);
|
||||
PowerMockito.when(DeviceHelper.getDeviceId(any())).thenReturn("123");
|
||||
|
||||
PowerMockito.mockStatic(Log.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdentityPacketReceived() throws Exception {
|
||||
|
||||
LanLinkProvider linkProvider = new LanLinkProvider(null);
|
||||
|
||||
NetworkPacket networkPacket = Mockito.mock(NetworkPacket.class);
|
||||
Mockito.when(networkPacket.getType()).thenReturn("kdeconnect.identity");
|
||||
Mockito.when(networkPacket.getString("deviceId")).thenReturn("testDevice");
|
||||
Mockito.when(networkPacket.getString("deviceName")).thenReturn("Test Device");
|
||||
Mockito.when(networkPacket.getInt("protocolVersion")).thenReturn(5);
|
||||
Mockito.when(networkPacket.getString("deviceType")).thenReturn("phone");
|
||||
|
||||
String serialized = "{\"type\":\"kdeconnect.identity\",\"id\":12345,\"body\":{\"deviceName\":\"Test Device\",\"deviceType\":\"phone\",\"deviceId\":\"testDevice\",\"protocolVersion\":5}}";
|
||||
Mockito.when(networkPacket.serialize()).thenReturn(serialized);
|
||||
|
||||
Socket channel = Mockito.mock(Socket.class);
|
||||
Method method = LanLinkProvider.class.getDeclaredMethod("identityPacketReceived", NetworkPacket.class, Socket.class, LanLink.ConnectionStarted.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(linkProvider, networkPacket, channel, LanLink.ConnectionStarted.Locally);
|
||||
|
||||
HashMap<String, LanLink> visibleComputers;
|
||||
Field field = LanLinkProvider.class.getDeclaredField("visibleComputers");
|
||||
field.setAccessible(true);
|
||||
visibleComputers = (HashMap<String, LanLink>) field.get(linkProvider);
|
||||
assertNotNull(visibleComputers.get("testDevice"));
|
||||
|
||||
}
|
||||
}
|
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015 Vineet Garg <grg.vineet@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLink;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({Log.class})
|
||||
public class LanLinkTest {
|
||||
|
||||
private LanLink badLanLink;
|
||||
private LanLink goodLanLink;
|
||||
|
||||
private OutputStream goodOutputStream;
|
||||
|
||||
private Device.SendPacketStatusCallback callback;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
PowerMockito.mockStatic(Log.class);
|
||||
|
||||
LanLinkProvider linkProvider = Mockito.mock(LanLinkProvider.class);
|
||||
Mockito.when(linkProvider.getName()).thenReturn("LanLinkProvider");
|
||||
|
||||
callback = Mockito.mock(Device.SendPacketStatusCallback.class);
|
||||
|
||||
goodOutputStream = Mockito.mock(OutputStream.class);
|
||||
OutputStream badOutputStream = Mockito.mock(OutputStream.class);
|
||||
Mockito.doThrow(new IOException("AAA")).when(badOutputStream).write(Mockito.any(byte[].class));
|
||||
|
||||
|
||||
SSLSocket socketMock = Mockito.mock(SSLSocket.class);
|
||||
Mockito.when(socketMock.getRemoteSocketAddress()).thenReturn(new InetSocketAddress(5000));
|
||||
Mockito.when(socketMock.getOutputStream()).thenReturn(goodOutputStream);
|
||||
|
||||
SSLSocket socketBadMock = Mockito.mock(SSLSocket.class);
|
||||
Mockito.when(socketBadMock.getRemoteSocketAddress()).thenReturn(new InetSocketAddress(5000));
|
||||
Mockito.when(socketBadMock.getOutputStream()).thenReturn(badOutputStream);
|
||||
|
||||
Context context = Mockito.mock(Context.class);
|
||||
goodLanLink = new LanLink(context, "testDevice", linkProvider, socketMock, LanLink.ConnectionStarted.Remotely);
|
||||
badLanLink = new LanLink(context, "testDevice", linkProvider, socketBadMock, LanLink.ConnectionStarted.Remotely);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendPacketSuccess() throws JSONException {
|
||||
|
||||
NetworkPacket testPacket = Mockito.mock(NetworkPacket.class);
|
||||
Mockito.when(testPacket.getType()).thenReturn("kdeconnect.test");
|
||||
Mockito.when(testPacket.getBoolean("isTesting")).thenReturn(true);
|
||||
Mockito.when(testPacket.getString("testName")).thenReturn("testSendPacketSuccess");
|
||||
Mockito.when(testPacket.serialize()).thenReturn("{\"id\":123,\"type\":\"kdeconnect.test\",\"body\":{\"isTesting\":true,\"testName\":\"testSendPacketSuccess\"}}");
|
||||
|
||||
goodLanLink.sendPacket(testPacket, callback);
|
||||
|
||||
Mockito.verify(callback).onSuccess();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendPacketFail() throws JSONException {
|
||||
|
||||
NetworkPacket testPacket = Mockito.mock(NetworkPacket.class);
|
||||
Mockito.when(testPacket.getType()).thenReturn("kdeconnect.test");
|
||||
Mockito.when(testPacket.getBoolean("isTesting")).thenReturn(true);
|
||||
Mockito.when(testPacket.getString("testName")).thenReturn("testSendPacketFail");
|
||||
Mockito.when(testPacket.serialize()).thenReturn("{\"id\":123,\"type\":\"kdeconnect.test\",\"body\":{\"isTesting\":true,\"testName\":\"testSendPacketFail\"}}");
|
||||
|
||||
badLanLink.sendPacket(testPacket, callback);
|
||||
|
||||
Mockito.verify(callback).onFailure(Mockito.any(IOException.class));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendPayload() throws Exception {
|
||||
|
||||
class Downloader extends Thread {
|
||||
|
||||
NetworkPacket np;
|
||||
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
void setNetworkPacket(NetworkPacket networkPacket) {
|
||||
this.np = networkPacket;
|
||||
}
|
||||
|
||||
ByteArrayOutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
Socket socket = null;
|
||||
try {
|
||||
socket = new Socket();
|
||||
int tcpPort = np.getPayloadTransferInfo().getInt("port");
|
||||
InetSocketAddress address = new InetSocketAddress(5000);
|
||||
socket.connect(new InetSocketAddress(address.getAddress(), tcpPort));
|
||||
np.setPayload(new NetworkPacket.Payload(socket.getInputStream(), np.getPayloadSize()));
|
||||
} catch (Exception e) {
|
||||
socket.close();
|
||||
Log.e("KDE/LanLinkTest", "Exception connecting to remote socket", e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
final InputStream input = np.getPayload().getInputStream();
|
||||
final long fileLength = np.getPayloadSize();
|
||||
|
||||
byte[] data = new byte[1024];
|
||||
long progress = 0, prevProgressPercentage = 0;
|
||||
int count;
|
||||
while ((count = input.read(data)) >= 0) {
|
||||
progress += count;
|
||||
outputStream.write(data, 0, count);
|
||||
if (fileLength > 0) {
|
||||
if (progress >= fileLength) break;
|
||||
long progressPercentage = (progress * 100 / fileLength);
|
||||
if (progressPercentage != prevProgressPercentage) {
|
||||
prevProgressPercentage = progressPercentage;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
outputStream.close();
|
||||
input.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("Downloader Test", "Exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final Downloader downloader = new Downloader();
|
||||
|
||||
// Using byte array for payload, try to use input stream as used in real device
|
||||
String dataString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." +
|
||||
" Cras vel erat et ante fringilla tristique. Sed consequat ligula at interdum " +
|
||||
"rhoncus. Integer semper enim felis, id sodales tellus aliquet eget." +
|
||||
" Sed fringilla ac metus eget dictum. Aliquam euismod non sem sit" +
|
||||
" amet dapibus. Interdum et malesuada fames ac ante ipsum primis " +
|
||||
"in faucibus. Nam et ligula placerat, varius justo eu, convallis " +
|
||||
"lorem. Nam consequat consequat tortor et gravida. Praesent " +
|
||||
"ultricies tortor eget ex elementum gravida. Suspendisse aliquet " +
|
||||
"erat a orci feugiat dignissim.";
|
||||
|
||||
// reallyLongString contains dataString 16 times
|
||||
String reallyLongString = dataString + dataString;
|
||||
reallyLongString = reallyLongString + reallyLongString;
|
||||
reallyLongString = reallyLongString + reallyLongString;
|
||||
reallyLongString = reallyLongString + reallyLongString;
|
||||
|
||||
final byte[] data = reallyLongString.getBytes();
|
||||
|
||||
final JSONObject sharePacketJson = new JSONObject("{\"id\":123,\"body\":{\"filename\":\"data.txt\"},\"payloadTransferInfo\":{},\"payloadSize\":8720,\"type\":\"kdeconnect.share\"}");
|
||||
|
||||
// Mocking share package
|
||||
final NetworkPacket sharePacket = Mockito.mock(NetworkPacket.class);
|
||||
Mockito.when(sharePacket.getType()).thenReturn("kdeconnect.share");
|
||||
Mockito.when(sharePacket.hasPayload()).thenReturn(true);
|
||||
Mockito.when(sharePacket.hasPayloadTransferInfo()).thenReturn(true);
|
||||
Mockito.doAnswer(invocationOnMock -> sharePacketJson.toString()).when(sharePacket).serialize();
|
||||
Mockito.when(sharePacket.getPayload()).thenReturn(new NetworkPacket.Payload(new ByteArrayInputStream(data), -1));
|
||||
Mockito.when(sharePacket.getPayloadSize()).thenReturn((long) data.length);
|
||||
Mockito.doAnswer(invocationOnMock -> sharePacketJson.getJSONObject("payloadTransferInfo")).when(sharePacket).getPayloadTransferInfo();
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
JSONObject object = (JSONObject) invocationOnMock.getArguments()[0];
|
||||
|
||||
sharePacketJson.put("payloadTransferInfo", object);
|
||||
return null;
|
||||
}).when(sharePacket).setPayloadTransferInfo(Mockito.any(JSONObject.class));
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
|
||||
Log.e("LanLinkTest", "Write to stream");
|
||||
String stringNetworkPacket = new String((byte[]) invocationOnMock.getArguments()[0]);
|
||||
final NetworkPacket np = NetworkPacket.unserialize(stringNetworkPacket);
|
||||
|
||||
downloader.setNetworkPacket(np);
|
||||
downloader.start();
|
||||
|
||||
return stringNetworkPacket.length();
|
||||
}).when(goodOutputStream).write(Mockito.any(byte[].class));
|
||||
|
||||
goodLanLink.sendPacket(sharePacket, callback);
|
||||
|
||||
try {
|
||||
// Wait 1 secs for downloader to finish (if some error, it will continue and assert will fail)
|
||||
downloader.join(1000);
|
||||
} catch (Exception e) {
|
||||
Log.e("Test", "Exception", e);
|
||||
throw e;
|
||||
}
|
||||
assertEquals(new String(data), new String(downloader.getOutputStream().toByteArray()));
|
||||
|
||||
Mockito.verify(callback).onSuccess();
|
||||
|
||||
}
|
||||
}
|
@@ -23,8 +23,8 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({DeviceHelper.class, Log.class})
|
||||
|
Reference in New Issue
Block a user