Compare commits
152 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
23648a03e5 | ||
|
3f188b5526 | ||
|
2d35b04713 | ||
|
9a5b03c423 | ||
|
ee336aa414 | ||
|
a81eba9ea1 | ||
|
c5022358de | ||
|
9d1734406b | ||
|
2d49715891 | ||
|
9e6a4938ed | ||
|
cc4a196334 | ||
|
c39620e33c | ||
|
0dd26e5729 | ||
|
86d0d3065c | ||
|
1f8f39a7f8 | ||
|
05ba2188de | ||
|
ba440bd5ea | ||
|
a94e082b68 | ||
|
def0cad889 | ||
|
c93e4400e2 | ||
|
9580154a13 | ||
|
48f5566326 | ||
|
3ea5d43b99 | ||
|
a172430c11 | ||
|
b4b7b58cb2 | ||
|
8d99de59fc | ||
|
337cdba68f | ||
|
b3e1f6fbf8 | ||
|
ecad7ccea2 | ||
|
b7df5348c0 | ||
|
440a12f86c | ||
|
0e3b5af6bc | ||
|
b167b9629e | ||
|
b6814c86c5 | ||
|
3cc71a69a4 | ||
|
c0502803c4 | ||
|
ec6696b33b | ||
|
7e30e27f61 | ||
|
92a10bcd35 | ||
|
723f398ea8 | ||
|
060fa8200e | ||
|
7045c50c81 | ||
|
fe0409e9e7 | ||
|
4f39aa2b65 | ||
|
cba67c73a0 | ||
|
2e5dc56366 | ||
|
5ece4e21e7 | ||
|
be66fb23cf | ||
|
a6bd803df8 | ||
|
a5a4b360ae | ||
|
71e7218b4e | ||
|
89ecdfc363 | ||
|
1179807bcf | ||
|
4279ae824f | ||
|
753a6425ef | ||
|
08312e409d | ||
|
22526fdaa8 | ||
|
963b29ef6b | ||
|
ca9704eab2 | ||
|
8d148aad92 | ||
|
1239944deb | ||
|
9e5e9b3047 | ||
|
42f8289071 | ||
|
371ffefd20 | ||
|
614becd1a7 | ||
|
3c101210e2 | ||
|
52a4ac20ee | ||
|
42be344336 | ||
|
1811b93b0a | ||
|
6ed1bf6284 | ||
|
f1ca9a3c33 | ||
|
9d4bbbb629 | ||
|
60ff59bc34 | ||
|
059a3b2437 | ||
|
eeb19bd206 | ||
|
5e229085e9 | ||
|
a7c4bbd379 | ||
|
a38ffe34bd | ||
|
b5e6519efe | ||
|
ad2b7678b9 | ||
|
9649efcdc4 | ||
|
99b7c4f312 | ||
|
c80820294c | ||
|
90856690fb | ||
|
1334dae342 | ||
|
f8dd9bf923 | ||
|
72d8ba647a | ||
|
b3449c87f7 | ||
|
5c3b5a2737 | ||
|
e2e40863f8 | ||
|
036737deae | ||
|
8d7337b6b0 | ||
|
0a4459e8a0 | ||
|
cef8cbd34a | ||
|
3afb8ae8f3 | ||
|
85fce32bcb | ||
|
d52be109ee | ||
|
66794002f7 | ||
|
d61536ef76 | ||
|
1dad3c145d | ||
|
33f7a4809d | ||
|
d81448ad34 | ||
|
ed4c0d24df | ||
|
fed9bb1eec | ||
|
b7418c1db6 | ||
|
e6bc78f013 | ||
|
22de200cbf | ||
|
22dde07892 | ||
|
f9bdfb9fbd | ||
|
9d6476a27e | ||
|
29a8db9c45 | ||
|
6e1f8e1496 | ||
|
82b15292fb | ||
|
32f9f3b76a | ||
|
fc25e42196 | ||
|
db3422268f | ||
|
71bef30624 | ||
|
15e0188538 | ||
|
8bc8a47e9d | ||
|
ad7769edde | ||
|
a2c51a16ee | ||
|
788555b69c | ||
|
ccdeb3d806 | ||
|
00a5ad3c1f | ||
|
b35ce0f821 | ||
|
77e38da2d9 | ||
|
8fb942ccdf | ||
|
74dc1bcd63 | ||
|
0f655cf4eb | ||
|
0de86785f8 | ||
|
5320c3c226 | ||
|
7234b34db7 | ||
|
428fa947a4 | ||
|
b454dec0a0 | ||
|
6c3811a0af | ||
|
86245a697e | ||
|
041f172195 | ||
|
6c1dcda744 | ||
|
91913664be | ||
|
9e680d1494 | ||
|
4158a14437 | ||
|
28a33172ce | ||
|
086194c629 | ||
|
75eca915dd | ||
|
cfcf9d97e7 | ||
|
4acf931f5a | ||
|
e95265c263 | ||
|
fa689bace6 | ||
|
625bdd36e3 | ||
|
717bb081a7 | ||
|
9d612192e3 | ||
|
4b171e624f |
@@ -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="1440"
|
||||
android:versionName="1.4.4">
|
||||
android:versionCode="1630"
|
||||
android:versionName="1.6.3">
|
||||
|
||||
<uses-sdk android:minSdkVersion="9"
|
||||
android:targetSdkVersion="22" />
|
||||
@@ -27,6 +27,7 @@
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
@@ -41,6 +42,17 @@
|
||||
android:enabled="true" >
|
||||
</service>
|
||||
|
||||
<!--Commented here and in PluginFactory until we release a desktop version with this feature, so we don't get bad "feature not working" reviews-->
|
||||
<!--
|
||||
<service android:name="org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin.RemoteKeyboardService"
|
||||
android:label="KDE Connect Remote Keyboard"
|
||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
<intent-filter>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/remotekeyboardplugin_method" />
|
||||
</service>
|
||||
-->
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.UserInterface.MaterialActivity"
|
||||
android:label="KDE Connect"
|
||||
@@ -83,6 +95,16 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.UserInterface.SettingsActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.SharePlugin.ShareSettingsActivity"
|
||||
android:label="@string/device_menu_plugins"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.SettingsActivity" >
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.Plugins.SharePlugin.ShareSettingsActivity" />
|
||||
</activity>
|
||||
|
||||
|
||||
|
||||
<receiver android:name="org.kde.kdeconnect.KdeConnectBroadcastReceiver" >
|
||||
<intent-filter>
|
||||
@@ -118,6 +140,8 @@
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneActivity"
|
||||
android:label="@string/findmyphone_title"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleInstance">
|
||||
</activity>
|
||||
|
||||
|
14
build.gradle
@@ -3,18 +3,18 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.0'
|
||||
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
buildToolsVersion '23.0.3'
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion '25.0.2'
|
||||
compileSdkVersion 25
|
||||
defaultConfig {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 22 //Bumping to 23 means we have to support the new permissions model
|
||||
targetSdkVersion 22 //Bumping to >22 means we have to support the new permissions model
|
||||
//multiDexEnabled true
|
||||
//testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
|
||||
}
|
||||
@@ -71,9 +71,9 @@ dependencies {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
compile 'com.android.support:support-v4:23.4.0'
|
||||
compile 'com.android.support:appcompat-v7:23.4.0'
|
||||
compile 'com.android.support:design:23.4.0'
|
||||
compile 'com.android.support:support-v4:25.1.1'
|
||||
compile 'com.android.support:appcompat-v7:25.1.1'
|
||||
compile 'com.android.support:design:25.1.1'
|
||||
|
||||
compile 'org.apache.sshd:sshd-core:0.8.0' //0.9 seems to fail on Android 6 and 1.+ requires java.nio.file, which doesn't exist in Android
|
||||
|
||||
|
BIN
res/drawable-hdpi/ic_accept_pairing.png
Normal file
After Width: | Height: | Size: 418 B |
BIN
res/drawable-hdpi/ic_keyboard_hide_white_36dp.png
Normal file
After Width: | Height: | Size: 358 B |
BIN
res/drawable-hdpi/ic_phonelink_off_white_36dp.png
Normal file
After Width: | Height: | Size: 378 B |
BIN
res/drawable-hdpi/ic_phonelink_white_36dp.png
Normal file
After Width: | Height: | Size: 220 B |
BIN
res/drawable-hdpi/ic_reject_pairing.png
Normal file
After Width: | Height: | Size: 474 B |
BIN
res/drawable-mdpi/ic_accept_pairing.png
Normal file
After Width: | Height: | Size: 287 B |
BIN
res/drawable-mdpi/ic_keyboard_hide_white_36dp.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
res/drawable-mdpi/ic_phonelink_off_white_36dp.png
Normal file
After Width: | Height: | Size: 277 B |
BIN
res/drawable-mdpi/ic_phonelink_white_36dp.png
Normal file
After Width: | Height: | Size: 168 B |
BIN
res/drawable-mdpi/ic_reject_pairing.png
Normal file
After Width: | Height: | Size: 337 B |
BIN
res/drawable-xhdpi/ic_accept_pairing.png
Normal file
After Width: | Height: | Size: 520 B |
BIN
res/drawable-xhdpi/ic_keyboard_hide_white_36dp.png
Normal file
After Width: | Height: | Size: 300 B |
BIN
res/drawable-xhdpi/ic_phonelink_off_white_36dp.png
Normal file
After Width: | Height: | Size: 412 B |
BIN
res/drawable-xhdpi/ic_phonelink_white_36dp.png
Normal file
After Width: | Height: | Size: 217 B |
BIN
res/drawable-xhdpi/ic_reject_pairing.png
Normal file
After Width: | Height: | Size: 624 B |
BIN
res/drawable-xxhdpi/ic_accept_pairing.png
Normal file
After Width: | Height: | Size: 786 B |
BIN
res/drawable-xxhdpi/ic_keyboard_hide_white_36dp.png
Normal file
After Width: | Height: | Size: 493 B |
BIN
res/drawable-xxhdpi/ic_phonelink_off_white_36dp.png
Normal file
After Width: | Height: | Size: 557 B |
BIN
res/drawable-xxhdpi/ic_phonelink_white_36dp.png
Normal file
After Width: | Height: | Size: 323 B |
BIN
res/drawable-xxhdpi/ic_reject_pairing.png
Normal file
After Width: | Height: | Size: 894 B |
BIN
res/drawable-xxxhdpi/ic_accept_pairing.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-xxxhdpi/ic_keyboard_hide_white_36dp.png
Normal file
After Width: | Height: | Size: 566 B |
BIN
res/drawable-xxxhdpi/ic_phonelink_off_white_36dp.png
Normal file
After Width: | Height: | Size: 753 B |
BIN
res/drawable-xxxhdpi/ic_phonelink_white_36dp.png
Normal file
After Width: | Height: | Size: 420 B |
BIN
res/drawable-xxxhdpi/ic_reject_pairing.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
@@ -70,7 +70,7 @@
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/unpair_message"
|
||||
android:id="@+id/not_reachable_message"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:drawableStart="@drawable/ic_error_outline_black_48dp"
|
||||
@@ -82,6 +82,19 @@
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/on_data_message"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:drawableStart="@drawable/ic_error_outline_black_48dp"
|
||||
android:drawableLeft="@drawable/ic_error_outline_black_48dp"
|
||||
android:drawablePadding="8dip"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/on_data_message"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
/>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/buttons_list"
|
||||
android:layout_width="match_parent"
|
||||
|
@@ -20,11 +20,6 @@
|
||||
android:id="@+id/no_players"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/artImageView" />
|
||||
|
||||
<Spinner
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@@ -62,7 +62,6 @@
|
||||
<string name="received_file_text">Tap to open \'%1s\'</string>
|
||||
<string name="sent_file_title">Unvióse\'l ficheru a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Fallu al unviar el ficheru %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Calca pa responder</string>
|
||||
<string name="reconnect">Reconeutar</string>
|
||||
|
@@ -64,7 +64,6 @@
|
||||
<string name="received_file_text">Kucni za otvaranje \'%1s\'</string>
|
||||
<string name="sent_file_title">Poslana datoteka na %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Neuspjelo slanje datoteke %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Kucni za odgovor</string>
|
||||
<string name="reconnect">Ponovo uspostavi vezu</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Comparteix el contingut del porta-retalls</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usa el vostre telèfon o tauleta com un ratolí i un teclat</string>
|
||||
<string name="pref_plugin_remotekeyboard">Rep les pulsacions de tecla remotes</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Rep els esdeveniments de pulsacions de tecla des de dispositius remots</string>
|
||||
<string name="pref_plugin_mpris">Controls multimèdia</string>
|
||||
<string name="pref_plugin_mpris_desc">Proporciona un comandament a distància pel reproductor multimèdia</string>
|
||||
<string name="pref_plugin_runcommand">Executa una ordre</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Us caldrà concedir permís per accedir a les notificacions</string>
|
||||
<string name="send_ping">Envia un ping</string>
|
||||
<string name="open_mpris_controls">Control multimèdia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Fes servir les tecles remotes només en editar</string>
|
||||
<string name="remotekeyboard_not_connected">No hi ha cap connexió activa amb el teclat remot, establiu-ne una al «kdeconnect»</string>
|
||||
<string name="remotekeyboard_connected">La connexió amb el teclat remot està activa</string>
|
||||
<string name="remotekeyboard_multiple_connections">Hi ha més d\'una connexió amb un teclat remot, seleccioneu el dispositiu per 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 un clic, i empreu dos/tres dits pels botons dret i mig. Empreu un toc llarg per arrossegar i deixar anar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Estableix l\'acció de tocar amb dos dits</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Fitxer entrant des de %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">S\'està enviant el fitxer a %1s</string>
|
||||
<string name="outgoing_files_title">S\'estan enviant fitxers a %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">S\'ha enviat %1$d de %2$d fitxers</string>
|
||||
<string name="received_file_title">Fitxer rebut des de %1s</string>
|
||||
<string name="received_file_fail_title">Ha fallat en rebre el fitxer des de %1s</string>
|
||||
<string name="received_file_text">Puntegeu per obrir «%1s»</string>
|
||||
<string name="sent_file_title">Envia el fitxer a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Ha fallat en enviar el fitxer %1s</string>
|
||||
<string name="sent_file_failed_title">Ha fallat en enviar el fitxer a %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Puntegeu per a respondre</string>
|
||||
<string name="reconnect">Reconnecta</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Afegeix dispositius per la IP</string>
|
||||
<string name="share_notification_preference">Rebombori de les notificacions</string>
|
||||
<string name="share_notification_preference_summary">Vibra i reprodueix un so en rebre un fitxer</string>
|
||||
<string name="share_destination_customize">Personalitza el directori de destinació</string>
|
||||
<string name="share_destination_customize_summary_disabled">Els fitxers rebuts apareixeran a Baixades</string>
|
||||
<string name="share_destination_customize_summary_enabled">Els fitxers seran emmagatzemats al directori de a sota</string>
|
||||
<string name="share_destination_folder_preference">Directori de destinació</string>
|
||||
<string name="title_activity_notification_filter">Filtre per a les notificacions</string>
|
||||
<string name="filter_apps_info">Les notificacions se sincronitzaran per a les aplicacions seleccionades.</string>
|
||||
<string name="sftp_internal_storage">Emmagatzematge intern</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Reanomena</string>
|
||||
<string name="refresh">Refresca</string>
|
||||
<string name="unreachable_description">Aquest dispositiu aparellat no és accessible. Assegureu-vos que està connectat a la mateixa xarxa.</string>
|
||||
<string name="on_data_message">Sembla que esteu amb una connexió de dades mòbils. El KDE Connect només funciona amb xarxes locals.</string>
|
||||
<string name="no_file_browser">No hi ha instal·lat cap explorador de fitxers.</string>
|
||||
<string name="pref_plugin_telepathy">Envia un SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Envia missatges de text des de l\'escriptori</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Sdílet obsah schránky</string>
|
||||
<string name="pref_plugin_mousepad">Vzdálený vstup</string>
|
||||
<string name="pref_plugin_mousepad_desc">Používejte svůj telefon nebo tablet jako touchpad a klávesnici</string>
|
||||
<string name="pref_plugin_remotekeyboard">Přijímat stisky kláves se vzdálených zařízení</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Přijímat události stisku kláves ze vzdálených zařízení</string>
|
||||
<string name="pref_plugin_mpris">Ovládání multimédií</string>
|
||||
<string name="pref_plugin_mpris_desc">Poskytuje dálkové ovládání přehrávačů médií</string>
|
||||
<string name="pref_plugin_runcommand">Spustit příkaz</string>
|
||||
@@ -20,7 +22,7 @@
|
||||
<string name="pref_plugin_notifications_desc">Zpřístupněte si upozornění z jiných zařízení</string>
|
||||
<string name="pref_plugin_receive_notifications">Přijímat oznámení</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Přijímat oznámení z jiného zařízení a zobrazovat je v Androidu</string>
|
||||
<string name="pref_plugin_sharereceiver">Sdílet s přijmnout</string>
|
||||
<string name="pref_plugin_sharereceiver">Sdílet a přijmout</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Sdílet soubory a odkazy mezi zařízeními</string>
|
||||
<string name="plugin_not_available">Tato vlastnost není pro vaši verzi Androidu platná</string>
|
||||
<string name="device_list_empty">Žádná zařízení</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Pro zpřístupnění upozornění potřebujete oprávnění</string>
|
||||
<string name="send_ping">Poslat ping</string>
|
||||
<string name="open_mpris_controls">Ovládání multimédií</string>
|
||||
<string name="remotekeyboard_editing_only_title">Ovládat vzdálené klávesy při editaci</string>
|
||||
<string name="remotekeyboard_not_connected">Není k dispozici žádné vzdálené připojení klávesnice. Nastavte nějaké pomocí kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Vzdálené připojení klávesnice je aktivní</string>
|
||||
<string name="remotekeyboard_multiple_connections">Je k dispozici více než jedno připojení klávesnice. Vyberte zařízení pro jeho nastavení.</string>
|
||||
<string name="open_mousepad">Vzdálený vstup</string>
|
||||
<string name="mousepad_info">Pohybujte prstem po obrazovce pro pohybování kurzorem myši. Ťukněte pro kliknutí a použijte dva/tři prsty jako pravé a prostřední tlačítko. Pro přetažení dlouze podržte.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Nastavit činnost pro ťuknutí dvěma prsty</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Příchozí soubor od %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Odesílám soubor do %1s</string>
|
||||
<string name="outgoing_files_title">Odesílám soubory do %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Odesláno %1$d ze %2$d souborů</string>
|
||||
<string name="received_file_title">Přijat soubor od %1s</string>
|
||||
<string name="received_file_fail_title">Selhalo přijímání souboru od %1s</string>
|
||||
<string name="received_file_text">Ťukněte pro otevření \'%1s\'</string>
|
||||
<string name="sent_file_title">Soubor byl odeslán do %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Nelze odeslat soubor %1s</string>
|
||||
<string name="sent_file_failed_title">Odesílání souborů na %1s selhalo</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Ťukněte pro odpovězení</string>
|
||||
<string name="reconnect">Znovu připojit</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Přidat zařízení podle IP</string>
|
||||
<string name="share_notification_preference">Hlasitá upozornění</string>
|
||||
<string name="share_notification_preference_summary">Vibrovat a přehrát melodii při přijímání souboru</string>
|
||||
<string name="share_destination_customize">Přizpůsobte si cílový adresář</string>
|
||||
<string name="share_destination_customize_summary_disabled">Přijaté soubory se objeví v Downloads</string>
|
||||
<string name="share_destination_customize_summary_enabled">Soubory budou ukládány v adresáři níže</string>
|
||||
<string name="share_destination_folder_preference">Cílový adresář</string>
|
||||
<string name="title_activity_notification_filter">Filtr upozornění</string>
|
||||
<string name="filter_apps_info">Upozorňování mezi vybranými aplikacemi bude synchronizováno.</string>
|
||||
<string name="sftp_internal_storage">Interní úložiště</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Přejmenovat</string>
|
||||
<string name="refresh">Obnovit</string>
|
||||
<string name="unreachable_description">Toto spárované zařízení je nedosažitelné. Ujistěte se, že běží ve stejné síti.</string>
|
||||
<string name="on_data_message">Vypadá to, že jste na mobilním internetovém připojení. KDE Connect funguje pouze na lokální síti.</string>
|
||||
<string name="no_file_browser">Není nainstalován žádný prohlížeč souborů.</string>
|
||||
<string name="pref_plugin_telepathy">Poslat SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Posílejte zprávy ze své pracovní plochy</string>
|
||||
|
@@ -10,9 +10,12 @@
|
||||
<string name="pref_plugin_clipboard_desc">Del indholdet af udklipsholderen</string>
|
||||
<string name="pref_plugin_mousepad">Eksternt input</string>
|
||||
<string name="pref_plugin_mousepad_desc">Brug din telefon eller tablet som mus og tastatur</string>
|
||||
<string name="pref_plugin_remotekeyboard">Modtag eksterne tastetryk</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Modtag tastetryk-hændelser fra eksterne enheder</string>
|
||||
<string name="pref_plugin_mpris">Multimediekontroller</string>
|
||||
<string name="pref_plugin_mpris_desc">Giver en fjernbetjening til din medieafspiller</string>
|
||||
<string name="pref_plugin_runcommand">Kør kommando</string>
|
||||
<string name="pref_plugin_runcommand_desc">Kør eksterne kommandoer fra din telefon eller tablet</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Send og modtag ping</string>
|
||||
<string name="pref_plugin_notifications">Synk. af bekendtgørelser</string>
|
||||
@@ -29,10 +32,16 @@
|
||||
<string name="no_permissions">Du skal give tilladelse for at tilgå bekendtgørelser</string>
|
||||
<string name="send_ping">Send ping</string>
|
||||
<string name="open_mpris_controls">Multimediekontrol</string>
|
||||
<string name="remotekeyboard_editing_only_title">Håndtér kun eksterne tastetryk under redigering</string>
|
||||
<string name="remotekeyboard_not_connected">Der er ingen aktiv ekstern tastaturforbindelse. Opret en i kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Ekstern tastaturforbindelse er aktiv</string>
|
||||
<string name="remotekeyboard_multiple_connections">Der er mere end en ekstern tastaturforbindelse, vælg den enhed der skal konfigureres</string>
|
||||
<string name="open_mousepad">Eksternt input</string>
|
||||
<string name="mousepad_info">Bevæg en finger på skærmen for at flytte musemarkøren. Tap for at klikke og brug to/tre-fingre for højre og midterste museknap. Brug et langt tryk til at trække og slippe.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Angiv handling for tap med to fingre</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Angiv handling for tap med tre fingre</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Angiv følsomhed for touchpad</string>
|
||||
<string name="mousepad_scroll_direction_title">Omvendt rulleretning</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Højreklik</item>
|
||||
<item>Midterklik</item>
|
||||
@@ -40,12 +49,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">højre</string>
|
||||
<string name="mousepad_triple_default">midter</string>
|
||||
<string name="mousepad_sensitivity_default">standard</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>Mest langsom</item>
|
||||
<item>Over mest langsom</item>
|
||||
<item>Standard</item>
|
||||
<item>Over standard</item>
|
||||
<item>Hurtigste</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Forbundne enheder</string>
|
||||
<string name="category_not_paired_devices">Tilgængelig enheder</string>
|
||||
@@ -64,6 +74,10 @@
|
||||
<string name="error_canceled_by_user">Annulleret af brugeren</string>
|
||||
<string name="error_canceled_by_other_peer">Annulleret af modpart</string>
|
||||
<string name="error_invalid_key">Ugyldige nøgle modtaget</string>
|
||||
<string name="encryption_info_title">Krypteringsinfo</string>
|
||||
<string name="encryption_info_msg_no_ssl">Den anden enhed bruger ikke en nylig version af KDE Connect, og bruger dermed den forældede krypteringsmetode.</string>
|
||||
<string name="my_device_fingerprint">SHA1-fingeraftrykket for dit enhedscertifikat er:</string>
|
||||
<string name="remote_device_fingerprint">SHA1-fingeraftrykket for det eksterne enhedscertifikat er:</string>
|
||||
<string name="pair_requested">Anmodet om parring</string>
|
||||
<string name="pairing_request_from">Parringsanmodning fra %1s</string>
|
||||
<string name="received_url_title">Modtog link fra %1s</string>
|
||||
@@ -77,7 +91,6 @@
|
||||
<string name="received_file_text">Tap for at åbne \"%1s\"</string>
|
||||
<string name="sent_file_title">Fil sendt til %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Kunne ikke sende filen %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tap for at svare</string>
|
||||
<string name="reconnect">Forbind igen</string>
|
||||
@@ -145,10 +158,15 @@
|
||||
<string name="device_rename_confirm">Omdøb</string>
|
||||
<string name="refresh">Genopfrisk</string>
|
||||
<string name="unreachable_description">Denne parrede enhed kan ikke nås. Sørg for at den er forbundet til samme netværk som dig.</string>
|
||||
<string name="on_data_message">Det lader til at du er på en mobil dataforbindelse. KDE Connect virker kun på lokale netværk.</string>
|
||||
<string name="no_file_browser">Der er ingen filhåndtering installeret.</string>
|
||||
<string name="pref_plugin_telepathy">Send SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Send SMS-beskeder fra din desktop</string>
|
||||
<string name="plugin_not_supported">Dette plugin er ikke understøttet af enheden</string>
|
||||
<string name="findmyphone_title">Find min telefon</string>
|
||||
<string name="findmyphone_title_tablet">Find min tablet</string>
|
||||
<string name="findmyphone_description">Ringer til denne enhed, så du kan finde den.</string>
|
||||
<string name="findmyphone_found">Fundet</string>
|
||||
<string name="open">Åbn</string>
|
||||
<string name="close">Luk</string>
|
||||
</resources>
|
||||
|
@@ -9,8 +9,9 @@
|
||||
<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_mousepad_desc">Verwendet Ihr Handy als Tablet, Touchpad und Tastatur</string>
|
||||
<string name="pref_plugin_mpris">Multimedia-Bedienung</string>
|
||||
<string name="pref_plugin_mpris_desc">Eine Fernbedienung für Ihre Medienwiedergabe</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>
|
||||
@@ -18,6 +19,7 @@
|
||||
<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_receive_notifications_desc">Empfangen und Anzeigen von Benachrichtigungen des anderen Geräts</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>
|
||||
@@ -29,6 +31,7 @@
|
||||
<string name="send_ping">Ping senden</string>
|
||||
<string name="open_mpris_controls">Multimedia-Bedienung</string>
|
||||
<string name="open_mousepad">Ferneingabe</string>
|
||||
<string name="mousepad_info">Bewegen Sie einen Finger auf dem Bildschirm um den Maus-Zeiger zu verschieben. Tippen zum Klicken, mit zwei oder drei Fingern für rechten bzw. mittleren Mausknopf. Tippen und Halten für Ziehen und Ablegen.</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>
|
||||
@@ -43,9 +46,9 @@
|
||||
<string name="mousepad_sensitivity_default">Standard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Langsamste</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Langsam</item>
|
||||
<item>Standard</item>
|
||||
<item>Above Default</item>
|
||||
<item>Schnell</item>
|
||||
<item>Schnellste</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Verbundene Geräte</string>
|
||||
@@ -66,17 +69,22 @@
|
||||
<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="encryption_info_msg_no_ssl">Das andere Gerät verwendet eine ältere Version von KDE-Connect, eine veraltete Verschlüsselungsmethode wird verwendet.</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>
|
||||
<string name="received_url_text">Tippen um „%1s“ zu öffnen</string>
|
||||
<string name="incoming_file_title">Eingehende Datei von %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Datei wird an %1s gesendet</string>
|
||||
<string name="outgoing_files_title">Datei wird an %1s gesendet</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">%1$d von %2$d Dateien gesendet</string>
|
||||
<string name="received_file_title">Datei von %1s erhalten</string>
|
||||
<string name="received_file_fail_title">Der Empfang der Datei %1s ist fehlgeschlagen</string>
|
||||
<string name="received_file_text">Tippen um „%1s“ zu öffnen</string>
|
||||
<string name="sent_file_title">Datei an %1s gesendet</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Das Senden der Datei an %1s ist fehlgeschlagen</string>
|
||||
@@ -102,6 +110,7 @@
|
||||
<string name="mpris_volume">Lautstärke</string>
|
||||
<string name="mpris_settings">Multimedia-Einstellungen</string>
|
||||
<string name="mpris_time_settings_title">Knöpfe Vorwärts/Rückwärts</string>
|
||||
<string name="mpris_time_settings_summary">Sprungweite für Vorlauf/Rücklauf anpassen.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 Sekunden</item>
|
||||
<item>20 Sekunden</item>
|
||||
@@ -122,9 +131,13 @@
|
||||
<string name="custom_devices_settings">Benutzerdefinierte Geräteliste</string>
|
||||
<string name="pair_device_action">Ein neues Gerät verbinden</string>
|
||||
<string name="unpair_device_action">Verbindung %s trennen</string>
|
||||
<string name="custom_device_list">Geräte nach IP hinzufügen</string>
|
||||
<string name="custom_device_list">Geräte nach IP-Adresse hinzufügen</string>
|
||||
<string name="share_notification_preference">Ausführliche Benachrichtigungen</string>
|
||||
<string name="share_notification_preference_summary">Beim Empfang einer Datei vibrieren und einen Sound abspielen</string>
|
||||
<string name="share_destination_customize">Zielverzeichnis anpassen</string>
|
||||
<string name="share_destination_customize_summary_disabled">Empfangene Dateien werden in Downloads gespeichert</string>
|
||||
<string name="share_destination_customize_summary_enabled">Dateien werden im folgenden Verzeichnis gespeichert</string>
|
||||
<string name="share_destination_folder_preference">Zielverzeichnis</string>
|
||||
<string name="title_activity_notification_filter">Benachrichtigungs-Filter</string>
|
||||
<string name="filter_apps_info">Benachrichtigungen werden zwischen den ausgewählten Anwendungen abgeglichen.</string>
|
||||
<string name="sftp_internal_storage">Interner Speicher</string>
|
||||
@@ -133,17 +146,19 @@
|
||||
<string name="sftp_sdcard">SD-Karte</string>
|
||||
<string name="sftp_readonly">(Nur lesen)</string>
|
||||
<string name="sftp_camera">Kamerabilder</string>
|
||||
<string name="add_host">Rechner/IP hinzufügen</string>
|
||||
<string name="add_host_hint">Rechnername oder IP</string>
|
||||
<string name="add_host">Rechner/IP-Adresse hinzufügen</string>
|
||||
<string name="add_host_hint">Rechnername oder IP-Adresse</string>
|
||||
<string name="no_players_connected">Keine Medienspieler gefunden</string>
|
||||
<string name="custom_dev_list_help">Benutzen Sie diese Funktion nur, wenn Ihr Gerät nicht automatisch erkannt wird. Geben hier Sie IP-Adresse oder Hostnamen ein und bestätigen Sie, um es zu der Liste hinzuzufügen. Tippen Sie ein bestehendes Gerät an, um es aus der Liste zu entfernen.</string>
|
||||
<string name="mpris_player_on_device">%1$s auf %2$s</string>
|
||||
<string name="send_files">Dateien senden</string>
|
||||
<string name="pairing_title">KDE-Connect-Geräte</string>
|
||||
<string name="pairing_description">Andere Geräte, auf denen KDE-Connect läuft im gleichen Netzwerk,sollte hier angezeigt werden.</string>
|
||||
<string name="pairing_description">Andere Geräte im selben Netzwerk, auf denen KDE-Connect läuft, sollten hier angezeigt werden.</string>
|
||||
<string name="device_paired">Gerät verbunden</string>
|
||||
<string name="device_rename_title">Geräte umbenennen</string>
|
||||
<string name="device_rename_confirm">Umbenennen</string>
|
||||
<string name="refresh">Aktualisieren</string>
|
||||
<string name="unreachable_description">Das verbundene Gerät ist nicht erreichbar. Stellen Sie sicher daß es mit demselben Netzwerk verbunden ist.</string>
|
||||
<string name="no_file_browser">Es sind keine Dateiverwaltungsprogramme installiert.</string>
|
||||
<string name="pref_plugin_telepathy">SMS senden</string>
|
||||
<string name="pref_plugin_telepathy_desc">Text-Nachrichten von Ihrer Arbeitsfläche senden</string>
|
||||
|
@@ -5,15 +5,21 @@
|
||||
<string name="pref_plugin_battery">Αναφορά μπαταρίας</string>
|
||||
<string name="pref_plugin_battery_desc">Περιοδική αναφορά κατάστασης μπαταρίας</string>
|
||||
<string name="pref_plugin_sftp">Αποκάλυψη συστήματος αρχείων</string>
|
||||
<string name="pref_plugin_sftp_desc">Επιτρέπει την απομακρυσμένη περιήγηση του συστήματος αρχείων του κινητού</string>
|
||||
<string name="pref_plugin_clipboard">Συγχρονισμός προχείρου</string>
|
||||
<string name="pref_plugin_clipboard_desc">Διαμοιρασμός περιεχομένου προχείρου</string>
|
||||
<string name="pref_plugin_mousepad">Απομακρυσμένη είσοδος στοιχείων</string>
|
||||
<string name="pref_plugin_mousepad_desc">Χρήση του τηλεφώνου ή της ταμπλέτας σας ως επιφάνεια αφής και πληκτρολόγιο</string>
|
||||
<string name="pref_plugin_mpris">Κονσόλα πολυμέσων</string>
|
||||
<string name="pref_plugin_mpris_desc">Παρέχει ένα τηλεχειριστήριο για την αναπαραγωγή πολυμέσων</string>
|
||||
<string name="pref_plugin_runcommand">Εκτέλεση εντολής</string>
|
||||
<string name="pref_plugin_runcommand_desc">Εκτέλεση απομακρυσμένων εντολών από το τηλέφωνο ή την ταμπλέτα</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Αποστολή και λήψη pings</string>
|
||||
<string name="pref_plugin_notifications">Συγχρονισμός ειδοποιήσεων</string>
|
||||
<string name="pref_plugin_notifications_desc">Πρόσβαση σε ειδοποιήσεις από άλλες συσκευές</string>
|
||||
<string name="pref_plugin_receive_notifications">Λήψη ειδοποιήσεων</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Λήψη ειδοποιήσεων από την άλλη συσκευή και προβολή τους στο Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Διαμοιρασμός και λήψη</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Διαμοιρασμός αρχείων και URL μεταξύ συσκευών</string>
|
||||
<string name="plugin_not_available">Αυτή η λειτουργία δεν είναι διαθέσιμη στην τρέχουσα έκδοση του Android</string>
|
||||
@@ -79,7 +85,6 @@
|
||||
<string name="received_file_text">Χτυπήστε για άνοιγμα \'%1s\'</string>
|
||||
<string name="sent_file_title">Εστάλη αρχείο στο %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Αποτυχία αποστολής αρχείου %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Χτυπήστε για να απαντήσετε</string>
|
||||
<string name="reconnect">Επανασύνδεση</string>
|
||||
@@ -152,6 +157,8 @@
|
||||
<string name="pref_plugin_telepathy_desc">Αποστολή μηνυμάτων κειμένου από τον υπολογιστή σας</string>
|
||||
<string name="plugin_not_supported">Αυτό το πρόσθετο δεν υποστηρίζεται από τη συσκευή</string>
|
||||
<string name="findmyphone_title">Αναζήτηση του κινητού μου</string>
|
||||
<string name="findmyphone_title_tablet">Εύρεση της ταμπλέτας μου</string>
|
||||
<string name="findmyphone_description">Καλεί αυτή τη συσκευή ώστε να την εντοπίσετε</string>
|
||||
<string name="findmyphone_found">Βρέθηκε</string>
|
||||
<string name="open">Άνοιγμα</string>
|
||||
<string name="close">Κλείσιμο</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Share the clipboard content</string>
|
||||
<string name="pref_plugin_mousepad">Remote input</string>
|
||||
<string name="pref_plugin_mousepad_desc">Use your phone or tablet as a touchpad and keyboard</string>
|
||||
<string name="pref_plugin_remotekeyboard">Receive remote keypresses</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Receive keypress events from remote devices</string>
|
||||
<string name="pref_plugin_mpris">Multimedia controls</string>
|
||||
<string name="pref_plugin_mpris_desc">Provides a remote control for your media player</string>
|
||||
<string name="pref_plugin_runcommand">Run Command</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">You need to grant permission to access notifications</string>
|
||||
<string name="send_ping">Send ping</string>
|
||||
<string name="open_mpris_controls">Multimedia control</string>
|
||||
<string name="remotekeyboard_editing_only_title">Handle remote keys only when editing</string>
|
||||
<string name="remotekeyboard_not_connected">There is no active remote keyboard connection, establish one in kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Remote keyboard connection is active</string>
|
||||
<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 a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Incoming file from %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Sending file to %1s</string>
|
||||
<string name="outgoing_files_title">Sending files to %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Sent %1$d out of %2$d files</string>
|
||||
<string name="received_file_title">Received file from %1s</string>
|
||||
<string name="received_file_fail_title">Failed receiving file from %1s</string>
|
||||
<string name="received_file_text">Tap to open \'%1s\'</string>
|
||||
<string name="sent_file_title">Sent file to %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Failed to send file %1s</string>
|
||||
<string name="sent_file_failed_title">Failed to send file to %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tap to answer</string>
|
||||
<string name="reconnect">Reconnect</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Add devices by IP</string>
|
||||
<string name="share_notification_preference">Noisy notifications</string>
|
||||
<string name="share_notification_preference_summary">Vibrate and play a sound when receiving a file</string>
|
||||
<string name="share_destination_customize">Customise destination directory</string>
|
||||
<string name="share_destination_customize_summary_disabled">Received files will appear in Downloads</string>
|
||||
<string name="share_destination_customize_summary_enabled">Files will be stored in the directory below</string>
|
||||
<string name="share_destination_folder_preference">Destination directory</string>
|
||||
<string name="title_activity_notification_filter">Notification filter</string>
|
||||
<string name="filter_apps_info">Notifications will be synchronised for the selected apps.</string>
|
||||
<string name="sftp_internal_storage">Internal storage</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Rename</string>
|
||||
<string name="refresh">Refresh</string>
|
||||
<string name="unreachable_description">This paired device is not reachable. Make sure it is connected to your same network.</string>
|
||||
<string name="on_data_message">It looks like you are on a mobile data connection. KDE Connect only works on local networks.</string>
|
||||
<string name="no_file_browser">There are no file browsers installed.</string>
|
||||
<string name="pref_plugin_telepathy">Send SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Send text messages from your desktop</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Compartir el contenido del portapapeles</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usar su teléfono o tableta como teclado y teclado táctil</string>
|
||||
<string name="pref_plugin_remotekeyboard">Recibir pulsaciones de teclas remotas</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Reciba eventos de pulsación de teclas desde dispositivos remotos</string>
|
||||
<string name="pref_plugin_mpris">Controles multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Proporciona un control remoto para su reproductor de medios</string>
|
||||
<string name="pref_plugin_runcommand">Ejecutar orden</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Debe otorgar permiso para acceder a las notificaciones</string>
|
||||
<string name="send_ping">Enviar ping</string>
|
||||
<string name="open_mpris_controls">Control multimedia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Manejar teclas remotas solo al editar</string>
|
||||
<string name="remotekeyboard_not_connected">No hay ninguna conexión remota de teclado activa, establezca una en kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">La conexión remota de teclado está activa</string>
|
||||
<string name="remotekeyboard_multiple_connections">Hay más de una conexión remota de teclado, seleccione el dispositivo a configurar</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_info">Mueva un dedo sobre la pantalla para mover el cursor del ratón. Pulse para ejecutar un clic y use dos/tres dedos para emular los botones derecho y central. Use una pulsación larga para arrastrar y soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Establecer la acción al pulsar con dos dedos</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Archivo entrante desde %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Enviando archivo a %1s</string>
|
||||
<string name="outgoing_files_title">Enviando archivos a %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Enviados %1$d de %2$d archivos</string>
|
||||
<string name="received_file_title">Archivo recibido desde %1s</string>
|
||||
<string name="received_file_fail_title">Fallo recibiendo archivo desde %1s</string>
|
||||
<string name="received_file_text">Pulse para abrir «%1s»</string>
|
||||
<string name="sent_file_title">Archivo enviado a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Fallo al enviar el archivo %1s</string>
|
||||
<string name="sent_file_failed_title">Fallo al enviar el archivo a %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Pulse para responder</string>
|
||||
<string name="reconnect">Reconectar</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Añadir dispositivos por IP</string>
|
||||
<string name="share_notification_preference">Notificaciones ruidosas</string>
|
||||
<string name="share_notification_preference_summary">Vibrar y reproducir un sonido cuando se reciba un archivo</string>
|
||||
<string name="share_destination_customize">Personalizar directorio destino</string>
|
||||
<string name="share_destination_customize_summary_disabled">Los archivos recibidos aparecerán en Descargas</string>
|
||||
<string name="share_destination_customize_summary_enabled">Los archivos se almacenarán en el directorio indicado más abajo</string>
|
||||
<string name="share_destination_folder_preference">Directorio destino</string>
|
||||
<string name="title_activity_notification_filter">Filtro de notificaciones</string>
|
||||
<string name="filter_apps_info">Las notificaciones se sincronizarán en las aplicaciones seleccionadas.</string>
|
||||
<string name="sftp_internal_storage">Almacenamiento interno</string>
|
||||
@@ -147,12 +159,13 @@
|
||||
<string name="mpris_player_on_device">%1$s en %2$s</string>
|
||||
<string name="send_files">Enviar archivos</string>
|
||||
<string name="pairing_title">Dispositivos de KDE Connect</string>
|
||||
<string name="pairing_description">Otros dispositivos ejecutando KDE Connect en su misma red deberían aparecer aquí.</string>
|
||||
<string name="pairing_description">Cualquier otro dispositivo ejecutando KDE Connect en su misma red debería aparecer aquí.</string>
|
||||
<string name="device_paired">Dispositivo vinculado</string>
|
||||
<string name="device_rename_title">Renombrar dispositivo</string>
|
||||
<string name="device_rename_confirm">Renombrar</string>
|
||||
<string name="refresh">Actualizar</string>
|
||||
<string name="unreachable_description">Este dispositivo vinculado no está disponible. Asegúrese que está conectado a su misma red.</string>
|
||||
<string name="on_data_message">Parece que se encuentra en una conexión de datos móviles. KDE Connect solo funciona en redes locales.</string>
|
||||
<string name="no_file_browser">No hay navegadores de archivos instalados.</string>
|
||||
<string name="pref_plugin_telepathy">Enviar SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensajes de texto desde el escritorio</string>
|
||||
|
@@ -79,13 +79,15 @@
|
||||
<string name="incoming_file_title">Saabuv fail seadmest %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Faili saatmine seadmesse %1s</string>
|
||||
<string name="outgoing_files_title">Failide saatmine seadmesse %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Saadetud %1$d / %2$d faili</string>
|
||||
<string name="received_file_title">Faili saamine seadmest %1s</string>
|
||||
<string name="received_file_fail_title">Faili saamine seadmest %1s nurjus</string>
|
||||
<string name="received_file_text">Koputa \"%1s\" avamiseks</string>
|
||||
<string name="sent_file_title">Fail saadeti seadmesse %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Faili %1s saatmine nurjus</string>
|
||||
<string name="sent_file_failed_title">Faili saatmine seadmesse %1s nurjus</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Koputa vastamiseks</string>
|
||||
<string name="reconnect">Ühenda uuesti</string>
|
||||
@@ -132,6 +134,10 @@
|
||||
<string name="custom_device_list">Lisa seadmeid IP järgi</string>
|
||||
<string name="share_notification_preference">Mürarikkad märguanded</string>
|
||||
<string name="share_notification_preference_summary">Vibreerimine ja heli esitamine faili saamisel</string>
|
||||
<string name="share_destination_customize">Sihtkataloogi kohandamine</string>
|
||||
<string name="share_destination_customize_summary_disabled">Saadud failid salvestatakse kataloogi Allalaaditud</string>
|
||||
<string name="share_destination_customize_summary_enabled">Failid salvestatakse allmääratud kataloogi</string>
|
||||
<string name="share_destination_folder_preference">Sihtkataloog</string>
|
||||
<string name="title_activity_notification_filter">Märguannete filter</string>
|
||||
<string name="filter_apps_info">Valitud rakenduste märguanded sünkroonitakse</string>
|
||||
<string name="sftp_internal_storage">Sisemine salvesti</string>
|
||||
|
@@ -5,15 +5,21 @@
|
||||
<string name="pref_plugin_battery">Akkuraportti</string>
|
||||
<string name="pref_plugin_battery_desc">Raportoi akun tila säännöllisesti</string>
|
||||
<string name="pref_plugin_sftp">Tiedostojärjestelmän paljastaminen</string>
|
||||
<string name="pref_plugin_sftp_desc">Mahdollistaa tämän laitteen tiedostojärjestelmän etäselaamisen</string>
|
||||
<string name="pref_plugin_clipboard">Leikepöydän synkronointi</string>
|
||||
<string name="pref_plugin_clipboard_desc">Jaa leikepöydän sisältö</string>
|
||||
<string name="pref_plugin_mousepad">Kauko-ohjaus</string>
|
||||
<string name="pref_plugin_mousepad_desc">Käytä puhelinta tai tablettia hiirenä ja näppäimistönä</string>
|
||||
<string name="pref_plugin_mpris">Multimedian ohjaus</string>
|
||||
<string name="pref_plugin_mpris_desc">Mahdollistaa mediasoittimen etäohjauksen</string>
|
||||
<string name="pref_plugin_runcommand">Suorita komento</string>
|
||||
<string name="pref_plugin_runcommand_desc">Suorita komentoja etänä puhelimelta tai tabletilta</string>
|
||||
<string name="pref_plugin_ping">Tiedustelupaketti</string>
|
||||
<string name="pref_plugin_ping_desc">Lähetä ja vastaanota tiedustelupaketteja</string>
|
||||
<string name="pref_plugin_notifications">Ilmoitusten synkronointi</string>
|
||||
<string name="pref_plugin_notifications_desc">Näe ilmoituksesi muissa laitteissa</string>
|
||||
<string name="pref_plugin_receive_notifications">Vastaanota ilmoituksia</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Vastaanota ilmoituksia toiselta laitteelta ja näytä ne Androidissa</string>
|
||||
<string name="pref_plugin_sharereceiver">Jako ja vastaanottaminen</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Jaa tiedostoja ja osoitteita laitteiden välillä</string>
|
||||
<string name="plugin_not_available">Piirre ei ole käytettävissä Android-versiossasi</string>
|
||||
@@ -28,6 +34,8 @@
|
||||
<string name="mousepad_info">Liikuta hiiren osoitinta liikuttamalla sormeasi näytöllä. Napsauta napauttamalla yhdellä sormella, käytä oikeaa painiketta kahdella sormella ja keskipainiketta kolmella. Vedä ja pudota painamalla pitkään.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Aseta kahden sormen napautuksen toiminto</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Aseta kolmen sormen napautuksen toiminto</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Aseta kosketuslevyn herkkyys</string>
|
||||
<string name="mousepad_scroll_direction_title">Käänteinen vierityssuunta</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Oikea napsautus</item>
|
||||
<item>Keskinapsautus</item>
|
||||
@@ -35,12 +43,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Oikea painike</string>
|
||||
<string name="mousepad_triple_default">Keskipainike</string>
|
||||
<string name="mousepad_sensitivity_default">oletus</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>Hitain</item>
|
||||
<item>Hitainta suurempi</item>
|
||||
<item>Oletus</item>
|
||||
<item>Oletusta suurempi</item>
|
||||
<item>Nopein</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Yhdistetyt laitteet</string>
|
||||
<string name="category_not_paired_devices">Saatavilla olevat laitteet</string>
|
||||
@@ -59,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Käyttäjä perui</string>
|
||||
<string name="error_canceled_by_other_peer">Vertaiskäyttäjä perui</string>
|
||||
<string name="error_invalid_key">Vastaanotettiin väärä avain</string>
|
||||
<string name="encryption_info_title">Salaustiedot</string>
|
||||
<string name="encryption_info_msg_no_ssl">Toinen laite ei käytä KDE Connectin uudehkoa versiota, joten käytetään vanhaa salausmenetelmää.</string>
|
||||
<string name="my_device_fingerprint">Laitteen varmenteen SHA1-sormenjälki on:</string>
|
||||
<string name="remote_device_fingerprint">Etälaitteen varmenteen SHA1-sormenjälki on:</string>
|
||||
<string name="pair_requested">Paripyyntö</string>
|
||||
<string name="pairing_request_from">Paripyyntö laitteesta %1s</string>
|
||||
<string name="received_url_title">Vastaanotettiin linkki lähettäjältä %1s</string>
|
||||
@@ -72,7 +85,6 @@
|
||||
<string name="received_file_text">Avaa ”%1s” napauttamalla</string>
|
||||
<string name="sent_file_title">Tiedosto lähetetty laitteeseen %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Tiedoston lähetys epäonnistui: %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Vastaa napauttamalla</string>
|
||||
<string name="reconnect">Yhdistä uudelleen</string>
|
||||
@@ -144,6 +156,9 @@
|
||||
<string name="pref_plugin_telepathy">Lähetä tekstiviesti</string>
|
||||
<string name="pref_plugin_telepathy_desc">Lähetä tekstiviestejä työpöydältäsi</string>
|
||||
<string name="plugin_not_supported">Laite ei tue tätä liitännäistä</string>
|
||||
<string name="findmyphone_title">Löydä puhelimeni</string>
|
||||
<string name="findmyphone_title_tablet">Löydä tablettini</string>
|
||||
<string name="findmyphone_description">Laittaa laitteen soimaan, jotta voit löytää sen.</string>
|
||||
<string name="findmyphone_found">Löytyi</string>
|
||||
<string name="open">Avaa</string>
|
||||
<string name="close">Sulje</string>
|
||||
|
@@ -70,7 +70,6 @@
|
||||
<string name="received_file_text">Appuyez pour ouvrir %1s</string>
|
||||
<string name="sent_file_title">Fichier envoyé à %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Impossible d\'envoyer le fichier %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Cliquer pour répondre</string>
|
||||
<string name="reconnect">Reconnecter</string>
|
||||
|
@@ -72,7 +72,6 @@
|
||||
<string name="received_file_text">Toque para abrir «%1s».</string>
|
||||
<string name="sent_file_title">Enviouse o ficheiro a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Non foi posíbel enviar o ficheiro %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Toque para contestar</string>
|
||||
<string name="reconnect">Conectar de novo</string>
|
||||
|
@@ -18,7 +18,7 @@
|
||||
<string name="pref_plugin_sharereceiver_desc">שתף וקבל קבצים וכתובת אינטרנט בין התקנים</string>
|
||||
<string name="plugin_not_available">אפשרות זו אינה זמינה בגרסת האנדרואיד שלך</string>
|
||||
<string name="device_list_empty">אין התקנים</string>
|
||||
<string name="ok">בסדר</string>
|
||||
<string name="ok">אישור</string>
|
||||
<string name="cancel">בטל</string>
|
||||
<string name="open_settings">פתח הגדרות</string>
|
||||
<string name="no_permissions">אתה צריך לתת הרשאות לגישה להתראות</string>
|
||||
@@ -79,7 +79,6 @@
|
||||
<string name="received_file_text">לחץ כדי לפתוח את %1s</string>
|
||||
<string name="sent_file_title">הקובץ נשלח ל־%1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">נכשל בשליחת הקובץ ל־%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">לחץ כדי לענות</string>
|
||||
<string name="reconnect">התחבר מחדש</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Condividi il contenuto degli appunti</string>
|
||||
<string name="pref_plugin_mousepad">Impulso remoto</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usa il tuo telefono o il tablet come touchpad e tastiera</string>
|
||||
<string name="pref_plugin_remotekeyboard">Ricevi pressioni dei tasti da remoto</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Ricevi eventi di pressione dei tasti da dispositivi remoti</string>
|
||||
<string name="pref_plugin_mpris">Controlli multimediali</string>
|
||||
<string name="pref_plugin_mpris_desc">Fornisce un controllo remoto per il tuo lettore multimediale</string>
|
||||
<string name="pref_plugin_runcommand">Esegui comando</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Devi concedere i permessi per l\'accesso alle notifiche</string>
|
||||
<string name="send_ping">Invia ping</string>
|
||||
<string name="open_mpris_controls">Controllo multimediale</string>
|
||||
<string name="remotekeyboard_editing_only_title">Gestisci i tasti remoti solo durante la modifica</string>
|
||||
<string name="remotekeyboard_not_connected">Non c\'è una connessione attiva della tastiera remota, stabiliscine una da kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">La connessione della tastiera remota è attiva</string>
|
||||
<string name="remotekeyboard_multiple_connections">Ci sono più connessioni di tastiere remote, seleziona il dispositivo da configurare</string>
|
||||
<string name="open_mousepad">Impulso remoto</string>
|
||||
<string name="mousepad_info">Muovi un dito sullo schermo per spostare il puntatore del mouse. Tocca per un clic e usa due/tre dita per i pulsanti destro e centrale. Utilizza una pressione lunga per trascinare e rilasciare.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Imposta azione per il tocco a due dita</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">File in ingresso da %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Invio file a %1s</string>
|
||||
<string name="outgoing_files_title">Invio file a %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Inviati %1$d di %2$d file</string>
|
||||
<string name="received_file_title">File ricevuto da %1s</string>
|
||||
<string name="received_file_fail_title">Ricezione file da %1s non riuscita</string>
|
||||
<string name="received_file_text">Tocca per aprire «%1s»</string>
|
||||
<string name="sent_file_title">File inviato a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Invio del file %1s non riuscito</string>
|
||||
<string name="sent_file_failed_title">Invio del file a %1s non riuscito</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tocca per rispondere</string>
|
||||
<string name="reconnect">Riconnetti</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Aggiungi dispositivi per IP</string>
|
||||
<string name="share_notification_preference">Notifiche rumorose</string>
|
||||
<string name="share_notification_preference_summary">Vibra e riproduci un suono alla ricezione di un file</string>
|
||||
<string name="share_destination_customize">Personalizza la cartella di destinazione</string>
|
||||
<string name="share_destination_customize_summary_disabled">I file ricevuti saranno visualizzati in Downloads</string>
|
||||
<string name="share_destination_customize_summary_enabled">I file saranno memorizzati nella cartella seguente</string>
|
||||
<string name="share_destination_folder_preference">Cartella di destinazione</string>
|
||||
<string name="title_activity_notification_filter">Filtro delle notifiche</string>
|
||||
<string name="filter_apps_info">Le notifiche saranno sincronizzate per le applicazioni selezionate.</string>
|
||||
<string name="sftp_internal_storage">Archiviazione interna</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Rinomina</string>
|
||||
<string name="refresh">Aggiorna</string>
|
||||
<string name="unreachable_description">Questo dispositivo associato non è raggiungibile. Assicurati che sia connesso alla tua stessa rete.</string>
|
||||
<string name="on_data_message">Sembra che tu stia utilizzando una connessione dati mobile. KDE Connect funziona solo su reti locali.</string>
|
||||
<string name="no_file_browser">Non ci sono navigatori di file installati.</string>
|
||||
<string name="pref_plugin_telepathy">Invia SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Invia messaggi di testo dal tuo desktop</string>
|
||||
|
@@ -5,15 +5,21 @@
|
||||
<string name="pref_plugin_battery">배터리 보고</string>
|
||||
<string name="pref_plugin_battery_desc">주기적으로 배터리 상태 보고</string>
|
||||
<string name="pref_plugin_sftp">파일 시스템 보기</string>
|
||||
<string name="pref_plugin_sftp_desc">원격으로 이 장치의 파일 시스템 보기</string>
|
||||
<string name="pref_plugin_clipboard">클립보드 동기화</string>
|
||||
<string name="pref_plugin_clipboard_desc">클립보드 내용 동기화</string>
|
||||
<string name="pref_plugin_mousepad">원격 입력</string>
|
||||
<string name="pref_plugin_mousepad_desc">내 휴대폰이나 태블릿을 터치패드와 키보드로 사용하기</string>
|
||||
<string name="pref_plugin_mpris">멀티미디어 제어</string>
|
||||
<string name="pref_plugin_mpris_desc">내 미디어 재생기 원격 제어</string>
|
||||
<string name="pref_plugin_runcommand">명령 실행</string>
|
||||
<string name="pref_plugin_runcommand_desc">내 휴대폰이나 태블릿에서 원격 명령 실행</string>
|
||||
<string name="pref_plugin_ping">핑</string>
|
||||
<string name="pref_plugin_ping_desc">핑 보내고 받기</string>
|
||||
<string name="pref_plugin_notifications">알림 동기화</string>
|
||||
<string name="pref_plugin_notifications_desc">다른 장치에서 알림 보기</string>
|
||||
<string name="pref_plugin_receive_notifications">알림 받기</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">다른 장치의 알림을 받아서 안드로이드 알림에 표시</string>
|
||||
<string name="pref_plugin_sharereceiver">공유하고 받기</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">장치끼리 파일과 URL 공유</string>
|
||||
<string name="plugin_not_available">현재 안드로이드 버전에서 사용할 수 없습니다</string>
|
||||
@@ -28,6 +34,8 @@
|
||||
<string name="mousepad_info">화면에서 손가락을 움직이면 마우스 커서를 움직입니다. 화면을 누르면 왼쪽 단추를 누르고, 두 손가락과 세 손가락으로 누르면 오른쪽/가운데 단추를 누릅니다. 드래그 앤 드롭을 사용하려면 길게 누르십시오.</string>
|
||||
<string name="mousepad_double_tap_settings_title">두 손가락으로 눌렀을 때 동작 설정</string>
|
||||
<string name="mousepad_triple_tap_settings_title">세 손가락으로 눌렀을 때 동작 설정</string>
|
||||
<string name="mousepad_sensitivity_settings_title">터치패드 감도 설정</string>
|
||||
<string name="mousepad_scroll_direction_title">스크롤 방향 뒤집기</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>오른쪽 단추 누름</item>
|
||||
<item>가운데 단추 누름</item>
|
||||
@@ -35,12 +43,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">오른쪽</string>
|
||||
<string name="mousepad_triple_default">가운데</string>
|
||||
<string name="mousepad_sensitivity_default">기본값</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>느리게</item>
|
||||
<item>느리게 이상</item>
|
||||
<item>기본값</item>
|
||||
<item>기본값 이상</item>
|
||||
<item>빠르게</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">연결된 장치</string>
|
||||
<string name="category_not_paired_devices">사용 가능한 장치</string>
|
||||
@@ -49,6 +58,7 @@
|
||||
<string name="device_menu_plugins">플러그인 설정</string>
|
||||
<string name="device_menu_unpair">연결 해제</string>
|
||||
<string name="device_not_reachable">연결된 장치에 도달할 수 없음</string>
|
||||
<string name="pair_new_device">새 장치 연결</string>
|
||||
<string name="unknown_device">알 수 없는 장치</string>
|
||||
<string name="error_not_reachable">장치에 접근할 수 없음</string>
|
||||
<string name="error_already_requested">연결이 이미 요청됨</string>
|
||||
@@ -58,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">사용자가 취소함</string>
|
||||
<string name="error_canceled_by_other_peer">다른 쪽에서 취소함</string>
|
||||
<string name="error_invalid_key">잘못된 키 받음</string>
|
||||
<string name="encryption_info_title">암호화 정보</string>
|
||||
<string name="encryption_info_msg_no_ssl">다른 장치에서 KDE Connect의 최근 버전을 실행하고 있지 않아서 레거시 암호화를 사용합니다.</string>
|
||||
<string name="my_device_fingerprint">내 장치 인증서의 SHA1 지문:</string>
|
||||
<string name="remote_device_fingerprint">원격 장치 인증서의 SHA1 지문:</string>
|
||||
<string name="pair_requested">연결 요청됨</string>
|
||||
<string name="pairing_request_from">%1s에서 연결 요청</string>
|
||||
<string name="received_url_title">%1s에서 링크 받음</string>
|
||||
@@ -65,13 +79,15 @@
|
||||
<string name="incoming_file_title">%1s에서 파일 보냄</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">%1s(으)로 파일 보내는 중</string>
|
||||
<string name="outgoing_files_title">%1s(으)로 파일 보내는 중</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">파일 %2$d개 중 %1$d개 보냄</string>
|
||||
<string name="received_file_title">%1s에서 파일 받음</string>
|
||||
<string name="received_file_fail_title">%1s에서 파일 받기 실패</string>
|
||||
<string name="received_file_text">\'%1s\'을(를) 열려면 누르십시오</string>
|
||||
<string name="sent_file_title">%1s(으)로 파일 보냄</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">파일 %1s을(를) 보낼 수 없음</string>
|
||||
<string name="sent_file_failed_title">파일을 %1s(으)로 보낼 수 없음</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">눌러서 응답하기</string>
|
||||
<string name="reconnect">다시 연결</string>
|
||||
@@ -118,6 +134,10 @@
|
||||
<string name="custom_device_list">IP로 장치 추가</string>
|
||||
<string name="share_notification_preference">시끄러운 알림</string>
|
||||
<string name="share_notification_preference_summary">파일을 받았을 때 진동과 소리로 알림</string>
|
||||
<string name="share_destination_customize">대상 디렉터리 사용자 정의</string>
|
||||
<string name="share_destination_customize_summary_disabled">받은 파일을 다운로드 디렉터리에 저장함</string>
|
||||
<string name="share_destination_customize_summary_enabled">받은 파일을 아래 디렉터리에 저장함</string>
|
||||
<string name="share_destination_folder_preference">대상 디렉터리</string>
|
||||
<string name="title_activity_notification_filter">알림 필터</string>
|
||||
<string name="filter_apps_info">선택한 앱의 알림을 동기화합니다.</string>
|
||||
<string name="sftp_internal_storage">내부 저장소</string>
|
||||
@@ -143,6 +163,9 @@
|
||||
<string name="pref_plugin_telepathy">SMS 보내기</string>
|
||||
<string name="pref_plugin_telepathy_desc">데스크톱에서 문자 메시지 보내기</string>
|
||||
<string name="plugin_not_supported">장치에서 이 플러그인을 지원하지 않습니다</string>
|
||||
<string name="findmyphone_title">내 휴대폰 찾기</string>
|
||||
<string name="findmyphone_title_tablet">내 태블릿 찾기</string>
|
||||
<string name="findmyphone_description">이 장치에서 소리를 울려서 찾는 데 도움을 줍니다</string>
|
||||
<string name="findmyphone_found">찾았음</string>
|
||||
<string name="open">열기</string>
|
||||
<string name="close">닫기</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">De inhoud van het klembord delen</string>
|
||||
<string name="pref_plugin_mousepad">Invoer op afstand</string>
|
||||
<string name="pref_plugin_mousepad_desc">Uw telefoon of tablet gebruiken als een touchpad en toetsenbord</string>
|
||||
<string name="pref_plugin_remotekeyboard">Toetsaanslagen van afstand ontvangen</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Toetsaanslaggebeurtenissen ontvangen van externe apparaten</string>
|
||||
<string name="pref_plugin_mpris">Bediening van multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Biedt een afstandsbediening voor uw mediaspeler</string>
|
||||
<string name="pref_plugin_runcommand">Commando uitvoeren</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">U moet toestemming geven voor toegang tot meldingen</string>
|
||||
<string name="send_ping">Ping verzenden</string>
|
||||
<string name="open_mpris_controls">Bediening van multimedia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Behandel toetsen op afstand alleen bij bewerken</string>
|
||||
<string name="remotekeyboard_not_connected">Er is geen actieve verbinding met een toetsenbord op afstand, maak er een in kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Verbinding met toetsenbord op afstand is actief</string>
|
||||
<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. Druk lang voor slepen en loslaten.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Tikactie met twee vingers instellen</string>
|
||||
@@ -61,7 +67,7 @@
|
||||
<string name="pair_new_device">Nieuw apparaat paren</string>
|
||||
<string name="unknown_device">Onbekend apparaat</string>
|
||||
<string name="error_not_reachable">Apparaat niet bereikbaar</string>
|
||||
<string name="error_already_requested">Paar maken is al gevraagd</string>
|
||||
<string name="error_already_requested">Paarvorming is al gevraagd</string>
|
||||
<string name="error_already_paired">Apparaat is al gepaard</string>
|
||||
<string name="error_could_not_send_package">Kon pakket niet verzenden</string>
|
||||
<string name="error_timed_out">Tijdslimiet overschreden</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Inkomend bestand van %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Bezig bestand te verzenden naar %1s</string>
|
||||
<string name="outgoing_files_title">Bestanden verzenden naar %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Verzonden %1$d van %2$d bestanden</string>
|
||||
<string name="received_file_title">Bestand ontvangen van %1s</string>
|
||||
<string name="received_file_fail_title">Bestand ontvangen van %1s is mislukt</string>
|
||||
<string name="received_file_text">Tap om \'%1s\' te openen</string>
|
||||
<string name="sent_file_title">Bestand verzonden naar %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Verzenden van bestand %1s is mislukt</string>
|
||||
<string name="sent_file_failed_title">Verzenden van bestanden naar %1s is mislukt</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tap om te antwoorden</string>
|
||||
<string name="reconnect">Opnieuw verbinden</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Voeg apparaten toe per IP-adres</string>
|
||||
<string name="share_notification_preference">Luidruchtige meldingen</string>
|
||||
<string name="share_notification_preference_summary">Vibreer en speel een geluidje bij ontvangen van een bestand</string>
|
||||
<string name="share_destination_customize">Pas bestemmingsmap aan</string>
|
||||
<string name="share_destination_customize_summary_disabled">Ontvangen bestanden zullen in Downloads verschijnen</string>
|
||||
<string name="share_destination_customize_summary_enabled">Bestanden zullen opgeslagen worden in de onderstaande map</string>
|
||||
<string name="share_destination_folder_preference">Bestemmingsmap</string>
|
||||
<string name="title_activity_notification_filter">Filter voor meldingen</string>
|
||||
<string name="filter_apps_info">Meldingen zullen gesynchroniseerd worden voor de geselecteerde apps.</string>
|
||||
<string name="sftp_internal_storage">Interne opslag</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Hernoemen</string>
|
||||
<string name="refresh">Verversen</string>
|
||||
<string name="unreachable_description">Dit gepaarde apparaat is niet bereikbaar. Ga na dat het is verbonden met uw zelfde netwerk.</string>
|
||||
<string name="on_data_message">Het lijkt of op een mobiele gegevensverbinding zit. KDE Connect werkt alleen op locale netwerken.</string>
|
||||
<string name="no_file_browser">Er zijn geen bestandsbrowsers geïnstalleerd.</string>
|
||||
<string name="pref_plugin_telepathy">SMS verzenden</string>
|
||||
<string name="pref_plugin_telepathy_desc">Stuur tekstberichten van uw bureaublad</string>
|
||||
|
165
res/values-nn/strings.xml
Normal file
@@ -0,0 +1,165 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Telefonvarsling</string>
|
||||
<string name="pref_plugin_telephony_desc">Send varsling ved SMS og oppringing</string>
|
||||
<string name="pref_plugin_battery">Batterirapport</string>
|
||||
<string name="pref_plugin_battery_desc">Meld regelmessig frå om batteristatusen</string>
|
||||
<string name="pref_plugin_sftp">Vis filsystem</string>
|
||||
<string name="pref_plugin_sftp_desc">Tillat lesing av filsystemet frå datamaskina</string>
|
||||
<string name="pref_plugin_clipboard">Synkroniser utklippstavle</string>
|
||||
<string name="pref_plugin_clipboard_desc">Del innhaldet på utklippstavla</string>
|
||||
<string name="pref_plugin_mousepad">Fjernstyring</string>
|
||||
<string name="pref_plugin_mousepad_desc">Bruk telefonen eller nettbrettet som styrepute og tastatur</string>
|
||||
<string name="pref_plugin_mpris">Mediekontrollar</string>
|
||||
<string name="pref_plugin_mpris_desc">Gjev fjernkontroll til mediespelarar</string>
|
||||
<string name="pref_plugin_runcommand">Køyr kommando</string>
|
||||
<string name="pref_plugin_runcommand_desc">Utløys fjernkommandoar frå telefonen eller nettbrettet</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Send og ta imot ping-signal</string>
|
||||
<string name="pref_plugin_notifications">Varslingssynkronisering</string>
|
||||
<string name="pref_plugin_notifications_desc">Få tilgang til varslingar frå andre einingar</string>
|
||||
<string name="pref_plugin_receive_notifications">Få varslingar</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Få varslingar frå den andre eininga og vis dei i Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Del og ta imot</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Del filer og nettadresser mellom einingar</string>
|
||||
<string name="plugin_not_available">Denne funksjonen er ikkje tilgjengeleg i din Android-versjon</string>
|
||||
<string name="device_list_empty">Ingen einingar</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">Avbryt</string>
|
||||
<string name="open_settings">Opna innstillingar</string>
|
||||
<string name="no_permissions">Du må gje tilgang til lesing av varslingar</string>
|
||||
<string name="send_ping">Send pingsignal</string>
|
||||
<string name="open_mpris_controls">Mediekontroll</string>
|
||||
<string name="open_mousepad">Fjernstyring</string>
|
||||
<string name="mousepad_info">Dra ein finger over skjermen for å flytta peikaren på datamaskina. Trykk for å klikka, og bruk to eller tre fingrar for høvesvis høgre- og midtknappen. Trykk og hald for å dra og sleppa.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Vel handling for tofingertrykk</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Vel handling for trefingertrykk</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Vel følsemd for styrepute</string>
|
||||
<string name="mousepad_scroll_direction_title">Omvend rulleretning</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Høgreklikk</item>
|
||||
<item>Midtklikk</item>
|
||||
<item>Ingenting</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">høgre</string>
|
||||
<string name="mousepad_triple_default">midt</string>
|
||||
<string name="mousepad_sensitivity_default">standard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Saktast</item>
|
||||
<item>Raskare enn saktast</item>
|
||||
<item>Standard</item>
|
||||
<item>Raskare enn standard</item>
|
||||
<item>Raskast</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Tilkopla einingar</string>
|
||||
<string name="category_not_paired_devices">Tilgjengelege einingar</string>
|
||||
<string name="category_remembered_devices">Hugs einingar</string>
|
||||
<string name="plugins_failed_to_load">Klarte ikkje lasta programtillegg (trykk for meir informasjon):</string>
|
||||
<string name="device_menu_plugins">Innstillingar for programtillegg</string>
|
||||
<string name="device_menu_unpair">Løys paring</string>
|
||||
<string name="device_not_reachable">Får ikkje kontakt med para eining</string>
|
||||
<string name="pair_new_device">Par ny eining</string>
|
||||
<string name="unknown_device">Ukjend eining</string>
|
||||
<string name="error_not_reachable">Får ikkje kontakt med eininga</string>
|
||||
<string name="error_already_requested">Paringsførespurnad er alt send</string>
|
||||
<string name="error_already_paired">Eininga er alt para</string>
|
||||
<string name="error_could_not_send_package">Klarte ikkje senda pakke</string>
|
||||
<string name="error_timed_out">Tidsavbrot</string>
|
||||
<string name="error_canceled_by_user">Avbroten av brukar</string>
|
||||
<string name="error_canceled_by_other_peer">Avbroten av den andre eininga</string>
|
||||
<string name="error_invalid_key">Fekk ugyldig nøkkel</string>
|
||||
<string name="encryption_info_title">Krypteringsinfo</string>
|
||||
<string name="encryption_info_msg_no_ssl">Den andre eininga brukar ein gammal versjon av KDE Connect, med ein utdatert krypteringsmetode.</string>
|
||||
<string name="my_device_fingerprint">SHA-fingeravtrykk av einingssertifikatet er:</string>
|
||||
<string name="remote_device_fingerprint">SHA-fingeravtrykk av fjerneiningssertifikatet er:</string>
|
||||
<string name="pair_requested">Paringsførespurnad</string>
|
||||
<string name="pairing_request_from">Paringsførespurnad frå %1s</string>
|
||||
<string name="received_url_title">Fekk lenkje frå %1s</string>
|
||||
<string name="received_url_text">Trykk for å opna «%1s»</string>
|
||||
<string name="incoming_file_title">Får fil frå %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Sender fil til %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="received_file_title">Fekk fil frå %1s</string>
|
||||
<string name="received_file_fail_title">Klarte ikkje ta imot fil frå %1s</string>
|
||||
<string name="received_file_text">Trykk for å opna «%1s»</string>
|
||||
<string name="sent_file_title">Send fil til %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Trykk for å svara</string>
|
||||
<string name="reconnect">Kopla til på nytt</string>
|
||||
<string name="right_click">Send høgreklikk</string>
|
||||
<string name="middle_click">Send midtklikk</string>
|
||||
<string name="show_keyboard">Vis tastatur</string>
|
||||
<string name="device_not_paired">Eininga er ikkje para</string>
|
||||
<string name="request_pairing">Be om paring</string>
|
||||
<string name="pairing_accept">Godta</string>
|
||||
<string name="pairing_reject">Avvis</string>
|
||||
<string name="device">Eining</string>
|
||||
<string name="pair_device">Par ny eining</string>
|
||||
<string name="remote_control">Fjernstyring</string>
|
||||
<string name="settings">Innstillingar for KDE Connect</string>
|
||||
<string name="mpris_play">Spel</string>
|
||||
<string name="mpris_previous">Førre</string>
|
||||
<string name="mpris_rew">Spol tilbake</string>
|
||||
<string name="mpris_ff">Spol fram</string>
|
||||
<string name="mpris_next">Neste</string>
|
||||
<string name="mpris_volume">Lydstyrke</string>
|
||||
<string name="mpris_settings">Medieinnstillingar</string>
|
||||
<string name="mpris_time_settings_title">Spoleknappar</string>
|
||||
<string name="mpris_time_settings_summary">Juster tida for spoling ved trykking.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 sekund</item>
|
||||
<item>20 sekund</item>
|
||||
<item>30 sekund</item>
|
||||
<item>1 minutt</item>
|
||||
<item>2 minutt</item>
|
||||
</string-array>
|
||||
<string name="share_to">Del til …</string>
|
||||
<string name="protocol_version_older">Denne eininga brukar ein gammal protokollversjon</string>
|
||||
<string name="protocol_version_newer">Denne eininga brukar ein nyare protokollversjon</string>
|
||||
<string name="general_settings">Generelle innstillingar</string>
|
||||
<string name="plugin_settings">Innstillingar</string>
|
||||
<string name="plugin_settings_with_name">%s-innstillingar</string>
|
||||
<string name="device_name">Einingsnamn</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Ugyldig einingsnamn</string>
|
||||
<string name="shareplugin_text_saved">Fekk tekst, som vart lagra på utklippstavla</string>
|
||||
<string name="custom_devices_settings">Tilpassa einingsliste</string>
|
||||
<string name="pair_device_action">Par ny eining</string>
|
||||
<string name="unpair_device_action">Løys paring for %s</string>
|
||||
<string name="custom_device_list">Legg til eining basert på IP</string>
|
||||
<string name="share_notification_preference">Lydvarsling</string>
|
||||
<string name="share_notification_preference_summary">Vibrer og spel ein lyd ved mottak av fil</string>
|
||||
<string name="title_activity_notification_filter">Varslingsfilter</string>
|
||||
<string name="filter_apps_info">Varslingar vert synkroniserte for dei valde appane.</string>
|
||||
<string name="sftp_internal_storage">Intern lagring</string>
|
||||
<string name="sftp_all_files">Alle filer</string>
|
||||
<string name="sftp_sdcard_num">SD-kort %d</string>
|
||||
<string name="sftp_sdcard">SD-kort</string>
|
||||
<string name="sftp_readonly">(skriveverna)</string>
|
||||
<string name="sftp_camera">Kamerabilete</string>
|
||||
<string name="add_host">Legg til vert/IP</string>
|
||||
<string name="add_host_hint">Vertsnamn/IP-adresse</string>
|
||||
<string name="no_players_connected">Fann ingen spelarar</string>
|
||||
<string name="custom_dev_list_help">Bruk berre dette valet viss eininga ikkje vert kjend att automatisk. Skriv inn IP-adressa eller vertsnamnet nedanfor, og trykk på knappen for å leggja eininga til oversikta. Trykk på element i oversikta for å fjerna dei.</string>
|
||||
<string name="mpris_player_on_device">%1$s på %2$s</string>
|
||||
<string name="send_files">Send filer</string>
|
||||
<string name="pairing_title">KDE Connect-einingar</string>
|
||||
<string name="pairing_description">Andre einingar i nettverket som køyrer KDE Connect vil dukka opp her.</string>
|
||||
<string name="device_paired">Eininga er para</string>
|
||||
<string name="device_rename_title">Endra namn på eining</string>
|
||||
<string name="device_rename_confirm">Endra namn</string>
|
||||
<string name="refresh">Oppdater</string>
|
||||
<string name="unreachable_description">Får ikkje kontakt med den para eininga. Sjå til at ho er kopla til same nettverk.</string>
|
||||
<string name="no_file_browser">Ingen filhandsamarar er installerte.</string>
|
||||
<string name="pref_plugin_telepathy">Send SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Send tekstmeldingar frå datamaskina</string>
|
||||
<string name="plugin_not_supported">Dette tillegget er ikkje støtta av eininga</string>
|
||||
<string name="findmyphone_title">Finn telefonen min</string>
|
||||
<string name="findmyphone_title_tablet">Finn nettbrettet mitt</string>
|
||||
<string name="findmyphone_description">Ring til eininga, slik at du kan finna ho</string>
|
||||
<string name="findmyphone_found">Fann</string>
|
||||
<string name="open">Opna</string>
|
||||
<string name="close">Lukk</string>
|
||||
</resources>
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Udostępnij zawartość schowka</string>
|
||||
<string name="pref_plugin_mousepad">Zdalne sterowanie</string>
|
||||
<string name="pref_plugin_mousepad_desc">Użyj swojego telefonu lub tabletu jako myszy i klawiatury</string>
|
||||
<string name="pref_plugin_remotekeyboard">Odbieraj zdalne naciśnięcia klawiszy</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Odbieraj naciśnięcia klawiszy od urządzeń zdalnych</string>
|
||||
<string name="pref_plugin_mpris">Sterowanie multimediami</string>
|
||||
<string name="pref_plugin_mpris_desc">Zapewnia zdalne sterowanie twoim odtwarzaczem multimedialnym</string>
|
||||
<string name="pref_plugin_runcommand">Wykonaj polecenie</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Musisz przydzielić uprawnienia, aby uzyskać dostęp do powiadomień</string>
|
||||
<string name="send_ping">Wyślij ping</string>
|
||||
<string name="open_mpris_controls">Sterowanie multimediami</string>
|
||||
<string name="remotekeyboard_editing_only_title">Obsługuj zdalne naciśnięcia klawiszy tylko podczas edycji</string>
|
||||
<string name="remotekeyboard_not_connected">Nie istnieje połączenie zdalnej klawiatury, nawiąż takie połączenie w kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Połączenie zdalnej klawiatury jest nawiązane</string>
|
||||
<string name="remotekeyboard_multiple_connections">Nawiązano więcej niż jedno połączenie zdalnej klawiatury, wybierz urządzenie do ustawienia</string>
|
||||
<string name="open_mousepad">Zdalne sterowanie</string>
|
||||
<string name="mousepad_info">Przesuń palcem po ekranie, aby przesunąć wskaźnik myszy. Stuknij, aby wywołać naciśniecie lewym przyciskiem myszy i użyj dwóch/trzech palców, aby wywołać naciśniecie prawym i środkowym przyciskiem myszy. Przyciśnij na dłużej, aby przeciągnąć i upuścić.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ustaw działanie po dwukrotnym stuknięciu palcem</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Plik przychodzący od %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Wysyłanie pliku do %1s</string>
|
||||
<string name="outgoing_files_title">Wysyłanie pliku do %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Wysłano %1$d z %2$d plików</string>
|
||||
<string name="received_file_title">Odebrano plik od %1s</string>
|
||||
<string name="received_file_fail_title">Nieudane odbieranie pliku z %1s</string>
|
||||
<string name="received_file_text">Znacznik do otwarcia \'%1s\'</string>
|
||||
<string name="sent_file_title">Plik wysłano do %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Nieudane wysyłanie pliku %1s</string>
|
||||
<string name="sent_file_failed_title">Nie udało się wyłanie pliku do %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Stuknij, aby odpowiedzieć</string>
|
||||
<string name="reconnect">Połącz ponownie</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Dodaj urządzenia po numerze IP</string>
|
||||
<string name="share_notification_preference">Hałaśliwe powiadomienia</string>
|
||||
<string name="share_notification_preference_summary">Zadrżyj i odegraj dźwięk przy odebraniu pliku</string>
|
||||
<string name="share_destination_customize">Własny katalog docelowy</string>
|
||||
<string name="share_destination_customize_summary_disabled">Pobrane pliki ukażą się w Pobranych</string>
|
||||
<string name="share_destination_customize_summary_enabled">Pliki zostaną zapisane w poniższym katalogu</string>
|
||||
<string name="share_destination_folder_preference">Katalog docelowy</string>
|
||||
<string name="title_activity_notification_filter">Filtr powiadomień</string>
|
||||
<string name="filter_apps_info">Powiadomienia zostaną zsynchronizowane z wybranymi aplikacjami.</string>
|
||||
<string name="sftp_internal_storage">"Pamięć wewnętrzna "</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Zmień nazwę</string>
|
||||
<string name="refresh">Odśwież</string>
|
||||
<string name="unreachable_description">To sparowane urządzenie jest nieosiągalne. Upewnij się, że jest podłączone do tej samej sieci.</string>
|
||||
<string name="on_data_message">Wygląda na to, że korzystasz z internetu mobilnego. KDE Connect działa tylko na lokalnych sieciach.</string>
|
||||
<string name="no_file_browser">Nie wgrano żadanych przeglądarek plików.</string>
|
||||
<string name="pref_plugin_telepathy">Wyślij SMS-a</string>
|
||||
<string name="pref_plugin_telepathy_desc">Wyślij wiadomość tekstową z komputera</string>
|
||||
|
@@ -80,7 +80,6 @@
|
||||
<string name="received_file_text">Toque para abrir o \'%1s\'</string>
|
||||
<string name="sent_file_title">Enviar arquivo para %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Falha ao enviar o arquivo %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Toque para responder</string>
|
||||
<string name="reconnect">Reconectar</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Partilhar o conteúdo da área de transferência</string>
|
||||
<string name="pref_plugin_mousepad">Introdução remota de dados</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usar o seu telefone ou \'tablet\' como um rato ou teclado</string>
|
||||
<string name="pref_plugin_remotekeyboard">Receber as teclas remotamente</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Receber eventos de teclas dos dispositivos remotos</string>
|
||||
<string name="pref_plugin_mpris">Comandos multimédia</string>
|
||||
<string name="pref_plugin_mpris_desc">Oferece um comando à distância para o seu leitor multimédia</string>
|
||||
<string name="pref_plugin_runcommand">Executar um Comando</string>
|
||||
@@ -19,7 +21,7 @@
|
||||
<string name="pref_plugin_notifications">Sincronização da notificação</string>
|
||||
<string name="pref_plugin_notifications_desc">Aceder às suas notificações a partir de outros dispositivos</string>
|
||||
<string name="pref_plugin_receive_notifications">Receber as notificações</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Receber as notificações do outro dispositivo e mostrá-las no Android</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Receber as notificações de outros dispositivos e mostrá-las no Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Partilhar e receber</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Partilhar ficheiros e URL\'s entre dispositivos</string>
|
||||
<string name="plugin_not_available">Esta funcionalidade não está disponível na sua versão do Android</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Precisa de dar permissões de acesso às notificações</string>
|
||||
<string name="send_ping">Enviar um pedido de contacto</string>
|
||||
<string name="open_mpris_controls">Comando multimédia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Lidar com as teclas remotas apenas na edição</string>
|
||||
<string name="remotekeyboard_not_connected">Não existe nenhuma ligação activa a teclados remotos - crie uma no \'kdeconnect\'</string>
|
||||
<string name="remotekeyboard_connected">A ligação ao teclado remoto está activa</string>
|
||||
<string name="remotekeyboard_multiple_connections">Existe mais que uma ligação a teclados remotos; seleccione o dispositivo a configurar</string>
|
||||
<string name="open_mousepad">Introdução remota de dados</string>
|
||||
<string name="mousepad_info">Mova um dedo pelo ecrã para mover o cursor do rato. Dê um toque para carregar no botão esquerdo e use dois/três dedos para os botões direito e do meio. Use uma pressão longa para arrastar e largar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Definir a acção do toque com dois dedos</string>
|
||||
@@ -43,13 +49,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">direita</string>
|
||||
<string name="mousepad_triple_default">meio</string>
|
||||
<string name="mousepad_sensitivity_default">por omissão</string>
|
||||
<string name="mousepad_sensitivity_default">predefinição</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Mais Lenta</item>
|
||||
<item>Ainda Mais Lenta</item>
|
||||
<item>Mais Lento</item>
|
||||
<item>Ainda Mais Lento</item>
|
||||
<item>Predefinição</item>
|
||||
<item>Acima da Predefinição</item>
|
||||
<item>Mais Rápida</item>
|
||||
<item>Mais Rápido</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivos ligados</string>
|
||||
<string name="category_not_paired_devices">Dispositivos disponíveis</string>
|
||||
@@ -68,8 +74,8 @@
|
||||
<string name="error_canceled_by_user">Cancelado pelo utilizador</string>
|
||||
<string name="error_canceled_by_other_peer">Cancelado pela outra máquina</string>
|
||||
<string name="error_invalid_key">Chave inválida recebida</string>
|
||||
<string name="encryption_info_title">Informação de Encriptação</string>
|
||||
<string name="encryption_info_msg_no_ssl">O outro dispositivo não usa uma versão recente do KDE Connect; a ser usado o método de encriptação antigo.</string>
|
||||
<string name="encryption_info_title">Dados de Encriptação</string>
|
||||
<string name="encryption_info_msg_no_ssl">O outro dispositivo não usa uma versão recente do KDE Connect; será usado o método antigo de encriptação.</string>
|
||||
<string name="my_device_fingerprint">A impressão digital SHA1 do certificado do seu dispositivo é:</string>
|
||||
<string name="remote_device_fingerprint">A impressão digital SHA1 do certificado do dispositivo remoto é:</string>
|
||||
<string name="pair_requested">Emparelhamento pedido</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Ficheiro recebido de %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">A enviar o ficheiro para o %1s</string>
|
||||
<string name="outgoing_files_title">A enviar os ficheiros para o %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Foram enviados %1$d de %2$d ficheiros</string>
|
||||
<string name="received_file_title">Ficheiro recebido de %1s</string>
|
||||
<string name="received_file_fail_title">Falhou a recepção do ficheiro de %1s</string>
|
||||
<string name="received_file_text">Toque para abrir o \'%1s\'</string>
|
||||
<string name="sent_file_title">O ficheiro foi enviado para %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Não foi possível enviar o ficheiro %1s</string>
|
||||
<string name="sent_file_failed_title">Não foi possível enviar o ficheiro para o %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Toque para responder</string>
|
||||
<string name="reconnect">Ligar de Novo</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Adicionar dispositivos pelo IP</string>
|
||||
<string name="share_notification_preference">Notificações com ruído</string>
|
||||
<string name="share_notification_preference_summary">Vibrar e tocar um som ao receber um ficheiro</string>
|
||||
<string name="share_destination_customize">Personalizar a pasta de destino</string>
|
||||
<string name="share_destination_customize_summary_disabled">Os ficheiros recebidos irão aparecer em \'Transferências\'</string>
|
||||
<string name="share_destination_customize_summary_enabled">Os ficheiros serão guardados na pasta abaixo</string>
|
||||
<string name="share_destination_folder_preference">Pasta de destino</string>
|
||||
<string name="title_activity_notification_filter">Filtro de notificações</string>
|
||||
<string name="filter_apps_info">As notificações serão sincronizadas para as aplicações seleccionadas.</string>
|
||||
<string name="sftp_internal_storage">Armazenamento interno</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Mudar o Nome</string>
|
||||
<string name="refresh">Actualizar</string>
|
||||
<string name="unreachable_description">Este dispositivo emparelhado não está acessível. Certifique-se que está ligado à mesma rede que você.</string>
|
||||
<string name="on_data_message">Parece que está com uma ligação de dados móveis. O KDE Connect só se liga em redes locais.</string>
|
||||
<string name="no_file_browser">Não existem gestores de ficheiros instalados.</string>
|
||||
<string name="pref_plugin_telepathy">Enviar um SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensagens de texto a partir do seu ambiente de trabalho</string>
|
||||
|
@@ -5,15 +5,23 @@
|
||||
<string name="pref_plugin_battery">Состояние батареи</string>
|
||||
<string name="pref_plugin_battery_desc">Периодическое информирование о состоянии батареи</string>
|
||||
<string name="pref_plugin_sftp">Просмотр файловой системы</string>
|
||||
<string name="pref_plugin_sftp_desc">Позволяет удалённо просматривать файловую систему устройства</string>
|
||||
<string name="pref_plugin_clipboard">Синхронизация буфера обмена</string>
|
||||
<string name="pref_plugin_clipboard_desc">Использование общего буфера обмена</string>
|
||||
<string name="pref_plugin_mousepad">Удалённый ввод</string>
|
||||
<string name="pref_plugin_mousepad_desc">Использование телефона или планшета в качестве сенсорной панели и клавиатуры</string>
|
||||
<string name="pref_plugin_remotekeyboard">Получение удалённых нажатий клавиш</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Получение нажатий клавиш с удалённых устройств</string>
|
||||
<string name="pref_plugin_mpris">Управление воспроизведением</string>
|
||||
<string name="pref_plugin_mpris_desc">Обеспечивает дистанционное управление медиапроигрывателем</string>
|
||||
<string name="pref_plugin_runcommand">Запуск команд</string>
|
||||
<string name="pref_plugin_runcommand_desc">Удалённый запуск команд с телефона или планшета</string>
|
||||
<string name="pref_plugin_ping">Пинг</string>
|
||||
<string name="pref_plugin_ping_desc">Отправка и получение тестовых сигналов</string>
|
||||
<string name="pref_plugin_notifications">Синхронизация уведомлений</string>
|
||||
<string name="pref_plugin_notifications_desc">Доступ к уведомлениям с других устройств</string>
|
||||
<string name="pref_plugin_receive_notifications">Получение уведомлений</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Получение уведомлений с другого устройства и показ их на Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Отправка и приём данных</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Пересылка файлов и адресов URL между устройствами</string>
|
||||
<string name="plugin_not_available">Эта функциональность недоступна в вашей версии Android</string>
|
||||
@@ -24,10 +32,16 @@
|
||||
<string name="no_permissions">Нужно разрешить доступ к уведомлениям</string>
|
||||
<string name="send_ping">Отправить тестовый сигнал</string>
|
||||
<string name="open_mpris_controls">Управление воспроизведением</string>
|
||||
<string name="remotekeyboard_editing_only_title">Обрабатывать удалённые нажатия только при редактировании</string>
|
||||
<string name="remotekeyboard_not_connected">Нет активного соединения с удалённой клавиатурой, установите его в KDE Connect</string>
|
||||
<string name="remotekeyboard_connected">Соединение с удалённой клавиатурой активно</string>
|
||||
<string name="remotekeyboard_multiple_connections">Подключено более одной удалённой клавиатуры, выберите устройство для настройки</string>
|
||||
<string name="open_mousepad">Удалённый ввод</string>
|
||||
<string name="mousepad_info">Перемещайте палец по экрану для перемещения курсора мыши. Коснитесь для нажатия, используйте два/три пальца для правой и средней кнопок. Используйте долгое нажатие для перетаскивания.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Действие при нажатии двумя пальцами</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Действие при нажатии тремя пальцами</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Чувствительность сенсорной панели</string>
|
||||
<string name="mousepad_scroll_direction_title">Инвертировать направление прокрутки</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Нажатие правой кнопки</item>
|
||||
<item>Нажатие средней кнопки</item>
|
||||
@@ -35,12 +49,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Нажатие правой кнопки</string>
|
||||
<string name="mousepad_triple_default">Нажатие средней кнопки</string>
|
||||
<string name="mousepad_sensitivity_default">Обычная</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>Самая низкая</item>
|
||||
<item>Низкая</item>
|
||||
<item>Обычная</item>
|
||||
<item>Высокая</item>
|
||||
<item>Самая высокая</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Подключённые устройства</string>
|
||||
<string name="category_not_paired_devices">Доступные устройства</string>
|
||||
@@ -49,15 +64,20 @@
|
||||
<string name="device_menu_plugins">Настройка модулей</string>
|
||||
<string name="device_menu_unpair">Снять сопряжение</string>
|
||||
<string name="device_not_reachable">Сопряжённое устройство недоступно</string>
|
||||
<string name="pair_new_device">Подключить новое устройство</string>
|
||||
<string name="unknown_device">Неизвестное устройство</string>
|
||||
<string name="error_not_reachable">Устройство недоступно</string>
|
||||
<string name="error_already_requested">Запрос на сопряжение уже был сделан</string>
|
||||
<string name="error_already_paired">Устройство уже сопряжено</string>
|
||||
<string name="error_could_not_send_package">Не удалось отправить пакет.</string>
|
||||
<string name="error_could_not_send_package">Не удалось отправить пакет</string>
|
||||
<string name="error_timed_out">Истекло время ожидания</string>
|
||||
<string name="error_canceled_by_user">Отменено пользователем</string>
|
||||
<string name="error_canceled_by_other_peer">Отменено другим участником</string>
|
||||
<string name="error_invalid_key">Получен недопустимый ключ</string>
|
||||
<string name="encryption_info_title">Информация о шифровании</string>
|
||||
<string name="encryption_info_msg_no_ssl">На другом устройстве используется старая версия KDE Connect, используется старый метод шифрования.</string>
|
||||
<string name="my_device_fingerprint">Отпечаток SHA-1 сертификата вашего устройства:</string>
|
||||
<string name="remote_device_fingerprint">Отпечаток SHA-1 сертификата удалённого устройства:</string>
|
||||
<string name="pair_requested">Запрошено сопряжение</string>
|
||||
<string name="pairing_request_from">Запрос на сопряжение от %1s</string>
|
||||
<string name="received_url_title">Получена ссылка от %1s</string>
|
||||
@@ -65,13 +85,15 @@
|
||||
<string name="incoming_file_title">Входящий файл с %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Отправка файла на %1s</string>
|
||||
<string name="outgoing_files_title">Отправка файлов на %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Отправлено %1$d из %2$d файлов</string>
|
||||
<string name="received_file_title">Получен файл с %1s</string>
|
||||
<string name="received_file_fail_title">Не удалось получить файл с %1s</string>
|
||||
<string name="received_file_text">Нажмите, чтобы открыть «%1s»</string>
|
||||
<string name="sent_file_title">Файл отправлен на %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Не удалось отправить файл %1s</string>
|
||||
<string name="sent_file_failed_title">Не удалось отправить файл на %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Нажмите, чтобы ответить</string>
|
||||
<string name="reconnect">Подключить заново</string>
|
||||
@@ -103,8 +125,8 @@
|
||||
<item>2 минуты</item>
|
||||
</string-array>
|
||||
<string name="share_to">Отправить на...</string>
|
||||
<string name="protocol_version_older">Это устройство использует старую версию протокола.</string>
|
||||
<string name="protocol_version_newer">Это устройство использует более новую версию протокола.</string>
|
||||
<string name="protocol_version_older">Это устройство использует старую версию протокола</string>
|
||||
<string name="protocol_version_newer">Это устройство использует более новую версию протокола</string>
|
||||
<string name="general_settings">Общие параметры</string>
|
||||
<string name="plugin_settings">Настройка</string>
|
||||
<string name="plugin_settings_with_name">Настройка %s</string>
|
||||
@@ -117,7 +139,11 @@
|
||||
<string name="unpair_device_action">Снять сопряжение с %s</string>
|
||||
<string name="custom_device_list">Добавить устройства по IP</string>
|
||||
<string name="share_notification_preference">Звуковые уведомления</string>
|
||||
<string name="share_notification_preference_summary">Использовать звуковой сигнал и вибрацию при получении файла.</string>
|
||||
<string name="share_notification_preference_summary">Использовать вибрацию и звуковой сигнал при получении файла</string>
|
||||
<string name="share_destination_customize">Задать целевой каталог</string>
|
||||
<string name="share_destination_customize_summary_disabled">Полученные файлы появятся в каталоге Загрузки</string>
|
||||
<string name="share_destination_customize_summary_enabled">Файлы будут сохранены в указанном ниже каталоге</string>
|
||||
<string name="share_destination_folder_preference">Целевой каталог</string>
|
||||
<string name="title_activity_notification_filter">Фильтр уведомлений</string>
|
||||
<string name="filter_apps_info">Уведомления будут синхронизированы для выбранных приложений.</string>
|
||||
<string name="sftp_internal_storage">Встроенная память</string>
|
||||
@@ -139,10 +165,14 @@
|
||||
<string name="device_rename_confirm">Переименовать</string>
|
||||
<string name="refresh">Обновить</string>
|
||||
<string name="unreachable_description">Это сопряжённое устройство недоступно. Проверьте, что оно подключено к той же локальной сети.</string>
|
||||
<string name="on_data_message">Похоже, вы подключены к мобильной сети. KDE Connect работает только в локальных сетях.</string>
|
||||
<string name="no_file_browser">Не удалось открыть диалог выбора файла.</string>
|
||||
<string name="pref_plugin_telepathy">Отправка SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Отправка SMS-сообщений с вашего компьютера</string>
|
||||
<string name="plugin_not_supported">Этот модуль не поддерживается устройством</string>
|
||||
<string name="findmyphone_title">Поиск телефона</string>
|
||||
<string name="findmyphone_title_tablet">Поиск планшета</string>
|
||||
<string name="findmyphone_description">Подача звукового сигнала на устройстве, чтобы вы могли его найти</string>
|
||||
<string name="findmyphone_found">Найден</string>
|
||||
<string name="open">Открыть</string>
|
||||
<string name="close">Закрыть</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<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_remotekeyboard">Prijímať vzdialené stlačenia klávesov</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Prijímať udalosti stlačení klávesov od vzdialených zariadení</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>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Musíte povoliť oprávnenia na prístup k pripomienkam</string>
|
||||
<string name="send_ping">Poslať ping</string>
|
||||
<string name="open_mpris_controls">Multimediálny ovládač</string>
|
||||
<string name="remotekeyboard_editing_only_title">Spracúva vzdialené klávesy len pri editácii</string>
|
||||
<string name="remotekeyboard_not_connected">Nie sú žiadne aktívne pripojenia vzdialenej klávesnice, vytvorte nejaké v Kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Vzdialené pripojenie klávesnice je aktívne</string>
|
||||
<string name="remotekeyboard_multiple_connections">Je viac ako jedno vzdialené pripojenie klávesnice, vyberte zariadenie na nastavenie</string>
|
||||
<string name="open_mousepad">Vzdialený vstup</string>
|
||||
<string name="mousepad_info">Posúvajte prst na obrazovke na posun kurzora. Ťuknutie vyvolá klik a použite dva/tri prsty pre pravé a stredné tlačidlo. Použite dlhé stlačenie pre drag and drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Nastaviť akciu dvoch prstov</string>
|
||||
@@ -79,7 +85,9 @@
|
||||
<string name="incoming_file_title">Prichádzajúci súbor od %s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Posielam súbor pre %1s</string>
|
||||
<string name="outgoing_files_title">Posielam súbor pre %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Poslať %1$d z %2$d súborov</string>
|
||||
<string name="received_file_title">Prijatý súbor od %1s</string>
|
||||
<string name="received_file_fail_title">Zlyhalo prijatie súboru od %1s</string>
|
||||
<string name="received_file_text">Ťuknite na otvorenie \'%1s\'</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Pridať zariadenia podľa IP</string>
|
||||
<string name="share_notification_preference">Hlučné pripomienky</string>
|
||||
<string name="share_notification_preference_summary">Vibrovať a prehrať zvuk pri prijatí súboru</string>
|
||||
<string name="share_destination_customize">Prispôsobiť cieľový adresár</string>
|
||||
<string name="share_destination_customize_summary_disabled">Prijaté súbory sa objavia v Preberaniach</string>
|
||||
<string name="share_destination_customize_summary_enabled">Súbory sa uložia v adresári dolu</string>
|
||||
<string name="share_destination_folder_preference">Cieľový adresár</string>
|
||||
<string name="title_activity_notification_filter">Filter upozornení</string>
|
||||
<string name="filter_apps_info">Upozornenia budú synchronizované pre vybrané aplikácie.</string>
|
||||
<string name="sftp_internal_storage">Interné úložisko</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Premenovať</string>
|
||||
<string name="refresh">Obnoviť</string>
|
||||
<string name="unreachable_description">Toto spárované zariadenie nie je dosiahnuteľné. Prosím, uistite sa, že je pripojené do rovnakej siete.</string>
|
||||
<string name="on_data_message">Zdá sa, že ste na mobilom dátovom pripojení. KDE Connect funguje iba na lokálnej sieti.</string>
|
||||
<string name="no_file_browser">Nie sú nainštalované žiadne prehliadače.</string>
|
||||
<string name="pref_plugin_telepathy">Poslať SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Posielať textové správy z vášho počítača</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Dela klippbordets innehåll</string>
|
||||
<string name="pref_plugin_mousepad">Fjärrinmatning</string>
|
||||
<string name="pref_plugin_mousepad_desc">Använd telefonen eller surfplattan som mus och tangentbord</string>
|
||||
<string name="pref_plugin_remotekeyboard">Ta emot fjärrtangentnedtryckningar</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Ta emot tangentnedtryckningar från fjärrenheter</string>
|
||||
<string name="pref_plugin_mpris">Multimediakontroller</string>
|
||||
<string name="pref_plugin_mpris_desc">Tillhandahåller en fjärrkontroll för mediaspelaren</string>
|
||||
<string name="pref_plugin_runcommand">Kör kommando</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Du måste ge rättighet att komma åt underrättelser</string>
|
||||
<string name="send_ping">Skicka ping</string>
|
||||
<string name="open_mpris_controls">Kontroll av multimedia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Hantera bara fjärrtangenter vid redigering</string>
|
||||
<string name="remotekeyboard_not_connected">Det finns ingen aktiv fjärrtangentbordsanslutning, upprätta en i KDE-anslut</string>
|
||||
<string name="remotekeyboard_connected">Fjärrtangentbordsanslutning är aktiv</string>
|
||||
<string name="remotekeyboard_multiple_connections">Det finns mer än en fjärrtangentbordsanslutning, välj enhet att anpassa</string>
|
||||
<string name="open_mousepad">Fjärrinmatning</string>
|
||||
<string name="mousepad_info">Flytta fingret på skärmen för att röra muspekaren. Rör för att klicka, och använd två eller tre fingrar för höger- och mittenknapparna. Använd en längre beröring för drag och släpp.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ställ in åtgärd vid två fingerberöringar</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Inkommande fil från %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Skickar fil till %1s</string>
|
||||
<string name="outgoing_files_title">Skickar filer till %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Skickade %1$d av %2$d filer</string>
|
||||
<string name="received_file_title">Tog emot fil från %1s</string>
|
||||
<string name="received_file_fail_title">Misslyckades ta emot fil från %1s</string>
|
||||
<string name="received_file_text">Rör för att öppna \'%1s\'</string>
|
||||
<string name="sent_file_title">Skickade fil till %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Misslyckades skicka fil %1s</string>
|
||||
<string name="sent_file_failed_title">Misslyckades skicka fil till %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Rör för att svara</string>
|
||||
<string name="reconnect">Anslut igen</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Lägg till apparater enligt IP-adress</string>
|
||||
<string name="share_notification_preference">Ljudliga underrättelser</string>
|
||||
<string name="share_notification_preference_summary">Vibrera och spela ett ljud när en fil tas emot</string>
|
||||
<string name="share_destination_customize">Anpassa målkatalog</string>
|
||||
<string name="share_destination_customize_summary_disabled">Mottagna filer hamnar i Nerladdningar</string>
|
||||
<string name="share_destination_customize_summary_enabled">Filer lagras i katalogen nedan</string>
|
||||
<string name="share_destination_folder_preference">Målkatalog</string>
|
||||
<string name="title_activity_notification_filter">Underrättelsefilter</string>
|
||||
<string name="filter_apps_info">Underrättelser synkroniseras för markerade applikationer.</string>
|
||||
<string name="sftp_internal_storage">Intern lagring</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Byt namn</string>
|
||||
<string name="refresh">Uppdatera</string>
|
||||
<string name="unreachable_description">Den här ihopparade apparaten kan inte nås. Försäkra dig om att den är ansluten till samma nätverk.</string>
|
||||
<string name="on_data_message">Det verkar som om du använder en mobil dataanslutning. KDE-anslut fungerar bara på lokala nätverk.</string>
|
||||
<string name="no_file_browser">Det finns inga filbläddrare installerade.</string>
|
||||
<string name="pref_plugin_telepathy">Skicka SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Skicka textmeddelanden från skrivbordet</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Спільне використання буфера обміну даними</string>
|
||||
<string name="pref_plugin_mousepad">Дистанційне введення</string>
|
||||
<string name="pref_plugin_mousepad_desc">Скористайтеся телефоном або планшетом як замінником сенсорної панелі і клавіатури</string>
|
||||
<string name="pref_plugin_remotekeyboard">Отримувати віддалені натискання клавіш</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Отримувати події натискання клавіш з віддаленого пристрою</string>
|
||||
<string name="pref_plugin_mpris">Керування відтворенням</string>
|
||||
<string name="pref_plugin_mpris_desc">Надає можливість віддаленого керування вашим мультимедійним програвачем</string>
|
||||
<string name="pref_plugin_runcommand">Виконати команду</string>
|
||||
@@ -30,6 +32,10 @@
|
||||
<string name="no_permissions">Вам слід надати доступ до сповіщень</string>
|
||||
<string name="send_ping">Надіслати сигнал підтримання зв’язку</string>
|
||||
<string name="open_mpris_controls">Керування відтворенням</string>
|
||||
<string name="remotekeyboard_editing_only_title">Обробляти віддалені клавіші лише під час редагування</string>
|
||||
<string name="remotekeyboard_not_connected">Немає активних з’єднань із віддаленою клавіатурою. Встановіть таке з’єднання у kdeconnect.</string>
|
||||
<string name="remotekeyboard_connected">З’єднання з віддаленою клавіатурою є активним</string>
|
||||
<string name="remotekeyboard_multiple_connections">Існує декілька з’єднань із віддаленою клавіатурою. Виберіть пристрій для налаштовування.</string>
|
||||
<string name="open_mousepad">Дистанційне введення</string>
|
||||
<string name="mousepad_info">Проведіть по екрану пальцем, щоб пересунути вказівник миші. Дотик одним пальцем означатиме клацання, дотиком двома або трьома пальцями можна імітувати праву і середню кнопки. Для перетягування зі скиданням скористайтеся тривалим натисканням.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Встановлення дії для торкання двома пальцями</string>
|
||||
@@ -79,13 +85,15 @@
|
||||
<string name="incoming_file_title">Вхідний файл з %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Надсилаємо файл до %1s</string>
|
||||
<string name="outgoing_files_title">Надсилаємо файли на %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Надіслано %1$d з %2$d файлів</string>
|
||||
<string name="received_file_title">Отримано файл з %1s</string>
|
||||
<string name="received_file_fail_title">Не вдалося отримати файл з %1s</string>
|
||||
<string name="received_file_text">Натисніть, щоб відкрити «%1s»</string>
|
||||
<string name="sent_file_title">Файл надіслано до %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Не вдалося надіслати файл %1s</string>
|
||||
<string name="sent_file_failed_title">Не вдалося надіслати файл на %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Натисніть, щоб відповісти</string>
|
||||
<string name="reconnect">З\'єднати знову</string>
|
||||
@@ -132,6 +140,10 @@
|
||||
<string name="custom_device_list">Додати пристрої за IP</string>
|
||||
<string name="share_notification_preference">Звукові сповіщення</string>
|
||||
<string name="share_notification_preference_summary">Вібрація і відтворення звуку у відповідь на отримання файла</string>
|
||||
<string name="share_destination_customize">Налаштування каталогу призначення</string>
|
||||
<string name="share_destination_customize_summary_disabled">Отримані файли зберігатимуться до каталогу «Завантаження»</string>
|
||||
<string name="share_destination_customize_summary_enabled">Файли зберігатимуться у вказаному нижче каталозі</string>
|
||||
<string name="share_destination_folder_preference">Каталог призначення</string>
|
||||
<string name="title_activity_notification_filter">Фільтр сповіщень</string>
|
||||
<string name="filter_apps_info">Сповіщення буде синхронізовано для позначених програм.</string>
|
||||
<string name="sftp_internal_storage">Вбудоване сховище даних</string>
|
||||
@@ -153,6 +165,7 @@
|
||||
<string name="device_rename_confirm">Перейменувати</string>
|
||||
<string name="refresh">Оновити</string>
|
||||
<string name="unreachable_description">Цей пов’язаний пристрій недоступний. Переконайтеся, що його з’єднано з вашою мережею.</string>
|
||||
<string name="on_data_message">Здається, мережа працює у режимі мобільного з’єднання. KDE Connect може працювати лише у локальних мережах.</string>
|
||||
<string name="no_file_browser">Програм для навігації файловою системою не встановлено.</string>
|
||||
<string name="pref_plugin_telepathy">Надіслати SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Надсилати текстові повідомлення з вашої робочої станції</string>
|
||||
|
@@ -5,15 +5,23 @@
|
||||
<string name="pref_plugin_battery">电池报告</string>
|
||||
<string name="pref_plugin_battery_desc">定期报告电池状态</string>
|
||||
<string name="pref_plugin_sftp">开放文件系统</string>
|
||||
<string name="pref_plugin_sftp_desc">允许远程浏览设备的文件系统</string>
|
||||
<string name="pref_plugin_clipboard">剪贴板同步</string>
|
||||
<string name="pref_plugin_clipboard_desc">共享剪贴板内容</string>
|
||||
<string name="pref_plugin_mousepad">远程输入</string>
|
||||
<string name="pref_plugin_mousepad_desc">将您的手机用或平板电脑用作触摸板和键盘</string>
|
||||
<string name="pref_plugin_remotekeyboard">接收远程按键</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">从远程设备接收按键事件</string>
|
||||
<string name="pref_plugin_mpris">多媒体控制</string>
|
||||
<string name="pref_plugin_mpris_desc">媒体播放器的遥控器</string>
|
||||
<string name="pref_plugin_runcommand">执行命令</string>
|
||||
<string name="pref_plugin_runcommand_desc">触发您的手机或平板电脑的远程命令</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">发送和接受ping</string>
|
||||
<string name="pref_plugin_notifications">通知同步</string>
|
||||
<string name="pref_plugin_notifications_desc">从其他设备访问你的通知</string>
|
||||
<string name="pref_plugin_receive_notifications">接收通知</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">从其他设备接收通知并显示在 Android 上</string>
|
||||
<string name="pref_plugin_sharereceiver">分享和接收</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">在设备间共享文件和 URL</string>
|
||||
<string name="plugin_not_available">该特性不适用于您的Android版本</string>
|
||||
@@ -24,10 +32,16 @@
|
||||
<string name="no_permissions">你需要授予权限以便访问通知</string>
|
||||
<string name="send_ping">发送ping</string>
|
||||
<string name="open_mpris_controls">多媒体控制</string>
|
||||
<string name="remotekeyboard_editing_only_title">只有在编辑时才接受远程按键</string>
|
||||
<string name="remotekeyboard_not_connected">没有活动的远程键盘链接,请在 KDE Connect 中连接</string>
|
||||
<string name="remotekeyboard_connected">远程键盘连接已启用</string>
|
||||
<string name="remotekeyboard_multiple_connections">发现多个远程键盘连接,请选择设备进行配置</string>
|
||||
<string name="open_mousepad">远程输入</string>
|
||||
<string name="mousepad_info">在屏幕上移动手指来移动光标。轻击代表左键,双指或三指点击代表右键或中键。用长按来拖放。</string>
|
||||
<string name="mousepad_double_tap_settings_title">设置双指点击动作</string>
|
||||
<string name="mousepad_triple_tap_settings_title">设置三指点击动作</string>
|
||||
<string name="mousepad_sensitivity_settings_title">设置触摸板灵敏度</string>
|
||||
<string name="mousepad_scroll_direction_title">滚动方向反向</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>右键点击</item>
|
||||
<item>中键点击</item>
|
||||
@@ -35,12 +49,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">右</string>
|
||||
<string name="mousepad_triple_default">中</string>
|
||||
<string name="mousepad_sensitivity_default">默认</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>最慢</item>
|
||||
<item>高于最慢</item>
|
||||
<item>默认</item>
|
||||
<item>高于默认</item>
|
||||
<item>最快</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">已连接设备</string>
|
||||
<string name="category_not_paired_devices">可用设备</string>
|
||||
@@ -59,6 +74,10 @@
|
||||
<string name="error_canceled_by_user">已被用户取消</string>
|
||||
<string name="error_canceled_by_other_peer">已被另一方取消</string>
|
||||
<string name="error_invalid_key">收到无效密钥</string>
|
||||
<string name="encryption_info_title">加密信息</string>
|
||||
<string name="encryption_info_msg_no_ssl">另一设备没有使用最新的 KDE Connect,使用旧版加密方法。</string>
|
||||
<string name="my_device_fingerprint">您的设备证书的 SHA1 指纹是:</string>
|
||||
<string name="remote_device_fingerprint">远程设备证书的 SHA1 指纹是:</string>
|
||||
<string name="pair_requested">已请求配对</string>
|
||||
<string name="pairing_request_from">来自%1s的配对请求</string>
|
||||
<string name="received_url_title">已从%1s接收链接</string>
|
||||
@@ -66,13 +85,15 @@
|
||||
<string name="incoming_file_title">来自%1s的文件</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">正在向%1s发送文件</string>
|
||||
<string name="outgoing_files_title">正在向 %1s 发送文件</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">已发送 %2$d 个文件中的 %1$d 个</string>
|
||||
<string name="received_file_title">已从%1s接收文件</string>
|
||||
<string name="received_file_fail_title">未能从%1s接收文件</string>
|
||||
<string name="received_file_text">点击以打开“%1s”</string>
|
||||
<string name="sent_file_title">发送文件到%1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">未能发送文件%1s</string>
|
||||
<string name="sent_file_failed_title">向 %1s 发送文件失败</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">点击以应答</string>
|
||||
<string name="reconnect">重新连接</string>
|
||||
@@ -119,6 +140,10 @@
|
||||
<string name="custom_device_list">通过IP增加设备</string>
|
||||
<string name="share_notification_preference">出声通知</string>
|
||||
<string name="share_notification_preference_summary">当收到文件时震动并播放声音</string>
|
||||
<string name="share_destination_customize">配置目标目录</string>
|
||||
<string name="share_destination_customize_summary_disabled">接收的文件会出现在“Downloads”中</string>
|
||||
<string name="share_destination_customize_summary_enabled">文件将会被存储在以下目录中</string>
|
||||
<string name="share_destination_folder_preference">目标目录</string>
|
||||
<string name="title_activity_notification_filter">通知过滤器</string>
|
||||
<string name="filter_apps_info">所选软件的通知将会被同步。</string>
|
||||
<string name="sftp_internal_storage">内部存储</string>
|
||||
@@ -144,5 +169,7 @@
|
||||
<string name="pref_plugin_telepathy">发送短消息</string>
|
||||
<string name="pref_plugin_telepathy_desc">从桌面发送短消息</string>
|
||||
<string name="plugin_not_supported">设备不支持此插件</string>
|
||||
<string name="findmyphone_title">找到我的手机</string>
|
||||
<string name="findmyphone_description">让设备响铃从而找到它</string>
|
||||
<string name="findmyphone_found">找到</string>
|
||||
</resources>
|
||||
|
@@ -1,22 +1,165 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">電話通知器</string>
|
||||
<string name="pref_plugin_telephony_desc">發送短訊與電話的通知</string>
|
||||
<string name="pref_plugin_battery">電池報告</string>
|
||||
<string name="pref_plugin_battery_desc">定期回報電池狀態</string>
|
||||
<string name="pref_plugin_sftp">顯示檔案系統</string>
|
||||
<string name="pref_plugin_sftp_desc">同意讓遠端可以瀏覽檔案系統</string>
|
||||
<string name="pref_plugin_clipboard">同步剪貼板</string>
|
||||
<string name="pref_plugin_clipboard_desc">分享剪貼板的內容</string>
|
||||
<string name="pref_plugin_mousepad">遠端輸入</string>
|
||||
<string name="pref_plugin_mousepad_desc">使用您的智慧型手機或者平板來模擬觸碰板與鍵盤</string>
|
||||
<string name="pref_plugin_mpris">多媒體控制</string>
|
||||
<string name="pref_plugin_mpris_desc">成為您多媒體播放器的遙控器</string>
|
||||
<string name="pref_plugin_runcommand">執行指令</string>
|
||||
<string name="pref_plugin_runcommand_desc">從您的智慧型手機或者平板當中觸發遠端設備上的命令</string>
|
||||
<string name="pref_plugin_ping">Ping回應封包</string>
|
||||
<string name="pref_plugin_ping_desc">傳送與接收Ping回應封包</string>
|
||||
<string name="pref_plugin_notifications">同步通知</string>
|
||||
<string name="pref_plugin_notifications_desc">存取其他設備上的通知</string>
|
||||
<string name="pref_plugin_receive_notifications">接收通知</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">在Android上顯示從其他裝置收到的通知</string>
|
||||
<string name="pref_plugin_sharereceiver">分享與接收</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">在兩個設備當中互相分享URL網址與檔案</string>
|
||||
<string name="plugin_not_available">這個功能無法在您的Android版本上執行。</string>
|
||||
<string name="device_list_empty">沒有裝置</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="open_settings">開啟設定</string>
|
||||
<string name="no_permissions">您需要授予存取通知的權限</string>
|
||||
<string name="send_ping">傳送Ping回應封包</string>
|
||||
<string name="open_mpris_controls">多媒體控制</string>
|
||||
<string name="open_mousepad">遠端輸入</string>
|
||||
<string name="mousepad_info">在您的智慧型手機的螢幕上移動手指頭,用來控制電腦螢幕的鼠標。點擊表示滑鼠的左鍵,使用兩隻/三隻手指頭點擊來表示滑鼠的右鍵/中鍵。長按則表示要拖拉。</string>
|
||||
<string name="mousepad_double_tap_settings_title">設定兩隻手指頭點擊的動作</string>
|
||||
<string name="mousepad_triple_tap_settings_title">設定三隻手指頭點擊的動作</string>
|
||||
<string name="mousepad_sensitivity_settings_title">設定觸碰板的靈敏度</string>
|
||||
<string name="mousepad_scroll_direction_title">滾動方向相反</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
<item>右鍵點擊</item>
|
||||
<item>中鍵點擊</item>
|
||||
<item>無</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">右</string>
|
||||
<string name="mousepad_triple_default">中</string>
|
||||
<string name="mousepad_sensitivity_default">預設</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>慢</item>
|
||||
<item>最慢</item>
|
||||
<item>預設</item>
|
||||
<item>高於預設值</item>
|
||||
<item>最快</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">已連接的設備</string>
|
||||
<string name="category_not_paired_devices">可連接的設備</string>
|
||||
<string name="category_remembered_devices">已記住的設備</string>
|
||||
<string name="plugins_failed_to_load">擴展插件讀取錯誤(點擊查看更多資訊)</string>
|
||||
<string name="device_menu_plugins">擴展插件設定</string>
|
||||
<string name="device_menu_unpair">取消配對</string>
|
||||
<string name="device_not_reachable">配對的設備無法連接</string>
|
||||
<string name="pair_new_device">配對新設備</string>
|
||||
<string name="unknown_device">不明的設備</string>
|
||||
<string name="error_not_reachable">設備無法連接</string>
|
||||
<string name="error_already_requested">已請求配對</string>
|
||||
<string name="error_already_paired">裝置已經配對</string>
|
||||
<string name="error_could_not_send_package">無法傳送封包</string>
|
||||
<string name="error_timed_out">逾時</string>
|
||||
<string name="error_canceled_by_user">使用者中斷</string>
|
||||
<string name="error_canceled_by_other_peer">被其他同等功能應用中斷</string>
|
||||
<string name="error_invalid_key">接收的密鑰無效</string>
|
||||
<string name="encryption_info_title">加密資訊</string>
|
||||
<string name="encryption_info_msg_no_ssl">其他的設備沒有使用新版本的KDE連線,使用傳統的加密模式。</string>
|
||||
<string name="my_device_fingerprint">您設備上的SHA1指紋辨識認證是:</string>
|
||||
<string name="remote_device_fingerprint">您遠端設備上的SHA1指紋辨識認證是:</string>
|
||||
<string name="pair_requested">已請求配對</string>
|
||||
<string name="pairing_request_from">從 %1s 來的配對請求</string>
|
||||
<string name="received_url_title">已從 %1s 連線接收</string>
|
||||
<string name="received_url_text">點擊開啟 \'%1s\'</string>
|
||||
<string name="incoming_file_title">從 %1s 傳來的檔案</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">正在將檔案發送到 %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="received_file_title">已從 %1s 接收檔案</string>
|
||||
<string name="received_file_fail_title">從 %1s 接收檔案失敗</string>
|
||||
<string name="received_file_text">點擊開啟 \'%1s\'</string>
|
||||
<string name="sent_file_title">將檔案傳送到 %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">點擊即可應答</string>
|
||||
<string name="reconnect">重新連線</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="device">裝置</string>
|
||||
<string name="pair_device">配對裝置</string>
|
||||
<string name="remote_control">遠端控制</string>
|
||||
<string name="settings">KDE連線設定</string>
|
||||
<string name="mpris_play">播放</string>
|
||||
<string name="mpris_previous">往前</string>
|
||||
<string name="mpris_rew">往後</string>
|
||||
<string name="mpris_ff">快轉</string>
|
||||
<string name="mpris_next">下一首</string>
|
||||
<string name="mpris_volume">音量</string>
|
||||
<string name="mpris_settings">多媒體設定</string>
|
||||
<string name="mpris_time_settings_title">往前/往後按鍵</string>
|
||||
<string name="mpris_time_settings_summary">調整按下時往前/往後的時間。</string>
|
||||
<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>
|
||||
<item>10秒鐘</item>
|
||||
<item>20秒鐘</item>
|
||||
<item>30秒鐘</item>
|
||||
<item>1分鐘</item>
|
||||
<item>2分鐘</item>
|
||||
</string-array>
|
||||
<string name="share_to">分享給</string>
|
||||
<string name="protocol_version_older">這個裝置使用舊版本的通訊協定</string>
|
||||
<string name="protocol_version_newer">此設備使用較新的通訊協定</string>
|
||||
<string name="general_settings">通用設定</string>
|
||||
<string name="plugin_settings">設定</string>
|
||||
<string name="plugin_settings_with_name">%s 設定</string>
|
||||
<string name="device_name">設備名稱</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">無效的設備名稱</string>
|
||||
<string name="shareplugin_text_saved">已接收文字,並且儲存到剪貼簿</string>
|
||||
<string name="custom_devices_settings">自定義設備列表</string>
|
||||
<string name="pair_device_action">配對新設備</string>
|
||||
<string name="unpair_device_action">未配對 %s</string>
|
||||
<string name="custom_device_list">以IP來新增設備</string>
|
||||
<string name="share_notification_preference">通知方式</string>
|
||||
<string name="share_notification_preference_summary">當接收檔案時發出振動以及播放聲音</string>
|
||||
<string name="title_activity_notification_filter">通知過濾器</string>
|
||||
<string name="filter_apps_info">將會以您選擇的App應用程式啟用同步通知</string>
|
||||
<string name="sftp_internal_storage">內部儲存空間</string>
|
||||
<string name="sftp_all_files">全部檔案</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_host">增加 host/IP</string>
|
||||
<string name="add_host_hint">Hostname或者IP</string>
|
||||
<string name="no_players_connected">沒有發現播放器</string>
|
||||
<string name="custom_dev_list_help">能夠在您的裝置沒有自動偵測到裝置時使用這個選項。輸入IP位址或者是Hostname在下面,並且按下按鈕來增加進入列表當中。觸碰以從列表中刪除現有項目。</string>
|
||||
<string name="mpris_player_on_device">%1$s on %2$s</string>
|
||||
<string name="send_files">傳送檔案</string>
|
||||
<string name="pairing_title">KDE連線裝置</string>
|
||||
<string name="pairing_description">在您相同網域當中,有其他有執行KDE連線的裝置會出現在這裡。</string>
|
||||
<string name="device_paired">裝置已配對</string>
|
||||
<string name="device_rename_title">更改裝置名稱</string>
|
||||
<string name="device_rename_confirm">更改名稱</string>
|
||||
<string name="refresh">刷新</string>
|
||||
<string name="unreachable_description">此配對的裝置無法連接。 請確保它連接到與您相同的網域。</string>
|
||||
<string name="no_file_browser">沒有安裝此檔案的瀏覽程式</string>
|
||||
<string name="pref_plugin_telepathy">傳送簡訊</string>
|
||||
<string name="pref_plugin_telepathy_desc">傳送文字簡訊到您的電腦桌面</string>
|
||||
<string name="plugin_not_supported">這個擴充插件並不支援您的手機</string>
|
||||
<string name="findmyphone_title">找尋我的手機</string>
|
||||
<string name="findmyphone_title_tablet">找尋我的平板</string>
|
||||
<string name="findmyphone_description">讓這個裝置發出聲響讓您能找到它</string>
|
||||
<string name="findmyphone_found">找到</string>
|
||||
<string name="open">開啟</string>
|
||||
<string name="close">關閉</string>
|
||||
</resources>
|
||||
|
@@ -2,4 +2,5 @@
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="key_height">48dip</dimen>
|
||||
</resources>
|
||||
|
@@ -11,6 +11,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Share the clipboard content</string>
|
||||
<string name="pref_plugin_mousepad">Remote input</string>
|
||||
<string name="pref_plugin_mousepad_desc">Use your phone or tablet as a touchpad and keyboard</string>
|
||||
<string name="pref_plugin_remotekeyboard">Receive remote keypresses</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Receive keypress events from remote devices</string>
|
||||
<string name="pref_plugin_mpris">Multimedia controls</string>
|
||||
<string name="pref_plugin_mpris_desc">Provides a remote control for your media player</string>
|
||||
<string name="pref_plugin_runcommand">Run Command</string>
|
||||
@@ -31,6 +33,11 @@
|
||||
<string name="no_permissions">You need to grant permission to access notifications</string>
|
||||
<string name="send_ping">Send ping</string>
|
||||
<string name="open_mpris_controls">Multimedia control</string>
|
||||
<string name="remotekeyboard_editing_only" translatable="false">remotekeyboard_editing_only</string>
|
||||
<string name="remotekeyboard_editing_only_title" translatable="true">Handle remote keys only when editing</string>
|
||||
<string name="remotekeyboard_not_connected" translatable="true">There is no active remote keyboard connection, establish one in kdeconnect</string>
|
||||
<string name="remotekeyboard_connected" translatable="true">Remote keyboard connection is active</string>
|
||||
<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 a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
@@ -96,13 +103,15 @@
|
||||
<string name="incoming_file_title">Incoming file from %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Sending file to %1s</string>
|
||||
<string name="outgoing_files_title">Sending files to %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Sent %1$d out of %2$d files</string>
|
||||
<string name="received_file_title">Received file from %1s</string>
|
||||
<string name="received_file_fail_title">Failed receiving file from %1s</string>
|
||||
<string name="received_file_text">Tap to open \'%1s\'</string>
|
||||
<string name="sent_file_title">Sent file to %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Failed to send file %1s</string>
|
||||
<string name="sent_file_failed_title">Failed to send file to %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tap to answer</string>
|
||||
<string name="reconnect">Reconnect</string>
|
||||
@@ -158,6 +167,10 @@
|
||||
<string name="custom_device_list">Add devices by IP</string>
|
||||
<string name="share_notification_preference">Noisy notifications</string>
|
||||
<string name="share_notification_preference_summary">Vibrate and play a sound when receiving a file</string>
|
||||
<string name="share_destination_customize">Customize destination directory</string>
|
||||
<string name="share_destination_customize_summary_disabled">Received files will appear in Downloads</string>
|
||||
<string name="share_destination_customize_summary_enabled">Files will be stored in the directory below</string>
|
||||
<string name="share_destination_folder_preference">Destination directory</string>
|
||||
<string name="title_activity_notification_filter">Notification filter</string>
|
||||
<string name="filter_apps_info">Notifications will be synchronized for the selected apps.</string>
|
||||
<string name="sftp_internal_storage">Internal storage</string>
|
||||
@@ -180,6 +193,7 @@
|
||||
<string name="device_rename_confirm">Rename</string>
|
||||
<string name="refresh">Refresh</string>
|
||||
<string name="unreachable_description">This paired device is not reachable. Make sure it is connected to your same network.</string>
|
||||
<string name="on_data_message">It looks like you are on a mobile data connection. KDE Connect only works on local networks.</string>
|
||||
<string name="no_file_browser">There are no file browsers installed.</string>
|
||||
<string name="pref_plugin_telepathy">Send SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Send text messages from your desktop</string>
|
||||
@@ -191,4 +205,5 @@
|
||||
|
||||
<string name="open">Open</string>
|
||||
<string name="close">Close</string>
|
||||
|
||||
</resources>
|
||||
|
14
res/xml/remotekeyboardplugin_keyboard.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Keyboard
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:keyHeight="@dimen/key_height"
|
||||
android:horizontalGap="0px"
|
||||
android:verticalGap="0px" >
|
||||
|
||||
<Row android:rowEdgeFlags="bottom">
|
||||
<Key android:keyIcon="@drawable/ic_keyboard_hide_white_36dp" android:codes="0" android:keyWidth="20%" />
|
||||
<Key android:keyIcon="@drawable/ic_action_settings" android:codes="1" android:keyWidth="40%"/>
|
||||
<Key android:keyIcon="@drawable/ic_action_keyboard" android:codes="2" android:keyWidth="40%"/>
|
||||
<Key android:keyIcon="@drawable/ic_phonelink_white_36dp" android:codes="3" android:keyWidth="20%" />-->
|
||||
</Row>
|
||||
</Keyboard>
|
4
res/xml/remotekeyboardplugin_method.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:supportsSwitchingToNextInputMethod="true">
|
||||
</input-method>
|
11
res/xml/remotekeyboardplugin_preferences.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/remotekeyboard_editing_only"
|
||||
android:key="@string/remotekeyboard_editing_only"
|
||||
android:title="@string/remotekeyboard_editing_only_title"
|
||||
android:defaultValue="true" />
|
||||
</PreferenceScreen>
|
@@ -3,6 +3,19 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/share_destination_customize"
|
||||
android:key="share_destination_custom"
|
||||
android:title="@string/share_destination_customize"
|
||||
android:summaryOff="@string/share_destination_customize_summary_disabled"
|
||||
android:summaryOn="@string/share_destination_customize_summary_enabled"
|
||||
android:defaultValue="false" />
|
||||
|
||||
<Preference
|
||||
android:id="@+id/share_destination_folder_preference"
|
||||
android:key="share_destination_folder_preference"
|
||||
android:title="@string/share_destination_folder_preference" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/share_notification_preference"
|
||||
android:key="share_notification_preference"
|
||||
|
@@ -89,7 +89,7 @@ public abstract class BaseLink {
|
||||
}
|
||||
|
||||
//TO OVERRIDE, should be sync
|
||||
public abstract void sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback);
|
||||
public abstract boolean sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback);
|
||||
@Deprecated
|
||||
public abstract void sendPackageEncrypted(NetworkPackage np,Device.SendPackageStatusCallback callback, PublicKey key);
|
||||
public abstract boolean sendPackageEncrypted(NetworkPackage np,Device.SendPackageStatusCallback callback, PublicKey key);
|
||||
}
|
||||
|
@@ -23,8 +23,6 @@ package org.kde.kdeconnect.Backends;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
import java.util.Timer;
|
||||
|
||||
/**
|
||||
* This class separates the pairing interface for each type of link.
|
||||
* Since different links can pair via different methods, like for LanLink certificate and public key should be shared,
|
||||
|
@@ -61,7 +61,7 @@ public class LanLink extends BaseLink {
|
||||
// because it's probably trying to find me and
|
||||
// potentially ask for pairing.
|
||||
|
||||
private Socket socket = null;
|
||||
private volatile Socket socket = null;
|
||||
|
||||
private LinkDisconnectedCallback callback;
|
||||
|
||||
@@ -142,11 +142,11 @@ public class LanLink extends BaseLink {
|
||||
}
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
private void sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
private boolean sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
if (socket == null) {
|
||||
Log.e("KDE/sendPackage", "Not yet connected");
|
||||
callback.sendFailure(new NotYetConnectedException());
|
||||
return;
|
||||
callback.onFailure(new NotYetConnectedException());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -171,14 +171,12 @@ public class LanLink extends BaseLink {
|
||||
|
||||
//Send body of the network package
|
||||
try {
|
||||
OutputStream writter = socket.getOutputStream();
|
||||
writter.write(np.serialize().getBytes(StringsHelper.UTF8));
|
||||
writter.flush();
|
||||
OutputStream writer = socket.getOutputStream();
|
||||
writer.write(np.serialize().getBytes(StringsHelper.UTF8));
|
||||
writer.flush();
|
||||
} catch (Exception e) {
|
||||
callback.sendFailure(e);
|
||||
e.printStackTrace();
|
||||
disconnect();
|
||||
return;
|
||||
disconnect(); //main socket is broken, disconnect
|
||||
throw e;
|
||||
}
|
||||
|
||||
//Send payload
|
||||
@@ -203,23 +201,24 @@ public class LanLink extends BaseLink {
|
||||
Log.i("KDE/LanLink", "Beginning to send payload");
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
long size = np.getPayloadSize();
|
||||
long progress = 0;
|
||||
long timeSinceLastUpdate = -1;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
//Log.e("ok",""+bytesRead);
|
||||
progress += bytesRead;
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
if (np.getPayloadSize() > 0) {
|
||||
callback.sendProgress((int)(progress / np.getPayloadSize()));
|
||||
if (size > 0) {
|
||||
if (timeSinceLastUpdate + 500 < System.currentTimeMillis()) { //Report progress every half a second
|
||||
long percent = ((100 * progress) / size);
|
||||
callback.onProgressChanged((int) percent);
|
||||
timeSinceLastUpdate = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
Log.i("KDE/LanLink", "Finished sending payload ("+progress+" bytes written)");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/sendPackage", "Exception: "+e);
|
||||
callback.sendFailure(e);
|
||||
return;
|
||||
} finally {
|
||||
try { server.close(); } catch (Exception e) { }
|
||||
try { payloadSocket.close(); } catch (Exception e) { }
|
||||
@@ -228,12 +227,13 @@ public class LanLink extends BaseLink {
|
||||
}
|
||||
}
|
||||
|
||||
callback.sendSuccess();
|
||||
|
||||
callback.onSuccess();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
if (callback != null) {
|
||||
callback.sendFailure(e);
|
||||
callback.onFailure(e);
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
//Make sure we close the payload stream, if any
|
||||
InputStream stream = np.getPayload();
|
||||
@@ -244,14 +244,14 @@ public class LanLink extends BaseLink {
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
@Override
|
||||
public void sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback) {
|
||||
sendPackageInternal(np, callback, null);
|
||||
public boolean sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback) {
|
||||
return sendPackageInternal(np, callback, null);
|
||||
}
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
@Override
|
||||
public void sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
sendPackageInternal(np, callback, key);
|
||||
public boolean sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
return sendPackageInternal(np, callback, key);
|
||||
}
|
||||
|
||||
private void receivedNetworkPackage(NetworkPackage np) {
|
||||
|
@@ -31,6 +31,7 @@ import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.kde.kdeconnect.Helpers.NetworkHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Helpers.StringsHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
@@ -68,18 +69,18 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
final static int MAX_PORT = 1764;
|
||||
final static int PAYLOAD_TRANSFER_MIN_PORT = 1739;
|
||||
|
||||
private final Context context;
|
||||
final Context context;
|
||||
|
||||
private final HashMap<String, LanLink> visibleComputers = new HashMap<>(); //Links by device id
|
||||
|
||||
private ServerSocket tcpServer;
|
||||
ServerSocket tcpServer;
|
||||
private DatagramSocket udpServer;
|
||||
private DatagramSocket udpServerOldPort;
|
||||
|
||||
private boolean listening = false;
|
||||
boolean listening = false;
|
||||
|
||||
// To prevent infinte loop between Android < IceCream because both device can only broadcast identity package but cannot connect via TCP
|
||||
private ArrayList<InetAddress> reverseConnectionBlackList = new ArrayList<>();
|
||||
ArrayList<InetAddress> reverseConnectionBlackList = new ArrayList<>();
|
||||
|
||||
@Override // SocketClosedCallback
|
||||
public void linkDisconnected(LanLink brokenLink) {
|
||||
@@ -89,7 +90,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
}
|
||||
|
||||
//They received my UDP broadcast and are connecting to me. The first thing they sned should be their identity.
|
||||
public void tcpPackageReceived(Socket socket) throws Exception {
|
||||
void tcpPackageReceived(Socket socket) throws Exception {
|
||||
|
||||
NetworkPackage networkPackage;
|
||||
try {
|
||||
@@ -112,7 +113,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
}
|
||||
|
||||
//I've received their broadcast and should connect to their TCP socket and send my identity.
|
||||
protected void udpPacketReceived(DatagramPacket packet) throws Exception {
|
||||
void udpPacketReceived(DatagramPacket packet) throws Exception {
|
||||
|
||||
final InetAddress address = packet.getAddress();
|
||||
|
||||
@@ -171,7 +172,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
}
|
||||
}
|
||||
|
||||
private void configureSocket(Socket socket) {
|
||||
void configureSocket(Socket socket) {
|
||||
try {
|
||||
socket.setKeepAlive(true);
|
||||
} catch (SocketException e) {
|
||||
@@ -360,7 +361,12 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
throw new IOException("No ports available");
|
||||
}
|
||||
|
||||
void broadcastUdpPackage() {
|
||||
private void broadcastUdpPackage() {
|
||||
|
||||
if (NetworkHelper.isOnMobileNetwork(context)) {
|
||||
Log.w("LanLinkProvider", "On 3G network, not sending broadcast.");
|
||||
return;
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
|
@@ -39,7 +39,7 @@ import java.util.TimerTask;
|
||||
|
||||
public class LanPairingHandler extends BasePairingHandler {
|
||||
|
||||
private Timer mPairingTimer;
|
||||
Timer mPairingTimer;
|
||||
|
||||
public LanPairingHandler(Device device, final PairingHandlerCallback callback) {
|
||||
super(device, callback);
|
||||
@@ -142,7 +142,7 @@ public class LanPairingHandler extends BasePairingHandler {
|
||||
|
||||
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
public void onSuccess() {
|
||||
hidePairingNotification(); //Will stop the pairingTimer if it was running
|
||||
mPairingTimer = new Timer();
|
||||
mPairingTimer.schedule(new TimerTask() {
|
||||
@@ -157,14 +157,19 @@ public class LanPairingHandler extends BasePairingHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable e) {
|
||||
public void onFailure(Throwable e) {
|
||||
if (e != null) {
|
||||
e.printStackTrace();
|
||||
} else {
|
||||
Log.e("LanPairing/onFailure", "Unknown (null) exception");
|
||||
}
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_could_not_send_package));
|
||||
}
|
||||
};
|
||||
mDevice.sendPackage(createPairPackage(), statusCallback);
|
||||
}
|
||||
|
||||
public void hidePairingNotification() {
|
||||
void hidePairingNotification() {
|
||||
mDevice.hidePairingNotification();
|
||||
if (mPairingTimer != null) {
|
||||
mPairingTimer .cancel();
|
||||
@@ -176,12 +181,17 @@ public class LanPairingHandler extends BasePairingHandler {
|
||||
hidePairingNotification();
|
||||
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
public void onSuccess() {
|
||||
pairingDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable e) {
|
||||
public void onFailure(Throwable e) {
|
||||
if (e != null) {
|
||||
e.printStackTrace();
|
||||
} else {
|
||||
Log.e("LanPairing/onFailure", "Unknown (null) exception");
|
||||
}
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_not_reachable));
|
||||
}
|
||||
};
|
||||
@@ -197,7 +207,7 @@ public class LanPairingHandler extends BasePairingHandler {
|
||||
mDevice.sendPackage(np);
|
||||
}
|
||||
|
||||
public void pairingDone() {
|
||||
void pairingDone() {
|
||||
// Store device information needed to create a Device object in a future
|
||||
//Log.e("KDE/PairingDone", "Pairing Done");
|
||||
SharedPreferences.Editor editor = mDevice.getContext().getSharedPreferences(mDevice.getDeviceId(), Context.MODE_PRIVATE).edit();
|
||||
|
@@ -47,18 +47,19 @@ public class LoopbackLink extends BaseLink {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackage(NetworkPackage in, Device.SendPackageStatusCallback callback) {
|
||||
public boolean sendPackage(NetworkPackage in, Device.SendPackageStatusCallback callback) {
|
||||
packageReceived(in);
|
||||
if (in.hasPayload()) {
|
||||
callback.sendProgress(0);
|
||||
callback.onProgressChanged(0);
|
||||
in.setPayload(in.getPayload(), in.getPayloadSize());
|
||||
callback.sendProgress(100);
|
||||
callback.onProgressChanged(100);
|
||||
}
|
||||
callback.sendSuccess();
|
||||
callback.onSuccess();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
sendPackage(np, callback);
|
||||
public boolean sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
return sendPackage(np, callback);
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,6 @@ import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
@@ -120,7 +119,7 @@ public class BackgroundService extends Service {
|
||||
}
|
||||
};
|
||||
|
||||
private void onDeviceListChanged() {
|
||||
public void onDeviceListChanged() {
|
||||
for(DeviceListChangedCallback callback : deviceListChangedCallbacks.values()) {
|
||||
callback.onDeviceListChanged();
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@ import android.util.Log;
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.Plugins.PluginFactory;
|
||||
@@ -367,7 +368,23 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
Intent intent = new Intent(getContext(), MaterialActivity.class);
|
||||
intent.putExtra("deviceId", getDeviceId());
|
||||
intent.putExtra("notificationId", notificationId);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
Intent acceptIntent = new Intent(getContext(), MaterialActivity.class);
|
||||
Intent rejectIntent = new Intent(getContext(), MaterialActivity.class);
|
||||
|
||||
acceptIntent.putExtra("deviceId", getDeviceId());
|
||||
acceptIntent.putExtra("notificationId", notificationId);
|
||||
acceptIntent.setAction("action "+System.currentTimeMillis());
|
||||
acceptIntent.putExtra(MaterialActivity.PAIR_REQUEST_STATUS, MaterialActivity.PAIRING_ACCEPTED);
|
||||
|
||||
rejectIntent.putExtra("deviceId", getDeviceId());
|
||||
rejectIntent.putExtra("notificationId", notificationId);
|
||||
rejectIntent.setAction("action "+System.currentTimeMillis());
|
||||
rejectIntent.putExtra(MaterialActivity.PAIR_REQUEST_STATUS, MaterialActivity.PAIRING_REJECTED);
|
||||
|
||||
PendingIntent acceptedPendingIntent = PendingIntent.getActivity(getContext(), 2, acceptIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||
PendingIntent rejectedPendingIntent = PendingIntent.getActivity(getContext(), 4, rejectIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||
|
||||
Resources res = getContext().getResources();
|
||||
|
||||
@@ -377,19 +394,16 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
.setContentIntent(pendingIntent)
|
||||
.setTicker(res.getString(R.string.pair_requested))
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.addAction(R.drawable.ic_accept_pairing, res.getString(R.string.pairing_accept), acceptedPendingIntent)
|
||||
.addAction(R.drawable.ic_reject_pairing, res.getString(R.string.pairing_reject), rejectedPendingIntent)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.build();
|
||||
|
||||
final NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, noti);
|
||||
|
||||
try {
|
||||
BackgroundService.addGuiInUseCounter(context);
|
||||
notificationManager.notify(notificationId, noti);
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
BackgroundService.addGuiInUseCounter(context);
|
||||
}
|
||||
|
||||
public void hidePairingNotification() {
|
||||
@@ -582,42 +596,43 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
}
|
||||
|
||||
public static abstract class SendPackageStatusCallback {
|
||||
protected abstract void onSuccess();
|
||||
protected abstract void onFailure(Throwable e);
|
||||
protected void onProgressChanged(int percent) { }
|
||||
public abstract void onSuccess();
|
||||
public abstract void onFailure(Throwable e);
|
||||
public void onProgressChanged(int percent) { }
|
||||
}
|
||||
|
||||
private boolean success = false;
|
||||
public void sendSuccess() {
|
||||
success = true;
|
||||
onSuccess();
|
||||
}
|
||||
public void sendFailure(Throwable e) {
|
||||
private SendPackageStatusCallback defaultCallback = new SendPackageStatusCallback() {
|
||||
@Override
|
||||
public void onSuccess() { }
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
if (e != null) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/sendPackage", "Exception: " + e.getMessage());
|
||||
} else {
|
||||
Log.e("KDE/sendPackage", "Unknown (null) exception");
|
||||
}
|
||||
onFailure(e);
|
||||
}
|
||||
public void sendProgress(int percent) { onProgressChanged(percent); }
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public void sendPackage(NetworkPackage np) {
|
||||
sendPackage(np,new SendPackageStatusCallback() {
|
||||
@Override
|
||||
protected void onSuccess() { }
|
||||
@Override
|
||||
protected void onFailure(Throwable e) { }
|
||||
});
|
||||
sendPackage(np, defaultCallback);
|
||||
}
|
||||
|
||||
public boolean sendPackageBlocking(NetworkPackage np) {
|
||||
return sendPackageBlocking(np, defaultCallback);
|
||||
}
|
||||
|
||||
//Async
|
||||
public void sendPackage(final NetworkPackage np, final SendPackageStatusCallback callback) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendPackageBlocking(np, callback);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
hackToMakeRetrocompatiblePacketTypes(np);
|
||||
|
||||
public boolean sendPackageBlocking(final NetworkPackage np, final SendPackageStatusCallback callback) {
|
||||
|
||||
/*
|
||||
if (!m_outgoingCapabilities.contains(np.getType()) && !NetworkPackage.protocolPackageTypes.contains(np.getType())) {
|
||||
@@ -626,37 +641,29 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
}
|
||||
*/
|
||||
|
||||
//Log.e("sendPackage", "Sending package...");
|
||||
//Log.e("sendPackage", np.serialize());
|
||||
hackToMakeRetrocompatiblePacketTypes(np);
|
||||
|
||||
final Throwable backtrace = new Throwable();
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
boolean useEncryption = (protocolVersion < LanLinkProvider.MIN_VERSION_WITH_SSL_SUPPORT && (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired()));
|
||||
|
||||
//Make a copy to avoid concurrent modification exception if the original list changes
|
||||
for (final BaseLink link : links) {
|
||||
if (link == null) continue; //Since we made a copy, maybe somebody destroyed the link in the meanwhile
|
||||
if (useEncryption) {
|
||||
link.sendPackageEncrypted(np, callback, publicKey);
|
||||
} else {
|
||||
link.sendPackage(np, callback);
|
||||
}
|
||||
if (callback.success) break; //If the link didn't call sendSuccess(), try the next one
|
||||
}
|
||||
|
||||
if (!callback.success) {
|
||||
Log.e("KDE/sendPackage", "No device link (of "+links.size()+" available) could send the package. Package "+np.getType()+" to " + name + " lost!");
|
||||
backtrace.printStackTrace();
|
||||
}
|
||||
boolean useEncryption = (protocolVersion < LanLinkProvider.MIN_VERSION_WITH_SSL_SUPPORT && (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired()));
|
||||
|
||||
boolean success = false;
|
||||
//Make a copy to avoid concurrent modification exception if the original list changes
|
||||
for (final BaseLink link : links) {
|
||||
if (link == null) continue; //Since we made a copy, maybe somebody destroyed the link in the meanwhile
|
||||
if (useEncryption) {
|
||||
success = link.sendPackageEncrypted(np, callback, publicKey);
|
||||
} else {
|
||||
success = link.sendPackage(np, callback);
|
||||
}
|
||||
}).start();
|
||||
if (success) break; //If the link didn't call sendSuccess(), try the next one
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Log.e("KDE/sendPackage", "No device link (of "+links.size()+" available) could send the package. Package "+np.getType()+" to " + name + " lost!");
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Plugin-related functions
|
||||
//
|
||||
|
@@ -450,13 +450,17 @@ public class DeviceHelper {
|
||||
public static String getAndroidDeviceName() {
|
||||
String deviceName = null;
|
||||
try {
|
||||
String dictName = humanReadableNames.get(Build.MODEL.replace(' ', '_'));
|
||||
String internalName = Build.MODEL.replace(' ', '_');
|
||||
String dictName = humanReadableNames.get(internalName);
|
||||
if (dictName != null) {
|
||||
deviceName = dictName;
|
||||
} else if (Build.BRAND.equalsIgnoreCase("samsung")) {
|
||||
deviceName = "Samsung " + Build.MODEL;
|
||||
} else {
|
||||
deviceName = Build.BRAND;
|
||||
Log.w("getAndroidDeviceName", "Not found human readable name for device '" + internalName + "'");
|
||||
if (Build.BRAND.equalsIgnoreCase("samsung")) {
|
||||
deviceName = "Samsung " + Build.MODEL;
|
||||
} else {
|
||||
deviceName = Build.BRAND;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//Some phones might not define BRAND or MODEL, ignore exceptions
|
||||
|
@@ -27,17 +27,35 @@ import java.io.File;
|
||||
|
||||
public class FilesHelper {
|
||||
|
||||
public static String getFileExt(String fileName) {
|
||||
//return MimeTypeMap.getFileExtensionFromUrl(fileName);
|
||||
return fileName.substring((fileName.lastIndexOf(".") + 1), fileName.length());
|
||||
public static String getFileExt(String filename) {
|
||||
//return MimeTypeMap.getFileExtensionFromUrl(filename);
|
||||
return filename.substring((filename.lastIndexOf(".") + 1));
|
||||
}
|
||||
|
||||
public static String getFileNameWithoutExt(String filename) {
|
||||
int dot = filename.lastIndexOf(".");
|
||||
return (dot < 0)? filename : filename.substring(0, dot);
|
||||
}
|
||||
public static String getMimeTypeFromFile(String file) {
|
||||
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileExt(file));
|
||||
if (mime == null) mime = "*/*";
|
||||
return mime;
|
||||
}
|
||||
|
||||
public static String findNonExistingNameForNewFile(String path, String filename) {
|
||||
int dot = filename.lastIndexOf(".");
|
||||
String name = (dot < 0)? filename : filename.substring(0, dot);
|
||||
String ext = (dot < 0)? "" : filename.substring(filename.lastIndexOf("."));
|
||||
|
||||
int num = 1;
|
||||
while (new File(path+"/"+filename).exists()) {
|
||||
filename = name+" ("+num+")"+ext;
|
||||
num++;
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
//Following code from http://activemq.apache.org/maven/5.7.0/kahadb/apidocs/src-html/org/apache/kahadb/util/IOHelper.html
|
||||
/**
|
||||
* Converts any string into a string that is safe to use as a file name.
|
||||
|
17
src/org/kde/kdeconnect/Helpers/MediaStoreHelper.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
public class MediaStoreHelper {
|
||||
|
||||
//Maybe this class could batch successive calls together
|
||||
|
||||
public static void indexFile(Context context, Uri path) {
|
||||
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
||||
mediaScanIntent.setData(path);
|
||||
context.sendBroadcast(mediaScanIntent);
|
||||
}
|
||||
|
||||
}
|
53
src/org/kde/kdeconnect/Helpers/NetworkHelper.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.LineNumberReader;
|
||||
|
||||
public class NetworkHelper {
|
||||
|
||||
public static boolean isOnMobileNetwork(Context context) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
return false; //No good way to know it
|
||||
}
|
||||
boolean mobile = false;
|
||||
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
Network[] networks = connMgr.getAllNetworks();
|
||||
for (Network network : networks) {
|
||||
NetworkInfo info = connMgr.getNetworkInfo(network);
|
||||
if (info == null) {
|
||||
continue;
|
||||
}
|
||||
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
|
||||
mobile = info.isConnected();
|
||||
continue;
|
||||
}
|
||||
//Log.e(info.getTypeName(),""+info.isAvailable());
|
||||
if (info.isAvailable()) return false; //We are connected to at least one non-mobile network
|
||||
}
|
||||
if (mobile) { //We suspect we are on a mobile net
|
||||
try {
|
||||
//Check the number of network neighbours, on data it should be 0
|
||||
LineNumberReader is = new LineNumberReader(new FileReader("/proc/net/arp"));
|
||||
is.skip(Long.MAX_VALUE);
|
||||
//Log.e("NetworkHelper", "procnetarp has " + is.getLineNumber() + " lines");
|
||||
if (is.getLineNumber() > 1) { //The first line are the headers
|
||||
return false; //I have neighbours, so this doesn't look like a mobile network
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("NetworkHelper", "Exception reading procnetarp");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
25
src/org/kde/kdeconnect/Helpers/NotificationHelper.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
|
||||
public class NotificationHelper {
|
||||
|
||||
public static void notifyCompat(NotificationManager notificationManager, int notificationId, Notification notification) {
|
||||
try {
|
||||
notificationManager.notify(notificationId, notification);
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyCompat(NotificationManager notificationManager, String tag, int notificationId, Notification notification) {
|
||||
try {
|
||||
notificationManager.notify(tag, notificationId, notification);
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
}
|
||||
}
|
@@ -67,6 +67,7 @@ public class KdeConnectBroadcastReceiver extends BroadcastReceiver
|
||||
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
service.onDeviceListChanged();
|
||||
service.onNetworkChange();
|
||||
}
|
||||
});
|
||||
|
@@ -8,6 +8,7 @@ import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
@@ -20,7 +21,12 @@ public class FindMyPhoneActivity extends Activity {
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
finish(); //If this activity was already open and we received the ring packet again, just finish it
|
||||
|
||||
if(ringtone != null) {
|
||||
// If this activity was already open and we received the ring packet again, just finish it
|
||||
finish();
|
||||
}
|
||||
// otherwise the activity will become active again
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -33,8 +39,28 @@ public class FindMyPhoneActivity extends Activity {
|
||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||
|
||||
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
|
||||
if (ringtone == null) {
|
||||
ringtoneUri = RingtoneManager.getValidRingtoneUri(getApplicationContext());
|
||||
if (ringtoneUri == null) {
|
||||
Log.e("FindMyPhone", "Could not find a ringtone to play!");
|
||||
return;
|
||||
}
|
||||
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= 21) {
|
||||
AudioAttributes.Builder b = new AudioAttributes.Builder();
|
||||
@@ -45,18 +71,16 @@ public class FindMyPhoneActivity extends Activity {
|
||||
}
|
||||
|
||||
ringtone.play();
|
||||
|
||||
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
ringtone.stop();
|
||||
super.finish();
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if(ringtone != null) {
|
||||
ringtone.stop();
|
||||
ringtone = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,7 +21,6 @@
|
||||
package org.kde.kdeconnect.Plugins.MprisPlugin;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@@ -34,7 +33,6 @@ import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
@@ -95,22 +93,16 @@ public class MprisActivity extends ActionBarActivity {
|
||||
TextView nowPlaying = (TextView) findViewById(R.id.now_playing_textview);
|
||||
if (!nowPlaying.getText().toString().equals(song)) {
|
||||
nowPlaying.setText(song);
|
||||
|
||||
Bitmap currentArt = mpris.getCurrentArt();
|
||||
ImageView artView = (ImageView) findViewById(R.id.artImageView);
|
||||
if (currentArt != null) {
|
||||
artView.setImageBitmap(currentArt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mpris.getLength() > -1 && mpris.getPosition() > -1 && !"spotify".equals(mpris.getPlayer().toLowerCase())) {
|
||||
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(mpris.getLength()));
|
||||
//Hacks for Spotify because it reports incorrect info about what it supports
|
||||
boolean isSpotify = "spotify".equals(mpris.getPlayer().toLowerCase());
|
||||
|
||||
if (mpris.getLength() > -1 && mpris.getPosition() > -1 && !isSpotify) {
|
||||
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(mpris.getLength()));
|
||||
SeekBar positionSeek = (SeekBar)findViewById(R.id.positionSeek);
|
||||
positionSeek.setMax((int)(mpris.getLength()));
|
||||
positionSeek.setProgress((int)(mpris.getPosition()));
|
||||
|
||||
findViewById(R.id.progress_slider).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.progress_slider).setVisibility(View.GONE);
|
||||
@@ -122,9 +114,23 @@ public class MprisActivity extends ActionBarActivity {
|
||||
boolean isPlaying = mpris.isPlaying();
|
||||
if (isPlaying) {
|
||||
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_pause);
|
||||
findViewById(R.id.play_button).setVisibility(mpris.isPauseAllowed() ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_play);
|
||||
findViewById(R.id.play_button).setVisibility(mpris.isPlayAllowed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
if (isSpotify) {
|
||||
findViewById(R.id.volume_layout).setVisibility(View.INVISIBLE);
|
||||
findViewById(R.id.rew_button).setVisibility(View.GONE);
|
||||
findViewById(R.id.ff_button).setVisibility(View.GONE);
|
||||
} else {
|
||||
findViewById(R.id.volume_layout).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.rew_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.ff_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
findViewById(R.id.next_button).setVisibility(mpris.isGoNextAllowed() ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.prev_button).setVisibility(mpris.isGoPreviousAllowed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -162,23 +168,16 @@ public class MprisActivity extends ActionBarActivity {
|
||||
|
||||
if (pos >= playerList.size()) return;
|
||||
|
||||
((TextView) findViewById(R.id.now_playing_textview)).setText("");
|
||||
String player = playerList.get(pos);
|
||||
mpris.setPlayer(player);
|
||||
//Spotify doesn't support changing the volume yet...
|
||||
//Also doesn't support seeking and telling actual position...
|
||||
if (player.toLowerCase().equals("spotify")) {
|
||||
findViewById(R.id.volume_layout).setVisibility(View.INVISIBLE);
|
||||
findViewById(R.id.rew_button).setVisibility(View.GONE);
|
||||
findViewById(R.id.ff_button).setVisibility(View.GONE);
|
||||
findViewById(R.id.positionSeek).setVisibility(View.INVISIBLE);
|
||||
findViewById(R.id.progress_slider).setVisibility(View.GONE);
|
||||
} else {
|
||||
findViewById(R.id.volume_layout).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.rew_button).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.ff_button).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.positionSeek).setVisibility(View.VISIBLE);
|
||||
if (player.equals(mpris.getPlayer())) {
|
||||
return; //Player hasn't actually changed
|
||||
}
|
||||
mpris.setPlayer(player);
|
||||
|
||||
//Clear values from previous player
|
||||
((TextView) findViewById(R.id.now_playing_textview)).setText("");
|
||||
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(0));
|
||||
((SeekBar)findViewById(R.id.positionSeek)).setMax(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -22,13 +22,10 @@ package org.kde.kdeconnect.Plugins.MprisPlugin;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
@@ -47,11 +44,15 @@ public class MprisPlugin extends Plugin {
|
||||
private String player = "";
|
||||
private boolean playing = false;
|
||||
private String currentSong = "";
|
||||
private Bitmap currentArt;
|
||||
private int volume = 50;
|
||||
private long length = -1;
|
||||
private long lastPosition;
|
||||
private long lastPositionTime;
|
||||
private boolean playAllowed = true;
|
||||
private boolean pauseAllowed = true;
|
||||
private boolean goNextAllowed = true;
|
||||
private boolean goPreviousAllowed = true;
|
||||
private boolean seekAllowed = true;
|
||||
private HashMap<String,Handler> playerStatusUpdated = new HashMap<>();
|
||||
|
||||
private List<String> playerList = new ArrayList<>();
|
||||
@@ -125,8 +126,7 @@ public class MprisPlugin extends Plugin {
|
||||
@Override
|
||||
public boolean onPackageReceived(NetworkPackage np) {
|
||||
|
||||
if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") ||
|
||||
np.has("pos") || np.has("artImage")) {
|
||||
if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") || np.has("pos")) {
|
||||
if (np.getString("player").equals(player)) {
|
||||
currentSong = np.getString("nowPlaying", currentSong);
|
||||
volume = np.getInt("volume", volume);
|
||||
@@ -135,12 +135,12 @@ public class MprisPlugin extends Plugin {
|
||||
lastPosition = np.getLong("pos", lastPosition);
|
||||
lastPositionTime = System.currentTimeMillis();
|
||||
}
|
||||
if (np.has("artImage")) {
|
||||
String base64Image = np.getString("artImage");
|
||||
byte[] decodedBytes = Base64.decode(base64Image, 0);
|
||||
currentArt = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
|
||||
}
|
||||
playing = np.getBoolean("isPlaying", playing);
|
||||
playAllowed = np.getBoolean("canPlay", playAllowed);
|
||||
pauseAllowed = np.getBoolean("canPause", pauseAllowed);
|
||||
goNextAllowed = np.getBoolean("canGoNext", goNextAllowed);
|
||||
goPreviousAllowed = np.getBoolean("canGoPrevious", goPreviousAllowed);
|
||||
seekAllowed = np.getBoolean("canSeek", seekAllowed);
|
||||
for (String key : playerStatusUpdated.keySet()) {
|
||||
try {
|
||||
playerStatusUpdated.get(key).dispatchMessage(new Message());
|
||||
@@ -218,9 +218,13 @@ public class MprisPlugin extends Plugin {
|
||||
if (player == null || player.equals(this.player)) return;
|
||||
this.player = player;
|
||||
currentSong = "";
|
||||
currentArt = null;
|
||||
volume = 50;
|
||||
playing = false;
|
||||
playAllowed = true;
|
||||
pauseAllowed = true;
|
||||
goNextAllowed = true;
|
||||
goPreviousAllowed = true;
|
||||
seekAllowed = true;
|
||||
for (String key : playerStatusUpdated.keySet()) {
|
||||
try {
|
||||
playerStatusUpdated.get(key).dispatchMessage(new Message());
|
||||
@@ -241,8 +245,6 @@ public class MprisPlugin extends Plugin {
|
||||
return currentSong;
|
||||
}
|
||||
|
||||
public Bitmap getCurrentArt() { return currentArt; }
|
||||
|
||||
public String getPlayer() {
|
||||
return player;
|
||||
}
|
||||
@@ -257,6 +259,26 @@ public class MprisPlugin extends Plugin {
|
||||
return playing;
|
||||
}
|
||||
|
||||
public boolean isPlayAllowed() {
|
||||
return playAllowed;
|
||||
}
|
||||
|
||||
public boolean isPauseAllowed() {
|
||||
return pauseAllowed;
|
||||
}
|
||||
|
||||
public boolean isGoNextAllowed() {
|
||||
return goNextAllowed;
|
||||
}
|
||||
|
||||
public boolean isGoPreviousAllowed() {
|
||||
return goPreviousAllowed;
|
||||
}
|
||||
|
||||
public boolean isSeekAllowed() {
|
||||
return seekAllowed;
|
||||
}
|
||||
|
||||
public long getPosition(){
|
||||
if(playing) {
|
||||
return lastPosition + (System.currentTimeMillis() - lastPositionTime);
|
||||
|
@@ -224,7 +224,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
Bundle extras = notification.extras;
|
||||
String extraTitle = extras.getString(TITLE_KEY);
|
||||
String extraTitle = extras.getCharSequence(TITLE_KEY).toString();
|
||||
String extraText = null;
|
||||
Object extraTextExtra = extras.get(TEXT_KEY);
|
||||
if (extraTextExtra != null) extraText = extraTextExtra.toString();
|
||||
|
@@ -30,6 +30,7 @@ import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.UserInterface.MaterialActivity;
|
||||
@@ -89,12 +90,7 @@ public class PingPlugin extends Plugin {
|
||||
.build();
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
try {
|
||||
notificationManager.notify(id, noti);
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
NotificationHelper.notifyCompat(notificationManager, id, noti);
|
||||
|
||||
return true;
|
||||
|
||||
|
@@ -161,8 +161,9 @@ public abstract class Plugin {
|
||||
public void onDestroy() { }
|
||||
|
||||
/**
|
||||
* If onCreate returns false, should create a dialog explaining
|
||||
* the problem (and how to fix it, if possible) to the user.
|
||||
* Called when a plugin receives a package. By convention we return true
|
||||
* when we have done something in response to the package or false
|
||||
* otherwise, even though that value is unused as of now.
|
||||
*/
|
||||
public boolean onPackageReceived(NetworkPackage np) { return false; }
|
||||
|
||||
|
@@ -33,6 +33,7 @@ import org.kde.kdeconnect.Plugins.MprisPlugin.MprisPlugin;
|
||||
import org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationsPlugin;
|
||||
import org.kde.kdeconnect.Plugins.PingPlugin.PingPlugin;
|
||||
import org.kde.kdeconnect.Plugins.ReceiveNotificationsPlugin.ReceiveNotificationsPlugin;
|
||||
import org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin.RemoteKeyboardPlugin;
|
||||
import org.kde.kdeconnect.Plugins.RunCommandPlugin.RunCommandPlugin;
|
||||
import org.kde.kdeconnect.Plugins.SftpPlugin.SftpPlugin;
|
||||
import org.kde.kdeconnect.Plugins.SharePlugin.SharePlugin;
|
||||
@@ -124,6 +125,8 @@ public class PluginFactory {
|
||||
PluginFactory.registerPlugin(TelepathyPlugin.class);
|
||||
PluginFactory.registerPlugin(FindMyPhonePlugin.class);
|
||||
PluginFactory.registerPlugin(RunCommandPlugin.class);
|
||||
//Commented here and in AndroidManifest until we release a desktop version with this feature, so we don't get bad "feature not working" reviews
|
||||
//PluginFactory.registerPlugin(RemoteKeyboardPlugin.class);
|
||||
}
|
||||
|
||||
public static PluginInfo getPluginInfo(Context context, String pluginKey) {
|
||||
|
@@ -32,6 +32,7 @@ import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.UserInterface.MaterialActivity;
|
||||
@@ -114,13 +115,8 @@ public class ReceiveNotificationsPlugin extends Plugin {
|
||||
.build();
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
try {
|
||||
// tag all incoming notifications
|
||||
notificationManager.notify("kdeconnectId:" + np.getString("id", "0"), np.getInt("id", 0), noti);
|
||||
} catch (Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
NotificationHelper.notifyCompat(notificationManager, "kdeconnectId:" + np.getString("id", "0"), np.getInt("id", 0), noti);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* Copyright 2017 Holger Kaelberer <holger.k@elberer.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class RemoteKeyboardPlugin extends Plugin {
|
||||
|
||||
public final static String PACKAGE_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
|
||||
public final static String PACKAGE_TYPE_MOUSEPAD_ECHO = "kdeconnect.mousepad.echo";
|
||||
public final static String PACKAGE_TYPE_MOUSEPAD_KEYBOARDSTATE = "kdeconnect.mousepad.keyboardstate";
|
||||
|
||||
/**
|
||||
* Track and expose plugin instances to allow for a 'connected'-indicator in the IME:
|
||||
*/
|
||||
private static ArrayList<RemoteKeyboardPlugin> instances = new ArrayList<RemoteKeyboardPlugin>();
|
||||
private static ReentrantLock instancesLock = new ReentrantLock(true);
|
||||
public static ArrayList<RemoteKeyboardPlugin> getInstances() {
|
||||
return instances;
|
||||
}
|
||||
public static ArrayList<RemoteKeyboardPlugin> acquireInstances() {
|
||||
instancesLock.lock();
|
||||
return getInstances();
|
||||
}
|
||||
public static ArrayList<RemoteKeyboardPlugin> releaseInstances() {
|
||||
instancesLock.unlock();
|
||||
return getInstances();
|
||||
}
|
||||
public static boolean isConnected() {
|
||||
return instances.size() > 0;
|
||||
}
|
||||
|
||||
private static SparseIntArray specialKeyMap = new SparseIntArray();
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_DEL); // 1
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_TAB); // 2
|
||||
++i; //specialKeyMap.put(++i, KeyEvent.KEYCODE_ENTER, 12); // 3 is not used
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_LEFT); // 4
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_UP); // 5
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_RIGHT); // 6
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_DOWN); // 7
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_PAGE_UP); // 8
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_PAGE_DOWN); // 9
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_MOVE_HOME); // 10
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_MOVE_END); // 11
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_ENTER); // 12
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_FORWARD_DEL); // 13
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_ESCAPE); // 14
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_SYSRQ); // 15
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_SCROLL_LOCK); // 16
|
||||
++i; // 17
|
||||
++i; // 18
|
||||
++i; // 19
|
||||
++i; // 20
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F1); // 21
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F2); // 22
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F3); // 23
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F4); // 24
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F5); // 25
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F6); // 26
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F7); // 27
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F8); // 28
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F9); // 29
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F10); // 30
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F11); // 31
|
||||
specialKeyMap.put(++i, KeyEvent.KEYCODE_F12); // 21
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
Log.d("RemoteKeyboardPlugin", "Creating for device " + device.getName());
|
||||
acquireInstances();
|
||||
try {
|
||||
instances.add(this);
|
||||
} finally {
|
||||
releaseInstances();
|
||||
}
|
||||
if (RemoteKeyboardService.instance != null)
|
||||
RemoteKeyboardService.instance.handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
RemoteKeyboardService.instance.updateInputView();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
acquireInstances();
|
||||
try {
|
||||
if (instances.contains(this)) {
|
||||
instances.remove(this);
|
||||
if (instances.size() < 1 && RemoteKeyboardService.instance != null)
|
||||
RemoteKeyboardService.instance.handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
RemoteKeyboardService.instance.updateInputView();
|
||||
}
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
releaseInstances();
|
||||
}
|
||||
|
||||
Log.d("RemoteKeyboardPlugin", "Destroying for device " + device.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return context.getString(R.string.pref_plugin_remotekeyboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return context.getString(R.string.pref_plugin_remotekeyboard_desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getIcon() {
|
||||
return ContextCompat.getDrawable(context, R.drawable.ic_action_keyboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSettings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMainActivity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
return new String[]{PACKAGE_TYPE_MOUSEPAD_REQUEST};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getOutgoingPackageTypes() {
|
||||
return new String[]{PACKAGE_TYPE_MOUSEPAD_ECHO, PACKAGE_TYPE_MOUSEPAD_KEYBOARDSTATE};
|
||||
}
|
||||
|
||||
private boolean isValidSpecialKey(int key) {
|
||||
return (specialKeyMap.get(key, 0) > 0);
|
||||
}
|
||||
|
||||
private int getCharPos(ExtractedText extractedText, char ch, boolean forward) {
|
||||
int pos = -1;
|
||||
if (extractedText != null) {
|
||||
if (!forward) // backward
|
||||
pos = extractedText.text.toString().lastIndexOf(" ", extractedText.selectionEnd - 2);
|
||||
else
|
||||
pos = extractedText.text.toString().indexOf(" ", extractedText.selectionEnd + 1);
|
||||
return pos;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private int currentTextLength(ExtractedText extractedText) {
|
||||
if (extractedText != null)
|
||||
return extractedText.text.length();
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int currentCursorPos(ExtractedText extractedText) {
|
||||
if (extractedText != null)
|
||||
return extractedText.selectionEnd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Pair<Integer,Integer> currentSelection(ExtractedText extractedText) {
|
||||
if (extractedText != null)
|
||||
return new Pair<>(extractedText.selectionStart, extractedText.selectionEnd);
|
||||
return new Pair<>(-1, -1);
|
||||
}
|
||||
|
||||
private boolean handleSpecialKey(int key, boolean shift, boolean ctrl, boolean alt) {
|
||||
int keyEvent = specialKeyMap.get(key, 0);
|
||||
if (keyEvent == 0)
|
||||
return false;
|
||||
InputConnection inputConn = RemoteKeyboardService.instance.getCurrentInputConnection();
|
||||
// Log.d("RemoteKeyboardPlugin", "Handling special key " + key + " translated to " + keyEvent + " shift=" + shift + " ctrl=" + ctrl + " alt=" + alt);
|
||||
|
||||
// special sequences:
|
||||
if (ctrl && (keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT)) {
|
||||
// Ctrl + right -> next word
|
||||
ExtractedText extractedText = inputConn.getExtractedText(new ExtractedTextRequest(), 0);
|
||||
int pos = getCharPos(extractedText, ' ', keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||
if (pos == -1)
|
||||
pos = currentTextLength(extractedText);
|
||||
else
|
||||
pos++;
|
||||
int startPos = pos;
|
||||
int endPos = pos;
|
||||
if (shift) { // Shift -> select word (otherwise jump)
|
||||
Pair<Integer,Integer> sel = currentSelection(extractedText);
|
||||
int cursor = currentCursorPos(extractedText);
|
||||
// Log.d("RemoteKeyboardPlugin", "Selection (to right): " + sel.first + " / " + sel.second + " cursor: " + cursor);
|
||||
startPos = cursor;
|
||||
if (sel.first < cursor || // active selection from left to right -> grow
|
||||
sel.first > sel.second) // active selection from right to left -> shrink
|
||||
startPos = sel.first;
|
||||
}
|
||||
inputConn.setSelection(startPos, endPos);
|
||||
} else if (ctrl && keyEvent == KeyEvent.KEYCODE_DPAD_LEFT) {
|
||||
// Ctrl + left -> previous word
|
||||
ExtractedText extractedText = inputConn.getExtractedText(new ExtractedTextRequest(), 0);
|
||||
int pos = getCharPos(extractedText, ' ', keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||
if (pos == -1)
|
||||
pos = 0;
|
||||
else
|
||||
pos++;
|
||||
int startPos = pos;
|
||||
int endPos = pos;
|
||||
if (shift) {
|
||||
Pair<Integer,Integer> sel = currentSelection(extractedText);
|
||||
int cursor = currentCursorPos(extractedText);
|
||||
// Log.d("RemoteKeyboardPlugin", "Selection (to left): " + sel.first + " / " + sel.second + " cursor: " + cursor);
|
||||
startPos = cursor;
|
||||
if (cursor < sel.first || // active selection from right to left -> grow
|
||||
sel.first < sel.second) // active selection from right to left -> shrink
|
||||
startPos = sel.first;
|
||||
}
|
||||
inputConn.setSelection(startPos, endPos);
|
||||
} else if (shift
|
||||
&& (keyEvent == KeyEvent.KEYCODE_DPAD_LEFT
|
||||
|| keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT
|
||||
|| keyEvent == KeyEvent.KEYCODE_DPAD_UP
|
||||
|| keyEvent == KeyEvent.KEYCODE_DPAD_DOWN
|
||||
|| keyEvent == KeyEvent.KEYCODE_MOVE_HOME
|
||||
|| keyEvent == KeyEvent.KEYCODE_MOVE_END)) {
|
||||
// Shift + up/down/left/right/home/end
|
||||
long now = SystemClock.uptimeMillis();
|
||||
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0));
|
||||
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyEvent, 0, KeyEvent.META_SHIFT_LEFT_ON));
|
||||
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyEvent, 0, KeyEvent.META_SHIFT_LEFT_ON));
|
||||
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0));
|
||||
} else if (keyEvent == KeyEvent.KEYCODE_NUMPAD_ENTER
|
||||
|| keyEvent == KeyEvent.KEYCODE_ENTER) {
|
||||
// Enter key
|
||||
EditorInfo editorInfo = RemoteKeyboardService.instance.getCurrentInputEditorInfo();
|
||||
// Log.d("RemoteKeyboardPlugin", "Enter: " + editorInfo.imeOptions);
|
||||
if (editorInfo != null
|
||||
&& (((editorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0)
|
||||
|| ctrl)) { // Ctrl+Return overrides IME_FLAG_NO_ENTER_ACTION (FIXME: make configurable?)
|
||||
// check for special DONE/GO/etc actions first:
|
||||
int[] actions = { EditorInfo.IME_ACTION_GO, EditorInfo.IME_ACTION_NEXT,
|
||||
EditorInfo.IME_ACTION_SEND, EditorInfo.IME_ACTION_SEARCH,
|
||||
EditorInfo.IME_ACTION_DONE}; // note: DONE should be last or we might hide the ime instead of "go"
|
||||
for (int i = 0; i < actions.length; i++) {
|
||||
if ((editorInfo.imeOptions & actions[i]) == actions[i]) {
|
||||
// Log.d("RemoteKeyboardPlugin", "Enter-action: " + actions[i]);
|
||||
inputConn.performEditorAction(actions[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// else: fall back to regular Enter-event:
|
||||
// Log.d("RemoteKeyboardPlugin", "Enter: normal keypress");
|
||||
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyEvent));
|
||||
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyEvent));
|
||||
}
|
||||
} else {
|
||||
// default handling:
|
||||
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyEvent));
|
||||
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyEvent));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleVisibleKey(String key, boolean shift, boolean ctrl, boolean alt) {
|
||||
// Log.d("RemoteKeyboardPlugin", "Handling visible key " + key + " shift=" + shift + " ctrl=" + ctrl + " alt=" + alt + " " + key.equalsIgnoreCase("c") + " " + key.length());
|
||||
|
||||
if (key.isEmpty())
|
||||
return false;
|
||||
|
||||
InputConnection inputConn = RemoteKeyboardService.instance.getCurrentInputConnection();
|
||||
if (inputConn == null)
|
||||
return false;
|
||||
|
||||
// ctrl+c/v/x
|
||||
if (key.equalsIgnoreCase("c") && ctrl) {
|
||||
return inputConn.performContextMenuAction(android.R.id.copy);
|
||||
} else if (key.equalsIgnoreCase("v") && ctrl)
|
||||
return inputConn.performContextMenuAction(android.R.id.paste);
|
||||
else if (key.equalsIgnoreCase("x") && ctrl)
|
||||
return inputConn.performContextMenuAction(android.R.id.cut);
|
||||
else if (key.equalsIgnoreCase("a") && ctrl)
|
||||
return inputConn.performContextMenuAction(android.R.id.selectAll);
|
||||
|
||||
// Log.d("RemoteKeyboardPlugin", "Committing visible key '" + key + "'");
|
||||
inputConn.commitText(key, key.length());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleEvent(NetworkPackage np) {
|
||||
if (np.has("specialKey") && isValidSpecialKey(np.getInt("specialKey")))
|
||||
return handleSpecialKey(np.getInt("specialKey"), np.getBoolean("shift"),
|
||||
np.getBoolean("ctrl"), np.getBoolean("alt"));
|
||||
|
||||
// try visible key
|
||||
return handleVisibleKey(np.getString("key"), np.getBoolean("shift"),
|
||||
np.getBoolean("ctrl"), np.getBoolean("alt"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPackageReceived(NetworkPackage np) {
|
||||
|
||||
if (!np.getType().equals(PACKAGE_TYPE_MOUSEPAD_REQUEST)
|
||||
|| (!np.has("key") && !np.has("specialKey"))) { // expect at least key OR specialKey
|
||||
Log.e("RemoteKeyboardPlugin", "Invalid package for remotekeyboard plugin!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RemoteKeyboardService.instance == null) {
|
||||
Log.i("RemoteKeyboardPlugin", "Remote keyboard is not the currently selected input method, dropping key");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RemoteKeyboardService.instance.visible &&
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getBoolean(context.getString(R.string.remotekeyboard_editing_only), true)) {
|
||||
Log.i("RemoteKeyboardPlugin", "Remote keyboard is currently not visible, dropping key");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!handleEvent(np)) {
|
||||
Log.i("RemoteKeyboardPlugin", "Could not handle event!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (np.getBoolean("sendAck")) {
|
||||
NetworkPackage reply = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_ECHO);
|
||||
reply.set("key", np.getString("key"));
|
||||
if (np.has("specialKey"))
|
||||
reply.set("specialKey", np.getInt("specialKey"));
|
||||
if (np.has("shift"))
|
||||
reply.set("shift", np.getBoolean("shift"));
|
||||
if (np.has("ctrl"))
|
||||
reply.set("ctrl", np.getBoolean("ctrl"));
|
||||
if (np.has("alt"))
|
||||
reply.set("alt", np.getBoolean("alt"));
|
||||
reply.set("isAck", true);
|
||||
device.sendPackage(reply);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void notifyKeyboardState(boolean state) {
|
||||
Log.d("RemoteKeyboardPlugin", "Keyboardstate changed to " + state);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_KEYBOARDSTATE);
|
||||
np.set("state", state);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
}
|
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright 2017 Holger Kaelberer <holger.k@elberer.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.inputmethodservice.Keyboard;
|
||||
import android.inputmethodservice.KeyboardView;
|
||||
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.kde.kdeconnect.UserInterface.MaterialActivity;
|
||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RemoteKeyboardService
|
||||
extends InputMethodService
|
||||
implements OnKeyboardActionListener {
|
||||
|
||||
/**
|
||||
* Reference to our instance
|
||||
* null if this InputMethod is not currently selected.
|
||||
*/
|
||||
public static RemoteKeyboardService instance = null;
|
||||
|
||||
/**
|
||||
* Whether input is currently accepted
|
||||
* Implies visible == true
|
||||
*/
|
||||
public boolean active = false;
|
||||
|
||||
/**
|
||||
* Whether this InputMethod is currently visible.
|
||||
*/
|
||||
public boolean visible = false;
|
||||
|
||||
KeyboardView inputView = null;
|
||||
private final int StatusKeyIdx = 3;
|
||||
private final int connectedIcon = R.drawable.ic_phonelink_white_36dp;
|
||||
private final int disconnectedIcon = R.drawable.ic_phonelink_off_white_36dp;
|
||||
|
||||
Handler handler;
|
||||
|
||||
void updateInputView() {
|
||||
if (inputView == null)
|
||||
return;
|
||||
Keyboard currentKeyboard = inputView.getKeyboard();
|
||||
List<Keyboard.Key> keys = currentKeyboard.getKeys();
|
||||
boolean connected = RemoteKeyboardPlugin.isConnected();
|
||||
// Log.d("RemoteKeyboardService", "Updating keyboard connection icon, connected=" + connected);
|
||||
keys.get(StatusKeyIdx).icon = getResources().getDrawable(connected ? connectedIcon : disconnectedIcon);
|
||||
inputView.invalidateKey(StatusKeyIdx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
active = false;
|
||||
visible = false;
|
||||
instance = this;
|
||||
handler = new Handler();
|
||||
Log.d("RemoteKeyboardService", "Remote keyboard initialized");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
instance = null;
|
||||
Log.d("RemoteKeyboardService", "Destroyed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeInterface() {
|
||||
super.onInitializeInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateInputView() {
|
||||
// Log.d("RemoteKeyboardService", "onCreateInputView connected=" + RemoteKeyboardPlugin.isConnected());
|
||||
inputView = new KeyboardView(this, null);
|
||||
inputView.setKeyboard(new Keyboard(this, R.xml.remotekeyboardplugin_keyboard));
|
||||
inputView.setPreviewEnabled(false);
|
||||
inputView.setOnKeyboardActionListener(this);
|
||||
updateInputView();
|
||||
return inputView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartInputView(EditorInfo attribute, boolean restarting) {
|
||||
// Log.d("RemoteKeyboardService", "onStartInputView");
|
||||
super.onStartInputView(attribute, restarting);
|
||||
visible = true;
|
||||
ArrayList<RemoteKeyboardPlugin> instances = RemoteKeyboardPlugin.acquireInstances();
|
||||
try {
|
||||
for (RemoteKeyboardPlugin i: instances)
|
||||
i.notifyKeyboardState(true);
|
||||
} finally {
|
||||
RemoteKeyboardPlugin.releaseInstances();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishInputView(boolean finishingInput) {
|
||||
// Log.d("RemoteKeyboardService", "onFinishInputView");
|
||||
super.onFinishInputView(finishingInput);
|
||||
visible = false;
|
||||
ArrayList<RemoteKeyboardPlugin> instances = RemoteKeyboardPlugin.acquireInstances();
|
||||
try {
|
||||
for (RemoteKeyboardPlugin i: instances)
|
||||
i.notifyKeyboardState(false);
|
||||
} finally {
|
||||
RemoteKeyboardPlugin.releaseInstances();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartInput(EditorInfo attribute, boolean restarting) {
|
||||
// Log.d("RemoteKeyboardService", "onStartInput");
|
||||
super.onStartInput(attribute, restarting);
|
||||
active = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishInput() {
|
||||
// Log.d("RemoteKeyboardService", "onFinishInput");
|
||||
super.onFinishInput();
|
||||
active = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPress(int primaryCode) {
|
||||
switch (primaryCode) {
|
||||
case 0: { // "hide keyboard"
|
||||
requestHideSelf(0);
|
||||
break;
|
||||
}
|
||||
case 1: { // "settings"
|
||||
ArrayList<RemoteKeyboardPlugin> instances = RemoteKeyboardPlugin.acquireInstances();
|
||||
try {
|
||||
if (instances.size() == 1) { // single instance of RemoteKeyboardPlugin -> access its settings
|
||||
RemoteKeyboardPlugin plugin = instances.get(0);
|
||||
if (plugin != null) {
|
||||
Intent intent = new Intent(this, PluginSettingsActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra("plugin_display_name", plugin.getDisplayName());
|
||||
intent.putExtra("plugin_key", plugin.getPluginKey());
|
||||
startActivity(intent);
|
||||
}
|
||||
} else { // != 1 instance of plugin -> show main activity view
|
||||
Intent intent = new Intent(this, MaterialActivity.class);
|
||||
intent.putExtra("forceOverview", true);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
if (instances.size() < 1)
|
||||
Toast.makeText(this, R.string.remotekeyboard_not_connected, Toast.LENGTH_SHORT).show();
|
||||
else // instances.size() > 1
|
||||
Toast.makeText(this, R.string.remotekeyboard_multiple_connections, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} finally {
|
||||
RemoteKeyboardPlugin.releaseInstances();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: { // "keyboard"
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showInputMethodPicker();
|
||||
break;
|
||||
}
|
||||
case 3: { // "connected"?
|
||||
if (RemoteKeyboardPlugin.isConnected())
|
||||
Toast.makeText(this, R.string.remotekeyboard_connected, Toast.LENGTH_SHORT).show();
|
||||
else
|
||||
Toast.makeText(this, R.string.remotekeyboard_not_connected, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKey(int primaryCode, int[] keyCodes) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onText(CharSequence text) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeRight() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeLeft() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeDown() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeUp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease(int primaryCode) {
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
Besides the official Android examples about implementing IMEs I learned a lot about using
|
||||
the Android APIs around InputConnection from the excellent "Remote Keyboard" app from onyxbits
|
||||
(http://www.onyxbits.de/remotekeyboard). Thanks!
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2016 Thomas Posch <kdeconnect@online.posch.name>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Plugins.RunCommandPlugin;
|
||||
|
||||
import org.kde.kdeconnect.UserInterface.List.EntryItem;
|
||||
|
||||
public class CommandEntry extends EntryItem {
|
||||
private final String key;
|
||||
|
||||
public CommandEntry(String name, String cmd, String key) {
|
||||
super(name, cmd);
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return title;
|
||||
}
|
||||
}
|
@@ -32,11 +32,12 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.UserInterface.List.EntryItem;
|
||||
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class RunCommandActivity extends ActionBarActivity {
|
||||
|
||||
@@ -59,28 +60,33 @@ public class RunCommandActivity extends ActionBarActivity {
|
||||
public void run() {
|
||||
ListView view = (ListView) findViewById(R.id.listView1);
|
||||
|
||||
final ArrayList<JSONObject> commands = plugin.getCommandList();
|
||||
|
||||
ArrayList<ListAdapter.Item> commandItems = new ArrayList<>();
|
||||
for (JSONObject obj : commands) {
|
||||
final ArrayList<ListAdapter.Item> commandItems = new ArrayList<>();
|
||||
for (JSONObject obj : plugin.getCommandList()) {
|
||||
try {
|
||||
commandItems.add(new EntryItem(obj.getString("name"), obj.getString("command")));
|
||||
commandItems.add(new CommandEntry(obj.getString("name"),
|
||||
obj.getString("command"), obj.getString("key")));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(commandItems, new Comparator<ListAdapter.Item>() {
|
||||
@Override
|
||||
public int compare(ListAdapter.Item lhs, ListAdapter.Item rhs) {
|
||||
String lName = ((CommandEntry) lhs).getName();
|
||||
String rName = ((CommandEntry) rhs).getName();
|
||||
return lName.compareTo(rName);
|
||||
}
|
||||
});
|
||||
|
||||
ListAdapter adapter = new ListAdapter(RunCommandActivity.this, commandItems);
|
||||
|
||||
view.setAdapter(adapter);
|
||||
view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
try {
|
||||
plugin.runCommand(commands.get(i).getString("key"));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
CommandEntry entry = (CommandEntry) commandItems.get(i);
|
||||
plugin.runCommand(entry.getKey());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -68,57 +68,55 @@ public class SftpPlugin extends Plugin {
|
||||
NetworkPackage np2 = new NetworkPackage(PACKAGE_TYPE_SFTP);
|
||||
|
||||
np2.set("ip", server.getLocalIpAddress());
|
||||
np2.set("port", server.port);
|
||||
np2.set("user", server.passwordAuth.getUser());
|
||||
np2.set("password", server.passwordAuth.getPassword());
|
||||
np2.set("port", server.getPort());
|
||||
np2.set("user", SimpleSftpServer.USER);
|
||||
np2.set("password", server.getPassword());
|
||||
|
||||
//Kept for compatibility, in case "multiPaths" is not possible or the other end does not support it
|
||||
np2.set("path", Environment.getExternalStorageDirectory().getAbsolutePath());
|
||||
|
||||
File root = new File("/");
|
||||
if (root.canExecute() && root.canRead()) {
|
||||
List<StorageHelper.StorageInfo> storageList = StorageHelper.getStorageList();
|
||||
ArrayList<String> paths = new ArrayList<>();
|
||||
ArrayList<String> pathNames = new ArrayList<>();
|
||||
List<StorageHelper.StorageInfo> storageList = StorageHelper.getStorageList();
|
||||
ArrayList<String> paths = new ArrayList<>();
|
||||
ArrayList<String> pathNames = new ArrayList<>();
|
||||
|
||||
for (StorageHelper.StorageInfo storage : storageList) {
|
||||
paths.add(storage.path);
|
||||
StringBuilder res = new StringBuilder();
|
||||
for (StorageHelper.StorageInfo storage : storageList) {
|
||||
paths.add(storage.path);
|
||||
StringBuilder res = new StringBuilder();
|
||||
|
||||
if (storageList.size() > 1) {
|
||||
if (!storage.removable) {
|
||||
res.append(context.getString(R.string.sftp_internal_storage));
|
||||
} else if (storage.number > 1) {
|
||||
res.append(context.getString(R.string.sftp_sdcard_num, storage.number));
|
||||
} else {
|
||||
res.append(context.getString(R.string.sftp_sdcard));
|
||||
}
|
||||
if (storageList.size() > 1) {
|
||||
if (!storage.removable) {
|
||||
res.append(context.getString(R.string.sftp_internal_storage));
|
||||
} else if (storage.number > 1) {
|
||||
res.append(context.getString(R.string.sftp_sdcard_num, storage.number));
|
||||
} else {
|
||||
res.append(context.getString(R.string.sftp_all_files));
|
||||
res.append(context.getString(R.string.sftp_sdcard));
|
||||
}
|
||||
String pathName = res.toString();
|
||||
if (storage.readonly) {
|
||||
res.append(" ");
|
||||
res.append(context.getString(R.string.sftp_readonly));
|
||||
}
|
||||
pathNames.add(res.toString());
|
||||
} else {
|
||||
res.append(context.getString(R.string.sftp_all_files));
|
||||
}
|
||||
String pathName = res.toString();
|
||||
if (storage.readonly) {
|
||||
res.append(" ");
|
||||
res.append(context.getString(R.string.sftp_readonly));
|
||||
}
|
||||
pathNames.add(res.toString());
|
||||
|
||||
//Shortcut for users that only want to browse camera pictures
|
||||
String dcim = storage.path + "/DCIM/Camera";
|
||||
if (new File(dcim).exists()) {
|
||||
paths.add(dcim);
|
||||
if (storageList.size() > 1) {
|
||||
pathNames.add(context.getString(R.string.sftp_camera) + "(" + pathName + ")");
|
||||
} else {
|
||||
pathNames.add(context.getString(R.string.sftp_camera));
|
||||
}
|
||||
//Shortcut for users that only want to browse camera pictures
|
||||
String dcim = storage.path + "/DCIM/Camera";
|
||||
if (new File(dcim).exists()) {
|
||||
paths.add(dcim);
|
||||
if (storageList.size() > 1) {
|
||||
pathNames.add(context.getString(R.string.sftp_camera) + "(" + pathName + ")");
|
||||
} else {
|
||||
pathNames.add(context.getString(R.string.sftp_camera));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paths.size() > 0) {
|
||||
np2.set("multiPaths", paths);
|
||||
np2.set("pathNames", pathNames);
|
||||
|
||||
if (paths.size() > 0) {
|
||||
np2.set("multiPaths", paths);
|
||||
np2.set("pathNames", pathNames);
|
||||
}
|
||||
}
|
||||
|
||||
device.sendPackage(np2);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
package org.kde.kdeconnect.Plugins.SftpPlugin;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.sshd.SshServer;
|
||||
@@ -42,33 +43,33 @@ import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||
import org.apache.sshd.server.session.ServerSession;
|
||||
import org.apache.sshd.server.sftp.SftpSubsystem;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.MediaStoreHelper;
|
||||
import org.kde.kdeconnect.Helpers.RandomHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Security;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
class SimpleSftpServer {
|
||||
private static final int STARTPORT = 1739;
|
||||
private static final int ENDPORT = 1764;
|
||||
|
||||
private static final String USER = "kdeconnect";
|
||||
static final String USER = "kdeconnect";
|
||||
|
||||
public static int port = -1;
|
||||
private static boolean started = false;
|
||||
private int port = -1;
|
||||
private boolean started = false;
|
||||
|
||||
public final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
|
||||
public final SimplePublicKeyAuthenticator keyAuth = new SimplePublicKeyAuthenticator();
|
||||
private final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
|
||||
private final SimplePublicKeyAuthenticator keyAuth = new SimplePublicKeyAuthenticator();
|
||||
|
||||
static {
|
||||
Security.insertProviderAt(SslHelper.BC, 1);
|
||||
@@ -76,20 +77,20 @@ class SimpleSftpServer {
|
||||
}
|
||||
private final SshServer sshd = SshServer.setUpDefaultServer();
|
||||
|
||||
public void init(Context ctx, Device device) {
|
||||
public void init(Context context, Device device) {
|
||||
|
||||
sshd.setKeyExchangeFactories(Arrays.asList(
|
||||
new DHG14.Factory(),
|
||||
new DHG1.Factory()));
|
||||
|
||||
passwordAuth.setUser(USER);
|
||||
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(ctx.getFilesDir() + "/sftpd.ser"));
|
||||
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(context.getFilesDir() + "/sftpd.ser"));
|
||||
|
||||
sshd.setFileSystemFactory(new SecureFileSystemFactory());
|
||||
sshd.setFileSystemFactory(new AndroidFileSystemFactory(context));
|
||||
sshd.setCommandFactory(new ScpCommandFactory());
|
||||
sshd.setSubsystemFactories(Collections.singletonList((NamedFactory<Command>)new SftpSubsystem.Factory()));
|
||||
|
||||
if (device.publicKey != null) {
|
||||
keyAuth.addKey(device.publicKey);
|
||||
keyAuth.deviceKey = device.publicKey;
|
||||
sshd.setPublickeyAuthenticator(keyAuth);
|
||||
}
|
||||
sshd.setPasswordAuthenticator(passwordAuth);
|
||||
@@ -98,8 +99,7 @@ class SimpleSftpServer {
|
||||
public boolean start() {
|
||||
if (!started) {
|
||||
|
||||
String password = RandomHelper.randomString(28);
|
||||
passwordAuth.setPassword(password);
|
||||
passwordAuth.password = RandomHelper.randomString(28);
|
||||
|
||||
port = STARTPORT;
|
||||
while(!started) {
|
||||
@@ -131,11 +131,30 @@ class SimpleSftpServer {
|
||||
}
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return passwordAuth.password;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getLocalIpAddress() {
|
||||
String ip6 = null;
|
||||
try {
|
||||
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
|
||||
NetworkInterface intf = en.nextElement();
|
||||
|
||||
// Anything with rmnet is related to cellular connections or USB
|
||||
// tethering mechanisms. See:
|
||||
//
|
||||
// https://android.googlesource.com/kernel/msm/+/android-msm-flo-3.4-kitkat-mr1/Documentation/usb/gadget_rmnet.txt
|
||||
//
|
||||
// If we run across an interface that has this, we can safely
|
||||
// ignore it. In fact, it's much safer to do. If we don't, we
|
||||
// might get invalid IP adddresses out of it.
|
||||
if(intf.getDisplayName().contains("rmnet")) continue;
|
||||
|
||||
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
|
||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||
if (!inetAddress.isLoopbackAddress()) {
|
||||
@@ -153,92 +172,89 @@ class SimpleSftpServer {
|
||||
return ip6;
|
||||
}
|
||||
|
||||
static class SecureFileSystemFactory implements FileSystemFactory {
|
||||
static class AndroidFileSystemFactory implements FileSystemFactory {
|
||||
|
||||
public SecureFileSystemFactory() {}
|
||||
final private Context context;
|
||||
|
||||
public AndroidFileSystemFactory(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileSystemView createFileSystemView(final Session username) {
|
||||
final String base = "/";
|
||||
return new SecureFileSystemView(base, username.getUsername());
|
||||
return new AndroidFileSystemView(username.getUsername(), context);
|
||||
}
|
||||
}
|
||||
|
||||
static class SecureFileSystemView extends NativeFileSystemView {
|
||||
// the first and the last character will always be '/'
|
||||
// It is always with respect to the root directory.
|
||||
private String currDir = "/";
|
||||
private String rootDir = "/";
|
||||
private String userName;
|
||||
//
|
||||
public SecureFileSystemView(final String rootDir, final String userName) {
|
||||
super(userName);
|
||||
this.rootDir = NativeSshFile.normalizeSeparateChar(rootDir);
|
||||
static class AndroidFileSystemView extends NativeFileSystemView {
|
||||
|
||||
final private String userName;
|
||||
final private Context context;
|
||||
|
||||
public AndroidFileSystemView(final String userName, Context context) {
|
||||
super(userName, true);
|
||||
this.userName = userName;
|
||||
}
|
||||
//
|
||||
@Override
|
||||
public SshFile getFile(final String file) {
|
||||
return getFile(currDir, file);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SshFile getFile(final SshFile baseDir, final String file) {
|
||||
return getFile(baseDir.getAbsolutePath(), file);
|
||||
}
|
||||
|
||||
//
|
||||
protected SshFile getFile(final String dir, final String file) {
|
||||
// get actual file object
|
||||
final boolean caseInsensitive = false;
|
||||
String physicalName = NativeSshFile.getPhysicalName("/", dir, file, caseInsensitive);
|
||||
File fileObj = new File(rootDir, physicalName); // chroot
|
||||
|
||||
// strip the root directory and return
|
||||
String userFileName = physicalName.substring("/".length() - 1);
|
||||
return new SecureSshFile(userFileName, fileObj, userName);
|
||||
File fileObj = new File(dir, file);
|
||||
return new AndroidSshFile(fileObj, userName, context);
|
||||
}
|
||||
}
|
||||
|
||||
static class SecureSshFile extends NativeSshFile {
|
||||
public SecureSshFile(final String fileName, final File file, final String userName) {
|
||||
super(fileName, file, userName);
|
||||
static class AndroidSshFile extends NativeSshFile {
|
||||
|
||||
final private Context context;
|
||||
final private File file;
|
||||
|
||||
public AndroidSshFile(final File file, final String userName, Context context) {
|
||||
super(file.getAbsolutePath(), file, userName);
|
||||
this.context = context;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
//Log.e("Sshd", "deleting file");
|
||||
boolean ret = super.delete();
|
||||
if (ret) {
|
||||
MediaStoreHelper.indexFile(context, Uri.fromFile(file));
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create() throws IOException {
|
||||
//Log.e("Sshd", "creating file");
|
||||
boolean ret = super.create();
|
||||
if (ret) {
|
||||
MediaStoreHelper.indexFile(context, Uri.fromFile(file));
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static class SimplePasswordAuthenticator implements PasswordAuthenticator {
|
||||
|
||||
public void setUser(String user) {this.user = user;}
|
||||
public String getUser() {return this.user;}
|
||||
|
||||
public void setPassword(String password) {this.password = password;}
|
||||
public String getPassword() {return this.password;}
|
||||
public String password;
|
||||
|
||||
@Override
|
||||
public boolean authenticate(String user, String password, ServerSession session) {
|
||||
return user.equals(this.user) && password.equals(this.password);
|
||||
return user.equals(SimpleSftpServer.USER) && password.equals(this.password);
|
||||
}
|
||||
|
||||
private String user;
|
||||
private String password;
|
||||
}
|
||||
|
||||
static class SimplePublicKeyAuthenticator implements PublickeyAuthenticator {
|
||||
|
||||
private final List<PublicKey> keys = new ArrayList<>();
|
||||
|
||||
public void addKey(PublicKey key) {
|
||||
keys.add(key);
|
||||
}
|
||||
public PublicKey deviceKey;
|
||||
|
||||
@Override
|
||||
public boolean authenticate(String user, PublicKey key, ServerSession session) {
|
||||
for (PublicKey k : keys) {
|
||||
if (key.equals(k)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return deviceKey.equals(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,122 @@
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
class NotificationUpdateCallback extends Device.SendPackageStatusCallback {
|
||||
|
||||
final Context context;
|
||||
final Resources res;
|
||||
final Device device;
|
||||
final NotificationManager notificationManager;
|
||||
final NotificationCompat.Builder builder;
|
||||
|
||||
final ArrayList<NetworkPackage> toSend;
|
||||
|
||||
final int notificationId;
|
||||
|
||||
int sentFiles = 0;
|
||||
final int numFiles;
|
||||
|
||||
NotificationUpdateCallback(Context context, Device device, ArrayList<NetworkPackage> toSend) {
|
||||
this.context = context;
|
||||
this.toSend = toSend;
|
||||
this.device = device;
|
||||
this.res = context.getResources();
|
||||
|
||||
String title;
|
||||
if (toSend.size() > 1) {
|
||||
title = res.getString(R.string.outgoing_files_title, device.getName());
|
||||
} else {
|
||||
title = res.getString(R.string.outgoing_file_title, device.getName());
|
||||
}
|
||||
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
builder = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_upload)
|
||||
.setAutoCancel(true)
|
||||
.setProgress(100, 0, false)
|
||||
.setContentTitle(title)
|
||||
.setTicker(title);
|
||||
|
||||
notificationId = (int)System.currentTimeMillis();
|
||||
|
||||
numFiles = toSend.size();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(int progress) {
|
||||
builder.setProgress(100 * numFiles, (100 * sentFiles) + progress, false);
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
sentFiles++;
|
||||
if (sentFiles == numFiles) {
|
||||
updateDone(true);
|
||||
} else {
|
||||
updateText();
|
||||
}
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
updateDone(false);
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
}
|
||||
|
||||
private void updateText() {
|
||||
String text;
|
||||
if (numFiles > 1) {
|
||||
text = res.getString(R.string.outgoing_files_text, sentFiles, numFiles);
|
||||
} else {
|
||||
text = res.getString(R.string.outgoing_file_text, device.getName());
|
||||
}
|
||||
builder.setContentText(text);
|
||||
}
|
||||
|
||||
private void updateDone(boolean successful) {
|
||||
int icon;
|
||||
String title;
|
||||
String text;
|
||||
int progress;
|
||||
if (successful) {
|
||||
progress = 1;
|
||||
if (numFiles > 1) {
|
||||
text = res.getString(R.string.outgoing_files_text, sentFiles, numFiles);
|
||||
} else {
|
||||
final String filename = toSend.get(0).getString("filename");
|
||||
text = res.getString(R.string.sent_file_text, filename);
|
||||
}
|
||||
title = res.getString(R.string.sent_file_title, device.getName());
|
||||
icon = android.R.drawable.stat_sys_upload_done;
|
||||
} else {
|
||||
progress = 0;
|
||||
final String filename = toSend.get(sentFiles).getString("filename");
|
||||
title = res.getString(R.string.sent_file_failed_title, device.getName());
|
||||
text = res.getString(R.string.sent_file_failed_text, filename);
|
||||
icon = android.R.drawable.stat_notify_error;
|
||||
}
|
||||
|
||||
builder.setOngoing(false)
|
||||
.setTicker(title)
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
.setSmallIcon(icon)
|
||||
.setProgress(progress, progress, false); //setting progress to 0 out of 0 remove the progress bar
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,8 +21,10 @@
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.util.Log;
|
||||
@@ -47,6 +49,9 @@ public class SendFileActivity extends ActionBarActivity {
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("*/*");
|
||||
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)) {
|
||||
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||
}
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
try {
|
||||
startActivityForResult(
|
||||
@@ -62,23 +67,39 @@ public class SendFileActivity extends ActionBarActivity {
|
||||
switch (requestCode) {
|
||||
case Activity.RESULT_FIRST_USER:
|
||||
if (resultCode == RESULT_OK) {
|
||||
final Uri uri = data.getData();
|
||||
Log.e("SendFileActivity", "File Uri: " + uri.toString());
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(mDeviceId);
|
||||
if (device == null) {
|
||||
Log.e("SendFileActivity", "Device is null");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
ArrayList<Uri> uris = new ArrayList<>();
|
||||
uris.add(uri);
|
||||
SharePlugin.queuedSendUriList(getApplicationContext(), device, uris);
|
||||
|
||||
final ArrayList<Uri> uris = new ArrayList<>();
|
||||
|
||||
Uri uri = data.getData();
|
||||
if (uri != null) {
|
||||
uris.add(uri);
|
||||
}
|
||||
|
||||
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)) {
|
||||
ClipData clipdata = data.getClipData();
|
||||
if (clipdata != null) {
|
||||
for (int i = 0; i < clipdata.getItemCount(); i++) {
|
||||
uris.add(clipdata.getItemAt(i).getUri());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (uris.isEmpty()) {
|
||||
Log.w("SendFileActivity", "No files to send?");
|
||||
} else {
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(mDeviceId);
|
||||
if (device == null) {
|
||||
Log.e("SendFileActivity", "Device is null");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
SharePlugin.queuedSendUriList(getApplicationContext(), device, uris);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
finish();
|
||||
break;
|
||||
|
@@ -198,6 +198,7 @@ public class ShareActivity extends ActionBarActivity {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
|
||||
|
||||
setContentView(R.layout.activity_list);
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.DownloadManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
@@ -33,25 +34,26 @@ import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.provider.DocumentFile;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.FilesHelper;
|
||||
import org.kde.kdeconnect.Helpers.MediaStoreHelper;
|
||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.UserInterface.SettingsActivity;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
@@ -110,23 +112,25 @@ public class SharePlugin extends Plugin {
|
||||
|
||||
final InputStream input = np.getPayload();
|
||||
final long fileLength = np.getPayloadSize();
|
||||
final String filename = np.getString("filename", Long.toString(System.currentTimeMillis()));
|
||||
final String originalFilename = np.getString("filename", Long.toString(System.currentTimeMillis()));
|
||||
|
||||
String deviceDir = FilesHelper.toFileSystemSafeName(device.getName());
|
||||
//Get the external storage and append "/kdeconnect/DEVICE_NAME/"
|
||||
String destinationDir = Environment.getExternalStorageDirectory().getPath();
|
||||
destinationDir = new File(destinationDir, "kdeconnect").getPath();
|
||||
destinationDir = new File(destinationDir, deviceDir).getPath();
|
||||
//We need to check for already existing files only when storing in the default path.
|
||||
//User-defined paths use the new Storage Access Framework that already handles this.
|
||||
final boolean customDestination = ShareSettingsActivity.isCustomDestinationEnabled(context);
|
||||
final String defaultPath = ShareSettingsActivity.getDefaultDestinationDirectory().getAbsolutePath();
|
||||
final String filename = customDestination? originalFilename : FilesHelper.findNonExistingNameForNewFile(defaultPath, originalFilename);
|
||||
|
||||
//Create directories if needed
|
||||
new File(destinationDir).mkdirs();
|
||||
String displayName = FilesHelper.getFileNameWithoutExt(filename);
|
||||
final String mimeType = FilesHelper.getMimeTypeFromFile(filename);
|
||||
|
||||
//Append filename to the destination path
|
||||
final File destinationFullPath = new File(destinationDir, filename);
|
||||
if ("*/*".equals(mimeType)) {
|
||||
displayName = filename;
|
||||
}
|
||||
|
||||
//Log.e("SharePlugin", "destinationFullPath:" + destinationFullPath);
|
||||
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
final DocumentFile destinationFolderDocument = ShareSettingsActivity.getDestinationDirectory(context);
|
||||
final DocumentFile destinationDocument = destinationFolderDocument.createFile(mimeType, displayName);
|
||||
final OutputStream destinationOutput = context.getContentResolver().openOutputStream(destinationDocument.getUri());
|
||||
final Uri destinationUri = destinationDocument.getUri();
|
||||
|
||||
final int notificationId = (int)System.currentTimeMillis();
|
||||
Resources res = context.getResources();
|
||||
@@ -139,103 +143,84 @@ public class SharePlugin extends Plugin {
|
||||
.setOngoing(true)
|
||||
.setProgress(100,0,true);
|
||||
|
||||
try {
|
||||
notificationManager.notify(notificationId,builder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationHelper.notifyCompat(notificationManager,notificationId, builder.build());
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
OutputStream output = null;
|
||||
boolean successul = true;
|
||||
boolean successful = true;
|
||||
try {
|
||||
output = new FileOutputStream(destinationFullPath.getPath());
|
||||
byte data[] = new byte[1024];
|
||||
long progress = 0, prevProgressPercentage = 0;
|
||||
int count;
|
||||
while ((count = input.read(data)) >= 0) {
|
||||
progress += count;
|
||||
output.write(data, 0, count);
|
||||
destinationOutput.write(data, 0, count);
|
||||
if (fileLength > 0) {
|
||||
if (progress >= fileLength) break;
|
||||
long progressPercentage = (progress * 100 / fileLength);
|
||||
if (progressPercentage != prevProgressPercentage) {
|
||||
prevProgressPercentage = progressPercentage;
|
||||
builder.setProgress(100, (int) progressPercentage, false);
|
||||
try {
|
||||
notificationManager.notify(notificationId,builder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
}
|
||||
}
|
||||
//else Log.e("SharePlugin", "Infinite loop? :D");
|
||||
}
|
||||
|
||||
output.flush();
|
||||
destinationOutput.flush();
|
||||
|
||||
} catch (Exception e) {
|
||||
successul = false;
|
||||
successful = false;
|
||||
Log.e("SharePlugin", "Receiver thread exception");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try { output.close(); } catch (Exception e) {}
|
||||
try { destinationOutput.close(); } catch (Exception e) {}
|
||||
try { input.close(); } catch (Exception e) {}
|
||||
}
|
||||
|
||||
try {
|
||||
Log.i("SharePlugin", "Transfer finished");
|
||||
|
||||
//Make sure it is added to the Android Gallery
|
||||
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
||||
mediaScanIntent.setData(Uri.fromFile(destinationFullPath));
|
||||
context.sendBroadcast(mediaScanIntent);
|
||||
Log.i("SharePlugin", "Transfer finished: "+destinationUri.getPath());
|
||||
|
||||
//Update the notification and allow to open the file from it
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.fromFile(destinationFullPath), FilesHelper.getMimeTypeFromFile(destinationFullPath.getPath()));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
|
||||
stackBuilder.addNextIntent(intent);
|
||||
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
|
||||
Resources res = context.getResources();
|
||||
|
||||
String message = successul? res.getString(R.string.received_file_title, device.getName()) : res.getString(R.string.received_file_fail_title, device.getName());
|
||||
String message = successful? res.getString(R.string.received_file_title, device.getName()) : res.getString(R.string.received_file_fail_title, device.getName());
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(message)
|
||||
.setTicker(message)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||
.setAutoCancel(true);
|
||||
|
||||
if (successul) {
|
||||
builder.setContentText(res.getString(R.string.received_file_text, filename))
|
||||
if (successful) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(destinationUri, mimeType);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
|
||||
stackBuilder.addNextIntent(intent);
|
||||
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentText(res.getString(R.string.received_file_text, destinationDocument.getName()))
|
||||
.setContentIntent(resultPendingIntent);
|
||||
}
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (prefs.getBoolean("share_notification_preference", true)) {
|
||||
builder.setDefaults(Notification.DEFAULT_ALL);
|
||||
}
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
|
||||
try {
|
||||
notificationManager.notify(notificationId,builder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
if (successful) {
|
||||
if (!customDestination && Build.VERSION.SDK_INT >= 12) {
|
||||
Log.i("SharePlugin","Adding to downloads");
|
||||
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.addCompletedDownload(destinationUri.getLastPathSegment(), device.getName(), true, mimeType, destinationUri.getPath(), fileLength, false);
|
||||
} else {
|
||||
//Make sure it is added to the Android Gallery anyway
|
||||
MediaStoreHelper.indexFile(context, destinationUri);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("SharePlugin", "Receiver thread exception");
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
@@ -244,7 +229,7 @@ public class SharePlugin extends Plugin {
|
||||
Log.i("SharePlugin", "hasText");
|
||||
|
||||
String text = np.getString("text");
|
||||
if(android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
if(Build.VERSION.SDK_INT >= 11) {
|
||||
ClipboardManager cm = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setText(text);
|
||||
} else {
|
||||
@@ -283,12 +268,7 @@ public class SharePlugin extends Plugin {
|
||||
.build();
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
try {
|
||||
notificationManager.notify((int) System.currentTimeMillis(), noti);
|
||||
} catch (Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
NotificationHelper.notifyCompat(notificationManager, (int) System.currentTimeMillis(), noti);
|
||||
}
|
||||
} else {
|
||||
Log.e("SharePlugin", "Error: Nothing attached!");
|
||||
@@ -303,37 +283,57 @@ public class SharePlugin extends Plugin {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPreferencesActivity(SettingsActivity parentActivity) {
|
||||
Intent intent = new Intent(parentActivity, ShareSettingsActivity.class);
|
||||
intent.putExtra("plugin_display_name", getDisplayName());
|
||||
intent.putExtra("plugin_key", getPluginKey());
|
||||
parentActivity.startActivity(intent);
|
||||
}
|
||||
|
||||
static void queuedSendUriList(Context context, final Device device, final ArrayList<Uri> uriList) {
|
||||
|
||||
//Read all the data early, as we only have permissions to do it while the activity is alive
|
||||
final ArrayList<NetworkPackage> toSend = new ArrayList<>();
|
||||
for (Uri uri : uriList) {
|
||||
toSend.add(uriToNetworkPackage(context, uri));
|
||||
}
|
||||
|
||||
//Callback that shows a progress notification
|
||||
final NotificationUpdateCallback notificationUpdateCallback = new NotificationUpdateCallback(context, device, toSend);
|
||||
|
||||
//Do the sending in background
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//Actually send the files
|
||||
try {
|
||||
for (NetworkPackage np : toSend) {
|
||||
boolean success = device.sendPackageBlocking(np, notificationUpdateCallback);
|
||||
if (!success) {
|
||||
Log.e("SharePlugin","Error sending files");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
|
||||
//Create the network package from the URI
|
||||
private static NetworkPackage uriToNetworkPackage(final Context context, final Uri uri) {
|
||||
|
||||
static void queuedSendUriList(final Context context, final Device device, final ArrayList<Uri> uriList) {
|
||||
try {
|
||||
Uri uri = uriList.remove(0);
|
||||
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
InputStream inputStream = cr.openInputStream(uri);
|
||||
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_SHARE_REQUEST);
|
||||
long size = -1;
|
||||
|
||||
final NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
final int notificationId = (int)System.currentTimeMillis();
|
||||
final NotificationCompat.Builder builder ;
|
||||
Resources res = context.getResources();
|
||||
builder = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(res.getString(R.string.outgoing_file_title, device.getName()))
|
||||
.setTicker(res.getString(R.string.outgoing_file_title, device.getName()))
|
||||
.setSmallIcon(android.R.drawable.stat_sys_upload)
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(true)
|
||||
.setProgress(100,0,true);
|
||||
|
||||
try {
|
||||
notificationManager.notify(notificationId,builder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
|
||||
final Handler progressBarHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
if (uri.getScheme().equals("file")) {
|
||||
// file:// is a non media uri, so we cannot query the ContentProvider
|
||||
|
||||
@@ -360,7 +360,7 @@ public class SharePlugin extends Plugin {
|
||||
size = new File(path).length();
|
||||
} catch(Exception unused) {
|
||||
|
||||
Log.e("SendFileActivity", "Could not resolve media to a file, trying to get info as media");
|
||||
Log.w("SendFileActivity", "Could not resolve media to a file, trying to get info as media");
|
||||
|
||||
try {
|
||||
int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME);
|
||||
@@ -389,108 +389,15 @@ public class SharePlugin extends Plugin {
|
||||
|
||||
np.setPayload(inputStream, size);
|
||||
|
||||
final String filename = np.getString("filename");
|
||||
|
||||
builder.setContentText(res.getString(R.string.outgoing_file_text,filename));
|
||||
try {
|
||||
notificationManager.notify(notificationId,builder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
|
||||
device.sendPackage(np, new Device.SendPackageStatusCallback() {
|
||||
|
||||
int prevProgress = 0;
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(final int progress) {
|
||||
if (progress != prevProgress) {
|
||||
prevProgress = progress;
|
||||
progressBarHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
builder.setProgress(100, progress, false);
|
||||
try {
|
||||
notificationManager.notify(notificationId,builder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
progressBarHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Resources res = context.getResources();
|
||||
NotificationCompat.Builder anotherBuilder = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(res.getString(R.string.sent_file_title, device.getName()))
|
||||
.setContentText(res.getString(R.string.sent_file_text, filename))
|
||||
.setTicker(res.getString(R.string.sent_file_title, device.getName()))
|
||||
.setSmallIcon(android.R.drawable.stat_sys_upload_done)
|
||||
.setOngoing(false)
|
||||
.setAutoCancel(true);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (prefs.getBoolean("share_notification_preference", true)) {
|
||||
anotherBuilder.setDefaults(Notification.DEFAULT_ALL);
|
||||
}
|
||||
try {
|
||||
notificationManager.notify(notificationId,anotherBuilder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!uriList.isEmpty()) queuedSendUriList(context, device, uriList);
|
||||
else Log.i("SendFileActivity", "All files sent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
progressBarHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Resources res = context.getResources();
|
||||
NotificationCompat.Builder anotherBuilder = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(res.getString(R.string.sent_file_failed_title, device.getName()))
|
||||
.setContentText(res.getString(R.string.sent_file_failed_text, filename))
|
||||
.setTicker(res.getString(R.string.sent_file_title, device.getName()))
|
||||
.setSmallIcon(android.R.drawable.stat_notify_error)
|
||||
.setOngoing(false)
|
||||
.setAutoCancel(true);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (prefs.getBoolean("share_notification_preference", true)) {
|
||||
anotherBuilder.setDefaults(Notification.DEFAULT_ALL);
|
||||
}
|
||||
try {
|
||||
notificationManager.notify(notificationId,anotherBuilder.build());
|
||||
} catch(Exception e) {
|
||||
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
|
||||
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Log.e("SendFileActivity", "Failed to send file");
|
||||
}
|
||||
});
|
||||
|
||||
return np;
|
||||
} catch (Exception e) {
|
||||
Log.e("SendFileActivity", "Exception sending files");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
return new String[]{PACKAGE_TYPE_SHARE_REQUEST};
|
||||
|
@@ -0,0 +1,120 @@
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.provider.DocumentFile;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ShareSettingsActivity extends PluginSettingsActivity {
|
||||
|
||||
private final static String PREFERENCE_CUSTOMIZE_DESTINATION = "share_destination_custom";
|
||||
private final static String PREFERENCE_DESTINATION = "share_destination_folder_uri";
|
||||
|
||||
private static final int RESULT_PICKER = Activity.RESULT_FIRST_USER;
|
||||
|
||||
private Preference filePicker;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final CheckBoxPreference customDownloads = (CheckBoxPreference) findPreference("share_destination_custom");
|
||||
filePicker = findPreference("share_destination_folder_preference");
|
||||
|
||||
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
|
||||
customDownloads.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
updateFilePickerStatus((Boolean) newValue);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
filePicker.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
startActivityForResult(intent, RESULT_PICKER);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
customDownloads.setEnabled(false);
|
||||
filePicker.setEnabled(false);
|
||||
}
|
||||
|
||||
boolean customized = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(PREFERENCE_CUSTOMIZE_DESTINATION, false);
|
||||
updateFilePickerStatus(customized);
|
||||
}
|
||||
|
||||
void updateFilePickerStatus(boolean enabled) {
|
||||
filePicker.setEnabled(enabled);
|
||||
String path = PreferenceManager.getDefaultSharedPreferences(this).getString(PREFERENCE_DESTINATION, null);
|
||||
if (enabled && path != null) {
|
||||
filePicker.setSummary(Uri.parse(path).getPath());
|
||||
} else {
|
||||
filePicker.setSummary(getDefaultDestinationDirectory().getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public static File getDefaultDestinationDirectory() {
|
||||
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
}
|
||||
|
||||
public static boolean isCustomDestinationEnabled(Context context) {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREFERENCE_CUSTOMIZE_DESTINATION, false);
|
||||
}
|
||||
|
||||
//Will return the appropriate directory, whether it is customized or not
|
||||
public static DocumentFile getDestinationDirectory(Context context) {
|
||||
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREFERENCE_CUSTOMIZE_DESTINATION, false)) {
|
||||
String path = PreferenceManager.getDefaultSharedPreferences(context).getString(PREFERENCE_DESTINATION, null);
|
||||
if (path != null) {
|
||||
//There should be no way to enter here on api level < kitkat
|
||||
DocumentFile treeDocumentFile = DocumentFile.fromTreeUri(context, Uri.parse(path));
|
||||
if (treeDocumentFile.canWrite()) { //Checks for FLAG_DIR_SUPPORTS_CREATE on directories
|
||||
return treeDocumentFile;
|
||||
} else {
|
||||
//Maybe permission was revoked
|
||||
Log.w("SharePlugin", "Share destination is not writable, falling back to default path.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return DocumentFile.fromFile(getDefaultDestinationDirectory());
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
||||
|
||||
if (requestCode == RESULT_PICKER
|
||||
&& resultCode == Activity.RESULT_OK
|
||||
&& resultData != null) {
|
||||
|
||||
Uri uri = resultData.getData();
|
||||
|
||||
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION |
|
||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
|
||||
Preference filePicker = findPreference("share_destination_folder_preference");
|
||||
filePicker.setSummary(uri.getPath());
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
prefs.edit().putString(PREFERENCE_DESTINATION, uri.toString()).apply();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -23,6 +23,8 @@ package org.kde.kdeconnect.Plugins.TelepathyPlugin;
|
||||
import android.telephony.SmsManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin;
|
||||
@@ -64,7 +66,13 @@ public class TelepathyPlugin extends Plugin {
|
||||
String sms = np.getString("messageBody");
|
||||
try {
|
||||
SmsManager smsManager = SmsManager.getDefault();
|
||||
smsManager.sendTextMessage(phoneNo, null, sms, null, null);
|
||||
|
||||
ArrayList<String> parts = smsManager.divideMessage(sms);
|
||||
|
||||
// If this message turns out to fit in a single SMS, sendMultpartTextMessage
|
||||
// properly handles that case
|
||||
smsManager.sendMultipartTextMessage(phoneNo, null, parts, null, null);
|
||||
|
||||
//TODO: Notify other end
|
||||
} catch (Exception e) {
|
||||
//TODO: Notify other end
|
||||
|
@@ -34,8 +34,10 @@ import android.util.Log;
|
||||
import org.kde.kdeconnect.Helpers.ContactsHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect_tp.BuildConfig;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
@@ -72,11 +74,19 @@ public class TelephonyPlugin extends Plugin {
|
||||
final Bundle bundle = intent.getExtras();
|
||||
if (bundle == null) return;
|
||||
final Object[] pdus = (Object[]) bundle.get("pdus");
|
||||
ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
|
||||
|
||||
for (Object pdu : pdus) {
|
||||
SmsMessage message = SmsMessage.createFromPdu((byte[])pdu);
|
||||
smsBroadcastReceived(message);
|
||||
// I hope, but am not sure, that the pdus array is in the order that the parts
|
||||
// of the SMS message should be
|
||||
// If it is not, I belive the pdu contains the information necessary to put it
|
||||
// in order, but in my testing the order seems to be correct, so I won't worry
|
||||
// about it now.
|
||||
messages.add(SmsMessage.createFromPdu((byte[])pdu));
|
||||
}
|
||||
|
||||
smsBroadcastReceived(messages);
|
||||
|
||||
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
|
||||
|
||||
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
|
||||
@@ -194,7 +204,14 @@ public class TelephonyPlugin extends Plugin {
|
||||
lastState = state;
|
||||
}
|
||||
|
||||
private void smsBroadcastReceived(SmsMessage message) {
|
||||
private void smsBroadcastReceived(ArrayList<SmsMessage> messages) {
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (!(messages.size() > 0))
|
||||
{
|
||||
throw new AssertionError("This method requires at least one message");
|
||||
}
|
||||
}
|
||||
|
||||
//Log.e("SmsBroadcastReceived", message.toString());
|
||||
|
||||
@@ -202,12 +219,18 @@ public class TelephonyPlugin extends Plugin {
|
||||
|
||||
np.set("event","sms");
|
||||
|
||||
String messageBody = message.getMessageBody();
|
||||
String messageBody = new String();
|
||||
|
||||
for (int index = 0; index < messages.size(); index ++)
|
||||
{
|
||||
messageBody += messages.get(index).getMessageBody();
|
||||
}
|
||||
|
||||
if (messageBody != null) {
|
||||
np.set("messageBody",messageBody);
|
||||
}
|
||||
|
||||
String phoneNumber = message.getOriginatingAddress();
|
||||
String phoneNumber = messages.get(0).getOriginatingAddress();
|
||||
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
|
||||
if (phoneNumber != null) {
|
||||
np.set("phoneNumber", phoneNumber);
|
||||
|
@@ -23,10 +23,10 @@ package org.kde.kdeconnect.UserInterface;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
@@ -82,10 +82,15 @@ public class CustomDevicesActivity extends ActionBarActivity {
|
||||
});
|
||||
}
|
||||
|
||||
boolean dialogAlreadyShown = false;
|
||||
private AdapterView.OnItemClickListener onClickListener = new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, final int position, final long id) {
|
||||
Log.i(LOG_ID, "Item clicked pos: " + position + " id: " + id);
|
||||
|
||||
if (dialogAlreadyShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove touched item after confirmation
|
||||
DialogInterface.OnClickListener confirmationListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
@@ -93,7 +98,6 @@ public class CustomDevicesActivity extends ActionBarActivity {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
ipAddressList.remove(position);
|
||||
Log.i(LOG_ID, "Removed item pos: " + position + " id: " + id);
|
||||
saveList();
|
||||
break;
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
@@ -101,12 +105,23 @@ public class CustomDevicesActivity extends ActionBarActivity {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(CustomDevicesActivity.this);
|
||||
builder.setMessage("Delete " + ipAddressList.get(position) + " ?");
|
||||
builder.setPositiveButton("Yes", confirmationListener);
|
||||
builder.setNegativeButton("No", confirmationListener);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { //DismissListener
|
||||
dialogAlreadyShown = true;
|
||||
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
dialogAlreadyShown = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
builder.show();
|
||||
((ArrayAdapter) list.getAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -143,37 +158,32 @@ public class CustomDevicesActivity extends ActionBarActivity {
|
||||
|
||||
}
|
||||
|
||||
public static String serializeIpList(ArrayList<String> iplist) {
|
||||
public static String serializeIpList(ArrayList<String> ipList) {
|
||||
String serialized = "";
|
||||
for (String ipaddr : iplist) {
|
||||
serialized += IP_DELIM+ipaddr;
|
||||
for (String ipAddress : ipList) {
|
||||
serialized += IP_DELIM+ipAddress;
|
||||
}
|
||||
// remove first delimiter
|
||||
serialized = serialized.substring(IP_DELIM.length());
|
||||
Log.d(LOG_ID, serialized);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
public static ArrayList<String> deserializeIpList(String serialized) {
|
||||
ArrayList<String> iplist = new ArrayList<>();
|
||||
Log.d(LOG_ID, serialized);
|
||||
for (String ipaddr : serialized.split(IP_DELIM)) {
|
||||
iplist.add(ipaddr);
|
||||
Log.d(LOG_ID, ipaddr);
|
||||
ArrayList<String> ipList = new ArrayList<>();
|
||||
for (String ipAddress : serialized.split(IP_DELIM)) {
|
||||
ipList.add(ipAddress);
|
||||
}
|
||||
return iplist;
|
||||
return ipList;
|
||||
}
|
||||
|
||||
private void initializeDeviceList(Context context){
|
||||
String deviceListPrefs = PreferenceManager.getDefaultSharedPreferences(context).getString(
|
||||
KEY_CUSTOM_DEVLIST_PREFERENCE, "");
|
||||
if(deviceListPrefs.isEmpty()){
|
||||
Log.i(LOG_ID, "Initialising empty custom device list");
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putString(
|
||||
KEY_CUSTOM_DEVLIST_PREFERENCE,
|
||||
deviceListPrefs).commit();
|
||||
} else {
|
||||
Log.i(LOG_ID, "Populating device list");
|
||||
ipAddressList = deserializeIpList(deviceListPrefs);
|
||||
}
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ import android.widget.TextView;
|
||||
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.NetworkHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.UserInterface.List.CustomItem;
|
||||
@@ -60,14 +61,15 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class DeviceFragment extends Fragment {
|
||||
|
||||
private static final String ARG_DEVICE_ID = "deviceId";
|
||||
private View rootView;
|
||||
static private String mDeviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
|
||||
private Device device;
|
||||
static final String ARG_DEVICE_ID = "deviceId";
|
||||
|
||||
private TextView errorHeader;
|
||||
View rootView;
|
||||
static String mDeviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
|
||||
Device device;
|
||||
|
||||
private MaterialActivity mActivity;
|
||||
TextView errorHeader;
|
||||
|
||||
MaterialActivity mActivity;
|
||||
|
||||
public DeviceFragment() { }
|
||||
|
||||
@@ -84,6 +86,13 @@ public class DeviceFragment extends Fragment {
|
||||
this.setArguments(args);
|
||||
}
|
||||
|
||||
public DeviceFragment(String deviceId, MaterialActivity activity){
|
||||
this.mActivity = activity;
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_DEVICE_ID, deviceId);
|
||||
this.setArguments(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
@@ -122,10 +131,6 @@ public class DeviceFragment extends Fragment {
|
||||
|
||||
refreshUI();
|
||||
|
||||
//TODO: Is this needed?
|
||||
//if (!device.hasPluginsLoaded() && device.isReachable()) {
|
||||
// device.reloadPluginsFromSettings();
|
||||
//}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -183,8 +188,7 @@ public class DeviceFragment extends Fragment {
|
||||
return rootView;
|
||||
}
|
||||
|
||||
|
||||
private final Device.PluginsChangedListener pluginsChangedListener = new Device.PluginsChangedListener() {
|
||||
final Device.PluginsChangedListener pluginsChangedListener = new Device.PluginsChangedListener() {
|
||||
@Override
|
||||
public void onPluginsChanged(final Device device) {
|
||||
refreshUI();
|
||||
@@ -289,21 +293,6 @@ public class DeviceFragment extends Fragment {
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
//TODO: Is this needed?
|
||||
/*
|
||||
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
if (mDeviceId != null) {
|
||||
Device device = service.getDevice(mDeviceId);
|
||||
if (device != null && device.isReachable()) {
|
||||
device.reloadPluginsFromSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
getView().setFocusableInTouchMode(true);
|
||||
getView().requestFocus();
|
||||
getView().setOnKeyListener(new View.OnKeyListener() {
|
||||
@@ -345,9 +334,11 @@ public class DeviceFragment extends Fragment {
|
||||
|
||||
boolean paired = device.isPaired();
|
||||
boolean reachable = device.isReachable();
|
||||
boolean onData = NetworkHelper.isOnMobileNetwork(getContext());
|
||||
|
||||
rootView.findViewById(R.id.pairing_buttons).setVisibility(paired ? View.GONE : View.VISIBLE);
|
||||
rootView.findViewById(R.id.unpair_message).setVisibility((paired && !reachable) ? View.VISIBLE : View.GONE);
|
||||
rootView.findViewById(R.id.not_reachable_message).setVisibility((paired && !reachable && !onData) ? View.VISIBLE : View.GONE);
|
||||
rootView.findViewById(R.id.on_data_message).setVisibility((paired && !reachable && onData) ? View.VISIBLE : View.GONE);
|
||||
|
||||
try {
|
||||
ArrayList<ListAdapter.Item> items = new ArrayList<>();
|
||||
@@ -418,7 +409,7 @@ public class DeviceFragment extends Fragment {
|
||||
|
||||
}
|
||||
|
||||
private final Device.PairingCallback pairingCallback = new Device.PairingCallback() {
|
||||
final Device.PairingCallback pairingCallback = new Device.PairingCallback() {
|
||||
|
||||
@Override
|
||||
public void incomingRequest() {
|
||||
@@ -435,6 +426,7 @@ public class DeviceFragment extends Fragment {
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (rootView == null) return;
|
||||
((TextView) rootView.findViewById(R.id.pair_message)).setText(error);
|
||||
rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE);
|
||||
rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE);
|
||||
@@ -449,6 +441,7 @@ public class DeviceFragment extends Fragment {
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (rootView == null) return;
|
||||
((TextView) rootView.findViewById(R.id.pair_message)).setText(R.string.device_not_paired);
|
||||
rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE);
|
||||
rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE);
|
||||
@@ -460,4 +453,45 @@ public class DeviceFragment extends Fragment {
|
||||
|
||||
};
|
||||
|
||||
public static void acceptPairing(final String devId, final MaterialActivity activity){
|
||||
final DeviceFragment frag = new DeviceFragment(devId, activity);
|
||||
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device dev = service.getDevice(devId);
|
||||
activity.getSupportActionBar().setTitle(dev.getName());
|
||||
|
||||
dev.addPairingCallback(frag.pairingCallback);
|
||||
dev.addPluginsChangedListener(frag.pluginsChangedListener);
|
||||
|
||||
frag.device = dev;
|
||||
frag.device.acceptPairing();
|
||||
|
||||
frag.refreshUI();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void rejectPairing(final String devId, final MaterialActivity activity){
|
||||
final DeviceFragment frag = new DeviceFragment(devId, activity);
|
||||
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device dev = service.getDevice(devId);
|
||||
activity.getSupportActionBar().setTitle(dev.getName());
|
||||
|
||||
dev.addPairingCallback(frag.pairingCallback);
|
||||
dev.addPluginsChangedListener(frag.pluginsChangedListener);
|
||||
|
||||
frag.device = dev;
|
||||
|
||||
//Remove listener so buttons don't show for a while before changing the view
|
||||
frag.device.removePluginsChangedListener(frag.pluginsChangedListener);
|
||||
frag.device.removePairingCallback(frag.pairingCallback);
|
||||
frag.device.rejectPairing();
|
||||
activity.onDeviceSelected(null);
|
||||
|
||||
frag.refreshUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|