mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-09-01 06:35:09 +00:00
Compare commits
74 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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="1500"
|
||||
android:versionName="1.5">
|
||||
|
||||
<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"
|
||||
@@ -83,6 +84,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 +129,7 @@
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneActivity"
|
||||
android:label="@string/findmyphone_title"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleInstance">
|
||||
</activity>
|
||||
|
||||
|
@@ -3,7 +3,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.0'
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -5,13 +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">الدّخل البعيد</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">شارك الملفّات والعناوين بين الجهازين</string>
|
||||
<string name="plugin_not_available">هذه الميزة غير متوفّرة في إصدار أندرويد لديك</string>
|
||||
<string name="device_list_empty">لا أجهزة</string>
|
||||
<string name="ok">حسنًا</string>
|
||||
@@ -19,24 +29,33 @@
|
||||
<string name="open_settings">افتح الإعدادات</string>
|
||||
<string name="no_permissions">عليك إعطاء التّطبيق صلاحيّات للنّفاذ إلى الإخطارات</string>
|
||||
<string name="send_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/>
|
||||
<item/>
|
||||
<item>Nothing</item>
|
||||
<item>النّقر باليمين</item>
|
||||
<item>النّقر بالوسط</item>
|
||||
<item>لا شيء</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
<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_unpair">أزل الاقتران</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>
|
||||
@@ -46,14 +65,24 @@
|
||||
<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">لا يستخدم الجهاز الآخر إصدارة حديثة من «كدي المتّصل»، ستُستخدم طريقة التّعمية القديمة.</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="received_file_title">استُلم ملفّ من %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>
|
||||
@@ -74,6 +103,8 @@
|
||||
<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 ثوان</item>
|
||||
<item>20 ثانية</item>
|
||||
@@ -92,9 +123,13 @@
|
||||
<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">أضف أجهزة بميفاق الإنترنت مإ</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">ستُزامن الإخطارات من التّطبيقات المحدّدة.</string>
|
||||
<string name="sftp_internal_storage">التّخزين الدّاخليّ</string>
|
||||
<string name="sftp_all_files">كلّ الملفّات</string>
|
||||
<string name="sftp_sdcard_num">بطاقة SD %d</string>
|
||||
@@ -102,7 +137,26 @@
|
||||
<string name="sftp_readonly">(للقراءة فقط)</string>
|
||||
<string name="sftp_camera">صور الكاميرا</string>
|
||||
<string name="add_host">أضف مضيفًا/مإ</string>
|
||||
<string name="add_host_hint">اسم المضيف أو عنوان IP</string>
|
||||
<string name="no_players_connected">لم يُعثر على مشغّلات</string>
|
||||
<string name="custom_dev_list_help">استخدم هذا الخيار فقط إن لم يُكتَشف جهازك آليًّا. أدخِل عنوان مإ أو اسم المضيف أدناه والمس الزرّ لإضافته إلى القائمة. المس عنصرًا موجودًا لإزالته من القائمة.</string>
|
||||
<string name="mpris_player_on_device">%1$s على %2$s</string>
|
||||
<string name="send_files">أرسل ملفّات</string>
|
||||
<string name="pairing_title">أجهزة «كدي المتّصل»</string>
|
||||
<string name="pairing_description">الأجهزة الأخرى التي تشغّل «كدي المتّصل» وعلى نفس الشّبكة ستظهر هنا.</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">أرسل 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>
|
||||
</resources>
|
||||
|
@@ -1,45 +1,64 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Notificador telefónicu</string>
|
||||
<string name="pref_plugin_telephony">Avisador telefónicu</string>
|
||||
<string name="pref_plugin_telephony_desc">Unvia avisos pa SMS y llamaes</string>
|
||||
<string name="pref_plugin_battery">Informe de batería</string>
|
||||
<string name="pref_plugin_battery_desc">Infoma davezu del estáu de la batería</string>
|
||||
<string name="pref_plugin_sftp">Esposición del sistema de ficheros</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite restolar remotamente el sistema de ficheros d\'esti preséu</string>
|
||||
<string name="pref_plugin_clipboard">Sincronización del cartafueyu</string>
|
||||
<string name="pref_plugin_clipboard_desc">Comparte\'l conteníu del cartafueyu</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usa\'l to preséu como panel táutil y tecláu</string>
|
||||
<string name="pref_plugin_mpris">Controles remotos multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Forne control multimedia pal to reproductor</string>
|
||||
<string name="pref_plugin_runcommand">Executar comandu</string>
|
||||
<string name="pref_plugin_runcommand_desc">Aiciona comandos remotos dende\'l to preséu</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Unvia y recibi pings</string>
|
||||
<string name="pref_plugin_ping_desc">Unvia y recibe pings</string>
|
||||
<string name="pref_plugin_notifications">Sincronización d\'avisos</string>
|
||||
<string name="pref_plugin_notifications_desc">Accede a los tos avisos dende otros preseos</string>
|
||||
<string name="pref_plugin_sharereceiver">Unvia y recibi pings</string>
|
||||
<string name="pref_plugin_receive_notifications">Recibir avisos</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Recibe avisos d\'otru preséu y amuésalos n\'Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Compartir y recibir</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Comparte ficheros y URLs ente preseos</string>
|
||||
<string name="plugin_not_available">Esta carauterística nun ta disponible na to versión d\'Android</string>
|
||||
<string name="device_list_empty">Ensin preseos</string>
|
||||
<string name="ok">Aceutar</string>
|
||||
<string name="cancel">Encaboxar</string>
|
||||
<string name="open_settings">Abrir axustes</string>
|
||||
<string name="no_permissions">Necesites garantizar l\'accesu a los avisos</string>
|
||||
<string name="no_permissions">Precises dar laude p\'acceder a los avisos</string>
|
||||
<string name="send_ping">Unviar ping</string>
|
||||
<string name="open_mpris_controls">Controles multimedia</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_info">Muevi un deu enriba la pantalla pa mover el mur. calca pa un clic y usa dos/tres deos pa los motones de drecha y mediu. Usa un primíu llargu pa arrastrar y soltar.</string>
|
||||
<string name="mousepad_info">Muevi un deu enriba la pantalla pa mover el mur. Calca pa un clic y usa dos/tres deos pa los botones de drecha y en mediu. Usa un primíu llargu p\'arrastrar y soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Afitar aición de calcu con dos deos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Afitar aición de calcu con tres deos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Afitar sensibilidá del panel táutil</string>
|
||||
<string name="mousepad_scroll_direction_title">Direición inversa de desplazamientu</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic drechu</item>
|
||||
<item>Clic d\'en mediu</item>
|
||||
<item>Nada</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">drecha</string>
|
||||
<string name="mousepad_triple_default">d\'en mediu</string>
|
||||
<string name="mousepad_sensitivity_default">por defeutu</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>Perlenta</item>
|
||||
<item>La más lenta</item>
|
||||
<item>Predeterminada</item>
|
||||
<item>Penriba lo predeterminao</item>
|
||||
<item>La más rápida</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Preseos coneutaos</string>
|
||||
<string name="category_not_paired_devices">Preseos disponibles</string>
|
||||
<string name="category_remembered_devices">Preseos recordaos</string>
|
||||
<string name="plugins_failed_to_load">Los complementos fallaron al cargase (calca pa más información):</string>
|
||||
<string name="device_menu_plugins">Axustes de complementos</string>
|
||||
<string name="device_menu_unpair">Desempareyar</string>
|
||||
<string name="device_not_reachable">El preséu empareyáu nun ye agamable</string>
|
||||
<string name="pair_new_device">Empareyar preséu nuevu</string>
|
||||
<string name="unknown_device">Preséu desconocíu</string>
|
||||
<string name="error_not_reachable">Nun ye algamable\'l preséu</string>
|
||||
<string name="error_already_requested">Empareyamientu yá solicitáu</string>
|
||||
@@ -49,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Encaboxáu pol usuariu</string>
|
||||
<string name="error_canceled_by_other_peer">Encaboxáu pola otra parte</string>
|
||||
<string name="error_invalid_key">Recibióse una clave non válida</string>
|
||||
<string name="encryption_info_title">Información de cifráu</string>
|
||||
<string name="encryption_info_msg_no_ssl">L\'otru preséu nun usa una versión recién de KDE Connect. Usando\'l métodu de cifráu heredáu.</string>
|
||||
<string name="my_device_fingerprint">La buelga SHA1 del certificáu del to preséu ye:</string>
|
||||
<string name="remote_device_fingerprint">La buelga SHA1 del certificáu del preséu remotu ye:</string>
|
||||
<string name="pair_requested">Solicitóse l\'empareyamientu</string>
|
||||
<string name="pairing_request_from">Solicitú d\'empareyamientu de %1s</string>
|
||||
<string name="received_url_title">Recibióse l\'enllaz de %1s</string>
|
||||
@@ -56,16 +79,20 @@
|
||||
<string name="incoming_file_title">Ficheru entrante de %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Unviando ficheru a %1s</string>
|
||||
<string name="outgoing_files_title">Unviando ficheros a %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Unviáronse %1$d de %2$d ficheros</string>
|
||||
<string name="received_file_title">Recibióse\'l ficheru de %1s</string>
|
||||
<string name="received_file_fail_title">Fallu al recibir el ficheru de %1s</string>
|
||||
<string name="received_file_text">Tap to open \'%1s\'</string>
|
||||
<string name="received_file_text">Calca p\'abrir «%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_title">Falló l\'unviu del ficheru a %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Calca pa responder</string>
|
||||
<string name="reconnect">Reconeutar</string>
|
||||
<string name="right_click">Unviar clic drechu</string>
|
||||
<string name="middle_click">Unviar clic d\'en mediu</string>
|
||||
<string name="show_keyboard">Amosar tecláu</string>
|
||||
<string name="device_not_paired">Preséu non empareyáu</string>
|
||||
<string name="request_pairing">Solicitar empareyamientu</string>
|
||||
@@ -91,6 +118,7 @@
|
||||
<item>1 minutu</item>
|
||||
<item>2 minutos</item>
|
||||
</string-array>
|
||||
<string name="share_to">Compartir en...</string>
|
||||
<string name="protocol_version_older">Esti preséu usa una versión vieya del protocolu</string>
|
||||
<string name="protocol_version_newer">Esti preséu usa una versión anovada del protocolu</string>
|
||||
<string name="general_settings">Axustes xenerales</string>
|
||||
@@ -100,12 +128,16 @@
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Nome de preséu non válidu</string>
|
||||
<string name="shareplugin_text_saved">Recibióse\'l testu y guardóse nel cartafueyu</string>
|
||||
<string name="custom_devices_settings">Llista de preseos personalizada</string>
|
||||
<string name="custom_devices_settings">Llistáu personalizáu de preseos</string>
|
||||
<string name="pair_device_action">Empareyar con un preséu nuevu</string>
|
||||
<string name="unpair_device_action">Desempareyar %s</string>
|
||||
<string name="custom_device_list">Amestar preseos pola IP</string>
|
||||
<string name="share_notification_preference">Avisos sonoros</string>
|
||||
<string name="share_notification_preference_summary">Fai vibrar y reproduz un soníu al recibir un ficheru</string>
|
||||
<string name="share_destination_customize">Personalizar direutoriu destín</string>
|
||||
<string name="share_destination_customize_summary_disabled">Los ficheros recibíos apaecerán en Descargues</string>
|
||||
<string name="share_destination_customize_summary_enabled">Los ficheros atroxaránse nel direutoriu d\'embaxo</string>
|
||||
<string name="share_destination_folder_preference">Direutoriu destín</string>
|
||||
<string name="title_activity_notification_filter">Peñera d\'avisos</string>
|
||||
<string name="filter_apps_info">Los avisos sincronizaránse coles aplicaciones esbillaes.</string>
|
||||
<string name="sftp_internal_storage">Almacenamientu internu</string>
|
||||
@@ -117,11 +149,11 @@
|
||||
<string name="add_host">Amestar agospiu/IP</string>
|
||||
<string name="add_host_hint">Nome d\'agospiu o IP</string>
|
||||
<string name="no_players_connected">Nun s\'alcontraron reproductores</string>
|
||||
<string name="custom_dev_list_help">Usa esta opción namái si\'l to preséu nun se deteuta automáticamente. Introduz la direición o\'l nome d\'agospiu y toca\'l botón p\'amestalu a la llista. Toca un elementu esistente pa desanicialu de la llista.</string>
|
||||
<string name="custom_dev_list_help">Usa esta opción namái si\'l to preséu nun se deteuta automáticamente. Introduz la direición o\'l nome d\'agospiu y toca\'l botón p\'amestalu al llistáu. Toca un elementu esistente pa desanicialu de la llistáu.</string>
|
||||
<string name="mpris_player_on_device">%1$s en %2$s</string>
|
||||
<string name="send_files">Unviar ficheros</string>
|
||||
<string name="pairing_title">Preseos KDE Connect</string>
|
||||
<string name="pairing_description">Deberíen apaecer equí otros preseos executando KDE Connect.</string>
|
||||
<string name="pairing_description">Equí deberíen apaecer otros preseos executando KDE Connect.</string>
|
||||
<string name="device_paired">Preséu empareyáu</string>
|
||||
<string name="device_rename_title">Renomar preséu</string>
|
||||
<string name="device_rename_confirm">Renomar</string>
|
||||
@@ -131,6 +163,9 @@
|
||||
<string name="pref_plugin_telepathy">Unviar SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Unvia mensaxes de testu dende\'l to escritoriu</string>
|
||||
<string name="plugin_not_supported">Esti complementu nun ta sofitáu pol preséu</string>
|
||||
<string name="findmyphone_title">Alcuentra\'l mio teléfonu</string>
|
||||
<string name="findmyphone_title_tablet">Alcuentra la mio tableta</string>
|
||||
<string name="findmyphone_description">Fai sonar esti preséu pa que pueas alcontralu.</string>
|
||||
<string name="findmyphone_found">Alcontrar</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Zarrar</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>
|
||||
|
@@ -79,13 +79,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 +134,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>
|
||||
|
@@ -85,7 +85,6 @@
|
||||
<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_text">%1s</string>
|
||||
<string name="tap_to_answer">Ťukněte pro odpovězení</string>
|
||||
<string name="reconnect">Znovu připojit</string>
|
||||
|
@@ -13,6 +13,7 @@
|
||||
<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>
|
||||
@@ -33,6 +34,8 @@
|
||||
<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 +43,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>Hurtigst</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Forbundne enheder</string>
|
||||
<string name="category_not_paired_devices">Tilgængelig enheder</string>
|
||||
@@ -64,6 +68,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>
|
||||
@@ -71,13 +79,15 @@
|
||||
<string name="incoming_file_title">Indkommende fil fra %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Sender fil til %1s</string>
|
||||
<string name="outgoing_files_title">Sender filer til %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Sendte %1$d ud af %2$d filer</string>
|
||||
<string name="received_file_title">Modtog fil fra %1s</string>
|
||||
<string name="received_file_fail_title">Kunne ikke modtage fil fra %1s</string>
|
||||
<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_title">Kunne ikke sende filen til %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>
|
||||
@@ -124,6 +134,10 @@
|
||||
<string name="custom_device_list">Tilføj enheder via IP</string>
|
||||
<string name="share_notification_preference">Støjende bekendtgørelser</string>
|
||||
<string name="share_notification_preference_summary">Vibrér og afspil en lyd når en fil modtages</string>
|
||||
<string name="share_destination_customize">Tilpas destinationsmappe</string>
|
||||
<string name="share_destination_customize_summary_disabled">Modtagne filer vil dukke op i Downloads</string>
|
||||
<string name="share_destination_customize_summary_enabled">Filer vil blive gemt i mappen nedenfor</string>
|
||||
<string name="share_destination_folder_preference">Destinationsmappe</string>
|
||||
<string name="title_activity_notification_filter">Bekendtgørelsesfilter</string>
|
||||
<string name="filter_apps_info">Bekendtgørelser vil blive synkroniseret for de valgte apps.</string>
|
||||
<string name="sftp_internal_storage">Intern lagring</string>
|
||||
@@ -149,6 +163,10 @@
|
||||
<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>
|
||||
|
@@ -79,7 +79,6 @@
|
||||
<string name="received_file_fail_title">Der Empfang der Datei %1s ist fehlgeschlagen</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>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tippen zum Antworten</string>
|
||||
<string name="reconnect">Erneut verbinden</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>
|
||||
|
@@ -79,13 +79,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>
|
||||
|
@@ -85,7 +85,6 @@
|
||||
<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_text">%1s</string>
|
||||
<string name="tap_to_answer">Pulse para responder</string>
|
||||
<string name="reconnect">Reconectar</string>
|
||||
|
@@ -85,7 +85,6 @@
|
||||
<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_text">%1s</string>
|
||||
<string name="tap_to_answer">Koputa vastamiseks</string>
|
||||
<string name="reconnect">Ühenda uuesti</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>
|
||||
|
@@ -28,6 +28,8 @@
|
||||
<string name="mousepad_info">Mova un dedo na pantalla para mover o cursor. Toque para facer clic, e use dous ou tres dedos para os botóns secundario e central. Prema durante un tempo para arrastrar e soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Definir a acción de tocar con dous dedos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Definir a acción de tocar con tres dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do punteiro táctil</string>
|
||||
<string name="mousepad_scroll_direction_title">Inverter a dirección de desprazamento</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic dereito</item>
|
||||
<item>Clic central</item>
|
||||
@@ -35,12 +37,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">dereita</string>
|
||||
<string name="mousepad_triple_default">medio</string>
|
||||
<string name="mousepad_sensitivity_default">predeterminado</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>O máis lento</item>
|
||||
<item>Lento</item>
|
||||
<item>Predeterminado</item>
|
||||
<item>Rápido</item>
|
||||
<item>O mais rápido</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivos conectados</string>
|
||||
<string name="category_not_paired_devices">Dispositivos dispoñíbeis</string>
|
||||
@@ -72,7 +75,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>
|
||||
|
@@ -79,13 +79,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 +134,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>
|
||||
|
@@ -71,7 +71,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>
|
||||
|
@@ -41,14 +41,11 @@
|
||||
<string name="error_already_requested">Jau paprašyta suporuoti</string>
|
||||
<string name="error_already_paired">Įrenginys jau suporuotas</string>
|
||||
<string name="error_could_not_send_package">Nepavyksta išsiųsti paketo</string>
|
||||
<string name="error_timed_out">Skirtasis laikas baigėsi</string>
|
||||
<string name="error_canceled_by_user">Naudotojas atšaukė užduotį</string>
|
||||
<string name="error_canceled_by_other_peer">Porininkas atšaukė užduotį</string>
|
||||
<string name="error_invalid_key">Gautas netinkamas raktas</string>
|
||||
<string name="pair_requested">Paprašyta suporuoti</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Norėdami atsakyti, palieskite</string>
|
||||
<string name="reconnect">Prisijungti iš naujo</string>
|
||||
<string name="show_keyboard">Rodyti klaviatūrą</string>
|
||||
@@ -86,7 +83,6 @@
|
||||
<string name="pair_device_action">Suporuoti naują įrenginį</string>
|
||||
<string name="unpair_device_action">Atrišti %s</string>
|
||||
<string name="custom_device_list">Pridėti įrenginį pagal IP</string>
|
||||
<string name="sftp_internal_storage">Vidinė saugykla</string>
|
||||
<string name="sftp_all_files">Visi failai</string>
|
||||
<string name="sftp_sdcard_num">SD kortelė %d</string>
|
||||
<string name="sftp_sdcard">SD kortelė</string>
|
||||
@@ -100,9 +96,12 @@
|
||||
<string name="pairing_description">Čia turėtų pasirodyti to kiti paties tinklo įrenginiai, kuriuose veikia „KDE Connect“</string>
|
||||
<string name="device_paired">Įrenginys suporuotas</string>
|
||||
<string name="device_rename_title">Pervadinti įrenginį</string>
|
||||
<string name="device_rename_confirm">Pervadinti</string>
|
||||
<string name="refresh">Atnaujinti</string>
|
||||
<string name="unreachable_description">Šis suporuotas įrenginys nepasiekiamas. Patikrinkite, ar jis prisijungęs prie to paties tinklo.</string>
|
||||
<string name="pref_plugin_telepathy">Siųsti SMS</string>
|
||||
<string name="plugin_not_supported">Telefonas nepalaiko šio papildinio</string>
|
||||
<string name="findmyphone_found">Radau</string>
|
||||
<string name="open">Atverti</string>
|
||||
<string name="close">Užverti</string>
|
||||
</resources>
|
||||
|
@@ -79,13 +79,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">Bezig bestanden te verzenden naar %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Verzonden %1$d uit %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 bestand 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 +134,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">De bestemmingsmap aanpassen</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>
|
||||
|
165
res/values-nn/strings.xml
Normal file
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>
|
@@ -85,7 +85,6 @@
|
||||
<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_text">%1s</string>
|
||||
<string name="tap_to_answer">Stuknij, aby odpowiedzieć</string>
|
||||
<string name="reconnect">Połącz ponownie</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>
|
||||
|
@@ -19,7 +19,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>
|
||||
@@ -43,13 +43,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 +68,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 +79,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 +134,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>
|
||||
|
@@ -71,7 +71,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>
|
||||
|
@@ -85,7 +85,6 @@
|
||||
<string name="received_file_text">Ťuknite na otvorenie \'%1s\'</string>
|
||||
<string name="sent_file_title">Poslať súbor pre %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Zlyhalo poslanie súboru %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tapnite na odpoveď</string>
|
||||
<string name="reconnect">Znovu pripojiť</string>
|
||||
|
@@ -79,13 +79,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 +134,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>
|
||||
|
@@ -79,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">Надіслано %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 +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>
|
||||
|
@@ -72,7 +72,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>
|
||||
@@ -145,4 +144,6 @@
|
||||
<string name="pref_plugin_telepathy_desc">从桌面发送短消息</string>
|
||||
<string name="plugin_not_supported">设备不支持此插件</string>
|
||||
<string name="findmyphone_found">找到</string>
|
||||
<string name="open">打开</string>
|
||||
<string name="close">关闭</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>
|
||||
|
@@ -96,13 +96,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 +160,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>
|
||||
@@ -191,4 +197,5 @@
|
||||
|
||||
<string name="open">Open</string>
|
||||
<string name="close">Close</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -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) {
|
||||
|
@@ -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,7 +157,12 @@ 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));
|
||||
}
|
||||
};
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
@@ -382,14 +383,9 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
.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 +578,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 +623,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
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);
|
||||
}
|
||||
|
||||
}
|
25
src/org/kde/kdeconnect/Helpers/NotificationHelper.java
Normal file
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!/
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
@@ -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; }
|
||||
|
||||
|
@@ -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,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,9 +68,9 @@ 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());
|
||||
|
@@ -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,6 +131,14 @@ class SimpleSftpServer {
|
||||
}
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return passwordAuth.password;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getLocalIpAddress() {
|
||||
String ip6 = null;
|
||||
try {
|
||||
@@ -153,92 +161,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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ public class SendFileActivity extends ActionBarActivity {
|
||||
case Activity.RESULT_FIRST_USER:
|
||||
if (resultCode == RESULT_OK) {
|
||||
final Uri uri = data.getData();
|
||||
Log.e("SendFileActivity", "File Uri: " + uri.toString());
|
||||
Log.i("SendFileActivity", "File Uri: " + uri.toString());
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
|
@@ -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,25 @@ 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.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 +111,21 @@ 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();
|
||||
final String nameWithoutExtension = FilesHelper.getFileNameWithoutExt(filename);
|
||||
final String mimeType = FilesHelper.getMimeTypeFromFile(filename);
|
||||
|
||||
//Append filename to the destination path
|
||||
final File destinationFullPath = new File(destinationDir, 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, nameWithoutExtension);
|
||||
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 +138,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) {
|
||||
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();
|
||||
@@ -283,12 +263,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 +278,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 +355,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 +384,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.KITKAT)) {
|
||||
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,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);
|
||||
}
|
||||
}
|
||||
|
@@ -28,8 +28,8 @@ import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class EntryItem implements ListAdapter.Item {
|
||||
|
||||
private final String title;
|
||||
private final String subtitle;
|
||||
protected final String title;
|
||||
protected final String subtitle;
|
||||
|
||||
public EntryItem(String title) {
|
||||
this.title = title;
|
||||
|
Reference in New Issue
Block a user