mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-09-01 14:45:08 +00:00
Compare commits
65 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
044e56184a | ||
|
f923ce198f | ||
|
a9508a7f46 | ||
|
cbbec32beb | ||
|
cf247b4d18 | ||
|
bfadb84b9f | ||
|
7db40ee20a | ||
|
5609c8ebcc | ||
|
1d1618d8ed | ||
|
47c2483d53 | ||
|
5659812428 | ||
|
418e1a813e | ||
|
50f395bdef | ||
|
9695e5a49e | ||
|
e36b80aa0c | ||
|
08230950b6 | ||
|
63e9e7f522 | ||
|
7e5df06972 | ||
|
8dd4297a0f | ||
|
1e58559584 | ||
|
503eaa7ca8 | ||
|
46cd99ba85 | ||
|
a7d6b9a805 | ||
|
f688aad3e1 | ||
|
906c04ac1a | ||
|
a61cb875f1 | ||
|
6e053a7e95 | ||
|
71b034a025 | ||
|
0e9dd25172 | ||
|
51e957d822 | ||
|
ec43336153 | ||
|
49295c0de9 | ||
|
56d01ed082 | ||
|
dbd9ece110 | ||
|
132e4e7e0f | ||
|
4cdda3f31b | ||
|
7c723eea8c | ||
|
22e7b91bb3 | ||
|
4aa365e4ff | ||
|
c50642e587 | ||
|
e52f418dad | ||
|
6a7fbecc97 | ||
|
db0c48cc6b | ||
|
35635a0b0b | ||
|
8a2cc4a841 | ||
|
a53bf9b191 | ||
|
2d3b0e7641 | ||
|
274621e79d | ||
|
ea136498b4 | ||
|
1e82c653d6 | ||
|
565be4a42a | ||
|
de4e203d8c | ||
|
86e698df08 | ||
|
3d5dcdacae | ||
|
8b145b4c6a | ||
|
52486ed2ec | ||
|
b8d327c2d9 | ||
|
630044e702 | ||
|
720421554a | ||
|
e045964592 | ||
|
98931c7bcf | ||
|
a616d5afbd | ||
|
1ffcaba71c | ||
|
260abb192c | ||
|
ea57aec40f |
@@ -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="11270"
|
||||
android:versionName="1.12.7">
|
||||
android:versionCode="11293"
|
||||
android:versionName="1.12.93">
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
@@ -32,11 +32,13 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||
<uses-permission android:name="android.permission.SEND_SMS" />
|
||||
<uses-permission android:name="android.permission.READ_SMS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/icon"
|
||||
android:label="KDE Connect"
|
||||
android:supportsRtl="true"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:theme="@style/KdeConnectTheme">
|
||||
<service
|
||||
android:name="org.kde.kdeconnect.BackgroundService"
|
||||
@@ -65,7 +67,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity"
|
||||
android:name="org.kde.kdeconnect.UserInterface.PluginSettingsActivity"
|
||||
android:label="@string/device_menu_plugins"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.MainActivity">
|
||||
<meta-data
|
||||
@@ -259,10 +261,10 @@
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity"
|
||||
android:label="@string/title_activity_notification_filter"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity">
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.PluginSettingsActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity" />
|
||||
android:value="org.kde.kdeconnect.UserInterface.PluginSettingsActivity" />
|
||||
</activity>
|
||||
<activity android:name="org.kde.kdeconnect.Plugins.PhotoPlugin.PhotoActivity" />
|
||||
|
||||
|
@@ -6,7 +6,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
9
res/layout/list_item_plugin_header.xml
Normal file
9
res/layout/list_item_plugin_header.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="28dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="8dp" />
|
@@ -1,64 +1,136 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="kde_connect">KDE Connect</string>
|
||||
<string name="pref_plugin_telephony">Avisador telefónicu</string>
|
||||
<string name="pref_plugin_battery">Informe de batería</string>
|
||||
<string name="pref_plugin_battery_desc">Informe periódicu del estáu de la batería</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite restolar remotamente a esti preséu</string>
|
||||
<string name="pref_plugin_telephony_desc">Unvia avisos de les llamaes entrantes</string>
|
||||
<string name="pref_plugin_battery">Informe de la batería</string>
|
||||
<string name="pref_plugin_battery_desc">Informa davezu del estáu de la batería</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite restolar remotamente\'l 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 teléfonu o tableta como panel táutil y tecláu</string>
|
||||
<string name="pref_plugin_remotekeyboard">Pulsaciones remotes</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usa\'l preséu como panel táutil y tecláu</string>
|
||||
<string name="pref_plugin_mpris">Controles multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Forne un control remotu pal to reproductor multimedia</string>
|
||||
<string name="pref_plugin_runcommand">Execución de comandos</string>
|
||||
<string name="pref_plugin_runcommand_desc">Aiciona comandos remotos del to teléfonu o tableta</string>
|
||||
<string name="pref_plugin_ping">Ping</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 d\'otros preseos</string>
|
||||
<string name="pref_plugin_receive_notifications">Recibir avisos</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Recibe avisos d\'otros preseos 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="pref_plugin_runcommand_desc">Aiciona comandos remotos dende\'l preséu</string>
|
||||
<string name="pref_plugin_contacts">Sincronizador de contautos</string>
|
||||
<string name="pref_plugin_notifications_desc">Accede a los avisos n\'otros preseos</string>
|
||||
<string name="device_list_empty">Nun hai preseos</string>
|
||||
<string name="ok">Aceutar</string>
|
||||
<string name="cancel">Encaboxar</string>
|
||||
<string name="open_settings">Abrir axustes</string>
|
||||
<string name="no_permissions">¡</string>
|
||||
<string name="send_ping">Unviar ping</string>
|
||||
<string name="open_mpris_controls">Control multimedia</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_scroll_direction_title">Direición de desplazamientu inversa</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
<item>Clic drechu</item>
|
||||
<item>Clic d\'en mediu</item>
|
||||
<item>Nada</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Perlenta</item>
|
||||
<item>Lenta</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
<item>Rápida</item>
|
||||
<item>Perrápida</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_acceleration_profile_entries">
|
||||
<item>No Acceleration</item>
|
||||
<item>Ensin aceleración</item>
|
||||
<item>Weakest</item>
|
||||
<item>Weaker</item>
|
||||
<item>Medium</item>
|
||||
<item>Stronger</item>
|
||||
<item>Strongest</item>
|
||||
<item>Normal</item>
|
||||
<item>Fuerte</item>
|
||||
<item>Perfuerte</item>
|
||||
</string-array>
|
||||
<string name="error_timed_out">Escosó\'l tiempu</string>
|
||||
<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="device_menu_plugins">Axustes de plugins</string>
|
||||
<string name="device_menu_unpair">Desempareyar</string>
|
||||
<string name="pair_new_device">Empareya un preséu nuevu</string>
|
||||
<plurals name="incoming_file_title">
|
||||
<item quantity="one">Recibiendo %1$d ficheru de %2$s</item>
|
||||
<item quantity="other">Recibiendo %1$d ficheros de %2$s</item>
|
||||
</plurals>
|
||||
<plurals name="incoming_files_text">
|
||||
<item quantity="one">Ficheru: %1s</item>
|
||||
<item quantity="other">(Ficheru %2$d de %3$d): %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_file_title">
|
||||
<item quantity="one">Unviando %1$d ficheru a %2$s</item>
|
||||
<item quantity="other">Unviando %1$d ficheros a %2$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_files_text">
|
||||
<item quantity="one">Ficheru: %1$s</item>
|
||||
<item quantity="other">(Ficheru %2$d de %3$d): %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_fail_title">
|
||||
<item quantity="one">Fallu al recibir el ficheru de %1$s</item>
|
||||
<item quantity="other">Fallu al recibir %2$d de los %3$d ficheros de %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="send_files_fail_title">
|
||||
<item quantity="one">Fallu al unviar el ficheru de %1$s</item>
|
||||
<item quantity="other">Fallu al unviar %2$d de los %3$d ficheros de %1$s</item>
|
||||
</plurals>
|
||||
<string name="cannot_create_file">Nun pue crease\'l ficheru %s</string>
|
||||
<string name="right_click">Unviar un clic drechu</string>
|
||||
<string name="middle_click">Unviar un clic d\'en mediu</string>
|
||||
<string name="show_keyboard">Amosar el tecláu</string>
|
||||
<string name="device_not_paired">Nun s\'empareyó\'l preséu</string>
|
||||
<string name="request_pairing">Solicitar l\'empareyamientu</string>
|
||||
<string name="device">Preséu</string>
|
||||
<string name="settings">Axustes</string>
|
||||
<string name="mpris_volume">Volume</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 segundos</item>
|
||||
<item>20 segundos</item>
|
||||
<item>30 segundos</item>
|
||||
<item>1 minutu</item>
|
||||
<item>2 minutos</item>
|
||||
</string-array>
|
||||
<string name="no_file_browser">Nun hai restoladores de ficheros instalaos</string>
|
||||
<string name="pref_plugin_telepathy_desc">Unvia mensaxes de testu dende\'l to escritoriu</string>
|
||||
<string name="plugin_not_supported">Esti complementu nun lu sofita\'l preséu</string>
|
||||
<string name="findmyphone_description">Fai sonar el teléfonu pa qu\'asina pueas alcontralu</string>
|
||||
<string name="protocol_version_older">Esti preséu una una versión vieya del protocolu</string>
|
||||
<string name="protocol_version_newer">Esti preséu una una versión nueva del protocolu</string>
|
||||
<string name="general_settings">Axustes xenerales</string>
|
||||
<string name="plugin_settings">Axustes</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="custom_devices_settings">Llista de preseos personalizaos</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">Vibra y reproduz un soníu al recibir un ficheru</string>
|
||||
<string name="share_destination_customize_summary_disabled">Los ficheros recibíos van apaecer en Descargues</string>
|
||||
<string name="share_destination_folder_preference">Direutoriu de destín</string>
|
||||
<string name="title_activity_notification_filter">Peñera d\'avisos</string>
|
||||
<string name="filter_apps_info">Van sincronizase los avisos de les aplicaciones esbillaes.</string>
|
||||
<string name="sftp_sdcard">Tarxeta SD</string>
|
||||
<string name="add_device_dialog_title">Amiestu d\'un preséu</string>
|
||||
<string name="add_device_hint">Nome d\'agospiu o direición IP</string>
|
||||
<string name="no_players_connected">Nun s\'alcontraron reproductores</string>
|
||||
<string name="send_files">Unviar ficheros</string>
|
||||
<string name="pairing_description">Equí deberíen apaecer los demás preseos que tean na mesma rede y executando KDE Connect.</string>
|
||||
<string name="device_rename_title">Renomáu del preséu</string>
|
||||
<string name="device_rename_confirm">Renomar</string>
|
||||
<string name="refresh">Refrescar</string>
|
||||
<string name="pref_plugin_telepathy_desc">Unvia SMS dende l\'ordenador</string>
|
||||
<string name="findmyphone_description">Fai qu\'esti preséu suene pa que pueas alcontralu</string>
|
||||
<string name="findmyphone_found">Alcontrélu</string>
|
||||
<string name="telephony_pref_blocked_title">Númberos bloquiaos</string>
|
||||
<string name="presenter_fullscreen">Pantalla completa</string>
|
||||
<string name="presenter_exit">Colar de la presentación</string>
|
||||
<string name="addcommand_explanation">Nun hai comandos rexistraos.</string>
|
||||
<string name="add_command_description">Pues amestar más comandos nel escritoriu</string>
|
||||
<string name="dark_theme">Estilu escuru</string>
|
||||
<string name="notification_channel_persistent">Indicador permanente</string>
|
||||
<string name="clipboard_toast">Copióse al cartafueyu</string>
|
||||
<string name="pref_plugin_findremotedevice_desc">Fai que\'l preséu remotu suene</string>
|
||||
<string name="ring">Facer sonar</string>
|
||||
<string name="pref_plugin_systemvolume">Volume del sistema</string>
|
||||
<string name="pref_plugin_systemvolume_desc">Controla\'l volume del sistema del preséu remotu</string>
|
||||
<string name="devices">Preseos</string>
|
||||
<string name="settings_rename">Nome del preséu</string>
|
||||
<string name="settings_dark_mode">Estilu escuru</string>
|
||||
<string name="settings_more_settings_title">Más axustes</string>
|
||||
<string name="setting_persistent_notification_oreo">Avisu permanente</string>
|
||||
<string name="extra_options">Opciones adicionales</string>
|
||||
<string name="new_notification">Avisu nuevu</string>
|
||||
<string name="notification_channel_receivenotification">Avisos d\'otros preseos</string>
|
||||
<string name="plugin_photo_desc">Llanza l\'aplicación de la cámarra p\'acenciellar la fechura y tresferencia de semeyes</string>
|
||||
</resources>
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<string name="pref_plugin_sftp">Menyingkap sistem file</string>
|
||||
<string name="pref_plugin_sftp_desc">Membolehkan menelusuri sistem file perangkat ini secara jarak jauh</string>
|
||||
<string name="pref_plugin_clipboard">Sinkron clipboard</string>
|
||||
<string name="pref_plugin_clipboard_desc">Berbagi konten clipboard</string>
|
||||
<string name="pref_plugin_clipboard_desc">Berbagi konten papan-klip</string>
|
||||
<string name="pref_plugin_mousepad">Input jarak jauh</string>
|
||||
<string name="pref_plugin_mousepad_desc">Gunakan telepon atau tabletmu sebagai touchpad dan keyboard</string>
|
||||
<string name="pref_plugin_presenter_desc">Gunakan perangkatmu untuk mengubah slide dalam sebuah presentasi</string>
|
||||
@@ -147,7 +147,7 @@
|
||||
<string name="device_name">Nama perangkat</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Nama perangkat tak absah</string>
|
||||
<string name="shareplugin_text_saved">Teks diterima, tersimpan ke clipboard</string>
|
||||
<string name="shareplugin_text_saved">Teks diterima, tersimpan ke papan-klip</string>
|
||||
<string name="custom_devices_settings">Kustom daftar perangkat</string>
|
||||
<string name="pair_device_action">Sandingkan sebuah perangkat baru</string>
|
||||
<string name="unpair_device_action">Leraikan %s</string>
|
||||
|
@@ -104,6 +104,14 @@
|
||||
<item quantity="one">File: %1s</item>
|
||||
<item quantity="other">(File %2$d di %3$d) : %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_file_title">
|
||||
<item quantity="one">Invio di %1$d file a %2$s</item>
|
||||
<item quantity="other">Invio di %1$d file a %2$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_files_text">
|
||||
<item quantity="one">File: %1$s</item>
|
||||
<item quantity="other">(File %2$d di %3$d) : %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_title">
|
||||
<item quantity="one">File ricevuto da %1$s</item>
|
||||
<item quantity="other">Ricevuti %2$d file da %1$s</item>
|
||||
@@ -112,6 +120,14 @@
|
||||
<item quantity="one">Ricezione file da di %1$s non riuscita</item>
|
||||
<item quantity="other">Ricezione di %2$d di %3$d file da %1$s non riuscita</item>
|
||||
</plurals>
|
||||
<plurals name="sent_files_title">
|
||||
<item quantity="one">File inviato a %1$s</item>
|
||||
<item quantity="other">Inviati %2$d file a %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="send_files_fail_title">
|
||||
<item quantity="one">Invio del file a %1$s non riuscito</item>
|
||||
<item quantity="other">Invio di %2$d di %3$d file a %1$s non riuscito</item>
|
||||
</plurals>
|
||||
<string name="received_file_text">Tocca per aprire «%1s»</string>
|
||||
<string name="cannot_create_file">Impossibile creare il file %s</string>
|
||||
<string name="tap_to_answer">Tocca per rispondere</string>
|
||||
@@ -230,6 +246,7 @@
|
||||
<string name="plugins_need_optional_permission">Alcune estensioni hanno funzioni disabilitate per una mancanza di permessi (tocca per maggiori informazioni):</string>
|
||||
<string name="share_optional_permission_explanation">Per condividere i file tra il telefono e il tuo desktop devi dare accesso alla memoria del telefono</string>
|
||||
<string name="telepathy_permission_explanation">Per leggere e scrivere SMS dal tuo desktop, devi concedere l\'autorizzazione per SMS</string>
|
||||
<string name="telephony_permission_explanation">Per vedere le chiamate telefoniche dal desktop devi dare l\'autorizzazione per accedere al registro delle chiamate e allo stato del telefono</string>
|
||||
<string name="telephony_optional_permission_explanation">Per vedere il nome di un contatto invece del numero di telefono devi dare accesso alla rubrica del telefono</string>
|
||||
<string name="contacts_permission_explanation">Per condividere la tua rubrica con il desktop, devi concedere l\'autorizzazione per i contatti</string>
|
||||
<string name="select_ringtone">Seleziona una suoneria</string>
|
||||
|
@@ -1,30 +1,259 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="foreground_notification_no_devices">デバイスに接続されていません</string>
|
||||
<string name="foreground_notification_devices">接続済み: %s</string>
|
||||
<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_presenter">リモートスライドショー</string>
|
||||
<string name="pref_plugin_presenter_desc">あなたのデバイスを使ってプレゼンテーションのスライドを変更</string>
|
||||
<string name="pref_plugin_remotekeyboard">リモートからキー入力を受信</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_contacts_desc">デバイスの連絡先の同期を許可</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="cancel">キャンセル</string>
|
||||
<string name="open_settings">設定を開く</string>
|
||||
<string name="no_permissions">通知にアクセスするには権限を許可する必要があります</string>
|
||||
<string name="no_permissions_remotekeyboard">キー入力を受信するには KDE Connect リモートキーボードをアクティブ化する必要があります</string>
|
||||
<string name="send_ping">Ping を送信</string>
|
||||
<string name="open_mpris_controls">マルチメディアの操作</string>
|
||||
<string name="remotekeyboard_connected">リモートキーボード接続はアクティブです</string>
|
||||
<string name="open_mousepad">リモート入力</string>
|
||||
<string name="mousepad_info">スクリーン上で指を動かしてマウスカーソルを移動します。タップはクリックとなり、2/3本指で右クリック、中クリックとなります。2本指を使ってスクロールが可能です。長押しすることでドラッグ&ドロップできます。</string>
|
||||
<string name="mousepad_double_tap_settings_title">2本指タップのアクションを設定</string>
|
||||
<string name="mousepad_triple_tap_settings_title">3本指タップのアクションを設定</string>
|
||||
<string name="mousepad_sensitivity_settings_title">タッチパッドの感度を設定</string>
|
||||
<string name="mousepad_acceleration_profile_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-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>デフォルト</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_acceleration_profile_entries">
|
||||
<item>No Acceleration</item>
|
||||
<item>Weakest</item>
|
||||
<item>Weaker</item>
|
||||
<item>Medium</item>
|
||||
<item>Stronger</item>
|
||||
<item>Strongest</item>
|
||||
<item>加速なし</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="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_timed_out">タイムアウト</string>
|
||||
<string name="error_canceled_by_user">ユーザにキャンセルされました</string>
|
||||
<string name="error_canceled_by_other_peer">他のピアにキャンセルされました</string>
|
||||
<string name="error_invalid_key">不正なキーを受信しました</string>
|
||||
<string name="encryption_info_title">暗号化情報</string>
|
||||
<string name="encryption_info_msg_no_ssl">他のデバイスは最近のバージョンの KDE Connect を利用していません。古い暗号化方式を使用しています</string>
|
||||
<string name="pair_requested">ペアリング要求済み</string>
|
||||
<string name="pairing_request_from">%1s からペアリングを要求されました</string>
|
||||
<string name="received_url_title">%1s からリンクを受信</string>
|
||||
<string name="received_url_text">タップして \'%1s\' を開く</string>
|
||||
<plurals name="incoming_file_title">
|
||||
<item quantity="other">%1$d ファイルを %2$s から受信しています</item>
|
||||
</plurals>
|
||||
<plurals name="incoming_files_text">
|
||||
<item quantity="other">ファイル: %1s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_file_title">
|
||||
<item quantity="other">%1$d ファイルを %2$s へ送信中</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_files_text">
|
||||
<item quantity="other">ファイル: %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_title">
|
||||
<item quantity="other">%1$s からファイルを受信</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_fail_title">
|
||||
<item quantity="other">%1$s からのファイルの受信に失敗</item>
|
||||
</plurals>
|
||||
<plurals name="sent_files_title">
|
||||
<item quantity="other">%1$s にファイルを送信済み</item>
|
||||
</plurals>
|
||||
<string name="received_file_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="settings">設定</string>
|
||||
<string name="mpris_play">再生</string>
|
||||
<string name="mpris_pause">一時停止</string>
|
||||
<string name="mpris_previous">前へ</string>
|
||||
<string name="mpris_rew">巻き戻し</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="mpris_notification_settings_title">メディア操作の通知を表示</string>
|
||||
<string name="mpris_notification_settings_summary">KDE Connect を開かずにメディアプレーヤーをコントロール可能にします</string>
|
||||
<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="invalid_device_name">不正なデバイス名</string>
|
||||
<string name="pair_device_action">新しいデバイスをペアリング</string>
|
||||
<string name="unpair_device_action">%s をペアリング解除</string>
|
||||
<string name="custom_device_list">IP アドレスでデバイスを追加</string>
|
||||
<string name="delete_custom_device">%s を削除しますか?</string>
|
||||
<string name="custom_device_fab_hint">デバイスを追加</string>
|
||||
<string name="undo">元に戻す</string>
|
||||
<string name="share_notification_preference">うるさい通知</string>
|
||||
<string name="share_notification_preference_summary">ファイル受信時にバイブレートし、音声を再生します</string>
|
||||
<string name="share_destination_customize">行き先ディレクトリをカスタマイズ</string>
|
||||
<string name="share_destination_customize_summary_disabled">受信したファイルは Downloads に保存されます</string>
|
||||
<string name="share_destination_customize_summary_enabled">ファイルは以下のディレクトリに保存されます</string>
|
||||
<string name="share_destination_folder_preference">行き先ディレクトリ</string>
|
||||
<string name="share">共有</string>
|
||||
<string name="share_received_file">\"%s\" を共有</string>
|
||||
<string name="title_activity_notification_filter">通知フィルタ</string>
|
||||
<string name="filter_apps_info">選択されたアプリケーションの通知が同期されます。</string>
|
||||
<string name="sftp_internal_storage">内部ストレージ</string>
|
||||
<string name="sftp_sdcard_num">SD カード %d</string>
|
||||
<string name="sftp_sdcard">SD カード</string>
|
||||
<string name="sftp_readonly">(読み取り専用)</string>
|
||||
<string name="add_device_dialog_title">デバイスを追加</string>
|
||||
<string name="add_device_hint">ホスト名/IPアドレス</string>
|
||||
<string name="sftp_preference_detected_sdcards">検出された SD カード</string>
|
||||
<string name="sftp_preference_configured_storage_locations">設定されたストレージの場所</string>
|
||||
<string name="sftp_preference_add_storage_location_title">ストレージの場所を追加</string>
|
||||
<string name="sftp_preference_edit_storage_location">ストレージの場所を編集</string>
|
||||
<string name="sftp_storage_preference_storage_location">ストレージの場所</string>
|
||||
<string name="sftp_storage_preference_storage_location_already_configured">この場所は既に設定されています</string>
|
||||
<string name="sftp_storage_preference_click_to_select">クリックして選択</string>
|
||||
<string name="sftp_storage_preference_display_name">表示名</string>
|
||||
<string name="sftp_storage_preference_display_name_already_used">この表示名は既に使用されています</string>
|
||||
<string name="sftp_storage_preference_display_name_cannot_be_empty">表示名は空にできません</string>
|
||||
<string name="sftp_action_mode_menu_delete">削除</string>
|
||||
<string name="sftp_no_sdcard_detected">SD カードが検出されません</string>
|
||||
<string name="sftp_no_storage_locations_configured">ストレージの場所が設定されていません</string>
|
||||
<string name="sftp_saf_permission_explanation">リモートからファイルにアクセスするには、ストレージの場所を設定する必要があります</string>
|
||||
<string name="add_host_hint">ホスト名かIPアドレス</string>
|
||||
<string name="no_players_connected">プレーヤーが見つかりませんでした</string>
|
||||
<string name="send_files">ファイルを送信</string>
|
||||
<string name="pairing_title">KDE Connect デバイス</string>
|
||||
<string name="pairing_description">同じネットワーク内で KDE Connect を実行しているデバイスがここに表示されます</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="on_data_message">モバイルデータ接続を使用しているようです。KDE Connect はローカルネットワークでしか機能しません</string>
|
||||
<string name="no_file_browser">ファイルブラウザがインストールされていません</string>
|
||||
<string name="pref_plugin_telepathy">SMS を送信</string>
|
||||
<string name="pref_plugin_telepathy_desc">デスクトップからテキストメッセージを送信</string>
|
||||
<string name="plugin_not_supported">このプラグインはデバイスにサポートされていません</string>
|
||||
<string name="findmyphone_title">スマートフォンを捜索</string>
|
||||
<string name="findmyphone_title_tablet">タブレットを捜索</string>
|
||||
<string name="findmyphone_title_tv">TV を捜索</string>
|
||||
<string name="findmyphone_description">このデバイスを鳴らすことで捜索できます</string>
|
||||
<string name="findmyphone_found">発見</string>
|
||||
<string name="open">開く</string>
|
||||
<string name="close">閉じる</string>
|
||||
<string name="no_permissions_storage">ストレージにアクセスするには権限を許可する必要があります</string>
|
||||
<string name="plugins_need_permission">いくつかのプラグインが機能するには権限が必要です (タップして詳細情報を表示):</string>
|
||||
<string name="permission_explanation">このプラグインが機能するには権限が必要です</string>
|
||||
<string name="optional_permission_explanation">すべての機能を有効にするには、追加の権限を許可する必要があります</string>
|
||||
<string name="plugins_need_optional_permission">権限が不足しているため、いくつかのプラグインの機能は無効化されています (タップして詳細情報を表示):</string>
|
||||
<string name="share_optional_permission_explanation">スマートフォンとデスクトップ間でファイルを共有するには、端末のストレージへのアクセスを許可する必要があります</string>
|
||||
<string name="telepathy_permission_explanation">デスクトップから SMS を送受信するには SMS の権限を付与する必要があります</string>
|
||||
<string name="telephony_optional_permission_explanation">電話番号ではなく連絡先名を見るには、端末の連絡先へのアクセスを許可する必要があります</string>
|
||||
<string name="contacts_permission_explanation">連絡先をデスクトップと共有するために、連絡先の権限が必要です</string>
|
||||
<string name="select_ringtone">着信音を選択</string>
|
||||
<string name="telephony_pref_blocked_title">ブロックされた番号</string>
|
||||
<string name="telephony_pref_blocked_dialog_desc">これらの番号からの通話と SMS を表示しません。一行に1つの電話番号を指定してください</string>
|
||||
<string name="mpris_coverart_description">現在のメディアのカバーアート</string>
|
||||
<string name="device_icon_description">デバイスアイコン</string>
|
||||
<string name="settings_icon_description">設定アイコン</string>
|
||||
<string name="presenter_fullscreen">フルスクリーン</string>
|
||||
<string name="presenter_exit">プレゼンテーションを終了</string>
|
||||
<string name="presenter_lock_tip">デバイスをロックして、音量キーでスライドを前/次に移動できます</string>
|
||||
<string name="add_command">コマンドを追加</string>
|
||||
<string name="addcommand_explanation">コマンドが登録されていません</string>
|
||||
<string name="addcommand_explanation2">KDE Connect のシステム設定で新しいコマンドを追加できます</string>
|
||||
<string name="add_command_description">デスクトップから新しいコマンドを追加できます</string>
|
||||
<string name="pref_plugin_mprisreceiver">メディアプレーヤーの操作</string>
|
||||
<string name="pref_plugin_mprisreceiver_desc">他のデバイスからスマートフォンのメディアプレーヤーを操作</string>
|
||||
<string name="dark_theme">ダーク テーマ</string>
|
||||
<string name="notification_channel_default">他の通知</string>
|
||||
<string name="notification_channel_persistent">永続的なインジケータ</string>
|
||||
<string name="notification_channel_media_control">メディアの操作</string>
|
||||
<string name="notification_channel_filetransfer">ファイル転送</string>
|
||||
<string name="mpris_stop">現在のプレーヤーを停止</string>
|
||||
<string name="copy_url_to_clipboard">URL をクリップボードにコピー</string>
|
||||
<string name="clipboard_toast">クリップボードにコピーしました</string>
|
||||
<string name="runcommand_notreachable">デバイスは到達不可です</string>
|
||||
<string name="runcommand_notpaired">デバイスはペアリングされていません</string>
|
||||
<string name="runcommand_noruncommandplugin">このデバイスは \'コマンドを実行\' プラグインを有効にしていません</string>
|
||||
<string name="pref_plugin_findremotedevice">リモートデバイスを捜索</string>
|
||||
<string name="pref_plugin_findremotedevice_desc">リモートデバイスを捜索</string>
|
||||
<string name="pref_plugin_systemvolume">システム音量</string>
|
||||
<string name="pref_plugin_systemvolume_desc">リモートデバイスのシステム音量を操作</string>
|
||||
<string name="mute">ミュート</string>
|
||||
<string name="all">すべて</string>
|
||||
<string name="devices">デバイス</string>
|
||||
<string name="settings_rename">デバイス名</string>
|
||||
<string name="settings_dark_mode">ダーク テーマ</string>
|
||||
<string name="settings_more_settings_title">その他の設定</string>
|
||||
<string name="settings_more_settings_text">デバイスごとの設定はデバイス内の \'プラグイン設定\' にあります</string>
|
||||
<string name="setting_persistent_notification">永続的な通知を表示</string>
|
||||
<string name="setting_persistent_notification_oreo">永続的な通知</string>
|
||||
<string name="setting_persistent_notification_description">タップして通知設定内で有効化/無効化します</string>
|
||||
<string name="extra_options">追加オプション</string>
|
||||
<string name="privacy_options">プライバシーオプション</string>
|
||||
<string name="set_privacy_options">プライバシーオプションを設定</string>
|
||||
<string name="new_notification">新しい通知</string>
|
||||
<string name="notification_channel_receivenotification">他のデバイスからの通知</string>
|
||||
<string name="take_picture">カメラを起動</string>
|
||||
</resources>
|
||||
|
@@ -1,6 +1,10 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="kde_connect">KDE Connect</string>
|
||||
<string name="foreground_notification_no_devices">연결된 장치 없음</string>
|
||||
<string name="foreground_notification_devices">연결됨: %s</string>
|
||||
<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>
|
||||
@@ -9,6 +13,7 @@
|
||||
<string name="pref_plugin_clipboard_desc">클립보드 내용 동기화</string>
|
||||
<string name="pref_plugin_mousepad">원격 입력</string>
|
||||
<string name="pref_plugin_mousepad_desc">내 휴대폰이나 태블릿을 터치패드와 키보드로 사용하기</string>
|
||||
<string name="pref_plugin_presenter">슬라이드 쇼 리모콘</string>
|
||||
<string name="pref_plugin_presenter_desc">내 장치로 프레젠테이션 슬라이드 전환하기</string>
|
||||
<string name="pref_plugin_remotekeyboard">원격 키 입력 받기</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">원격 장치의 키 입력 이벤트 받기</string>
|
||||
@@ -33,6 +38,7 @@
|
||||
<string name="open_settings">설정 열기</string>
|
||||
<string name="no_permissions">알림 접근 권한이 필요합니다</string>
|
||||
<string name="no_permission_mprisreceiver">미디어 재생기를 제어하려면 알림 접근 권한이 필요합니다</string>
|
||||
<string name="no_permissions_remotekeyboard">키 입력을 받으려면 KDE Connect 원격 키보드를 활성화해야 합니다</string>
|
||||
<string name="send_ping">핑 보내기</string>
|
||||
<string name="open_mpris_controls">멀티미디어 제어</string>
|
||||
<string name="remotekeyboard_editing_only_title">편집할 때에만 원격 키 처리하기</string>
|
||||
@@ -90,7 +96,32 @@
|
||||
<string name="pairing_request_from">%1s에서 연결 요청</string>
|
||||
<string name="received_url_title">%1s에서 링크 받음</string>
|
||||
<string name="received_url_text">\'%1s\'을(를) 열려면 누르십시오</string>
|
||||
<plurals name="incoming_file_title">
|
||||
<item quantity="other">%2$s에서 보낸 파일 %1$d개 받음</item>
|
||||
</plurals>
|
||||
<plurals name="incoming_files_text">
|
||||
<item quantity="other">(파일 %3$d개 중 %2$d개): %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_file_title">
|
||||
<item quantity="other">%2$s(으)로 파일 %1$d개 보내는 중</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_files_text">
|
||||
<item quantity="other">(파일 %3$d개 중 %2$d개): %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_title">
|
||||
<item quantity="other">%1$s에서 파일 %2$d개 받음</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_fail_title">
|
||||
<item quantity="other">%1$s에서 보낸 파일 %3$d개 중 %2$d개를 받을 수 없음</item>
|
||||
</plurals>
|
||||
<plurals name="sent_files_title">
|
||||
<item quantity="other">%1$s(으)로 파일 %2$d개 보냄</item>
|
||||
</plurals>
|
||||
<plurals name="send_files_fail_title">
|
||||
<item quantity="other">%1$s(으)로 파일 %3$d개 중 %2$d개를 보낼 수 없음</item>
|
||||
</plurals>
|
||||
<string name="received_file_text">\'%1s\'을(를) 열려면 누르십시오</string>
|
||||
<string name="cannot_create_file">파일 %s을(를) 만들 수 없음</string>
|
||||
<string name="tap_to_answer">눌러서 응답하기</string>
|
||||
<string name="reconnect">다시 연결</string>
|
||||
<string name="right_click">오른쪽 단추 누름 신호 보내기</string>
|
||||
@@ -102,6 +133,7 @@
|
||||
<string name="pairing_reject">거부</string>
|
||||
<string name="device">장치</string>
|
||||
<string name="pair_device">장치 연결</string>
|
||||
<string name="settings">설정</string>
|
||||
<string name="mpris_play">재생</string>
|
||||
<string name="mpris_pause">일시 정지</string>
|
||||
<string name="mpris_previous">이전</string>
|
||||
@@ -111,6 +143,7 @@
|
||||
<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>
|
||||
@@ -119,6 +152,8 @@
|
||||
<item>2분</item>
|
||||
</string-array>
|
||||
<string name="mpris_notification_settings_title">미디어 제어 알림 보이기</string>
|
||||
<string name="mpris_notification_settings_summary">KDE Connect를 열지 않고 미디어 재생기 제어</string>
|
||||
<string name="share_to">다음으로 공유…</string>
|
||||
<string name="protocol_version_older">이 장치의 프로토콜 버전이 오래되었습니다</string>
|
||||
<string name="protocol_version_newer">이 장치의 프로토콜 버전이 더 새롭습니다</string>
|
||||
<string name="general_settings">일반 설정</string>
|
||||
@@ -127,11 +162,16 @@
|
||||
<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="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="delete_custom_device">%s을(를) 삭제하시겠습니까?</string>
|
||||
<string name="custom_device_deleted">사용자 정의 장치 삭제됨</string>
|
||||
<string name="custom_device_list_help">장치가 자동으로 감지되지 않았다면 떠 다니는 동작 단추를 눌러서 IP 주소나 호스트 이름으로 장치를 수동으로 추가할 수 있습니다</string>
|
||||
<string name="custom_device_fab_hint">장치 추가</string>
|
||||
<string name="undo">실행 취소</string>
|
||||
<string name="share_notification_preference">시끄러운 알림</string>
|
||||
<string name="share_notification_preference_summary">파일을 받았을 때 진동과 소리로 알림</string>
|
||||
<string name="share_destination_customize">대상 디렉터리 사용자 정의</string>
|
||||
@@ -147,7 +187,28 @@
|
||||
<string name="sftp_sdcard">SD 카드</string>
|
||||
<string name="sftp_readonly">(읽기 전용)</string>
|
||||
<string name="sftp_camera">카메라 사진</string>
|
||||
<string name="add_device_dialog_title">장치 추가</string>
|
||||
<string name="add_device_hint">호스트 이름이나 IP 주소</string>
|
||||
<string name="sftp_preference_detected_sdcards">감지된 SD 카드</string>
|
||||
<string name="sftp_preference_edit_sdcard_title">SD 카드 편집</string>
|
||||
<string name="sftp_preference_configured_storage_locations">설정된 저장소 위치</string>
|
||||
<string name="sftp_preference_add_storage_location_title">저장소 위치 추가</string>
|
||||
<string name="sftp_preference_edit_storage_location">저장소 위치 편집</string>
|
||||
<string name="sftp_preference_add_camera_shortcut">카메라 폴더 바로 가기 추가</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_on">카메라 폴더 바로 가기 추가</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_off">카메라 폴더 바로 가기 추가하지 않음</string>
|
||||
<string name="sftp_storage_preference_storage_location">저장소 위치</string>
|
||||
<string name="sftp_storage_preference_storage_location_already_configured">이 위치는 이미 설정됨</string>
|
||||
<string name="sftp_storage_preference_click_to_select">눌러서 선택</string>
|
||||
<string name="sftp_storage_preference_display_name">표시 이름</string>
|
||||
<string name="sftp_storage_preference_display_name_already_used">이 표시 이름이 이미 사용 중임</string>
|
||||
<string name="sftp_storage_preference_display_name_cannot_be_empty">표시 이름을 비워둘 수 없음</string>
|
||||
<string name="sftp_action_mode_menu_delete">삭제</string>
|
||||
<string name="sftp_no_sdcard_detected">SD 카드가 감지되지 않았음</string>
|
||||
<string name="sftp_no_storage_locations_configured">저장소 위치가 설정되지 않았음</string>
|
||||
<string name="sftp_saf_permission_explanation">원격으로 파일에 접근하려면 저장소 위치를 설정해야 함</string>
|
||||
<string name="add_host">호스트/IP 주소 추가</string>
|
||||
<string name="add_host_hint">호스트 이름이나 IP</string>
|
||||
<string name="no_players_connected">재생기를 찾을 수 없음</string>
|
||||
<string name="mpris_player_on_device">%2$s의 %1$s</string>
|
||||
<string name="send_files">파일 보내기</string>
|
||||
@@ -177,6 +238,7 @@
|
||||
<string name="plugins_need_optional_permission">일부 플러그인은 권한이 없어서 비활성화되었습니다(정보를 보려면 누르기):</string>
|
||||
<string name="share_optional_permission_explanation">휴대폰과 데스크톱간 파일을 공유하려면 휴대폰 저장소 접근 권한이 필요합니다</string>
|
||||
<string name="telepathy_permission_explanation">데스크톱에서 문자 메시지를 읽고 보내려면 문자 메시지 접근 권한이 필요합니다</string>
|
||||
<string name="telephony_permission_explanation">데스크톱에서 통화와 문자 메시지를 보려면 통화 기록 및 휴대폰 상태 접근 권한이 필요합니다</string>
|
||||
<string name="telephony_optional_permission_explanation">전화번호 대신 연락처에 등록된 이름을 보려면 주소록 접근 권한이 필요합니다</string>
|
||||
<string name="contacts_permission_explanation">데스크톱과 주소록을 공유하려면 주소록 접근 권한이 필요합니다</string>
|
||||
<string name="select_ringtone">벨소리 선택</string>
|
||||
@@ -187,6 +249,7 @@
|
||||
<string name="settings_icon_description">설정 아이콘</string>
|
||||
<string name="presenter_fullscreen">전체 화면</string>
|
||||
<string name="presenter_exit">프레젠테이션 끝내기</string>
|
||||
<string name="presenter_lock_tip">장치 잠금 상태에서는 음량 키를 이전/다음 슬라이드 단추로 사용할 수 있습니다</string>
|
||||
<string name="add_command">명령 추가</string>
|
||||
<string name="addcommand_explanation">등록된 명령이 없습니다</string>
|
||||
<string name="addcommand_explanation2">시스템 설정의 KDE Connect에서 새로운 명령을 추가할 수 있습니다</string>
|
||||
@@ -194,9 +257,13 @@
|
||||
<string name="pref_plugin_mprisreceiver">미디어 재생기 제어</string>
|
||||
<string name="pref_plugin_mprisreceiver_desc">다른 장치에서 휴대폰 미디어 재생기 제어</string>
|
||||
<string name="dark_theme">어두운 테마</string>
|
||||
<string name="mpris_stop">현재 플레이어 정지</string>
|
||||
<string name="notification_channel_default">기타 알림</string>
|
||||
<string name="notification_channel_persistent">항상 표시된 표시기</string>
|
||||
<string name="notification_channel_media_control">미디어 제어</string>
|
||||
<string name="notification_channel_filetransfer">파일 전송</string>
|
||||
<string name="mpris_stop">현재 재생기 정지</string>
|
||||
<string name="copy_url_to_clipboard">클립보드로 URL 복사</string>
|
||||
<string name="clipboard_toast">클립보드에 복사됨</string>
|
||||
<string name="clipboard_toast">클립보드로 복사됨</string>
|
||||
<string name="runcommand_notreachable">장치에 접근할 수 없음</string>
|
||||
<string name="runcommand_notpaired">장치가 연결되지 않음</string>
|
||||
<string name="runcommand_nosuchdevice">장치가 없음</string>
|
||||
@@ -207,4 +274,23 @@
|
||||
<string name="pref_plugin_systemvolume">시스템 음량</string>
|
||||
<string name="pref_plugin_systemvolume_desc">원격 장치의 시스템 음량 제어</string>
|
||||
<string name="mute">음소거</string>
|
||||
<string name="all">모두</string>
|
||||
<string name="devices">장치</string>
|
||||
<string name="settings_rename">장치 이름</string>
|
||||
<string name="settings_dark_mode">어두운 테마</string>
|
||||
<string name="settings_more_settings_title">더 많은 설정</string>
|
||||
<string name="settings_more_settings_text">장치별 설정은 각각 장치의 \'플러그인 설정\'에서 확인할 수 있습니다.</string>
|
||||
<string name="setting_persistent_notification">항상 표시되는 알림 보이기</string>
|
||||
<string name="setting_persistent_notification_oreo">항상 표시되는 알림</string>
|
||||
<string name="setting_persistent_notification_description">알림 설정에서 활성화/비활성화하려면 누르십시오</string>
|
||||
<string name="extra_options">추가 설정</string>
|
||||
<string name="privacy_options">프라이버시 설정</string>
|
||||
<string name="set_privacy_options">프라이버시 설정 변경</string>
|
||||
<string name="new_notification">새 알림</string>
|
||||
<string name="block_contents">알림 내용 숨기기</string>
|
||||
<string name="block_images">알림 이미지 숨기기</string>
|
||||
<string name="notification_channel_receivenotification">다른 장치의 알림</string>
|
||||
<string name="take_picture">카메라 실행</string>
|
||||
<string name="plugin_photo_desc">카메라 앱을 실행하여 쉽게 사진을 찍고 전송</string>
|
||||
<string name="no_app_for_opening">이 파일을 열 수 있는 앱을 찾을 수 없음</string>
|
||||
</resources>
|
||||
|
@@ -1,75 +1,173 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Telefono žinutės ir skambučiai</string>
|
||||
<string name="kde_connect">KDE Connect</string>
|
||||
<string name="foreground_notification_no_devices">Neprisijungta prie jokio įrenginio</string>
|
||||
<string name="foreground_notification_devices">Prisijungta prie: %s</string>
|
||||
<string name="pref_plugin_telephony">Telefonijos pranešiklis</string>
|
||||
<string name="pref_plugin_telephony_desc">Siųsti gaunamųjų skambučių pranešimus</string>
|
||||
<string name="pref_plugin_battery">Akumuliatoriaus ataskaita</string>
|
||||
<string name="pref_plugin_battery_desc">Periodiškai pranešti apie akumuliatoriaus būseną</string>
|
||||
<string name="pref_plugin_sftp">Failų sistemos naršymas</string>
|
||||
<string name="pref_plugin_sftp_desc">Leidžia nuotoliniu būdu naršyti šio įrenginio failų sistemą</string>
|
||||
<string name="pref_plugin_clipboard">Iškarpinės sinchronizavimas</string>
|
||||
<string name="pref_plugin_clipboard_desc">Bendrinti iškarpinės turinį</string>
|
||||
<string name="pref_plugin_mousepad">Nuotolinis įvedimas</string>
|
||||
<string name="pref_plugin_mousepad_desc">Naudoti savo telefoną ar planšetę kaip jutiklinį kilimėlį ir klaviatūrą</string>
|
||||
<string name="pref_plugin_presenter">Nuotolinis skaidrių rodymas</string>
|
||||
<string name="pref_plugin_presenter_desc">Naudoti savo įrenginį pateikties skaidrių keitimui</string>
|
||||
<string name="pref_plugin_remotekeyboard">Gauti nuotolinius klavišų paspaudimus</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Gauti klavišų paspaudimo įvykius iš nuotolinių įrenginių</string>
|
||||
<string name="pref_plugin_mpris">Įvairialypės terpės valdikliai</string>
|
||||
<string name="pref_plugin_mpris_desc">Pateikia jūsų medijos leistuvės nuotolinį valdymą</string>
|
||||
<string name="pref_plugin_runcommand">Vykdyti komandą</string>
|
||||
<string name="pref_plugin_runcommand_desc">Paleisti nuotolines komandas iš savo telefono ar planšetės</string>
|
||||
<string name="pref_plugin_contacts">Adresatų sinchronizavimas</string>
|
||||
<string name="pref_plugin_contacts_desc">Leisti sinchronizuoti įrenginio adresatų knygą</string>
|
||||
<string name="pref_plugin_ping">Ryšio patikrinimas</string>
|
||||
<string name="pref_plugin_ping_desc">Siųsti ir gauti ryšio patikrinimus</string>
|
||||
<string name="pref_plugin_notifications">Pranešimų sinchronizavimas</string>
|
||||
<string name="pref_plugin_sharereceiver">Dalintis ir gauti</string>
|
||||
<string name="device_list_empty">Įrenginių nerasta</string>
|
||||
<string name="pref_plugin_notifications_desc">Gauti prieigą prie savo pranešimų iš kitų įrenginių</string>
|
||||
<string name="pref_plugin_receive_notifications">Gauti pranešimus</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Gauti pranešimus iš kito įrenginio ir rodyti juos Android įrenginyje</string>
|
||||
<string name="pref_plugin_sharereceiver">Bendrinti ir gauti</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Bendrinti failus ir URL adresus tarp įrenginių</string>
|
||||
<string name="plugin_not_available">Ši ypatybė jūsų Android versijoje yra neprieinama</string>
|
||||
<string name="device_list_empty">Jokių įrenginių</string>
|
||||
<string name="ok">Gerai</string>
|
||||
<string name="cancel">Atšaukti</string>
|
||||
<string name="open_settings">Atverti nuostatas</string>
|
||||
<string name="cancel">Atsisakyti</string>
|
||||
<string name="open_settings">Atverti nustatymus</string>
|
||||
<string name="no_permissions">Norėdami gauti prieigą prie pranešimų, turite suteikti leidimą</string>
|
||||
<string name="no_permission_mprisreceiver">Norėdami valdyti savo medijos leistuves, turite suteikti prieigą prie pranešimų</string>
|
||||
<string name="no_permissions_remotekeyboard">Norėdami gauti klavišų paspaudimus, turite aktyvuoti KDE Connect nuotolinę klaviatūrą</string>
|
||||
<string name="send_ping">Tikrinti ryšį</string>
|
||||
<string name="open_mpris_controls">Garso ir vaizdo kūrinių grojimo valdymas</string>
|
||||
<string name="open_mpris_controls">Įvairialypės terpės valdymas</string>
|
||||
<string name="remotekeyboard_editing_only_title">Apdoroti nuotolinius klavišus tik redaguojant</string>
|
||||
<string name="remotekeyboard_not_connected">Nėra jokio aktyvaus nuotolinės klaviatūros ryšio, užmegzkite jį naudodami kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Nuotolinės klaviatūros ryšys yra aktyvus</string>
|
||||
<string name="remotekeyboard_multiple_connections">Yra daugiau nei vienas nuotolinės klaviatūros ryšys, pasirinkite kurį įrenginį konfigūruoti</string>
|
||||
<string name="open_mousepad">Nuotolinis įvedimas</string>
|
||||
<string name="mousepad_info">Norėdami judinti pelės žymeklį, judinkite pirštu po ekraną. Bakstelėkite vienkartiniam spustelėjimui ir naudokite du/tris pirštus dešiniajam ir viduriniajam mygtukui. Naudokite 2 pirštus, norėdami slinkti. Naudokite ilgą paspaudimą, norėdami tempti.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Nustatyti bakstelėjimo dviem pirštais veiksmą</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Nustatyti bakstelėjimo trimis pirštais veiksmą</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Nustatyti jutiklinio kilimėlio jautrumą</string>
|
||||
<string name="mousepad_acceleration_profile_settings_title">Nustatyti rodyklės pagreitį</string>
|
||||
<string name="mousepad_scroll_direction_title">Apversti slinkimo kryptį</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
<item>Dešinysis spustelėjimas</item>
|
||||
<item>Vidurinysis spustelėjimas</item>
|
||||
<item>Nieko</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>Lėčiausias</item>
|
||||
<item>Virš lėčiausio</item>
|
||||
<item>Numatytasis</item>
|
||||
<item>Virš numatytojo</item>
|
||||
<item>Greičiausias</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_acceleration_profile_entries">
|
||||
<item>No Acceleration</item>
|
||||
<item>Weakest</item>
|
||||
<item>Weaker</item>
|
||||
<item>Medium</item>
|
||||
<item>Stronger</item>
|
||||
<item>Strongest</item>
|
||||
<item>Jokio pagreičio</item>
|
||||
<item>Silpniausias</item>
|
||||
<item>Silpnesnis</item>
|
||||
<item>Vidutinis</item>
|
||||
<item>Stipresnis</item>
|
||||
<item>Stipriausias</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Prijungti įrenginiai</string>
|
||||
<string name="category_not_paired_devices">Pasiekiami įrenginiai</string>
|
||||
<string name="category_remembered_devices">Įsimintieji įrenginiai</string>
|
||||
<string name="device_menu_plugins">Papildinio nuostatos</string>
|
||||
<string name="device_menu_unpair">Atrišti</string>
|
||||
<string name="device_not_reachable">Nepavyksta pasiekti suporuoto įrenginio</string>
|
||||
<string name="category_not_paired_devices">Prieinami įrenginiai</string>
|
||||
<string name="category_remembered_devices">Įsiminti įrenginiai</string>
|
||||
<string name="device_menu_plugins">Priedo nustatymai</string>
|
||||
<string name="device_menu_unpair">Panaikinti suporavimą</string>
|
||||
<string name="device_not_reachable">Suporuotas įrenginys nepasiekiamas</string>
|
||||
<string name="pair_new_device">Suporuoti naują įrenginį</string>
|
||||
<string name="unknown_device">Nežinomas įrenginys</string>
|
||||
<string name="error_not_reachable">Įrenginys nepasiekiamas</string>
|
||||
<string name="error_already_requested">Jau paprašyta suporuoti</string>
|
||||
<string name="error_already_requested">Suporavimas jau užklaustas</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="tap_to_answer">Norėdami atsakyti, palieskite</string>
|
||||
<string name="error_could_not_send_package">Nepavyko išsiųsti paketo</string>
|
||||
<string name="error_timed_out">Pasibaigė skirtas laikas</string>
|
||||
<string name="error_canceled_by_user">Naudotojas atsisakė</string>
|
||||
<string name="error_canceled_by_other_peer">Lygiarangis atsisakė</string>
|
||||
<string name="error_invalid_key">Gautas negaliojantis raktas</string>
|
||||
<string name="encryption_info_title">Šifravimo informacija</string>
|
||||
<string name="encryption_info_msg_no_ssl">Kitas įrenginys nenaudoja paskiausios KDE Connect versijos, naudojamas pasenęs šifravimo metodas.</string>
|
||||
<string name="my_device_fingerprint">Jūsų įrenginio liudijimo SHA1 kontrolinis kodas yra:</string>
|
||||
<string name="remote_device_fingerprint">Nuotolinio įrenginio liudijimo SHA1 kontrolinis kodas yra:</string>
|
||||
<string name="pair_requested">Užklaustas suporavimas</string>
|
||||
<string name="pairing_request_from">Suporavimo užklausa iš %1s</string>
|
||||
<string name="received_url_title">Gauta nuoroda iš %1s</string>
|
||||
<string name="received_url_text">Bakstelėkite, norėdami atverti \"%1s\"</string>
|
||||
<plurals name="incoming_file_title">
|
||||
<item quantity="one">Gaunamas %1$d failas iš %2$s</item>
|
||||
<item quantity="few">Gaunami %1$d failai iš %2$s</item>
|
||||
<item quantity="many">Gaunama %1$d failų iš %2$s</item>
|
||||
<item quantity="other">Gaunamas %1$d failas iš %2$s</item>
|
||||
</plurals>
|
||||
<plurals name="incoming_files_text">
|
||||
<item quantity="one">Failas: %1s</item>
|
||||
<item quantity="few">(Failas %2$d iš %3$d) : %1$s</item>
|
||||
<item quantity="many">(Failas %2$d iš %3$d) : %1$s</item>
|
||||
<item quantity="other">(Failas %2$d iš %3$d) : %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_file_title">
|
||||
<item quantity="one">Siunčiamas %1$d failas į %2$s</item>
|
||||
<item quantity="few">Siunčiami %1$d failai į %2$s</item>
|
||||
<item quantity="many">Siunčiama %1$d failų į %2$s</item>
|
||||
<item quantity="other">Siunčiamas %1$d failas į %2$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_files_text">
|
||||
<item quantity="one">Failas: %1$s</item>
|
||||
<item quantity="few">(Failas %2$d iš %3$d) : %1$s</item>
|
||||
<item quantity="many">(Failas %2$d iš %3$d) : %1$s</item>
|
||||
<item quantity="other">(Failas %2$d iš %3$d) : %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_title">
|
||||
<item quantity="one">Gautas failas iš %1$s</item>
|
||||
<item quantity="few">Gauti %2$d failai iš %1$s</item>
|
||||
<item quantity="many">Gauta %2$d failų iš %1$s</item>
|
||||
<item quantity="other">Gautas %2$d failas iš %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_fail_title">
|
||||
<item quantity="one">Nepavyko gauti failo iš %1$s</item>
|
||||
<item quantity="few">Nepavyko gauti %2$d iš %3$d failų iš %1$s</item>
|
||||
<item quantity="many">Nepavyko gauti %2$d iš %3$d failų iš %1$s</item>
|
||||
<item quantity="other">Nepavyko gauti %2$d iš %3$d failo iš %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="sent_files_title">
|
||||
<item quantity="one">Failas išsiųstas į %1$s</item>
|
||||
<item quantity="few">Išsiųsti %2$d failai į %1$s</item>
|
||||
<item quantity="many">Išsiųsta %2$d failų į %1$s</item>
|
||||
<item quantity="other">Išsiųstas %2$d failas į %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="send_files_fail_title">
|
||||
<item quantity="one">Nepavyko išsiųsti failo į %1$s</item>
|
||||
<item quantity="few">Nepavyko išsiųsti %2$d iš %3$d failų į %1$s</item>
|
||||
<item quantity="many">Nepavyko išsiųsti %2$d iš %3$d failų į %1$s</item>
|
||||
<item quantity="other">Nepavyko išsiųsti %2$d iš %3$d failo į %1$s</item>
|
||||
</plurals>
|
||||
<string name="received_file_text">Bakstelėkite,norėdami atverti \"%1s\"</string>
|
||||
<string name="cannot_create_file">Nepavyksta sukurti failo %s</string>
|
||||
<string name="tap_to_answer">Bakstelėkite norėdami atsakyti</string>
|
||||
<string name="reconnect">Prisijungti iš naujo</string>
|
||||
<string name="right_click">Siųsti dešinįjį spustelėjimą</string>
|
||||
<string name="middle_click">Siųsti vidurinįjį spustelėjimą</string>
|
||||
<string name="show_keyboard">Rodyti klaviatūrą</string>
|
||||
<string name="device_not_paired">Įrenginys nesuporuotas</string>
|
||||
<string name="request_pairing">Bandyti suporuoti</string>
|
||||
<string name="request_pairing">Užklausti suporuoti</string>
|
||||
<string name="pairing_accept">Priimti</string>
|
||||
<string name="pairing_reject">Atmesti</string>
|
||||
<string name="device">Įrenginys</string>
|
||||
<string name="pair_device">Suporuoti įrenginį</string>
|
||||
<string name="mpris_play">Groti</string>
|
||||
<string name="settings">Nustatyti</string>
|
||||
<string name="mpris_play">Atkurti</string>
|
||||
<string name="mpris_pause">Pristabdyti</string>
|
||||
<string name="mpris_previous">Ankstesnis</string>
|
||||
<string name="mpris_rew">Atsukti</string>
|
||||
<string name="mpris_ff">Prasukti</string>
|
||||
<string name="mpris_next">Tolesnis</string>
|
||||
<string name="mpris_rew">Persukti atgal</string>
|
||||
<string name="mpris_ff">Persukti pirmyn</string>
|
||||
<string name="mpris_next">Kitas</string>
|
||||
<string name="mpris_volume">Garsumas</string>
|
||||
<string name="mpris_settings">Įvairialypės terpės nuostatos</string>
|
||||
<string name="mpris_time_settings_title">Prasukimo ir atsukimo mygtukai</string>
|
||||
<string name="mpris_settings">Įvairialypės terpės nustatymai</string>
|
||||
<string name="mpris_time_settings_title">Persukimo pirmyn/atgal mygtukai</string>
|
||||
<string name="mpris_time_settings_summary">Reguliuoti persukimo pirmyn/atgal laiką, spustelėjus</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 sekundžių</item>
|
||||
<item>20 sekundžių</item>
|
||||
@@ -77,33 +175,146 @@
|
||||
<item>1 minutė</item>
|
||||
<item>2 minutės</item>
|
||||
</string-array>
|
||||
<string name="general_settings">Bendrosios nuostatos</string>
|
||||
<string name="plugin_settings">Nuostatos</string>
|
||||
<string name="plugin_settings_with_name">%s nuostatos</string>
|
||||
<string name="mpris_notification_settings_title">Rodyti įvairialypės terpės valdymo pranešimus</string>
|
||||
<string name="mpris_notification_settings_summary">Leisti valdyti medijos leistuves neatveriant KDE Connect</string>
|
||||
<string name="share_to">Bendrinti su…</string>
|
||||
<string name="protocol_version_older">Šis įrenginys naudoja seną protokolo versiją</string>
|
||||
<string name="protocol_version_newer">Šis įrenginys naudoja naujesnę protokolo versiją</string>
|
||||
<string name="general_settings">Bendri nustatymai</string>
|
||||
<string name="plugin_settings">Nustatymai</string>
|
||||
<string name="plugin_settings_with_name">%s nustatymai</string>
|
||||
<string name="device_name">Įrenginio pavadinimas</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Netinkamas įrenginio pavadinimas</string>
|
||||
<string name="custom_devices_settings">Savitas įrenginių sąrašas</string>
|
||||
<string name="shareplugin_text_saved">Gautas tekstas, įrašytas į iškarpinę</string>
|
||||
<string name="custom_devices_settings">Tinkintų įrenginių sąrašas</string>
|
||||
<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="unpair_device_action">Panaikinti suporavimą su %s</string>
|
||||
<string name="custom_device_list">Pridėti įrenginius pagal IP</string>
|
||||
<string name="delete_custom_device">Ištrinti %s?</string>
|
||||
<string name="custom_device_deleted">Tinkintas įrenginys ištrintas</string>
|
||||
<string name="custom_device_list_help">Jeigu jūsų įrenginys nėra automatiškai aptinkamas, galite pridėti jo IP adresą arba mazgo pavadinimą, spusteldami ant slankiojančio veiksmo mygtuko</string>
|
||||
<string name="custom_device_fab_hint">Pridėti įrenginį</string>
|
||||
<string name="undo">Atšaukti</string>
|
||||
<string name="share_notification_preference">Triukšmingi pranešimai</string>
|
||||
<string name="share_notification_preference_summary">Gaunant failą, vibruoti ir atkurti garsą</string>
|
||||
<string name="share_destination_customize">Tinkinti paskirties katalogą</string>
|
||||
<string name="share_destination_customize_summary_disabled">Gauti failai atsiras Atsiuntimų aplanke</string>
|
||||
<string name="share_destination_customize_summary_enabled">Failai bus saugomi žemiau esančiame kataloge</string>
|
||||
<string name="share_destination_folder_preference">Paskirties katalogas</string>
|
||||
<string name="share">Bendrinti</string>
|
||||
<string name="share_received_file">Bendrinti \"%s\"</string>
|
||||
<string name="title_activity_notification_filter">Pranešimų filtras</string>
|
||||
<string name="filter_apps_info">Pranešimai bus sinchronizuojami pasirinktoms programėlėms.</string>
|
||||
<string name="sftp_internal_storage">Vidinė saugykla</string>
|
||||
<string name="sftp_sdcard_num">SD kortelė %d</string>
|
||||
<string name="sftp_sdcard">SD kortelė</string>
|
||||
<string name="sftp_readonly">(tik skaitymui)</string>
|
||||
<string name="sftp_camera">Nuotraukos</string>
|
||||
<string name="add_host">Pridėti kompiuterį / IP</string>
|
||||
<string name="sftp_camera">Kameros nuotraukos</string>
|
||||
<string name="add_device_dialog_title">Pridėti įrenginį</string>
|
||||
<string name="add_device_hint">Mazgo pavadinimas arba IP adresas</string>
|
||||
<string name="sftp_preference_detected_sdcards">Aptiktos SD kortelės</string>
|
||||
<string name="sftp_preference_edit_sdcard_title">Taisyti SD kortelė</string>
|
||||
<string name="sftp_preference_configured_storage_locations">Sukonfigūruotos saugyklų vietos</string>
|
||||
<string name="sftp_preference_add_storage_location_title">Pridėti saugyklos vietą</string>
|
||||
<string name="sftp_preference_edit_storage_location">Taisyti saugyklos vietą</string>
|
||||
<string name="sftp_preference_add_camera_shortcut">Pridėti kameros aplanko trumpinį</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_on">Pridėti šaukinį į kameros aplanką</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_off">Nepridėti šaukinio į kameros aplanką</string>
|
||||
<string name="sftp_storage_preference_storage_location">Saugyklos vieta</string>
|
||||
<string name="sftp_storage_preference_storage_location_already_configured">Ši vieta jau yra sukonfigūruota</string>
|
||||
<string name="sftp_storage_preference_click_to_select">spustelėkite norėdami pasirinkti</string>
|
||||
<string name="sftp_storage_preference_display_name">Rodomas pavadinimas</string>
|
||||
<string name="sftp_storage_preference_display_name_already_used">Šis rodomas pavadinimas jau yra naudojamas</string>
|
||||
<string name="sftp_storage_preference_display_name_cannot_be_empty">Rodomas pavadinimas negali būti tuščias</string>
|
||||
<string name="sftp_action_mode_menu_delete">Ištrinti</string>
|
||||
<string name="sftp_no_sdcard_detected">Neaptikta jokios SD kortelės</string>
|
||||
<string name="sftp_no_storage_locations_configured">Nėra sukonfigūruota jokių saugyklos vietų</string>
|
||||
<string name="sftp_saf_permission_explanation">Norėdami gauti nuotolinę prieigą prie failų, turite sukonfigūruoti saugyklos vietas</string>
|
||||
<string name="add_host">Pridėti mazgą/IP</string>
|
||||
<string name="add_host_hint">Mazgo pavadinimas ar IP</string>
|
||||
<string name="no_players_connected">Nerasta jokių leistuvių</string>
|
||||
<string name="mpris_player_on_device">%1$s - %2$s</string>
|
||||
<string name="send_files">Siųsti failus</string>
|
||||
<string name="pairing_title">„KDE Connect“ įrenginiai</string>
|
||||
<string name="pairing_description">Čia turėtų pasirodyti to kiti paties tinklo įrenginiai, kuriuose veikia „KDE Connect“</string>
|
||||
<string name="pairing_title">KDE Connect įrenginiai</string>
|
||||
<string name="pairing_description">Čia turėtų atsirasti kiti to paties tinklo įrenginiai, naudojantys 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="refresh">Įkelti iš naujo</string>
|
||||
<string name="unreachable_description">Šis suporuotas įrenginys nepasiekiamas. Įsitikinkite, kad jis yra prijungtas prie to paties tinklo.</string>
|
||||
<string name="on_data_message">Atrodo, kad naudojate mobiliųjų duomenų ryšį. KDE Connect veikia tik vietiniuose tinkluose.</string>
|
||||
<string name="no_file_browser">Nėra įdiegta jokių failų tvarkytuvių.</string>
|
||||
<string name="pref_plugin_telepathy">Siųsti SMS žinutę</string>
|
||||
<string name="pref_plugin_telepathy_desc">Siųsti tekstines žinutes iš savo darbalaukio</string>
|
||||
<string name="plugin_not_supported">Šis įrenginys nepalaiko šio priedo</string>
|
||||
<string name="findmyphone_title">Rasti telefoną</string>
|
||||
<string name="findmyphone_title_tablet">Rasti planšetę</string>
|
||||
<string name="findmyphone_title_tv">Rasti televizorių</string>
|
||||
<string name="findmyphone_description">Skambina į šį įrenginį, kad galėtumėte jį rasti</string>
|
||||
<string name="findmyphone_found">Rastas</string>
|
||||
<string name="open">Atverti</string>
|
||||
<string name="close">Užverti</string>
|
||||
<string name="no_permissions_storage">Norėdami gauti prieigą prie saugyklos, turite suteikti leidimus</string>
|
||||
<string name="plugins_need_permission">Kai kurie priedai tam, kad veiktų, reikalauja leidimų (bakstelėkite išsamesnei informacijai):</string>
|
||||
<string name="permission_explanation">Šis priedas tam, kad veiktų, reikalauja leidimų</string>
|
||||
<string name="optional_permission_explanation">Norėdami įjungti visas funkcijas, turite suteikti papildomus leidimus</string>
|
||||
<string name="plugins_need_optional_permission">Kai kurių priedų ypatybės, dėl leidimų trūkumo, buvo išjungtos (bakstelėkite išsamesnei informacijai):</string>
|
||||
<string name="share_optional_permission_explanation">Norėdami bendrinti failus tarp savo telefono ir savo darbalaukio, turite suteikti prieigą prie telefono saugyklos</string>
|
||||
<string name="telepathy_permission_explanation">Norėdami skaityti ir rašyti SMS žinutes iš savo darbalaukio, turite suteikti prieigą prie SMS žinučių</string>
|
||||
<string name="telephony_permission_explanation">Norėdami matyti telefono skambučius darbalaukyje, turite suteikti prieigą prie telefono skambučių žurnalo ir telefono būsenos</string>
|
||||
<string name="telephony_optional_permission_explanation">Norėdami vietoj adresato numerio matyti adresato vardą, turite suteikti priegą prie telefono adresatų</string>
|
||||
<string name="contacts_permission_explanation">Norėdami bendrinti savo adresatų knygą su darbalaukiu, turite suteikti adresatų leidimą</string>
|
||||
<string name="select_ringtone">Pasirinkti skambučio melodiją</string>
|
||||
<string name="telephony_pref_blocked_title">Užblokuoti numeriai</string>
|
||||
<string name="telephony_pref_blocked_dialog_desc">Nerodyti skambučių ir SMS žinučių iš šių numerių. Nurodykite kiekvienoje eilutėje po vieną</string>
|
||||
<string name="mpris_coverart_description">Dabartinės įvairialypės terpės iliustracija</string>
|
||||
<string name="device_icon_description">Įrenginio ženkliukas</string>
|
||||
<string name="settings_icon_description">Nustatymų ženkliukas</string>
|
||||
<string name="presenter_fullscreen">Visas ekranas</string>
|
||||
<string name="presenter_exit">Išeiti iš pristatymo</string>
|
||||
<string name="presenter_lock_tip">Galite užrakinti savo įrenginį ir perėjimui prie kitos/ankstesnės skaidrės naudoti garsumo mygtukus</string>
|
||||
<string name="add_command">Pridėti komandą</string>
|
||||
<string name="addcommand_explanation">Nėra registruota jokių komandų</string>
|
||||
<string name="addcommand_explanation2">Galite pridėti naujas komandas KDE Connect sistemos nustatymuose</string>
|
||||
<string name="add_command_description">Galite pridėti komandas darbalaukyje</string>
|
||||
<string name="pref_plugin_mprisreceiver">Medijos leistuvės valdymas</string>
|
||||
<string name="pref_plugin_mprisreceiver_desc">Valdyti savo telefonų medijos leistuves iš kito įrenginio</string>
|
||||
<string name="dark_theme">Tamsus apipavidalinimas</string>
|
||||
<string name="notification_channel_default">Kiti pranešimai</string>
|
||||
<string name="notification_channel_persistent">Pastovus indikatorius</string>
|
||||
<string name="notification_channel_media_control">Įvairialypės terpės valdymas</string>
|
||||
<string name="notification_channel_filetransfer">Failų persiuntimas</string>
|
||||
<string name="mpris_stop">Stabdyti dabartinę leistuvę</string>
|
||||
<string name="copy_url_to_clipboard">Kopijuoti URL į iškarpinę</string>
|
||||
<string name="clipboard_toast">Nukopijuota į iškarpinę</string>
|
||||
<string name="runcommand_notreachable">Device is not reachable</string>
|
||||
<string name="runcommand_notpaired">Device is not paired</string>
|
||||
<string name="runcommand_nosuchdevice">Nėra tokio įrenginio</string>
|
||||
<string name="runcommand_noruncommandplugin">Šis įrenginys neturi įjungto priedo Vykdyti komandą</string>
|
||||
<string name="pref_plugin_findremotedevice">Rasti nuotolinį įrenginį</string>
|
||||
<string name="pref_plugin_findremotedevice_desc">Skambinti į nuotolinį įrenginį</string>
|
||||
<string name="ring">Skambinti</string>
|
||||
<string name="pref_plugin_systemvolume">Sistemos garsumas</string>
|
||||
<string name="pref_plugin_systemvolume_desc">Valdyti nuotolinio įrenginio sistemos garsumą</string>
|
||||
<string name="mute">Nutildyti</string>
|
||||
<string name="all">Visi</string>
|
||||
<string name="devices">Įrenginiai</string>
|
||||
<string name="settings_rename">Įrenginio pavadinimas</string>
|
||||
<string name="settings_dark_mode">Tamsus apipavidalinimas</string>
|
||||
<string name="settings_more_settings_title">Daugiau nustatymų</string>
|
||||
<string name="settings_more_settings_text">Nustatymus kiekvienam atskiram įrenginiui galima rasti įrenginyje \"Priedo nustatymuose\".</string>
|
||||
<string name="setting_persistent_notification">Rodyti pastovų pranešimą</string>
|
||||
<string name="setting_persistent_notification_oreo">Pastovus pranešimas</string>
|
||||
<string name="setting_persistent_notification_description">Bakstelėkite, norėdami įjungti/išjungti Pranešimų nustatymuose</string>
|
||||
<string name="extra_options">Papildomos parinktys</string>
|
||||
<string name="privacy_options">Privatumo parinktys</string>
|
||||
<string name="set_privacy_options">Nustatyti savo privatumo parinktis</string>
|
||||
<string name="new_notification">Naujas pranešimas</string>
|
||||
<string name="block_contents">Blokuoti pranešimų turinį</string>
|
||||
<string name="block_images">Blokuoti pranešimuose paveiksliukus</string>
|
||||
<string name="notification_channel_receivenotification">Pranešimai iš kitų įrenginių</string>
|
||||
<string name="take_picture">Paleisti kamerą</string>
|
||||
<string name="plugin_photo_desc">Paleisti kameros programėlę, kad būtų palengvintas nuotraukų darymas ir persiuntimas</string>
|
||||
<string name="no_app_for_opening">Šio failo atvėrimui nerasta jokios tinkamos programėlės</string>
|
||||
</resources>
|
||||
|
@@ -6,37 +6,39 @@
|
||||
<string name="pref_plugin_telephony">Powiadomienia telefonu</string>
|
||||
<string name="pref_plugin_telephony_desc">Wysyła powiadomienia o rozmowach przychodzących</string>
|
||||
<string name="pref_plugin_battery">Stan baterii</string>
|
||||
<string name="pref_plugin_battery_desc">Okresowo zgłasza stan baterii</string>
|
||||
<string name="pref_plugin_sftp">Udostępnienie systemu plików</string>
|
||||
<string name="pref_plugin_sftp_desc">Zezwala na zdalne przeglądanie systemu plików tego urządzenia</string>
|
||||
<string name="pref_plugin_battery_desc">Okresowo powiadamia o stanie baterii</string>
|
||||
<string name="pref_plugin_sftp">Udostępnianie systemu plików</string>
|
||||
<string name="pref_plugin_sftp_desc">Daje dostęp do plików innemu urządzeniu</string>
|
||||
<string name="pref_plugin_clipboard">Synchronizacja schowka</string>
|
||||
<string name="pref_plugin_clipboard_desc">Udostępnia zawartość schowka</string>
|
||||
<string name="pref_plugin_mousepad">Zdalne sterowanie</string>
|
||||
<string name="pref_plugin_mousepad_desc">Umożliwia wykorzystanie telefonu lub tabletu jako myszy i klawiatury</string>
|
||||
<string name="pref_plugin_presenter_desc">Umożliwia zmianę slajdów w prezentacji telefonem</string>
|
||||
<string name="pref_plugin_remotekeyboard">Odbiera zdalne naciśnięcia klawiszy</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Odbiera naciśnięcia klawiszy od urządzeń zdalnych</string>
|
||||
<string name="pref_plugin_mousepad_desc">Wykorzystuje ekran jako mysz i klawiaturę</string>
|
||||
<string name="pref_plugin_presenter">Sterowanie pokazem przeźroczy</string>
|
||||
<string name="pref_plugin_presenter_desc">Przełącza przeźrocza przy użyciu telefonu</string>
|
||||
<string name="pref_plugin_remotekeyboard">Odbieranie zdalnych naciśnięć klawiszy</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Odbiera naciśnięcia klawiszy z innego urządzenia</string>
|
||||
<string name="pref_plugin_mpris">Sterowanie multimediami</string>
|
||||
<string name="pref_plugin_mpris_desc">Umożliwia zdalne sterowanie odtwarzaczem multimedialnym</string>
|
||||
<string name="pref_plugin_mpris_desc">Steruje odtwarzaczem multimedialnym</string>
|
||||
<string name="pref_plugin_runcommand">Wykonywanie poleceń</string>
|
||||
<string name="pref_plugin_runcommand_desc">Umożliwia wykonywanie zdalnych poleceń z telefonu lub tabletu</string>
|
||||
<string name="pref_plugin_runcommand_desc">Wykonuje zdalne polecenia z telefonu lub tabletu</string>
|
||||
<string name="pref_plugin_contacts">Synchronizacja kontaktów</string>
|
||||
<string name="pref_plugin_contacts_desc">Umożliwia synchronizację książki kontaktów urządzenia</string>
|
||||
<string name="pref_plugin_contacts_desc">Synchronizuje książkę kontaktów urządzenia</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Wysyła i odbiera pingi</string>
|
||||
<string name="pref_plugin_notifications">Powiadomienia synchronizacji</string>
|
||||
<string name="pref_plugin_notifications_desc">Udostępnianie powiadomień telefonu innym urządzeniom</string>
|
||||
<string name="pref_plugin_receive_notifications">Otrzymywanie powiadomień</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Odbiera powiadomienia z innych urządzeń i wyświetla je na Androidzie</string>
|
||||
<string name="pref_plugin_notifications">Synchronizacja powiadomień</string>
|
||||
<string name="pref_plugin_notifications_desc">Wysyła powiadomienia na inne urządzenia</string>
|
||||
<string name="pref_plugin_receive_notifications">Odbieranie powiadomień</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Odbiera powiadomienia z innych urządzeń</string>
|
||||
<string name="pref_plugin_sharereceiver">Udostępnianie i odbieranie</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Współdzielenie plików i adresów URL pomiędzy urządzeniami</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Współdzieli pliki i adresy URL pomiędzy urządzeniami</string>
|
||||
<string name="plugin_not_available">Funkcja ta nie jest dostępna w twojej wersji Androida</string>
|
||||
<string name="device_list_empty">Brak urządzeń</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">Zaniechaj</string>
|
||||
<string name="open_settings">Otwórz ustawienia</string>
|
||||
<string name="no_permissions">Musisz przydzielić uprawnienia, aby uzyskać dostęp do powiadomień</string>
|
||||
<string name="no_permission_mprisreceiver">Aby móc sterować odtwarzaczami multimedialnymi musisz udzielić dostępu powiadomieniom</string>
|
||||
<string name="no_permissions">Aby uzyskać dostęp do powiadomień, należy przydzielić uprawnienia</string>
|
||||
<string name="no_permission_mprisreceiver">Aby móc sterować odtwarzaczami multimedialnymi, należy udzielić dostępu powiadomieniom</string>
|
||||
<string name="no_permissions_remotekeyboard">Aby otrzymywać naciśnięcia klawiszy, należy włączyć zdalną klawiaturę KDE Connect</string>
|
||||
<string name="send_ping">Wyślij ping</string>
|
||||
<string name="open_mpris_controls">Sterowanie multimediami</string>
|
||||
<string name="remotekeyboard_editing_only_title">Obsługuj zdalne naciśnięcia klawiszy tylko podczas edycji</string>
|
||||
@@ -44,7 +46,7 @@
|
||||
<string name="remotekeyboard_connected">Połączenie zdalnej klawiatury jest nawiązane</string>
|
||||
<string name="remotekeyboard_multiple_connections">Nawiązano więcej niż jedno połączenie zdalnej klawiatury, wybierz urządzenie do ustawienia</string>
|
||||
<string name="open_mousepad">Zdalne sterowanie</string>
|
||||
<string name="mousepad_info">Przesuń palcem po ekranie, aby przesunąć wskaźnik myszy. Stuknij, aby wywołać naciśniecie lewym przyciskiem myszy i użyj dwóch/trzech palców, aby wywołać naciśniecie prawym i środkowym przyciskiem myszy. Przewijaj przy użyciu dwóch palców. Przyciśnij na dłużej, aby przeciągnąć i upuścić.</string>
|
||||
<string name="mousepad_info">Przesuwanie palcem po ekranie przesuwa wskaźnik myszy. Stuknięcie jednym, dwoma i trzema palcami wywołuje odpowiednio naciśnięcie lewym, prawym i środkowym przyciskiem myszy. Dwa palce przewijają. Długie naciśnięcie rozpoczyna czynność przeciągania i upuszczania.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ustaw działanie po dwukrotnym stuknięciu palcem</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ustaw działanie po trzykrotnym stuknięciu palcem</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Ustaw czułość gładzika</string>
|
||||
@@ -73,7 +75,7 @@
|
||||
<string name="category_connected_devices">Podłączone urządzenia</string>
|
||||
<string name="category_not_paired_devices">Dostępne urządzenia</string>
|
||||
<string name="category_remembered_devices">Zapamiętane urządzenia</string>
|
||||
<string name="device_menu_plugins">Ustawienia wtyczki</string>
|
||||
<string name="device_menu_plugins">Ustawienia wtyczek</string>
|
||||
<string name="device_menu_unpair">Odparuj</string>
|
||||
<string name="device_not_reachable">Sparowane urządzenie nieosiągalne</string>
|
||||
<string name="pair_new_device">Sparuj nowe urządzenie</string>
|
||||
@@ -82,22 +84,22 @@
|
||||
<string name="error_already_requested">Już zażądano parowania</string>
|
||||
<string name="error_already_paired">Urządzenie już sparowano</string>
|
||||
<string name="error_could_not_send_package">Nie można wysłać pakietu</string>
|
||||
<string name="error_timed_out">Przekroczono czasu odpowiedzi</string>
|
||||
<string name="error_canceled_by_user">Anulowane przez użytkownika</string>
|
||||
<string name="error_canceled_by_other_peer">Anulowane przez innego partnera</string>
|
||||
<string name="error_timed_out">Upłynął czas na odpowiedź</string>
|
||||
<string name="error_canceled_by_user">Użytkownik zaniechał</string>
|
||||
<string name="error_canceled_by_other_peer">Inny uczestnik zaniechał</string>
|
||||
<string name="error_invalid_key">Otrzymano nieprawidłowy klucz</string>
|
||||
<string name="encryption_info_title">Zaszyfrowane informacje</string>
|
||||
<string name="encryption_info_title">Dane o szyfrowaniu</string>
|
||||
<string name="encryption_info_msg_no_ssl">Drugie urządzenie nie używa ostatniej wersji KDE Connect, użyto przestarzałego szyfrowania.</string>
|
||||
<string name="my_device_fingerprint">Odcisk palca SHA1 certyfikatu twojego urządzenia to:</string>
|
||||
<string name="remote_device_fingerprint">Odcisk palca SHA1 certyfikatu twojego zdalnego urządzenia to:</string>
|
||||
<string name="pair_requested">Zażądano parowania</string>
|
||||
<string name="pairing_request_from">Żądanie parowania z %1s</string>
|
||||
<string name="received_url_title">Odebrano odsyłacz od %1s</string>
|
||||
<string name="received_url_text">Znacznik do otwarcia \'%1s\'</string>
|
||||
<string name="received_url_text">Stuknij, aby otworzyć \'%1s\'</string>
|
||||
<plurals name="incoming_file_title">
|
||||
<item quantity="one">Odebrano %1$d plik z %2$s</item>
|
||||
<item quantity="few">Odebrano %1$d pliki z %2$s</item>
|
||||
<item quantity="many">Odebrano %1$d plików z %2$s</item>
|
||||
<item quantity="one">Odbieranie %1$d pliku od %2$s</item>
|
||||
<item quantity="few">Odbieranie %1$d plików od %2$s</item>
|
||||
<item quantity="many">Odbieranie %1$d plików od %2$s</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<plurals name="incoming_files_text">
|
||||
@@ -106,6 +108,18 @@
|
||||
<item quantity="many">(Plik %2$d z %3$d) : %1$s</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<plurals name="outgoing_file_title">
|
||||
<item quantity="one">Wysyłanie %1$d pliku do %2$s</item>
|
||||
<item quantity="few">Wysyłanie %1$d plików do %2$s</item>
|
||||
<item quantity="many">Wysyłanie %1$d plików do %2$s</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<plurals name="outgoing_files_text">
|
||||
<item quantity="one">Plik: %1$s</item>
|
||||
<item quantity="few">(Plik %2$d z %3$d) : %1$s</item>
|
||||
<item quantity="many">(Plik %2$d z %3$d) : %1$s</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<plurals name="received_files_title">
|
||||
<item quantity="one">Odebrano plik od %1$s</item>
|
||||
<item quantity="few">Odebrano %2$d pliki od %1$s</item>
|
||||
@@ -118,6 +132,18 @@
|
||||
<item quantity="many">Nie udało się odebrać %2$d z %3$d plików od %1$s</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<plurals name="sent_files_title">
|
||||
<item quantity="one">Wyślij plik do %1$s</item>
|
||||
<item quantity="few">Wyślij %2$d pliki do %1$s</item>
|
||||
<item quantity="many">Wyślij %2$d plików do %1$s</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<plurals name="send_files_fail_title">
|
||||
<item quantity="one">Nie udało się wysłać pliku do %1$s</item>
|
||||
<item quantity="few">Nie udało się wysłać %2$d z %3$d plików do %1$s</item>
|
||||
<item quantity="many">Nie udało się wysłać %2$d z %3$d plików do %1$s</item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<string name="received_file_text">Stuknij, aby otworzyć \'%1s\'</string>
|
||||
<string name="cannot_create_file">Nie można utworzyć pliku %s</string>
|
||||
<string name="tap_to_answer">Stuknij, aby odpowiedzieć</string>
|
||||
@@ -150,7 +176,7 @@
|
||||
<item>2 minuty</item>
|
||||
</string-array>
|
||||
<string name="mpris_notification_settings_title">Pokaż powiadomienia sterowania mediami</string>
|
||||
<string name="mpris_notification_settings_summary">Umożliwia sterowanie odtwarzaczami bez otwierania KDE Connect</string>
|
||||
<string name="mpris_notification_settings_summary">Steruje odtwarzaczami bez otwierania KDE Connect</string>
|
||||
<string name="share_to">Współdziel z...</string>
|
||||
<string name="protocol_version_older">Urządzenie to używa starej wersji protokołu</string>
|
||||
<string name="protocol_version_newer">Urządzenie to używa nowszej wersji protokołu</string>
|
||||
@@ -166,6 +192,10 @@
|
||||
<string name="unpair_device_action">Rozparuj %s</string>
|
||||
<string name="custom_device_list">Dodaj urządzenia po numerze IP</string>
|
||||
<string name="delete_custom_device">Usunąć %s?</string>
|
||||
<string name="custom_device_deleted">Usunięto własne urządzenie</string>
|
||||
<string name="custom_device_list_help">Jeśli twoje urządzenie nie zostało samo wykryte, to możesz dodać jego adres IP lub nazwę gospodarza klikając na pływającym przycisku działania</string>
|
||||
<string name="custom_device_fab_hint">Dodaj urządzenie</string>
|
||||
<string name="undo">Cofnij</string>
|
||||
<string name="share_notification_preference">Hałaśliwe powiadomienia</string>
|
||||
<string name="share_notification_preference_summary">Zadrżyj i odegraj dźwięk przy odebraniu pliku</string>
|
||||
<string name="share_destination_customize">Własny katalog docelowy</string>
|
||||
@@ -176,17 +206,38 @@
|
||||
<string name="share_received_file">Udostępnij \"%s\"</string>
|
||||
<string name="title_activity_notification_filter">Filtr powiadomień</string>
|
||||
<string name="filter_apps_info">Powiadomienia zostaną zsynchronizowane z wybranymi aplikacjami.</string>
|
||||
<string name="sftp_internal_storage">"Pamięć wewnętrzna "</string>
|
||||
<string name="sftp_internal_storage">Pamięć wewnętrzna</string>
|
||||
<string name="sftp_sdcard_num">Karta SD %d</string>
|
||||
<string name="sftp_sdcard">Karta SD</string>
|
||||
<string name="sftp_readonly">(tylko do odczytu)</string>
|
||||
<string name="sftp_camera">Zdjęcia z aparatu</string>
|
||||
<string name="add_device_dialog_title">Dodaj urządzenie</string>
|
||||
<string name="add_device_hint">Nazwa gospodarza lub adres IP</string>
|
||||
<string name="sftp_preference_detected_sdcards">Wykryte karty SD</string>
|
||||
<string name="sftp_preference_edit_sdcard_title">Edytuj kartę SD</string>
|
||||
<string name="sftp_preference_configured_storage_locations">Wybrane miejsca w pamięci</string>
|
||||
<string name="sftp_preference_add_storage_location_title">Dodawanie miejsca w pamięci</string>
|
||||
<string name="sftp_preference_edit_storage_location">Edytowanie miejsca w pamięci</string>
|
||||
<string name="sftp_preference_add_camera_shortcut">Dodaj skrót katalogu aparatu</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_on">Dodaj skrót do katalogu aparatu</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_off">Nie dodawaj skrótu do katalogu aparatu</string>
|
||||
<string name="sftp_storage_preference_storage_location">Miejsce w pamięci</string>
|
||||
<string name="sftp_storage_preference_storage_location_already_configured">To miejsce było już ustawione</string>
|
||||
<string name="sftp_storage_preference_click_to_select">kliknij, aby wybrać</string>
|
||||
<string name="sftp_storage_preference_display_name">Nazwa do wyświetlania</string>
|
||||
<string name="sftp_storage_preference_display_name_already_used">Nazwa do wyświetlania jest już używana</string>
|
||||
<string name="sftp_storage_preference_display_name_cannot_be_empty">Nazwa do wyświetlania nie może być pusta</string>
|
||||
<string name="sftp_action_mode_menu_delete">Usuń</string>
|
||||
<string name="sftp_no_sdcard_detected">Nie wykryto żadnej karty SD</string>
|
||||
<string name="sftp_no_storage_locations_configured">Nie ustawiono miejsc w pamięci</string>
|
||||
<string name="sftp_saf_permission_explanation">Aby przeglądać pliki zdalnie, należy ustawić miejsca w pamięci</string>
|
||||
<string name="add_host">Dodaj gospodarza/IP</string>
|
||||
<string name="add_host_hint">Nazwa gospodarza lub IP</string>
|
||||
<string name="no_players_connected">Nie znaleziono żadnego odtwarzacza</string>
|
||||
<string name="mpris_player_on_device">%1$s na %2$s</string>
|
||||
<string name="send_files">Wyślij pliki</string>
|
||||
<string name="pairing_title">Urządzenia KDE Connect</string>
|
||||
<string name="pairing_description">Tutaj powinny pojawić się inne urządzenia uruchmione z KDE Connect w twojej sieci.</string>
|
||||
<string name="pairing_description">Tu powinny pojawić się urządzenia podłączone do tej samej sieci i które także mają uruchomione KDE Connect.</string>
|
||||
<string name="device_paired">Urządzenie sparowane</string>
|
||||
<string name="device_rename_title">Zmień nazwę urządzenia</string>
|
||||
<string name="device_rename_confirm">Zmień nazwę</string>
|
||||
@@ -205,13 +256,14 @@
|
||||
<string name="open">Otwórz</string>
|
||||
<string name="close">Zamknij</string>
|
||||
<string name="no_permissions_storage">Musisz nadać uprawnienia, aby uzyskać dostęp do pamięci masowej</string>
|
||||
<string name="plugins_need_permission">Niektóre z wtyczek wymagają uprawnień do działania (stuknij po więcej informacji)</string>
|
||||
<string name="plugins_need_permission">Niektóre wtyczki wymagają uprawnień do swojego działania (stuknij, aby dowiedzieć się więcej)</string>
|
||||
<string name="permission_explanation">Ta wtyczka wymaga uprawnień do działania</string>
|
||||
<string name="optional_permission_explanation">Musisz przydzielić dodatkowe uprawnienia, aby włączyć wszystkie funkcje</string>
|
||||
<string name="plugins_need_optional_permission">Niektóre z wtyczek mają ograniczone możliwości ze względu na ograniczone uprawnienia (stuknij po więcej informacji)</string>
|
||||
<string name="share_optional_permission_explanation">Aby udostępniać pliki z twojego telefonu na twoim komputerze musisz pozowolić na dostęp do pamięci telefonu</string>
|
||||
<string name="telepathy_permission_explanation">Aby odczytywać i pisać SMSy z twojego komputera musisz nadać uprawnienia do SMSów</string>
|
||||
<string name="telephony_optional_permission_explanation">Aby widzieć nazwę kontaktu zamiast numeru telefonu musisz pozwolić na dostęp do kontaktów telefonu</string>
|
||||
<string name="plugins_need_optional_permission">Niektóre wtyczki mają ograniczone możliwości ze względu na ograniczone uprawnienia (stuknij, aby dowiedzieć się więcej)</string>
|
||||
<string name="share_optional_permission_explanation">Aby udostępniać pliki z twojego telefonu na twoim komputerze, należy zezwolić na dostęp do pamięci telefonu</string>
|
||||
<string name="telepathy_permission_explanation">Aby odbierać i wysyłać esemesy z pulpitu, należy nadać uprawnienia do esemesów</string>
|
||||
<string name="telephony_permission_explanation">Aby widzieć rozmowy telefoniczne na pulpicie, należy nadać uprawnienia do dziennika rozmów i stanu telefonu</string>
|
||||
<string name="telephony_optional_permission_explanation">Aby widzieć nazwę kontaktu zamiast numeru telefonu, należy zezwolić na dostęp do kontaktów telefonu</string>
|
||||
<string name="contacts_permission_explanation">Aby współdzielić swoją książkę adresową z komputerem musisz udzielić uprawnień do kontaktów</string>
|
||||
<string name="select_ringtone">Wybierz dzwonek</string>
|
||||
<string name="telephony_pref_blocked_title">Zablokowane numery</string>
|
||||
@@ -221,9 +273,10 @@
|
||||
<string name="settings_icon_description">Ikona ustawień</string>
|
||||
<string name="presenter_fullscreen">Pełny ekran</string>
|
||||
<string name="presenter_exit">Zakończ prezentację</string>
|
||||
<string name="presenter_lock_tip">Możesz zablokować swoje urządzenie i używać przycisków głośności, aby przejść do kolejnego/poprzedniego przeźrocza</string>
|
||||
<string name="add_command">Dodaj polecenie</string>
|
||||
<string name="addcommand_explanation">Nie zarejestrowano żadnych poleceń</string>
|
||||
<string name="addcommand_explanation2">Nowe polecenia można dodawać w ustawieniach systemowych KDE Connect</string>
|
||||
<string name="addcommand_explanation2">Nowe polecenie można dodać w ustawieniach systemowych KDE Connect</string>
|
||||
<string name="add_command_description">Możesz dodawać polecenia na pulpicie</string>
|
||||
<string name="pref_plugin_mprisreceiver">Sterowanie odtwarzaczem mediów</string>
|
||||
<string name="pref_plugin_mprisreceiver_desc">Sterowanie odtwarzaczami multimedialnymi z innego urządzenia</string>
|
||||
@@ -250,15 +303,18 @@
|
||||
<string name="settings_rename">Nazwa urządzenia</string>
|
||||
<string name="settings_dark_mode">Ciemny wygląd</string>
|
||||
<string name="settings_more_settings_title">Więcej ustawień</string>
|
||||
<string name="settings_more_settings_text">Wstępne ustawienia urządzenia można znaleźć w \'Ustawieniach wtyczki\' z poziomu urządzenia.</string>
|
||||
<string name="settings_more_settings_text">Ustawienia nadawane urządzeniu można znaleźć w \'Ustawienia wtyczek\' w danym urządzeniu.</string>
|
||||
<string name="setting_persistent_notification">Pokaż nieznikające powiadomienie</string>
|
||||
<string name="setting_persistent_notification_oreo">Nieznikające powiadomienie</string>
|
||||
<string name="setting_persistent_notification_description">Stuknij, aby włączyć/wyłączyć ustawienia powiadomienia</string>
|
||||
<string name="setting_persistent_notification_description">Stuknij, aby je ustawić w ustawieniach powiadamiania</string>
|
||||
<string name="extra_options">Opcje dodatkowe</string>
|
||||
<string name="privacy_options">Opcje prywatności</string>
|
||||
<string name="set_privacy_options">Ustaw swoje opcje prywatności</string>
|
||||
<string name="new_notification">Nowe powiadomienie</string>
|
||||
<string name="block_contents">Blokuj treści w powiadomieniach</string>
|
||||
<string name="block_images">Blokuj obrazy w powiadomieniach</string>
|
||||
<string name="notification_channel_receivenotification">Powiadomienie z innych urządzeń</string>
|
||||
<string name="notification_channel_receivenotification">Powiadomienia z innych urządzeń</string>
|
||||
<string name="take_picture">Uruchom aparat</string>
|
||||
<string name="plugin_photo_desc">Uruchom aplikację aparatu, aby ułatwić robienie i przesyłanie zdjęć</string>
|
||||
<string name="no_app_for_opening">Nie znaleziono aplikacji do otwarcia tego pliku</string>
|
||||
</resources>
|
||||
|
@@ -13,6 +13,7 @@
|
||||
<string name="pref_plugin_clipboard_desc">Использование общего буфера обмена</string>
|
||||
<string name="pref_plugin_mousepad">Удалённый ввод</string>
|
||||
<string name="pref_plugin_mousepad_desc">Использование телефона или планшета в качестве сенсорной панели и клавиатуры</string>
|
||||
<string name="pref_plugin_presenter">Пульт управления слайд-шоу</string>
|
||||
<string name="pref_plugin_presenter_desc">Использование телефона для смены слайдов презентации</string>
|
||||
<string name="pref_plugin_remotekeyboard">Получение удалённых нажатий клавиш</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Получение нажатий клавиш с удалённых устройств</string>
|
||||
@@ -35,6 +36,8 @@
|
||||
<string name="cancel">Отмена</string>
|
||||
<string name="open_settings">Настроить</string>
|
||||
<string name="no_permissions">Нужно разрешить доступ к уведомлениям</string>
|
||||
<string name="no_permission_mprisreceiver">Чтобы управлять мультимедийными проигрывателями, необходимо разрешить доступ к уведомлениям</string>
|
||||
<string name="no_permissions_remotekeyboard">Чтобы получать нажатия клавиш, необходимо включить удалённую клавиатуру KDE Connect.</string>
|
||||
<string name="send_ping">Отправить тестовый сигнал</string>
|
||||
<string name="open_mpris_controls">Управление воспроизведением</string>
|
||||
<string name="remotekeyboard_editing_only_title">Обрабатывать удалённые нажатия только при редактировании</string>
|
||||
@@ -149,6 +152,8 @@
|
||||
<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="share">Отправить</string>
|
||||
<string name="share_received_file">Поделиться «%s» с помощью:</string>
|
||||
<string name="title_activity_notification_filter">Фильтр уведомлений</string>
|
||||
<string name="filter_apps_info">Уведомления будут синхронизированы для выбранных приложений.</string>
|
||||
<string name="sftp_internal_storage">Встроенная память</string>
|
||||
@@ -156,6 +161,18 @@
|
||||
<string name="sftp_sdcard">SD-карта</string>
|
||||
<string name="sftp_readonly">(только чтение)</string>
|
||||
<string name="sftp_camera">Фотографии с камеры</string>
|
||||
<string name="add_device_dialog_title">Добавление устройства</string>
|
||||
<string name="add_device_hint">Имя хоста или IP-адрес</string>
|
||||
<string name="sftp_preference_configured_storage_locations">Настроенные общие папки</string>
|
||||
<string name="sftp_preference_add_storage_location_title">Добавить общую папку</string>
|
||||
<string name="sftp_preference_edit_storage_location">Изменение общей папки</string>
|
||||
<string name="sftp_storage_preference_storage_location">Расположение на устройстве</string>
|
||||
<string name="sftp_storage_preference_storage_location_already_configured">Это расположение уже было добавлено</string>
|
||||
<string name="sftp_storage_preference_display_name">Отображаемое имя</string>
|
||||
<string name="sftp_storage_preference_display_name_already_used">Отображаемое имя уже используется</string>
|
||||
<string name="sftp_storage_preference_display_name_cannot_be_empty">Отображаемое имя не может быть пустым</string>
|
||||
<string name="sftp_no_storage_locations_configured">Нет настроенных общих папок</string>
|
||||
<string name="sftp_saf_permission_explanation">Чтобы разрешить удалённый доступ к файлам, необходимо настроить список общих папок.</string>
|
||||
<string name="add_host">Добавить хост/IP-адрес</string>
|
||||
<string name="no_players_connected">Медиапроигрывателей не найдено</string>
|
||||
<string name="mpris_player_on_device">%1$s на %2$s</string>
|
||||
@@ -174,6 +191,7 @@
|
||||
<string name="plugin_not_supported">Этот модуль не поддерживается устройством</string>
|
||||
<string name="findmyphone_title">Поиск телефона</string>
|
||||
<string name="findmyphone_title_tablet">Поиск планшета</string>
|
||||
<string name="findmyphone_title_tv">Поиск телевизора</string>
|
||||
<string name="findmyphone_description">Подача звукового сигнала на устройстве, чтобы вы могли его найти</string>
|
||||
<string name="findmyphone_found">Найден</string>
|
||||
<string name="open">Открыть</string>
|
||||
@@ -185,12 +203,28 @@
|
||||
<string name="plugins_need_optional_permission">Некоторые функции модулей отключены из-за отсутствия необходимых разрешений (нажмите для просмотра подробностей):</string>
|
||||
<string name="share_optional_permission_explanation">Чтобы обмениваться файлами между телефоном и компьютером, необходимо предоставить доступ к встроенной памяти телефона</string>
|
||||
<string name="telepathy_permission_explanation">Чтобы читать и писать SMS с компьютера, вам необходимо дать разрешение на доступ к SMS</string>
|
||||
<string name="telephony_permission_explanation">Чтобы видеть телефонные звонки на компьютере, необходимо дать разрешение на доступ к списку звонков и состоянию телефона</string>
|
||||
<string name="telephony_optional_permission_explanation">Чтобы видеть имя контакта вместо номера телефона, необходимо предоставить доступ к контактам</string>
|
||||
<string name="presenter_fullscreen">На весь экран</string>
|
||||
<string name="presenter_exit">Закончить слайд-шоу</string>
|
||||
<string name="presenter_lock_tip">Вы можете заблокировать устройство и использовать кнопки управления громкостью для перехода к предыдущему/следующему слайду.</string>
|
||||
<string name="addcommand_explanation">Нет настроенных команд.</string>
|
||||
<string name="addcommand_explanation2">Вы можете добавить новые команды в «Параметрах системы» в разделе «KDE Connect».</string>
|
||||
<string name="pref_plugin_mprisreceiver">Управление мультимедиа</string>
|
||||
<string name="dark_theme">Тёмное оформление</string>
|
||||
<string name="notification_channel_default">Прочие уведомления</string>
|
||||
<string name="notification_channel_persistent">Постоянный индикатор</string>
|
||||
<string name="notification_channel_media_control">Управление воспроизведением</string>
|
||||
<string name="notification_channel_filetransfer">Передача файлов</string>
|
||||
<string name="copy_url_to_clipboard">Копировать URL в буфер обмена</string>
|
||||
<string name="clipboard_toast">Скопировано в буфер обмена</string>
|
||||
<string name="runcommand_notreachable">Устройство недоступно</string>
|
||||
<string name="runcommand_notpaired">Устройство не сопряжено</string>
|
||||
<string name="devices">Устройства</string>
|
||||
<string name="settings_rename">Имя устройства</string>
|
||||
<string name="settings_dark_mode">Тёмное оформление</string>
|
||||
<string name="settings_more_settings_title">Дополнительные параметры</string>
|
||||
<string name="setting_persistent_notification">Показывать постоянное уведомление</string>
|
||||
<string name="setting_persistent_notification_oreo">Постоянное уведомление</string>
|
||||
<string name="notification_channel_receivenotification">Уведомления с других устройств</string>
|
||||
</resources>
|
||||
|
@@ -1,6 +1,10 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="kde_connect">KDE Connect</string>
|
||||
<string name="foreground_notification_no_devices">Hiçbir aygıta bağlı değil</string>
|
||||
<string name="foreground_notification_devices">Bağlı: %s</string>
|
||||
<string name="pref_plugin_telephony">Telefon bildiricisi</string>
|
||||
<string name="pref_plugin_telephony_desc">Gelen aramalar için bildirim gönder</string>
|
||||
<string name="pref_plugin_battery">Batarya raporu</string>
|
||||
<string name="pref_plugin_battery_desc">Batarya durumunu belirli aralıklarla raporla</string>
|
||||
<string name="pref_plugin_sftp">Dosya sistemi gösterme</string>
|
||||
@@ -9,12 +13,16 @@
|
||||
<string name="pref_plugin_clipboard_desc">Pano içeriğini paylaş</string>
|
||||
<string name="pref_plugin_mousepad">Uzak girdi</string>
|
||||
<string name="pref_plugin_mousepad_desc">Telefonunuzu veya tabletinizi, dokunmatik veya klavye olarak kullanın</string>
|
||||
<string name="pref_plugin_presenter">Uzaktan slayt gösterisi</string>
|
||||
<string name="pref_plugin_presenter_desc">Sunumdaki slaytları değiştirmek için aygıtınızı kullanın</string>
|
||||
<string name="pref_plugin_remotekeyboard">Uzak tuşa basmaları getir</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Tuş basma eylemlerini, uzak aygıtlardan getir</string>
|
||||
<string name="pref_plugin_mpris">Çoklu ortam denetimleri</string>
|
||||
<string name="pref_plugin_mpris_desc">Ortam oynatıcınız için uzak denetim sağlar</string>
|
||||
<string name="pref_plugin_runcommand">Komut Çalıştır</string>
|
||||
<string name="pref_plugin_runcommand_desc">Uzak komutları, telefon veya tabletinizden tetikler</string>
|
||||
<string name="pref_plugin_contacts">Rehber Eşitleyici</string>
|
||||
<string name="pref_plugin_contacts_desc">Aygıtın rehberini eşitle</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Ping gönder ve al</string>
|
||||
<string name="pref_plugin_notifications">Bildirim eşitleme</string>
|
||||
@@ -29,6 +37,8 @@
|
||||
<string name="cancel">İptal</string>
|
||||
<string name="open_settings">Ayarları aç</string>
|
||||
<string name="no_permissions">Bildirimler erişebilmek için izine ihtiyacınız var</string>
|
||||
<string name="no_permission_mprisreceiver">Medya oynatıcılarınızı kontrol edebilmek için bildirimlere erişim izni vermeniz gerekir</string>
|
||||
<string name="no_permissions_remotekeyboard">Tuşlara basmak için KDE Connect Uzak Klavye\'yi etkinleştirmeniz gerekir</string>
|
||||
<string name="send_ping">Ping gönder</string>
|
||||
<string name="open_mpris_controls">Çoklu ortam denetimi</string>
|
||||
<string name="remotekeyboard_editing_only_title">Uzak tuşları, sadece düzenleme yaparken işle</string>
|
||||
@@ -36,9 +46,11 @@
|
||||
<string name="remotekeyboard_connected">Uzak klavye bağlantısı etkin</string>
|
||||
<string name="remotekeyboard_multiple_connections">Birden çok uzak klavye bağlantısı mevcut, yapılandırmak istediğiniz aygıtı seçin</string>
|
||||
<string name="open_mousepad">Girdi sil</string>
|
||||
<string name="mousepad_info">İmleç kontrolü için parmağınızı ekranda hareket ettirin. Bir tıklama için hafifçe vurun, sağ ve orta düğmeler için iki/üç parmağınızı kullanın. Kaydırmak için 2 parmağınızı kullanın. Bırakıp sürüklemek için uzun basın.</string>
|
||||
<string name="mousepad_double_tap_settings_title">İki parmak dokunma eylemini ayarla</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Üç parmak dokunma eylemini ayarla</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Dokunmatik yüzey hassasiyetini ayarla</string>
|
||||
<string name="mousepad_acceleration_profile_settings_title">İşaretçi ivmesini ayarla</string>
|
||||
<string name="mousepad_scroll_direction_title">Ters Kaydırma Yönü</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Sağ tık</item>
|
||||
@@ -53,12 +65,12 @@
|
||||
<item>En Hızlı</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_acceleration_profile_entries">
|
||||
<item>No Acceleration</item>
|
||||
<item>Weakest</item>
|
||||
<item>Weaker</item>
|
||||
<item>Medium</item>
|
||||
<item>Stronger</item>
|
||||
<item>Strongest</item>
|
||||
<item>Hızlandırıcı Yok</item>
|
||||
<item>Zayıf</item>
|
||||
<item>Güçsüz</item>
|
||||
<item>Orta</item>
|
||||
<item>Güçlü</item>
|
||||
<item>Kuvvetli</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Bağlı aygıtlar</string>
|
||||
<string name="category_not_paired_devices">Kullanılabilir aygıtlar</string>
|
||||
@@ -84,7 +96,40 @@
|
||||
<string name="pairing_request_from">%1s için eşleşme talebi</string>
|
||||
<string name="received_url_title">%1s üzerinden bağlantı alındı</string>
|
||||
<string name="received_url_text">\'%1s\' açmak için dokunun</string>
|
||||
<plurals name="incoming_file_title">
|
||||
<item quantity="one">%2$s içinden %1$d dosya alınıyor</item>
|
||||
<item quantity="other">%2$s içinden %1$d dosyalar alınıyor</item>
|
||||
</plurals>
|
||||
<plurals name="incoming_files_text">
|
||||
<item quantity="one">Dosya: %1s</item>
|
||||
<item quantity="other">(Dosya %2$d %3$d) : %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_file_title">
|
||||
<item quantity="one">%1$d dosya %2$s gönderiliyor</item>
|
||||
<item quantity="other">%1$d dosyalar %2$s gönderiliyor</item>
|
||||
</plurals>
|
||||
<plurals name="outgoing_files_text">
|
||||
<item quantity="one">Dosya: %1$s</item>
|
||||
<item quantity="other">(Dosya %2$d %3$d) : %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_title">
|
||||
<item quantity="one">%1$s ögesinden alınan dosya</item>
|
||||
<item quantity="other">%1$s içinden %2$d dosya alındı</item>
|
||||
</plurals>
|
||||
<plurals name="received_files_fail_title">
|
||||
<item quantity="one">%1$s dosya alınamadı</item>
|
||||
<item quantity="other">%1$s içindeki %2$d / %3$d dosya alınamadı</item>
|
||||
</plurals>
|
||||
<plurals name="sent_files_title">
|
||||
<item quantity="one">Dosyayı şuraya gönder %1$s</item>
|
||||
<item quantity="other">Gönder %2$d şuraya %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="send_files_fail_title">
|
||||
<item quantity="one">Dosya gönderilemedi %1$s</item>
|
||||
<item quantity="other">Dosya gönderilemedi %2$d %3$d şuraya %1$s</item>
|
||||
</plurals>
|
||||
<string name="received_file_text">\'%1s\' açmak için dokunun</string>
|
||||
<string name="cannot_create_file">Dosya oluşturulamıyor %s</string>
|
||||
<string name="tap_to_answer">Cevap için dokunun</string>
|
||||
<string name="reconnect">Yeniden Bağlan</string>
|
||||
<string name="right_click">Sağ Tık Gönder</string>
|
||||
@@ -96,7 +141,9 @@
|
||||
<string name="pairing_reject">Reddet</string>
|
||||
<string name="device">Aygıt</string>
|
||||
<string name="pair_device">Aygıt eşleştir</string>
|
||||
<string name="settings">Ayarlar</string>
|
||||
<string name="mpris_play">Oynat</string>
|
||||
<string name="mpris_pause">Duraklat</string>
|
||||
<string name="mpris_previous">Önceki</string>
|
||||
<string name="mpris_rew">Geri Sar</string>
|
||||
<string name="mpris_ff">Hızlı İleri Sar</string>
|
||||
@@ -104,6 +151,7 @@
|
||||
<string name="mpris_volume">Ses</string>
|
||||
<string name="mpris_settings">Çoklu Ortam Ayarları</string>
|
||||
<string name="mpris_time_settings_title">İleri/geri düğmeleri</string>
|
||||
<string name="mpris_time_settings_summary">Basıldığında hızlı ileri/geri sarma süresini ayarlayın</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 saniye</item>
|
||||
<item>20 saniye</item>
|
||||
@@ -111,6 +159,9 @@
|
||||
<item>1 dakika</item>
|
||||
<item>2 dakika</item>
|
||||
</string-array>
|
||||
<string name="mpris_notification_settings_title">Medya kontrol bildirimini göster</string>
|
||||
<string name="mpris_notification_settings_summary">KDE Connect\'i açmadan medya oynatıcılarınızı kontrol etmenize izin verin</string>
|
||||
<string name="share_to">Paylaş…</string>
|
||||
<string name="protocol_version_older">Bu aygıt, eski bir protokol sürümü kullanıyor</string>
|
||||
<string name="protocol_version_newer">Bu aygıt, daha yeni bir protokol sürümü kullanıyor</string>
|
||||
<string name="general_settings">Genel Ayarlar</string>
|
||||
@@ -124,12 +175,19 @@
|
||||
<string name="pair_device_action">Yeni bir aygıt eşleştir</string>
|
||||
<string name="unpair_device_action">Ayır %s</string>
|
||||
<string name="custom_device_list">IP\'ye göre aygıtları ekle</string>
|
||||
<string name="delete_custom_device">Sil %s?</string>
|
||||
<string name="custom_device_deleted">Özel aygıt silindi</string>
|
||||
<string name="custom_device_list_help">Cihazınız otomatik olarak algılanmazsa, İşlem Düğmesine tıklayarak IP adresini veya ana bilgisayar adını ekleyebilirsiniz</string>
|
||||
<string name="custom_device_fab_hint">Aygıt ekle</string>
|
||||
<string name="undo">Geri al</string>
|
||||
<string name="share_notification_preference">Sesli bildirimler</string>
|
||||
<string name="share_notification_preference_summary">Bir dosya alırken, ses çıkar ve titret</string>
|
||||
<string name="share_destination_customize">Hedef dizini özelleştir</string>
|
||||
<string name="share_destination_customize_summary_disabled">Gelen dosyalar İndirilenler\'de gözükecektir</string>
|
||||
<string name="share_destination_customize_summary_enabled">Dosyalar aşağıdaki dizinden depolanacaktır</string>
|
||||
<string name="share_destination_folder_preference">Hedef dizin</string>
|
||||
<string name="share">Paylaş</string>
|
||||
<string name="share_received_file">Paylaş \"%s\"</string>
|
||||
<string name="title_activity_notification_filter">Bildirim süzgeci</string>
|
||||
<string name="filter_apps_info">Bildirimler, seçili uygulamalar için eşitlenecektir.</string>
|
||||
<string name="sftp_internal_storage">Harici depolama</string>
|
||||
@@ -137,7 +195,28 @@
|
||||
<string name="sftp_sdcard">SD kart</string>
|
||||
<string name="sftp_readonly">(salt okunur)</string>
|
||||
<string name="sftp_camera">Kamera resimleri</string>
|
||||
<string name="add_device_dialog_title">Aygıt ekle</string>
|
||||
<string name="add_device_hint">Makine adı veya IP adresi</string>
|
||||
<string name="sftp_preference_detected_sdcards">Algılanan SD kartlar</string>
|
||||
<string name="sftp_preference_edit_sdcard_title">SD Kartı Düzenle</string>
|
||||
<string name="sftp_preference_configured_storage_locations">Yapılandırılmış depolama yerleri</string>
|
||||
<string name="sftp_preference_add_storage_location_title">Depolama yeri ekle</string>
|
||||
<string name="sftp_preference_edit_storage_location">Depolama yerini düzenle</string>
|
||||
<string name="sftp_preference_add_camera_shortcut">Kamera klasörü kısayolu ekle</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_on">Kamera klasörüne kısayol ekle</string>
|
||||
<string name="sftp_preference_add_camera_shortcut_summary_off">Kamera klasörüne kısayol eklemeyin</string>
|
||||
<string name="sftp_storage_preference_storage_location">Depolama yeri</string>
|
||||
<string name="sftp_storage_preference_storage_location_already_configured">Bu konum zaten yapılandırılmış</string>
|
||||
<string name="sftp_storage_preference_click_to_select">seçmek için tıkla</string>
|
||||
<string name="sftp_storage_preference_display_name">Ekran adı</string>
|
||||
<string name="sftp_storage_preference_display_name_already_used">Bu görünen ad zaten kullanılıyor</string>
|
||||
<string name="sftp_storage_preference_display_name_cannot_be_empty">Görünen ad boş olamaz</string>
|
||||
<string name="sftp_action_mode_menu_delete">Sil</string>
|
||||
<string name="sftp_no_sdcard_detected">SD kart algılanmadı</string>
|
||||
<string name="sftp_no_storage_locations_configured">Yapılandırılmış depolama yeri yok</string>
|
||||
<string name="sftp_saf_permission_explanation">Dosyalara uzaktan erişmek için depolama konumlarını yapılandırmanız gerekir</string>
|
||||
<string name="add_host">Makine/IP ekle</string>
|
||||
<string name="add_host_hint">Makine adı yada IP</string>
|
||||
<string name="no_players_connected">Onatıcı bulunamadı</string>
|
||||
<string name="mpris_player_on_device">%2$s üzerindeki %1$s</string>
|
||||
<string name="send_files">Dosyaları gönder</string>
|
||||
@@ -155,6 +234,7 @@
|
||||
<string name="plugin_not_supported">Eklenti, aygıt tarafından desteklenmiyor</string>
|
||||
<string name="findmyphone_title">Telefonumu bul</string>
|
||||
<string name="findmyphone_title_tablet">Tabletimi bul</string>
|
||||
<string name="findmyphone_title_tv">TV\'mi bul</string>
|
||||
<string name="findmyphone_description">Aygıtı bulmak için onu çaldır</string>
|
||||
<string name="findmyphone_found">Bulundu</string>
|
||||
<string name="open">Aç</string>
|
||||
@@ -166,5 +246,59 @@
|
||||
<string name="plugins_need_optional_permission">Bazı eklentilerin özellikleri, izin yetersizliğinden kapalı gelmektedir (daha fazla bilgi için dokunun):</string>
|
||||
<string name="share_optional_permission_explanation">Telefon ve masaüstünüz arasında dosya paylaşılabilmesi için, telefonun depolama alanına erişim izni olmalıdır</string>
|
||||
<string name="telepathy_permission_explanation">Masaüstünde SMS yazma ve okuma yapmak için SMS izni gereklidir</string>
|
||||
<string name="telephony_permission_explanation">Masaüstünde telefon görüşmelerini görmek için telefon görüşmesi kayıtlarına ve telefon durumuna izin vermeniz gerekir</string>
|
||||
<string name="telephony_optional_permission_explanation">Telefon numarası yerine kişi ismi görebilmek için telefonun kişilerine erişim gereklidir</string>
|
||||
<string name="contacts_permission_explanation">Rehberinizi masaüstüyle paylaşmak için rehbere izin vermeniz gerekir</string>
|
||||
<string name="select_ringtone">Bir zil sesi seç</string>
|
||||
<string name="telephony_pref_blocked_title">Engellenen numaralar</string>
|
||||
<string name="telephony_pref_blocked_dialog_desc">Bu numaralardan gelen aramaları ve SMS\'leri gösterme. Lütfen her satıra bir numara belirtin</string>
|
||||
<string name="mpris_coverart_description">Güncel medyanın kapak resmi</string>
|
||||
<string name="device_icon_description">Aygıt simgesi</string>
|
||||
<string name="settings_icon_description">Ayarlar simgesi</string>
|
||||
<string name="presenter_fullscreen">Tam ekran</string>
|
||||
<string name="presenter_exit">Sunumdan çık</string>
|
||||
<string name="presenter_lock_tip">Bir önceki/bir sonraki slayta geçmek için aygıtınızı kilitleyebilir ve ses seviyesi tuşlarını kullanabilirsiniz</string>
|
||||
<string name="add_command">Komut ekle</string>
|
||||
<string name="addcommand_explanation">Kayıtlı komut yok</string>
|
||||
<string name="addcommand_explanation2">KDE Connect Sistem Ayarlarında yeni komutlar ekleyebilirsiniz</string>
|
||||
<string name="add_command_description">Masaüstüne komut ekleyebilirsiniz</string>
|
||||
<string name="pref_plugin_mprisreceiver">Medya Oynatıcı Kontrolü</string>
|
||||
<string name="pref_plugin_mprisreceiver_desc">Telefonunuzun medya oynatıcılarını başka bir cihazdan kontrol edin</string>
|
||||
<string name="dark_theme">Karanlık tema</string>
|
||||
<string name="notification_channel_default">Diğer bildirimler</string>
|
||||
<string name="notification_channel_persistent">Kalıcı gösterge</string>
|
||||
<string name="notification_channel_media_control">Medya kontrolü</string>
|
||||
<string name="notification_channel_filetransfer">Dosya aktarımı</string>
|
||||
<string name="mpris_stop">Geçerli oynatıcıyı durdur</string>
|
||||
<string name="copy_url_to_clipboard">URL\'yi panoya kopyala</string>
|
||||
<string name="clipboard_toast">Panoya kopyalandı</string>
|
||||
<string name="runcommand_notreachable">Aygıt erişilebilir değil</string>
|
||||
<string name="runcommand_notpaired">Aygıt eşleştirilmedi</string>
|
||||
<string name="runcommand_nosuchdevice">Böyle bir aygıt yok</string>
|
||||
<string name="runcommand_noruncommandplugin">Bu cihazda Komut Çalıştır Eklentisi etkin değil</string>
|
||||
<string name="pref_plugin_findremotedevice">Uzak aygıtı bul</string>
|
||||
<string name="pref_plugin_findremotedevice_desc">Uzak aygıtı çaldır</string>
|
||||
<string name="ring">Zil sesi</string>
|
||||
<string name="pref_plugin_systemvolume">Sistem sesi</string>
|
||||
<string name="pref_plugin_systemvolume_desc">Uzak cihazın sistem sesini kontrol et</string>
|
||||
<string name="mute">Sessiz</string>
|
||||
<string name="all">Tümü</string>
|
||||
<string name="devices">Aygıtlar</string>
|
||||
<string name="settings_rename">Aygıt adı</string>
|
||||
<string name="settings_dark_mode">Karanlık tema</string>
|
||||
<string name="settings_more_settings_title">Daha fazla ayar</string>
|
||||
<string name="settings_more_settings_text">Aygıt başına ayarlar, bir aygıt içinden \'Eklenti ayarları\' altında bulunabilir.</string>
|
||||
<string name="setting_persistent_notification">Kalıcı bildirim göster</string>
|
||||
<string name="setting_persistent_notification_oreo">Kalıcı bildirim</string>
|
||||
<string name="setting_persistent_notification_description">Bildirim ayarlarında etkinleştirmek/devre dışı bırakmak için dokun</string>
|
||||
<string name="extra_options">Ek seçenekler</string>
|
||||
<string name="privacy_options">Gizlilik seçenekleri</string>
|
||||
<string name="set_privacy_options">Gizlilik seçeneklerinizi ayarlayın</string>
|
||||
<string name="new_notification">Yeni bildirim</string>
|
||||
<string name="block_contents">Bildirimlerin içeriğini engelle</string>
|
||||
<string name="block_images">Bildirimlerde görüntüleri engelle</string>
|
||||
<string name="notification_channel_receivenotification">Diğer aygıtlardan gelen bildirimler</string>
|
||||
<string name="take_picture">Kamerayı başlat</string>
|
||||
<string name="plugin_photo_desc">Fotoğraf çekmeyi ve aktarmayı kolaylaştırmak için kamera uygulamasını başlatın</string>
|
||||
<string name="no_app_for_opening">Bu dosyayı açmak için uygun bir uygulama bulunamadı</string>
|
||||
</resources>
|
||||
|
@@ -13,6 +13,7 @@
|
||||
<string name="pref_plugin_clipboard_desc">共享剪贴板内容</string>
|
||||
<string name="pref_plugin_mousepad">远程输入</string>
|
||||
<string name="pref_plugin_mousepad_desc">将您的手机用或平板电脑用作触摸板和键盘</string>
|
||||
<string name="pref_plugin_presenter">幻灯片遥控器</string>
|
||||
<string name="pref_plugin_presenter_desc">使用移动设备切换幻灯片</string>
|
||||
<string name="pref_plugin_remotekeyboard">接收远程按键</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">从远程设备接收按键事件</string>
|
||||
|
5
res/xml/network_security_config.xml
Normal file
5
res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<!--Set application-wide security config using base-config tag.-->
|
||||
<base-config cleartextTrafficPermitted="true"/>
|
||||
</network-security-config>
|
@@ -100,24 +100,9 @@ public class BackgroundService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
public static void addGuiInUseCounter(Context activity) {
|
||||
addGuiInUseCounter(activity, false);
|
||||
}
|
||||
|
||||
public static void addGuiInUseCounter(final Context activity, final boolean forceNetworkRefresh) {
|
||||
BackgroundService.RunCommand(activity, service -> {
|
||||
boolean refreshed = service.acquireDiscoveryMode(activity);
|
||||
if (!refreshed && forceNetworkRefresh) {
|
||||
service.onNetworkChange();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void removeGuiInUseCounter(final Context activity) {
|
||||
BackgroundService.RunCommand(activity, service -> {
|
||||
//If no user interface is open, close the connections open to other devices
|
||||
service.releaseDiscoveryMode(activity);
|
||||
});
|
||||
private boolean isInDiscoveryMode() {
|
||||
//return !discoveryModeAcquisitions.isEmpty();
|
||||
return true; // Keep it always on for now
|
||||
}
|
||||
|
||||
private final Device.PairingCallback devicePairingCallback = new Device.PairingCallback() {
|
||||
@@ -209,7 +194,7 @@ public class BackgroundService extends Service {
|
||||
device = new Device(BackgroundService.this, identityPacket, link);
|
||||
if (device.isPaired() || device.isPairRequested() || device.isPairRequestedByPeer()
|
||||
|| link.linkShouldBeKeptAlive()
|
||||
|| !discoveryModeAcquisitions.isEmpty()) {
|
||||
|| isInDiscoveryMode()) {
|
||||
devices.put(deviceId, device);
|
||||
device.addPairingCallback(devicePairingCallback);
|
||||
} else {
|
||||
|
@@ -401,14 +401,11 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
.build();
|
||||
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, noti);
|
||||
|
||||
BackgroundService.addGuiInUseCounter(context);
|
||||
}
|
||||
|
||||
public void hidePairingNotification() {
|
||||
final NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(notificationId);
|
||||
BackgroundService.removeGuiInUseCounter(context);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -421,6 +418,8 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
|
||||
public void addLink(NetworkPacket identityPacket, BaseLink link) {
|
||||
//FilesHelper.LogOpenFileCount();
|
||||
links.add(link);
|
||||
link.addPacketReceiver(this);
|
||||
|
||||
this.protocolVersion = identityPacket.getInt("protocolVersion");
|
||||
|
||||
@@ -448,9 +447,6 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
links.add(link);
|
||||
|
||||
try {
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
byte[] privateKeyBytes = Base64.decode(globalSettings.getString("privateKey", ""), 0);
|
||||
@@ -499,7 +495,6 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
supportedPlugins = new Vector<>(PluginFactory.getAvailablePlugins());
|
||||
}
|
||||
|
||||
link.addPacketReceiver(this);
|
||||
|
||||
reloadPluginsFromSettings();
|
||||
|
||||
|
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Albert Vaca Cintora <albertvaka@gmail.com>
|
||||
*
|
||||
* 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.Helpers;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
class ImagesHelper {
|
||||
|
||||
public static Bitmap drawableToBitmap(Drawable drawable) {
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
return ((BitmapDrawable) drawable).getBitmap();
|
||||
}
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
}
|
@@ -1,17 +1,14 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.LineNumberReader;
|
||||
|
||||
public class NetworkHelper {
|
||||
|
||||
public static boolean isOnMobileNetwork(Context context) {
|
||||
|
||||
return false;
|
||||
|
||||
/*
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -52,6 +49,8 @@ public class NetworkHelper {
|
||||
Log.e("isOnMobileNetwork", "Something went wrong, but this is non-critical.", e);
|
||||
}
|
||||
return false;
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -20,9 +20,12 @@
|
||||
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Looper;
|
||||
@@ -32,17 +35,26 @@ import android.util.Log;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
public class SMSHelper {
|
||||
|
||||
/**
|
||||
@@ -62,7 +74,6 @@ public class SMSHelper {
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.KITKAT)
|
||||
private static Uri getSMSURIGood() {
|
||||
// TODO: Why not use Telephony.MmsSms.CONTENT_URI?
|
||||
return Telephony.Sms.CONTENT_URI;
|
||||
}
|
||||
|
||||
@@ -74,12 +85,34 @@ public class SMSHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private static Uri getMMSUri() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
return Telephony.Mms.CONTENT_URI;
|
||||
} else {
|
||||
// Same as with getSMSUriBad, this is unsafe if the manufacturer did their own thing
|
||||
// before this was part of the API
|
||||
return Uri.parse("content://mms/");
|
||||
}
|
||||
}
|
||||
|
||||
private static Uri getMMSPartUri() {
|
||||
// Android says we should have Telephony.Mms.Part.CONTENT_URI. Alas, we do not.
|
||||
return Uri.parse("content://mms/part/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base address for all message conversations
|
||||
*/
|
||||
private static Uri getConversationUri() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
return Telephony.MmsSms.CONTENT_CONVERSATIONS_URI;
|
||||
} else if ("Samsung".equals(Build.MANUFACTURER)){
|
||||
// For some presumably asinine reason, Samsung devices do not support the regular SmsMms column.
|
||||
// However, according to https://stackoverflow.com/a/13640868/3723163, we can work around it this way.
|
||||
// By my understanding, "simple=true" means we can't support multi-target messages.
|
||||
// Go complain to Samsung about their crappy OS changes!
|
||||
Log.i("SMSHelper", "Samsung compatibility mode enabled. This may cause some features to not work properly.");
|
||||
return Uri.parse("content://mms-sms/conversations?simple=true");
|
||||
} else {
|
||||
// As with getSMSUriBad, this is potentially unsafe depending on whether a specific
|
||||
// manufacturer decided to do their own thing
|
||||
@@ -87,6 +120,26 @@ public class SMSHelper {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.FROYO)
|
||||
private static Uri getCompleteConversationsUri() {
|
||||
// This glorious - but completely undocumented - content URI gives us all messages, both MMS and SMS,
|
||||
// in all conversations
|
||||
// See https://stackoverflow.com/a/36439630/3723163
|
||||
return Uri.parse("content://mms-sms/complete-conversations");
|
||||
}
|
||||
|
||||
/**
|
||||
* Column used to discriminate between SMS and MMS messages
|
||||
* Unfortunately, this column is not defined for Telephony.MmsSms.CONTENT_CONVERSATIONS_URI
|
||||
* (aka. content://mms-sms/conversations)
|
||||
* which gives us the first message in every conversation, but it *is* defined for
|
||||
* content://mms-sms/conversations/<threadID> which gives us the complete conversation matching
|
||||
* that threadID, so at least it's partially useful to us.
|
||||
*/
|
||||
private static String getTransportTypeDiscriminatorColumn() {
|
||||
return Telephony.MmsSms.TYPE_DISCRIMINATOR_COLUMN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the messages in a requested thread
|
||||
*
|
||||
@@ -94,53 +147,108 @@ public class SMSHelper {
|
||||
* @param threadID Thread to look up
|
||||
* @return List of all messages in the thread
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public static List<Message> getMessagesInThread(Context context, ThreadID threadID) {
|
||||
final String selection = ThreadID.lookupColumn + " == ?";
|
||||
final String[] selectionArgs = new String[] { threadID.toString() };
|
||||
public static @NonNull List<Message> getMessagesInThread(
|
||||
@NonNull Context context,
|
||||
@NonNull ThreadID threadID
|
||||
) {
|
||||
Uri uri = Uri.withAppendedPath(getConversationUri(), threadID.toString());
|
||||
|
||||
return getMessagesWithFilter(context, selection, selectionArgs);
|
||||
return getMessages(uri, context, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all messages which have a timestamp after the requested timestamp
|
||||
* Get the newest sent or received message
|
||||
*
|
||||
* This might have some potential for race conditions if many messages are received in a short
|
||||
* timespan, but my target use-case is humans sending and receiving messages, so I don't think
|
||||
* it will be an issue
|
||||
*
|
||||
* @param timestamp epoch in millis matching the timestamp to return
|
||||
* @return null if no matching message is found, otherwise return a Message
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public static List<Message> getMessagesSinceTimestamp(Context context, long timestamp) {
|
||||
final String selection = Message.DATE + " > ?";
|
||||
final String[] selectionArgs = new String[] {Long.toString(timestamp)};
|
||||
public static @Nullable Message getNewestMessage(
|
||||
@NonNull Context context
|
||||
) {
|
||||
List<Message> messages = getMessagesWithFilter(context, null, null, 1L);
|
||||
|
||||
return getMessagesWithFilter(context, selection, selectionArgs);
|
||||
if (messages.size() > 1) {
|
||||
Log.w("SMSHelper", "getNewestMessage asked for one message but got " + messages.size());
|
||||
}
|
||||
if (messages.size() < 1) {
|
||||
return null;
|
||||
} else {
|
||||
return messages.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Messages for caller functions, such as: getMessagesWithFilter() and getConversations()
|
||||
* Gets messages which match the selection
|
||||
*
|
||||
* @param Uri Uri indicating the messages database to read
|
||||
* @param uri Uri indicating the messages database to read
|
||||
* @param context android.content.Context running the request.
|
||||
* @param selection Parameterizable filter to use with the ContentResolver query. May be null.
|
||||
* @param selectionArgs Parameters for selection. May be null.
|
||||
* @return Returns HashMap<ThreadID, List<Message>>, which is transformed in caller functions into other classes.
|
||||
* @param sortOrder Sort ordering passed to Android's content resolver. May be null for unspecified
|
||||
* @param numberToGet Number of things to get from the result. Pass null to get all
|
||||
* @return Returns List<Message> of all messages in the return set, either in the order of sortOrder or in an unspecified order
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private static HashMap<ThreadID, List<Message>> getMessages(Uri Uri,
|
||||
Context context,
|
||||
String selection,
|
||||
String[] selectionArgs) {
|
||||
HashMap<ThreadID, List<Message>> toReturn = new HashMap<>();
|
||||
try (Cursor myCursor = context.getContentResolver().query(
|
||||
Uri,
|
||||
Message.smsColumns,
|
||||
private static @NonNull List<Message> getMessages(
|
||||
@NonNull Uri uri,
|
||||
@NonNull Context context,
|
||||
@Nullable String selection,
|
||||
@Nullable String[] selectionArgs,
|
||||
@Nullable String sortOrder,
|
||||
@Nullable Long numberToGet
|
||||
) {
|
||||
List<Message> toReturn = new ArrayList<>();
|
||||
|
||||
Set<String> allColumns = new HashSet<>();
|
||||
allColumns.addAll(Arrays.asList(Message.smsColumns));
|
||||
allColumns.addAll(Arrays.asList(Message.mmsColumns));
|
||||
|
||||
if (uri != getConversationUri()) {
|
||||
// See https://issuetracker.google.com/issues/134592631
|
||||
allColumns.add(getTransportTypeDiscriminatorColumn());
|
||||
}
|
||||
|
||||
String[] fetchColumns = {};
|
||||
fetchColumns = allColumns.toArray(fetchColumns);
|
||||
try (Cursor myCursor = context.getContentResolver().query(
|
||||
uri,
|
||||
fetchColumns,
|
||||
selection,
|
||||
selectionArgs,
|
||||
null)
|
||||
sortOrder)
|
||||
) {
|
||||
if (myCursor != null && myCursor.moveToFirst()) {
|
||||
int threadColumn = myCursor.getColumnIndexOrThrow(ThreadID.lookupColumn);
|
||||
do {
|
||||
int transportTypeColumn = myCursor.getColumnIndex(getTransportTypeDiscriminatorColumn());
|
||||
|
||||
TransportType transportType;
|
||||
if (transportTypeColumn < 0) {
|
||||
// The column didn't actually exist. See https://issuetracker.google.com/issues/134592631
|
||||
// Try to determine using other information
|
||||
int messageBoxColumn = myCursor.getColumnIndex(Telephony.Mms.MESSAGE_BOX);
|
||||
// MessageBoxColumn is defined for MMS only
|
||||
boolean messageBoxExists = !myCursor.isNull(messageBoxColumn);
|
||||
if (messageBoxExists) {
|
||||
transportType = TransportType.MMS;
|
||||
} else {
|
||||
// There is room here for me to have made an assumption and we'll guess wrong
|
||||
// The penalty is the user will potentially get some garbled data, so that's not too bad.
|
||||
transportType = TransportType.SMS;
|
||||
}
|
||||
} else {
|
||||
String transportTypeString = myCursor.getString(transportTypeColumn);
|
||||
if ("mms".equals(transportTypeString)) {
|
||||
transportType = TransportType.MMS;
|
||||
} else if ("sms".equals(transportTypeString)) {
|
||||
transportType = TransportType.SMS;
|
||||
} else {
|
||||
Log.w("SMSHelper", "Skipping message with unknown TransportType: " + transportTypeString);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
HashMap<String, String> messageInfo = new HashMap<>();
|
||||
for (int columnIdx = 0; columnIdx < myCursor.getColumnCount(); columnIdx++) {
|
||||
String colName = myCursor.getColumnName(columnIdx);
|
||||
@@ -148,38 +256,41 @@ public class SMSHelper {
|
||||
messageInfo.put(colName, body);
|
||||
}
|
||||
|
||||
Message message = new Message(messageInfo);
|
||||
ThreadID threadID = new ThreadID(message.threadID);
|
||||
|
||||
if (!toReturn.containsKey(threadID)) {
|
||||
toReturn.put(threadID, new ArrayList<>());
|
||||
if (transportType == TransportType.SMS) {
|
||||
parseSMS(context, messageInfo);
|
||||
} else if (transportType == TransportType.MMS) {
|
||||
parseMMS(context, messageInfo);
|
||||
}
|
||||
toReturn.get(threadID).add(message);
|
||||
} while (myCursor.moveToNext());
|
||||
} else {
|
||||
// No conversations or SMSes available?
|
||||
|
||||
Message message = new Message(messageInfo);
|
||||
|
||||
toReturn.add(message);
|
||||
} while ((numberToGet == null || toReturn.size() != numberToGet) && myCursor.moveToNext());
|
||||
}
|
||||
} catch (SQLiteException e) {
|
||||
throw new MessageAccessException(fetchColumns, uri, e);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all messages matching the passed filter. See documentation for Android's ContentResolver
|
||||
*
|
||||
* @param context android.content.Context running the request
|
||||
* @param selection Parameterizable filter to use with the ContentResolver query. May be null.
|
||||
* @param selectionArgs Parameters for selection. May be null.
|
||||
* @return List of messages matching the filter
|
||||
* @param numberToGet Number of things to return. Pass null to get all
|
||||
* @return List of messages matching the filter, from newest to oldest
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private static List<Message> getMessagesWithFilter(Context context, String selection, String[] selectionArgs) {
|
||||
HashMap<ThreadID, List<Message>> result = getMessages(SMSHelper.getSMSUri(), context, selection, selectionArgs);
|
||||
List<Message> toReturn = new ArrayList<>();
|
||||
private static List<Message> getMessagesWithFilter(
|
||||
@NonNull Context context,
|
||||
@Nullable String selection,
|
||||
@Nullable String[] selectionArgs,
|
||||
@Nullable Long numberToGet
|
||||
) {
|
||||
String sortOrder = Message.DATE + " DESC";
|
||||
|
||||
for(Map.Entry<ThreadID, List<Message>> entry : result.entrySet()) {
|
||||
toReturn.addAll(entry.getValue());
|
||||
}
|
||||
return toReturn;
|
||||
return getMessages(getCompleteConversationsUri(), context, selection, selectionArgs, sortOrder, numberToGet);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,28 +300,230 @@ public class SMSHelper {
|
||||
* @param context android.content.Context running the request
|
||||
* @return Mapping of thread_id to the first message in each thread
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public static Map<ThreadID, Message> getConversations(Context context) {
|
||||
HashMap<ThreadID, List<Message>> result = getMessages(SMSHelper.getConversationUri(), context, null, null);
|
||||
HashMap<ThreadID, Message> toReturn = new HashMap<>();
|
||||
public static Map<ThreadID, Message> getConversations(
|
||||
@NonNull Context context
|
||||
) {
|
||||
Uri uri = SMSHelper.getConversationUri();
|
||||
|
||||
for(Map.Entry<ThreadID, List<Message>> entry : result.entrySet()) {
|
||||
ThreadID returnThreadID = entry.getKey();
|
||||
List<Message> messages = entry.getValue();
|
||||
List<Message> unthreadedMessages = getMessages(uri, context, null, null, null, null);
|
||||
|
||||
toReturn.put(returnThreadID, messages.get(0));
|
||||
Map<ThreadID, Message> toReturn = new HashMap<>();
|
||||
|
||||
for (Message message : unthreadedMessages) {
|
||||
ThreadID tID = message.threadID;
|
||||
|
||||
if (toReturn.containsKey(tID)) {
|
||||
Log.w("SMSHelper", "getConversations got two messages for the same ThreadID: " + tID);
|
||||
}
|
||||
|
||||
toReturn.put(tID, message);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
private static void addEventFlag(
|
||||
@NonNull Map<String, String> messageInfo,
|
||||
@NonNull int eventFlag
|
||||
) {
|
||||
int oldEvent = 0; //Default value
|
||||
String oldEventString = messageInfo.get(Message.EVENT);
|
||||
if (oldEventString != null) {
|
||||
oldEvent = Integer.parseInt(oldEventString);
|
||||
}
|
||||
messageInfo.put(Message.EVENT, Integer.toString(oldEvent | eventFlag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Do any parsing of an SMS message which still needs to be done
|
||||
*/
|
||||
private static void parseSMS(
|
||||
@NonNull Context context,
|
||||
@NonNull Map<String, String> messageInfo
|
||||
) {
|
||||
addEventFlag(messageInfo, Message.EVENT_TEXT_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all parts of the MMS message into the messageInfo format
|
||||
* Original implementation from https://stackoverflow.com/a/6446831/3723163
|
||||
*/
|
||||
private static void parseMMS(
|
||||
@NonNull Context context,
|
||||
@NonNull Map<String, String> messageInfo
|
||||
) {
|
||||
addEventFlag(messageInfo, Message.EVENT_UNKNOWN);
|
||||
|
||||
String[] columns = {
|
||||
Telephony.Mms.Part._ID, // The content ID of this part
|
||||
Telephony.Mms.Part._DATA, // The location in the filesystem of the data
|
||||
Telephony.Mms.Part.CONTENT_TYPE, // The mime type of the data
|
||||
Telephony.Mms.Part.TEXT, // The plain text body of this MMS
|
||||
Telephony.Mms.Part.CHARSET, // Charset of the plain text body
|
||||
};
|
||||
|
||||
String mmsID = messageInfo.get(Message.U_ID);
|
||||
String selection = Telephony.Mms.Part.MSG_ID + " = ?";
|
||||
String[] selectionArgs = {mmsID};
|
||||
|
||||
// Get text body and attachments of the message
|
||||
try (Cursor cursor = context.getContentResolver().query(
|
||||
getMMSPartUri(),
|
||||
columns,
|
||||
selection,
|
||||
selectionArgs,
|
||||
null
|
||||
)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
int partIDColumn = cursor.getColumnIndexOrThrow(Telephony.Mms.Part._ID);
|
||||
int contentTypeColumn = cursor.getColumnIndexOrThrow(Telephony.Mms.Part.CONTENT_TYPE);
|
||||
int dataColumn = cursor.getColumnIndexOrThrow(Telephony.Mms.Part._DATA);
|
||||
int textColumn = cursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT);
|
||||
// TODO: Parse charset (As usual, it is skimpily documented) (Possibly refer to MMS spec)
|
||||
|
||||
do {
|
||||
Long partID = cursor.getLong(partIDColumn);
|
||||
String contentType = cursor.getString(contentTypeColumn);
|
||||
String data = cursor.getString(dataColumn);
|
||||
if ("text/plain".equals(contentType)) {
|
||||
String body;
|
||||
if (data != null) {
|
||||
// data != null means the data is on disk. Go get it.
|
||||
body = getMmsText(context, partID);
|
||||
} else {
|
||||
body = cursor.getString(textColumn);
|
||||
}
|
||||
messageInfo.put(Message.BODY, body);
|
||||
addEventFlag(messageInfo, Message.EVENT_TEXT_MESSAGE);
|
||||
} //TODO: Parse more content types (photos and other attachments) here
|
||||
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether the message was in- our out- bound
|
||||
long messageBox = Long.parseLong(messageInfo.get(Telephony.Mms.MESSAGE_BOX));
|
||||
if (messageBox == Telephony.Mms.MESSAGE_BOX_INBOX) {
|
||||
messageInfo.put(Message.TYPE, Integer.toString(Telephony.Sms.MESSAGE_TYPE_INBOX));
|
||||
} else if (messageBox == Telephony.Mms.MESSAGE_BOX_SENT) {
|
||||
messageInfo.put(Message.TYPE, Integer.toString(Telephony.Sms.MESSAGE_TYPE_SENT));
|
||||
} else {
|
||||
// As an undocumented feature, it looks like the values of Mms.MESSAGE_BOX_*
|
||||
// are the same as Sms.MESSAGE_TYPE_* of the same type. So by default let's just use
|
||||
// the value we've got.
|
||||
// This includes things like drafts, which are a far-distant plan to support
|
||||
messageInfo.put(Message.TYPE, messageInfo.get(Telephony.Mms.MESSAGE_BOX));
|
||||
}
|
||||
|
||||
// Get address(es) of the message
|
||||
List<String> addresses = getMmsAddresses(context, Long.parseLong(mmsID));
|
||||
// It looks like addresses[0] is always the sender of the message and
|
||||
// following addresses are recipient(s)
|
||||
// This usually means the addresses list is at least 2 long, but there are cases (special
|
||||
// telco service messages) where it is not (only 1 long in that case, just the "sender")
|
||||
|
||||
// The address field which will get written to the message.
|
||||
// Remember that this is always the address of the other side of the conversation
|
||||
String address = "";
|
||||
|
||||
if (addresses.size() > 2) {
|
||||
// TODO: Collect addresses for multi-target MMS
|
||||
// Probably we will need to figure out the user's address at this point and strip it out of the list
|
||||
addEventFlag(messageInfo, Message.EVENT_MULTI_TARGET);
|
||||
} else {
|
||||
if (messageBox == Telephony.Mms.MESSAGE_BOX_INBOX) {
|
||||
address = addresses.get(0);
|
||||
} else if (messageBox == Telephony.Mms.MESSAGE_BOX_SENT) {
|
||||
address = addresses.get(1);
|
||||
} else {
|
||||
Log.w("SMSHelper", "Unknown message type " + messageBox + " while parsing addresses.");
|
||||
// Not much smart to do here. Just leave as default.
|
||||
}
|
||||
}
|
||||
messageInfo.put(Message.ADDRESS, address);
|
||||
|
||||
// Canonicalize the date field
|
||||
// SMS uses epoch milliseconds, MMS uses epoch seconds. Standardize on milliseconds.
|
||||
long rawDate = Long.parseLong(messageInfo.get(Message.DATE));
|
||||
messageInfo.put(Message.DATE, Long.toString(rawDate * 1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address(es) of an MMS message
|
||||
* Original implementation from https://stackoverflow.com/a/6446831/3723163
|
||||
*/
|
||||
private static @NonNull List<String> getMmsAddresses(
|
||||
@NonNull Context context,
|
||||
@NonNull Long messageID
|
||||
) {
|
||||
Uri uri = ContentUris.appendId(getMMSUri().buildUpon(), messageID).appendPath("addr").build();
|
||||
|
||||
String[] columns = {
|
||||
Telephony.Mms.Addr.MSG_ID, // ID of the message for which we are fetching addresses
|
||||
Telephony.Mms.Addr.ADDRESS, // Address of this part
|
||||
Telephony.Mms.Addr.CHARSET, // Charset of the returned address (where relevant) //TODO: Handle
|
||||
};
|
||||
|
||||
String selection = Telephony.Mms.Addr.MSG_ID + " = ?";
|
||||
String[] selectionArgs = {messageID.toString()};
|
||||
|
||||
List<String> addresses = new ArrayList<>();
|
||||
|
||||
try (Cursor addrCursor = context.getContentResolver().query(
|
||||
uri,
|
||||
columns,
|
||||
selection,
|
||||
selectionArgs,
|
||||
null
|
||||
)) {
|
||||
if (addrCursor != null && addrCursor.moveToFirst()) {
|
||||
int addressIndex = addrCursor.getColumnIndex(Telephony.Mms.Addr.ADDRESS);
|
||||
|
||||
do {
|
||||
String address = addrCursor.getString(addressIndex);
|
||||
addresses.add(address);
|
||||
} while (addrCursor.moveToNext());
|
||||
}
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a text part of an MMS message
|
||||
* Original implementation from https://stackoverflow.com/a/6446831/3723163
|
||||
*/
|
||||
private static String getMmsText(
|
||||
@NonNull Context context,
|
||||
@NonNull Long id
|
||||
) {
|
||||
Uri partURI = ContentUris.withAppendedId(getMMSPartUri(), id);
|
||||
StringBuilder body = new StringBuilder();
|
||||
try (InputStream is = context.getContentResolver().openInputStream(partURI)) {
|
||||
if (is != null) {
|
||||
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
|
||||
BufferedReader reader = new BufferedReader(isr);
|
||||
String temp = reader.readLine();
|
||||
while (temp != null) {
|
||||
body.append(temp);
|
||||
temp = reader.readLine();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new SMSHelper.MessageAccessException(partURI, e);
|
||||
}
|
||||
return body.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a ContentObserver for the Messages database
|
||||
*
|
||||
* @param observer ContentObserver to alert on Message changes
|
||||
*/
|
||||
public static void registerObserver(ContentObserver observer, Context context) {
|
||||
public static void registerObserver(
|
||||
@NonNull ContentObserver observer,
|
||||
@NonNull Context context
|
||||
) {
|
||||
context.getContentResolver().registerContentObserver(
|
||||
SMSHelper.getSMSUri(),
|
||||
SMSHelper.getConversationUri(),
|
||||
true,
|
||||
observer
|
||||
);
|
||||
@@ -219,7 +532,6 @@ public class SMSHelper {
|
||||
/**
|
||||
* Represent an ID used to uniquely identify a message thread
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public static class ThreadID {
|
||||
final Long threadID;
|
||||
static final String lookupColumn = Telephony.Sms.THREAD_ID;
|
||||
@@ -244,10 +556,32 @@ public class SMSHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that some error has occurred while reading a message.
|
||||
* More useful for logging than catching and handling
|
||||
*/
|
||||
public static class MessageAccessException extends RuntimeException {
|
||||
MessageAccessException(Uri uri, Throwable cause) {
|
||||
super("Error getting messages from " + uri.toString(), cause);
|
||||
}
|
||||
|
||||
MessageAccessException(String[] availableColumns, Uri uri, Throwable cause) {
|
||||
super("Error getting messages from " + uri.toString() + " . Available columns were: " + Arrays.toString(availableColumns), cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent all known transport types
|
||||
*/
|
||||
public enum TransportType {
|
||||
SMS,
|
||||
MMS,
|
||||
// Maybe in the future there will be more TransportType, but for now these are all I know about
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent a message and all of its interesting data columns
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
public static class Message {
|
||||
|
||||
final String address;
|
||||
@@ -255,8 +589,10 @@ public class SMSHelper {
|
||||
public final long date;
|
||||
final int type;
|
||||
final int read;
|
||||
final long threadID; // ThreadID is *int* for SMS messages but *long* for MMS
|
||||
final int uID;
|
||||
final ThreadID threadID; // ThreadID is *int* for SMS messages but *long* for MMS
|
||||
final long uID;
|
||||
final int event;
|
||||
final int subscriptionID;
|
||||
|
||||
/**
|
||||
* Named constants which are used to construct a Message
|
||||
@@ -268,15 +604,19 @@ public class SMSHelper {
|
||||
static final String TYPE = Telephony.Sms.TYPE; // Compare with Telephony.TextBasedSmsColumns.MESSAGE_TYPE_*
|
||||
static final String READ = Telephony.Sms.READ; // Whether we have received a read report for this message (int)
|
||||
static final String THREAD_ID = ThreadID.lookupColumn; // Magic number which binds (message) threads
|
||||
static final String U_ID = Telephony.Sms._ID; // Something which uniquely identifies this message
|
||||
static final String U_ID = Telephony.Sms._ID; // Something which uniquely identifies this message
|
||||
static final String EVENT = "event";
|
||||
static final String SUBSCRIPTION_ID = Telephony.Sms.SUBSCRIPTION_ID; // An ID which appears to identify a SIM card
|
||||
|
||||
/**
|
||||
* Event flags
|
||||
* A message should have a bitwise-or of event flags before delivering the packet
|
||||
* Any events not supported by the receiving device should be ignored
|
||||
*/
|
||||
public static final int TEXT_MESSAGE = 0x1; // This message has a "body" field which contains
|
||||
// pure, human-readable text
|
||||
public static final int EVENT_UNKNOWN = 0x0; // The message was of some type we did not understand
|
||||
public static final int EVENT_TEXT_MESSAGE = 0x1; // This message has a "body" field which contains
|
||||
// pure, human-readable text
|
||||
public static final int EVENT_MULTI_TARGET = 0x2; // Indicates that this message has multiple recipients
|
||||
|
||||
/**
|
||||
* Define the columns which are to be extracted from the Android SMS database
|
||||
@@ -289,6 +629,16 @@ public class SMSHelper {
|
||||
Message.READ,
|
||||
Message.THREAD_ID,
|
||||
Message.U_ID,
|
||||
Message.SUBSCRIPTION_ID,
|
||||
};
|
||||
|
||||
static final String[] mmsColumns = new String[]{
|
||||
Message.U_ID,
|
||||
Message.THREAD_ID,
|
||||
Message.DATE,
|
||||
Message.READ,
|
||||
Telephony.Mms.TEXT_ONLY,
|
||||
Telephony.Mms.MESSAGE_BOX, // Compare with Telephony.BaseMmsColumns.MESSAGE_BOX_*
|
||||
};
|
||||
|
||||
Message(final HashMap<String, String> messageInfo) {
|
||||
@@ -298,15 +648,17 @@ public class SMSHelper {
|
||||
if (messageInfo.get(Message.TYPE) == null)
|
||||
{
|
||||
// To be honest, I have no idea why this happens. The docs say the TYPE field is mandatory.
|
||||
// Just stick some junk in here and hope we can figure it out later.
|
||||
// Quick investigation suggests that these are multi-target MMSes
|
||||
Log.w("SMSHelper", "Encountered undefined message type");
|
||||
type = -1;
|
||||
// Proceed anyway, maybe this is not an important problem.
|
||||
} else {
|
||||
type = Integer.parseInt(messageInfo.get(Message.TYPE));
|
||||
}
|
||||
read = Integer.parseInt(messageInfo.get(Message.READ));
|
||||
threadID = Long.parseLong(messageInfo.get(Message.THREAD_ID));
|
||||
threadID = new ThreadID(Long.parseLong(messageInfo.get(Message.THREAD_ID)));
|
||||
uID = Integer.parseInt(messageInfo.get(Message.U_ID));
|
||||
subscriptionID = Integer.parseInt(messageInfo.get(Message.SUBSCRIPTION_ID));
|
||||
event = Integer.parseInt(messageInfo.get(Message.EVENT));
|
||||
}
|
||||
|
||||
public JSONObject toJSONObject() throws JSONException {
|
||||
@@ -319,6 +671,8 @@ public class SMSHelper {
|
||||
json.put(Message.READ, read);
|
||||
json.put(Message.THREAD_ID, threadID);
|
||||
json.put(Message.U_ID, uID);
|
||||
json.put(Message.SUBSCRIPTION_ID, subscriptionID);
|
||||
json.put(Message.EVENT, event);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
@@ -29,8 +29,11 @@ import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.kde.kdeconnect.Helpers.RandomHelper;
|
||||
import org.spongycastle.asn1.x500.RDN;
|
||||
import org.spongycastle.asn1.x500.X500Name;
|
||||
import org.spongycastle.asn1.x500.X500NameBuilder;
|
||||
import org.spongycastle.asn1.x500.style.BCStyle;
|
||||
import org.spongycastle.asn1.x500.style.IETFUtils;
|
||||
import org.spongycastle.cert.X509CertificateHolder;
|
||||
import org.spongycastle.cert.X509v3CertificateBuilder;
|
||||
import org.spongycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||
@@ -62,6 +65,7 @@ import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
public class SslHelper {
|
||||
|
||||
@@ -80,12 +84,39 @@ public class SslHelper {
|
||||
Log.e("SslHelper", "Error getting keys, can't create certificate");
|
||||
return;
|
||||
}
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (!settings.contains("certificate")) {
|
||||
try {
|
||||
|
||||
String deviceId = DeviceHelper.getDeviceId(context);
|
||||
|
||||
boolean needsToGenerateCertificate = false;
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (settings.contains("certificate")) {
|
||||
try {
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
byte[] certificateBytes = Base64.decode(globalSettings.getString("certificate", ""), 0);
|
||||
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
|
||||
X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
|
||||
|
||||
String certDeviceId = getCommonNameFromCertificate(cert);
|
||||
if (!certDeviceId.equals(deviceId)) {
|
||||
Log.e("KDE/SslHelper", "The certificate stored is from a different device id! (found: " + certDeviceId + " expected:" + deviceId + ")");
|
||||
needsToGenerateCertificate = true;
|
||||
} else {
|
||||
certificate = cert;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/SslHelper", "Exception reading own certificate", e);
|
||||
needsToGenerateCertificate = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
needsToGenerateCertificate = true;
|
||||
}
|
||||
|
||||
if (needsToGenerateCertificate) {
|
||||
Log.i("KDE/SslHelper", "Generating a certificate");
|
||||
try {
|
||||
X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
|
||||
nameBuilder.addRDN(BCStyle.CN, DeviceHelper.getDeviceId(context));
|
||||
nameBuilder.addRDN(BCStyle.CN, deviceId);
|
||||
nameBuilder.addRDN(BCStyle.OU, "KDE Connect");
|
||||
nameBuilder.addRDN(BCStyle.O, "KDE");
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
@@ -107,20 +138,9 @@ public class SslHelper {
|
||||
SharedPreferences.Editor edit = settings.edit();
|
||||
edit.putString("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
|
||||
edit.apply();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/initialiseCert", "Exception", e);
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
byte[] certificateBytes = Base64.decode(globalSettings.getString("certificate", ""), 0);
|
||||
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
|
||||
certificate = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/SslHelper", "Exception reading own certificate", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,4 +267,11 @@ public class SslHelper {
|
||||
return new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
|
||||
}
|
||||
|
||||
private static String getCommonNameFromCertificate(X509Certificate cert) {
|
||||
X500Principal principal = cert.getSubjectX500Principal();
|
||||
X500Name x500name = new X500Name(principal.getName());
|
||||
RDN rdn = x500name.getRDNs(BCStyle.CN)[0];
|
||||
return IETFUtils.valueToString(rdn.getFirst().getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -173,6 +173,13 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_mousepad, menu);
|
||||
|
||||
BackgroundService.RunWithPlugin(this, deviceId, MousePadPlugin.class, plugin -> {
|
||||
if (!plugin.isKeyboardEnabled()) {
|
||||
menu.removeItem(R.id.menu_show_keyboard);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -366,17 +373,5 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
|
||||
imm.toggleSoftInputFromWindow(keyListenerView.getWindowToken(), 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -15,8 +15,8 @@
|
||||
* 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/>.
|
||||
*/
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Plugins.MousePadPlugin;
|
||||
|
||||
@@ -36,6 +36,17 @@ public class MousePadPlugin extends Plugin {
|
||||
|
||||
//public final static String PACKET_TYPE_MOUSEPAD = "kdeconnect.mousepad";
|
||||
public final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
|
||||
private final static String PACKET_TYPE_MOUSEPAD_KEYBOARDSTATE = "kdeconnect.mousepad.keyboardstate";
|
||||
|
||||
private boolean keyboardEnabled = true;
|
||||
|
||||
@Override
|
||||
public boolean onPacketReceived(NetworkPacket np) {
|
||||
|
||||
keyboardEnabled = np.getBoolean("state", true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
@@ -71,7 +82,7 @@ public class MousePadPlugin extends Plugin {
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPacketTypes() {
|
||||
return new String[0];
|
||||
return new String[]{PACKET_TYPE_MOUSEPAD_KEYBOARDSTATE};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,4 +146,8 @@ public class MousePadPlugin extends Plugin {
|
||||
device.sendPacket(np);
|
||||
}
|
||||
|
||||
boolean isKeyboardEnabled() {
|
||||
return keyboardEnabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -445,16 +445,4 @@ public class MprisActivity extends AppCompatActivity {
|
||||
nowPlayingText.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -191,35 +191,44 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
|
||||
}
|
||||
|
||||
private Pair<Device, MprisPlugin.MprisPlayer> findPlayer(BackgroundService service) {
|
||||
//First try the previously displayed player
|
||||
//First try the previously displayed player (if still playing) or the previous displayed device (otherwise)
|
||||
if (notificationDevice != null && mprisDevices.contains(notificationDevice)) {
|
||||
Device device = service.getDevice(notificationDevice);
|
||||
|
||||
if (device != null && device.isPluginEnabled("MprisPlugin")) {
|
||||
if (shouldShowPlayer(notificationPlayer)){
|
||||
return new Pair<>(device, notificationPlayer);
|
||||
}
|
||||
|
||||
// Try a different player for the same device
|
||||
MprisPlugin.MprisPlayer player = getPlayerFromDevice(device);
|
||||
if (player != null) {
|
||||
return new Pair<>(device, player);
|
||||
}
|
||||
MprisPlugin.MprisPlayer player;
|
||||
if (notificationPlayer != null && notificationPlayer.isPlaying()) {
|
||||
player = getPlayerFromDevice(device, notificationPlayer);
|
||||
} else {
|
||||
player = getPlayerFromDevice(device, null);
|
||||
}
|
||||
if (player != null) {
|
||||
return new Pair<>(device, player);
|
||||
}
|
||||
}
|
||||
|
||||
// Try a different player from another device
|
||||
for (Device otherDevice : service.getDevices().values()) {
|
||||
MprisPlugin.MprisPlayer player = getPlayerFromDevice(otherDevice);
|
||||
MprisPlugin.MprisPlayer player = getPlayerFromDevice(otherDevice, null);
|
||||
if (player != null) {
|
||||
return new Pair<>(otherDevice, player);
|
||||
}
|
||||
}
|
||||
|
||||
//So no player is playing. Try the previously displayed player again
|
||||
// This will succeed if it's paused:
|
||||
// that allows pausing and subsequently resuming via the notification
|
||||
if (notificationDevice != null && mprisDevices.contains(notificationDevice)) {
|
||||
Device device = service.getDevice(notificationDevice);
|
||||
|
||||
MprisPlugin.MprisPlayer player = getPlayerFromDevice(device, notificationPlayer);
|
||||
if (player != null) {
|
||||
return new Pair<>(device, player);
|
||||
}
|
||||
}
|
||||
return new Pair<>(null, null);
|
||||
}
|
||||
|
||||
private MprisPlugin.MprisPlayer getPlayerFromDevice(Device device) {
|
||||
|
||||
private MprisPlugin.MprisPlayer getPlayerFromDevice(Device device, MprisPlugin.MprisPlayer preferredPlayer) {
|
||||
if (!mprisDevices.contains(device.getDeviceId()))
|
||||
return null;
|
||||
|
||||
@@ -229,6 +238,12 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
|
||||
return null;
|
||||
}
|
||||
|
||||
//First try the preferred player, if supplied
|
||||
if (plugin.hasPlayer(preferredPlayer) && shouldShowPlayer(preferredPlayer)) {
|
||||
return preferredPlayer;
|
||||
}
|
||||
|
||||
//Otherwise, accept any playing player
|
||||
MprisPlugin.MprisPlayer player = plugin.getPlayingPlayer();
|
||||
if (shouldShowPlayer(player)) {
|
||||
return player;
|
||||
@@ -383,7 +398,7 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
|
||||
iCloseNotification.setAction(MprisMediaNotificationReceiver.ACTION_CLOSE_NOTIFICATION);
|
||||
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
|
||||
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
|
||||
PendingIntent piCloseNotification = PendingIntent.getActivity(service, 0, iCloseNotification, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
PendingIntent piCloseNotification = PendingIntent.getBroadcast(service, 0, iCloseNotification, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
notification.setDeleteIntent(piCloseNotification);
|
||||
}
|
||||
|
||||
@@ -448,6 +463,9 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
|
||||
//Clear the current player and media session
|
||||
notificationPlayer = null;
|
||||
if (mediaSession != null) {
|
||||
mediaSession.setPlaybackState(new PlaybackStateCompat.Builder().build());
|
||||
mediaSession.setMetadata(new MediaMetadataCompat.Builder().build());
|
||||
mediaSession.setActive(false);
|
||||
mediaSession.release();
|
||||
mediaSession = null;
|
||||
}
|
||||
|
@@ -422,6 +422,10 @@ public class MprisPlugin extends Plugin {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean hasPlayer(MprisPlayer player) {
|
||||
return players.containsValue(player);
|
||||
}
|
||||
|
||||
private void requestPlayerList() {
|
||||
NetworkPacket np = new NetworkPacket(PACKET_TYPE_MPRIS_REQUEST);
|
||||
np.set("requestPlayerList", true);
|
||||
|
@@ -34,6 +34,7 @@ import org.kde.kdeconnect.Helpers.AppsHelper;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
import org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationReceiver;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.Plugins.PluginFactory;
|
||||
import org.kde.kdeconnect.UserInterface.AlertDialogFragment;
|
||||
import org.kde.kdeconnect.UserInterface.StartActivityAlertDialogFragment;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
@@ -44,17 +45,16 @@ import java.util.List;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
//FIXME: Breaks on Android 4 because it extends OnActiveSessionsChangedListener
|
||||
//@PluginFactory.LoadablePlugin
|
||||
public class MprisReceiverPlugin extends Plugin implements MediaSessionManager.OnActiveSessionsChangedListener {
|
||||
|
||||
@PluginFactory.LoadablePlugin
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
|
||||
public class MprisReceiverPlugin extends Plugin {
|
||||
private final static String PACKET_TYPE_MPRIS = "kdeconnect.mpris";
|
||||
private final static String PACKET_TYPE_MPRIS_REQUEST = "kdeconnect.mpris.request";
|
||||
|
||||
private static final String TAG = "MprisReceiver";
|
||||
|
||||
private HashMap<String, MprisReceiverPlayer> players;
|
||||
private MediaSessionChangeListener mediaSessionChangeListener;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
@@ -68,7 +68,9 @@ public class MprisReceiverPlugin extends Plugin implements MediaSessionManager.O
|
||||
if (null == manager)
|
||||
return false;
|
||||
|
||||
manager.addOnActiveSessionsChangedListener(MprisReceiverPlugin.this, new ComponentName(context, NotificationReceiver.class), new Handler(Looper.getMainLooper()));
|
||||
assert(mediaSessionChangeListener == null);
|
||||
mediaSessionChangeListener = new MediaSessionChangeListener();
|
||||
manager.addOnActiveSessionsChangedListener(mediaSessionChangeListener, new ComponentName(context, NotificationReceiver.class), new Handler(Looper.getMainLooper()));
|
||||
|
||||
createPlayers(manager.getActiveSessions(new ComponentName(context, NotificationReceiver.class)));
|
||||
sendPlayerList();
|
||||
@@ -83,8 +85,9 @@ public class MprisReceiverPlugin extends Plugin implements MediaSessionManager.O
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
MediaSessionManager manager = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
||||
if (manager != null) {
|
||||
manager.removeOnActiveSessionsChangedListener(MprisReceiverPlugin.this);
|
||||
if (manager != null && mediaSessionChangeListener != null) {
|
||||
manager.removeOnActiveSessionsChangedListener(mediaSessionChangeListener);
|
||||
mediaSessionChangeListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,18 +172,20 @@ public class MprisReceiverPlugin extends Plugin implements MediaSessionManager.O
|
||||
return new String[]{PACKET_TYPE_MPRIS};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActiveSessionsChanged(@Nullable List<MediaController> controllers) {
|
||||
private final class MediaSessionChangeListener implements MediaSessionManager.OnActiveSessionsChangedListener {
|
||||
@Override
|
||||
public void onActiveSessionsChanged(@Nullable List<MediaController> controllers) {
|
||||
|
||||
if (null == controllers) {
|
||||
return;
|
||||
}
|
||||
|
||||
players.clear();
|
||||
|
||||
createPlayers(controllers);
|
||||
sendPlayerList();
|
||||
|
||||
if (null == controllers) {
|
||||
return;
|
||||
}
|
||||
|
||||
players.clear();
|
||||
|
||||
createPlayers(controllers);
|
||||
sendPlayerList();
|
||||
|
||||
}
|
||||
|
||||
private void createPlayer(MediaController controller) {
|
||||
|
@@ -218,18 +218,6 @@ public class NotificationFilterActivity extends AppCompatActivity {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
private Drawable resizeIcon(Drawable icon, int maxSize) {
|
||||
Resources res = getResources();
|
||||
|
||||
|
@@ -35,10 +35,18 @@ import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.kde.kdeconnect.Helpers.AppsHelper;
|
||||
@@ -59,11 +67,9 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
@PluginFactory.LoadablePlugin
|
||||
public class NotificationsPlugin extends Plugin implements NotificationReceiver.NotificationListener {
|
||||
@@ -73,7 +79,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
private final static String PACKET_TYPE_NOTIFICATION_REPLY = "kdeconnect.notification.reply";
|
||||
private final static String PACKET_TYPE_NOTIFICATION_ACTION = "kdeconnect.notification.action";
|
||||
|
||||
private final static String TAG = "NotificationsPlugin";
|
||||
private final static String TAG = "KDE/NotificationsPlugin";
|
||||
|
||||
private AppDatabase appDatabase;
|
||||
|
||||
@@ -157,7 +163,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
@Override
|
||||
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
|
||||
if (statusBarNotification == null) {
|
||||
Log.w("onNotificationRemoved", "notification is null");
|
||||
Log.w(TAG, "onNotificationRemoved: notification is null");
|
||||
return;
|
||||
}
|
||||
String id = getNotificationKeyCompat(statusBarNotification);
|
||||
@@ -191,7 +197,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
|
||||
if (!appDatabase.isEnabled(statusBarNotification.getPackageName())) {
|
||||
return;
|
||||
// we dont want notification from this app
|
||||
// we don't want notification from this app
|
||||
}
|
||||
|
||||
String key = getNotificationKeyCompat(statusBarNotification);
|
||||
@@ -221,85 +227,165 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
NetworkPacket np = new NetworkPacket(PACKET_TYPE_NOTIFICATION);
|
||||
|
||||
boolean isUpdate = currentNotifications.contains(key);
|
||||
//If it's an update, the other end should have the icon already: no need to extract it and create the payload again
|
||||
if (!isUpdate) {
|
||||
//If it's an update, the other end should have the icon already: no need to extract it and create the payload again
|
||||
try {
|
||||
Bitmap appIcon;
|
||||
Context foreignContext = context.createPackageContext(statusBarNotification.getPackageName(), 0);
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
appIcon = iconToBitmap(foreignContext, notification.getLargeIcon());
|
||||
} else {
|
||||
appIcon = notification.largeIcon;
|
||||
}
|
||||
|
||||
if (appIcon == null) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
appIcon = iconToBitmap(foreignContext, notification.getSmallIcon());
|
||||
} else {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
Resources foreignResources = pm.getResourcesForApplication(statusBarNotification.getPackageName());
|
||||
Drawable foreignIcon = foreignResources.getDrawable(notification.icon);
|
||||
appIcon = drawableToBitmap(foreignIcon);
|
||||
}
|
||||
}
|
||||
|
||||
if (appIcon != null && !appDatabase.getPrivacy(packageName, AppDatabase.PrivacyOptions.BLOCK_IMAGES)) {
|
||||
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
appIcon.compress(Bitmap.CompressFormat.PNG, 90, outStream);
|
||||
byte[] bitmapData = outStream.toByteArray();
|
||||
|
||||
Log.e("PAYLOAD", "PAYLOAD: " + getChecksum(bitmapData));
|
||||
|
||||
np.setPayload(new NetworkPacket.Payload(bitmapData));
|
||||
|
||||
np.set("payloadHash", getChecksum(bitmapData));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("NotificationsPlugin", "Error retrieving icon", e);
|
||||
}
|
||||
} else {
|
||||
currentNotifications.add(key);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (notification.actions != null && notification.actions.length > 0) {
|
||||
actions.put(key, new LinkedList<>());
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (Notification.Action action : notification.actions) {
|
||||
Bitmap appIcon = extractIcon(statusBarNotification, notification);
|
||||
|
||||
if (null == action.title)
|
||||
continue;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH)
|
||||
if (action.getRemoteInputs() != null && action.getRemoteInputs().length > 0)
|
||||
continue;
|
||||
|
||||
jsonArray.put(action.title.toString());
|
||||
actions.get(key).add(action);
|
||||
}
|
||||
np.set("actions", jsonArray);
|
||||
if (appIcon != null && !appDatabase.getPrivacy(packageName, AppDatabase.PrivacyOptions.BLOCK_IMAGES)) {
|
||||
attachIcon(np, appIcon);
|
||||
}
|
||||
}
|
||||
|
||||
np.set("actions", extractActions(notification, key));
|
||||
|
||||
np.set("id", key);
|
||||
np.set("isClearable", statusBarNotification.isClearable());
|
||||
np.set("appName", appName == null ? packageName : appName);
|
||||
np.set("time", Long.toString(statusBarNotification.getPostTime()));
|
||||
|
||||
if (!appDatabase.getPrivacy(packageName, AppDatabase.PrivacyOptions.BLOCK_CONTENTS)) {
|
||||
RepliableNotification rn = extractRepliableNotification(statusBarNotification);
|
||||
if (rn.pendingIntent != null) {
|
||||
if (rn != null) {
|
||||
np.set("requestReplyId", rn.id);
|
||||
pendingIntents.put(rn.id, rn);
|
||||
}
|
||||
np.set("ticker", getTickerText(notification));
|
||||
np.set("title", getNotificationTitle(notification));
|
||||
np.set("text", getNotificationText(notification));
|
||||
|
||||
Pair<String, String> conversation = extractConversation(notification);
|
||||
|
||||
if (conversation.first != null) {
|
||||
np.set("title", conversation.first);
|
||||
} else {
|
||||
np.set("title", extractStringFromExtra(getExtras(notification), NotificationCompat.EXTRA_TITLE));
|
||||
}
|
||||
|
||||
np.set("text", extractText(notification, conversation));
|
||||
}
|
||||
|
||||
device.sendPacket(np);
|
||||
}
|
||||
|
||||
private String extractText(Notification notification, Pair<String, String> conversation) {
|
||||
|
||||
if (conversation.second != null) {
|
||||
return conversation.second;
|
||||
}
|
||||
|
||||
Bundle extras = getExtras(notification);
|
||||
|
||||
if (extras.containsKey(NotificationCompat.EXTRA_BIG_TEXT)) {
|
||||
return extractStringFromExtra(extras, NotificationCompat.EXTRA_BIG_TEXT);
|
||||
}
|
||||
|
||||
return extractStringFromExtra(extras, NotificationCompat.EXTRA_TEXT);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
private static Bundle getExtras(Notification notification) {
|
||||
// NotificationCompat.getExtras() is expected to return non-null values for JELLY_BEAN+
|
||||
return Objects.requireNonNull(NotificationCompat.getExtras(notification));
|
||||
}
|
||||
|
||||
private void attachIcon(NetworkPacket np, Bitmap appIcon) {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
appIcon.compress(Bitmap.CompressFormat.PNG, 90, outStream);
|
||||
byte[] bitmapData = outStream.toByteArray();
|
||||
|
||||
np.setPayload(new NetworkPacket.Payload(bitmapData));
|
||||
np.set("payloadHash", getChecksum(bitmapData));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Bitmap extractIcon(StatusBarNotification statusBarNotification, Notification notification) {
|
||||
try {
|
||||
Context foreignContext = context.createPackageContext(statusBarNotification.getPackageName(), 0);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && notification.getLargeIcon() != null) {
|
||||
return iconToBitmap(foreignContext, notification.getLargeIcon());
|
||||
} else if (notification.largeIcon != null) {
|
||||
return notification.largeIcon;
|
||||
}
|
||||
|
||||
PackageManager pm = context.getPackageManager();
|
||||
Resources foreignResources = pm.getResourcesForApplication(statusBarNotification.getPackageName());
|
||||
Drawable foreignIcon = foreignResources.getDrawable(notification.icon); //Might throw Resources.NotFoundException
|
||||
return drawableToBitmap(foreignIcon);
|
||||
|
||||
} catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
|
||||
Log.e(TAG, "Package not found", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JSONArray extractActions(Notification notification, String key) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (notification.actions == null || notification.actions.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
actions.put(key, new LinkedList<>());
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
|
||||
for (Notification.Action action : notification.actions) {
|
||||
|
||||
if (null == action.title)
|
||||
continue;
|
||||
|
||||
// Check whether it is a reply action. We have special treatment for them
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH)
|
||||
if (action.getRemoteInputs() != null && action.getRemoteInputs().length > 0)
|
||||
continue;
|
||||
|
||||
jsonArray.put(action.title.toString());
|
||||
actions.get(key).add(action);
|
||||
}
|
||||
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
private Pair<String, String> extractConversation(Notification notification) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
|
||||
return new Pair<>(null, null);
|
||||
|
||||
if (!notification.extras.containsKey(Notification.EXTRA_MESSAGES))
|
||||
return new Pair<>(null, null);
|
||||
|
||||
Parcelable[] ms = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES);
|
||||
|
||||
if (ms == null)
|
||||
return new Pair<>(null, null);
|
||||
|
||||
String title = notification.extras.getString(Notification.EXTRA_CONVERSATION_TITLE);
|
||||
|
||||
boolean isGroupConversation = notification.extras.getBoolean(NotificationCompat.EXTRA_IS_GROUP_CONVERSATION);
|
||||
|
||||
StringBuilder messagesBuilder = new StringBuilder();
|
||||
|
||||
for (Parcelable p : ms) {
|
||||
Bundle m = (Bundle) p;
|
||||
|
||||
if (isGroupConversation) {
|
||||
messagesBuilder.append(m.get("sender"));
|
||||
messagesBuilder.append(": ");
|
||||
}
|
||||
|
||||
messagesBuilder.append(extractStringFromExtra(m, "text"));
|
||||
messagesBuilder.append("\n");
|
||||
}
|
||||
|
||||
return new Pair<>(title, messagesBuilder.toString());
|
||||
}
|
||||
|
||||
private Bitmap drawableToBitmap(Drawable drawable) {
|
||||
if (drawable == null) return null;
|
||||
|
||||
@@ -328,13 +414,13 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
|
||||
private void replyToNotification(String id, String message) {
|
||||
if (pendingIntents.isEmpty() || !pendingIntents.containsKey(id)) {
|
||||
Log.e("NotificationsPlugin", "No such notification");
|
||||
Log.e(TAG, "No such notification");
|
||||
return;
|
||||
}
|
||||
|
||||
RepliableNotification repliableNotification = pendingIntents.get(id);
|
||||
if (repliableNotification == null) {
|
||||
Log.e("NotificationsPlugin", "No such notification");
|
||||
Log.e(TAG, "No such notification");
|
||||
return;
|
||||
}
|
||||
RemoteInput[] remoteInputs = new RemoteInput[repliableNotification.remoteInputs.size()];
|
||||
@@ -344,7 +430,6 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
Bundle localBundle = new Bundle();
|
||||
int i = 0;
|
||||
for (RemoteInput remoteIn : repliableNotification.remoteInputs) {
|
||||
getDetailsOfNotification(remoteIn);
|
||||
remoteInputs[i] = remoteIn;
|
||||
localBundle.putCharSequence(remoteInputs[i].getResultKey(), message);
|
||||
i++;
|
||||
@@ -354,91 +439,38 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
try {
|
||||
repliableNotification.pendingIntent.send(context, 0, localIntent);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Log.e("NotificationPlugin", "replyToNotification error: " + e.getMessage());
|
||||
Log.e(TAG, "replyToNotification error: " + e.getMessage());
|
||||
}
|
||||
pendingIntents.remove(id);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
|
||||
private void getDetailsOfNotification(RemoteInput remoteInput) {
|
||||
//Some more details of RemoteInput... no idea what for but maybe it will be useful at some point
|
||||
String resultKey = remoteInput.getResultKey();
|
||||
String label = remoteInput.getLabel().toString();
|
||||
Boolean canFreeForm = remoteInput.getAllowFreeFormInput();
|
||||
if (remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
|
||||
String[] possibleChoices = new String[remoteInput.getChoices().length];
|
||||
for (int i = 0; i < remoteInput.getChoices().length; i++) {
|
||||
possibleChoices[i] = remoteInput.getChoices()[i].toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getNotificationTitle(Notification notification) {
|
||||
final String TITLE_KEY = "android.title";
|
||||
final String TEXT_KEY = "android.text";
|
||||
String title = "";
|
||||
|
||||
if (notification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
Bundle extras = notification.extras;
|
||||
title = extractStringFromExtra(extras, TITLE_KEY);
|
||||
} catch (Exception e) {
|
||||
Log.e("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RepliableNotification extractRepliableNotification(StatusBarNotification statusBarNotification) {
|
||||
RepliableNotification repliableNotification = new RepliableNotification();
|
||||
|
||||
if (statusBarNotification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
try {
|
||||
if (statusBarNotification.getNotification().actions != null) {
|
||||
for (Notification.Action act : statusBarNotification.getNotification().actions) {
|
||||
if (act != null && act.getRemoteInputs() != null) {
|
||||
// Is a reply
|
||||
repliableNotification.remoteInputs.addAll(Arrays.asList(act.getRemoteInputs()));
|
||||
repliableNotification.pendingIntent = act.actionIntent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
repliableNotification.packageName = statusBarNotification.getPackageName();
|
||||
repliableNotification.tag = statusBarNotification.getTag();//TODO find how to pass Tag with sending PendingIntent, might fix Hangout problem
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("NotificationPlugin", "problem extracting notification wear for " + statusBarNotification.getNotification().tickerText, e);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (statusBarNotification.getNotification().actions == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Notification.Action act : statusBarNotification.getNotification().actions) {
|
||||
if (act != null && act.getRemoteInputs() != null) {
|
||||
// Is a reply
|
||||
RepliableNotification repliableNotification = new RepliableNotification();
|
||||
repliableNotification.remoteInputs.addAll(Arrays.asList(act.getRemoteInputs()));
|
||||
repliableNotification.pendingIntent = act.actionIntent;
|
||||
repliableNotification.packageName = statusBarNotification.getPackageName();
|
||||
repliableNotification.tag = statusBarNotification.getTag(); //TODO find how to pass Tag with sending PendingIntent, might fix Hangout problem
|
||||
|
||||
return repliableNotification;
|
||||
}
|
||||
}
|
||||
|
||||
return repliableNotification;
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getNotificationText(Notification notification) {
|
||||
final String TEXT_KEY = "android.text";
|
||||
String text = "";
|
||||
|
||||
if (notification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
Bundle extras = notification.extras;
|
||||
Object extraTextExtra = extras.get(TEXT_KEY);
|
||||
if (extraTextExtra != null) text = extraTextExtra.toString();
|
||||
} catch (Exception e) {
|
||||
Log.e("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
private static String extractStringFromExtra(Bundle extras, String key) {
|
||||
Object extra = extras.get(key);
|
||||
if (extra == null) {
|
||||
@@ -448,7 +480,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
} else if (extra instanceof SpannableString) {
|
||||
return extra.toString();
|
||||
} else {
|
||||
Log.e("NotificationsPlugin", "Don't know how to extract text from extra of type: " + extra.getClass().getCanonicalName());
|
||||
Log.e(TAG, "Don't know how to extract text from extra of type: " + extra.getClass().getCanonicalName());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -459,32 +491,26 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
* instead the ticker text.
|
||||
*/
|
||||
private String getTickerText(Notification notification) {
|
||||
final String TITLE_KEY = "android.title";
|
||||
final String TEXT_KEY = "android.text";
|
||||
String ticker = "";
|
||||
|
||||
if (notification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
Bundle extras = notification.extras;
|
||||
String extraTitle = extractStringFromExtra(extras, TITLE_KEY);
|
||||
String extraText = extractStringFromExtra(extras, TEXT_KEY);
|
||||
try {
|
||||
Bundle extras = getExtras(notification);
|
||||
String extraTitle = extractStringFromExtra(extras, NotificationCompat.EXTRA_TITLE);
|
||||
String extraText = extractStringFromExtra(extras, NotificationCompat.EXTRA_TEXT);
|
||||
|
||||
if (extraTitle != null && extraText != null && !extraText.isEmpty()) {
|
||||
ticker = extraTitle + ": " + extraText;
|
||||
} else if (extraTitle != null) {
|
||||
ticker = extraTitle;
|
||||
} else if (extraText != null) {
|
||||
ticker = extraText;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText, e);
|
||||
}
|
||||
if (extraTitle != null && !TextUtils.isEmpty(extraText)) {
|
||||
ticker = extraTitle + ": " + extraText;
|
||||
} else if (extraTitle != null) {
|
||||
ticker = extraTitle;
|
||||
} else if (extraText != null) {
|
||||
ticker = extraText;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "problem parsing notification extras for " + notification.tickerText, e);
|
||||
}
|
||||
|
||||
if (ticker.isEmpty()) {
|
||||
ticker = (notification.tickerText != null) ? notification.tickerText.toString() : "";
|
||||
}
|
||||
if (ticker.isEmpty()) {
|
||||
ticker = (notification.tickerText != null) ? notification.tickerText.toString() : "";
|
||||
}
|
||||
|
||||
return ticker;
|
||||
@@ -568,12 +594,12 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
|
||||
//For compat with API<21, because lollipop changed the way to cancel notifications
|
||||
private static void cancelNotificationCompat(NotificationReceiver service, String compatKey) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
service.cancelNotification(compatKey);
|
||||
} else {
|
||||
int first = compatKey.indexOf(':');
|
||||
if (first == -1) {
|
||||
Log.e("cancelNotificationCompa", "Not formatted like a notification key: " + compatKey);
|
||||
Log.e(TAG, "Not formatted like a notification key: " + compatKey);
|
||||
return;
|
||||
}
|
||||
int last = compatKey.lastIndexOf(':');
|
||||
@@ -597,7 +623,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
String tag = statusBarNotification.getTag();
|
||||
if (tag != null && tag.startsWith("kdeconnectId:"))
|
||||
result = Integer.toString(statusBarNotification.getId());
|
||||
else if (Build.VERSION.SDK_INT >= 21) {
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
result = statusBarNotification.getKey();
|
||||
} else {
|
||||
String packageName = statusBarNotification.getPackageName();
|
||||
@@ -616,7 +642,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
md.update(data);
|
||||
return bytesToHex(md.digest());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log.e("KDEConnect", "Error while generating checksum", e);
|
||||
Log.e(TAG, "Error while generating checksum", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -82,7 +82,6 @@ public class PresenterActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
if (mMediaSession != null) {
|
||||
mMediaSession.setActive(true);
|
||||
return;
|
||||
@@ -93,7 +92,6 @@ public class PresenterActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
|
||||
if (mMediaSession != null) {
|
||||
PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
|
||||
|
@@ -34,7 +34,7 @@ import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.kde.kdeconnect.UserInterface.DeviceSettingsActivity;
|
||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
||||
import org.kde.kdeconnect.UserInterface.MainActivity;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
@@ -167,10 +167,10 @@ public class RemoteKeyboardService
|
||||
if (instances.size() == 1) { // single instance of RemoteKeyboardPlugin -> access its settings
|
||||
RemoteKeyboardPlugin plugin = instances.get(0);
|
||||
if (plugin != null) {
|
||||
Intent intent = new Intent(this, DeviceSettingsActivity.class);
|
||||
Intent intent = new Intent(this, PluginSettingsActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(DeviceSettingsActivity.EXTRA_DEVICE_ID, plugin.getDeviceId());
|
||||
intent.putExtra(DeviceSettingsActivity.EXTRA_PLUGIN_KEY, plugin.getPluginKey());
|
||||
intent.putExtra(PluginSettingsActivity.EXTRA_DEVICE_ID, plugin.getDeviceId());
|
||||
intent.putExtra(PluginSettingsActivity.EXTRA_PLUGIN_KEY, plugin.getPluginKey());
|
||||
startActivity(intent);
|
||||
}
|
||||
} else { // != 1 instance of plugin -> show main activity view
|
||||
|
@@ -22,6 +22,7 @@
|
||||
package org.kde.kdeconnect.Plugins.SMSPlugin;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -54,17 +55,18 @@ import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import static org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin.PACKET_TYPE_TELEPHONY;
|
||||
|
||||
@PluginFactory.LoadablePlugin
|
||||
@SuppressLint("InlinedApi")
|
||||
public class SMSPlugin extends Plugin {
|
||||
|
||||
/**
|
||||
@@ -161,18 +163,15 @@ public class SMSPlugin extends Plugin {
|
||||
private final Lock mostRecentTimestampLock = new ReentrantLock();
|
||||
|
||||
private class MessageContentObserver extends ContentObserver {
|
||||
final SMSPlugin mPlugin;
|
||||
|
||||
/**
|
||||
* Create a ContentObserver to watch the Messages database. onChange is called for
|
||||
* every subscribed change
|
||||
*
|
||||
* @param parent Plugin which owns this observer
|
||||
* @param handler Handler object used to make the callback
|
||||
*/
|
||||
MessageContentObserver(SMSPlugin parent, Handler handler) {
|
||||
MessageContentObserver(Handler handler) {
|
||||
super(handler);
|
||||
mPlugin = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,40 +180,34 @@ public class SMSPlugin extends Plugin {
|
||||
* In this case, this onChange expects to be called whenever *anything* in the Messages
|
||||
* database changes and simply reports those updated messages to anyone who might be listening
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
if (mPlugin.mostRecentTimestamp == 0) {
|
||||
// Lock so no one uses the mostRecentTimestamp between the moment we read it and the
|
||||
// moment we update it. This is because reading the Messages DB can take long.
|
||||
mostRecentTimestampLock.lock();
|
||||
|
||||
if (mostRecentTimestamp == 0) {
|
||||
// Since the timestamp has not been initialized, we know that nobody else
|
||||
// has requested a message. That being the case, there is most likely
|
||||
// nobody listening for message updates, so just drop them
|
||||
mostRecentTimestampLock.unlock();
|
||||
return;
|
||||
}
|
||||
mostRecentTimestampLock.lock();
|
||||
// Grab the mostRecentTimestamp into the local stack because reading the Messages
|
||||
// database could potentially be a long operation
|
||||
long mostRecentTimestamp = mPlugin.mostRecentTimestamp;
|
||||
mostRecentTimestampLock.unlock();
|
||||
|
||||
List<SMSHelper.Message> messages = SMSHelper.getMessagesSinceTimestamp(mPlugin.context, mostRecentTimestamp);
|
||||
SMSHelper.Message message = SMSHelper.getNewestMessage(context);
|
||||
|
||||
if (messages.size() == 0) {
|
||||
// Our onChange often gets called many times for a single message. Don't make unnecessary
|
||||
// noise
|
||||
if (message == null || message.date <= mostRecentTimestamp) {
|
||||
// onChange can trigger many times for a single message. Don't make unnecessary noise
|
||||
mostRecentTimestampLock.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the most recent counter
|
||||
mostRecentTimestampLock.lock();
|
||||
for (SMSHelper.Message message : messages) {
|
||||
if (message.date > mostRecentTimestamp) {
|
||||
mPlugin.mostRecentTimestamp = message.date;
|
||||
}
|
||||
}
|
||||
mostRecentTimestamp = message.date;
|
||||
mostRecentTimestampLock.unlock();
|
||||
|
||||
// Send the alert about the update
|
||||
device.sendPacket(constructBulkMessagePacket(messages));
|
||||
device.sendPacket(constructBulkMessagePacket(Collections.singleton(message)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +268,6 @@ public class SMSPlugin extends Plugin {
|
||||
device.sendPacket(np);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
permissionExplanation = R.string.telepathy_permission_explanation;
|
||||
@@ -285,7 +277,7 @@ public class SMSPlugin extends Plugin {
|
||||
context.registerReceiver(receiver, filter);
|
||||
|
||||
Looper helperLooper = SMSHelper.MessageLooper.getLooper();
|
||||
ContentObserver messageObserver = new MessageContentObserver(this, new Handler(helperLooper));
|
||||
ContentObserver messageObserver = new MessageContentObserver(new Handler(helperLooper));
|
||||
SMSHelper.registerObserver(messageObserver, context);
|
||||
|
||||
return true;
|
||||
@@ -301,7 +293,6 @@ public class SMSPlugin extends Plugin {
|
||||
return context.getResources().getString(R.string.pref_plugin_telepathy_desc);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
@Override
|
||||
public boolean onPacketReceived(NetworkPacket np) {
|
||||
|
||||
@@ -344,7 +335,6 @@ public class SMSPlugin extends Plugin {
|
||||
* @param messages Messages to include in the packet
|
||||
* @return NetworkPacket of type PACKET_TYPE_SMS_MESSAGE
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private static NetworkPacket constructBulkMessagePacket(Collection<SMSHelper.Message> messages) {
|
||||
NetworkPacket reply = new NetworkPacket(PACKET_TYPE_SMS_MESSAGE);
|
||||
|
||||
@@ -354,8 +344,6 @@ public class SMSPlugin extends Plugin {
|
||||
try {
|
||||
JSONObject json = message.toJSONObject();
|
||||
|
||||
json.put("event", SMSHelper.Message.TEXT_MESSAGE);
|
||||
|
||||
body.put(json);
|
||||
} catch (JSONException e) {
|
||||
Log.e("Conversations", "Error serializing message");
|
||||
@@ -373,7 +361,6 @@ public class SMSPlugin extends Plugin {
|
||||
* <p>
|
||||
* Send one packet of type PACKET_TYPE_SMS_MESSAGE with the first message in all conversations
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private boolean handleRequestConversations(NetworkPacket packet) {
|
||||
Map<SMSHelper.ThreadID, SMSHelper.Message> conversations = SMSHelper.getConversations(this.context);
|
||||
|
||||
@@ -394,7 +381,6 @@ public class SMSPlugin extends Plugin {
|
||||
return true;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private boolean handleRequestConversation(NetworkPacket packet) {
|
||||
SMSHelper.ThreadID threadID = new SMSHelper.ThreadID(packet.getLong("threadID"));
|
||||
|
||||
@@ -443,6 +429,9 @@ public class SMSPlugin extends Plugin {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* I suspect we can actually go lower than this, but it might get unstable
|
||||
*/
|
||||
@Override
|
||||
public int getMinSdk() {
|
||||
return Build.VERSION_CODES.KITKAT;
|
||||
|
@@ -42,7 +42,7 @@ import org.json.JSONObject;
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.StorageHelper;
|
||||
import org.kde.kdeconnect.UserInterface.DeviceSettingsActivity;
|
||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
||||
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
@@ -185,7 +185,7 @@ public class SftpSettingsFragment
|
||||
private void restoreActionMode() {
|
||||
try {
|
||||
if (savedActionModeState.getBoolean(KEY_ACTION_MODE_ENABLED)) {
|
||||
actionMode = ((DeviceSettingsActivity)requireActivity()).startSupportActionMode(this);
|
||||
actionMode = ((PluginSettingsActivity)requireActivity()).startSupportActionMode(this);
|
||||
|
||||
if (actionMode != null) {
|
||||
JSONArray jsonArray = savedActionModeState.getJSONArray(KEY_ACTION_MODE_SELECTED_ITEMS);
|
||||
@@ -438,7 +438,7 @@ public class SftpSettingsFragment
|
||||
@Override
|
||||
public void onLongClick(StoragePreference storagePreference) {
|
||||
if (actionMode == null) {
|
||||
actionMode = ((DeviceSettingsActivity)requireActivity()).startSupportActionMode(this);
|
||||
actionMode = ((PluginSettingsActivity)requireActivity()).startSupportActionMode(this);
|
||||
|
||||
if (actionMode != null) {
|
||||
for (int i = 0, count = preferenceCategory.getPreferenceCount(); i < count; i++) {
|
||||
|
@@ -66,8 +66,7 @@ public class CompositeReceiveFileJob extends BackgroundJob<Device, Void> {
|
||||
|
||||
lock = new Object();
|
||||
networkPacketList = new ArrayList<>();
|
||||
receiveNotification = new ReceiveNotification(device);
|
||||
receiveNotification.addCancelAction(getId());
|
||||
receiveNotification = new ReceiveNotification(device, getId());
|
||||
currentFileNum = 0;
|
||||
totalNumFiles = 0;
|
||||
totalPayloadSize = 0;
|
||||
@@ -190,7 +189,7 @@ public class CompositeReceiveFileJob extends BackgroundJob<Device, Void> {
|
||||
numFiles = totalNumFiles;
|
||||
}
|
||||
|
||||
if (numFiles == 1 && currentNetworkPacket.has("open")) {
|
||||
if (numFiles == 1 && currentNetworkPacket.getBoolean("open", false)) {
|
||||
receiveNotification.cancel();
|
||||
openFile(fileDocument);
|
||||
} else {
|
||||
|
@@ -65,8 +65,7 @@ public class CompositeUploadFileJob extends BackgroundJob<Device, Void> {
|
||||
totalPayloadSize = 0;
|
||||
totalSend = 0;
|
||||
prevProgressPercentage = 0;
|
||||
uploadNotification = new UploadNotification(getDevice());
|
||||
uploadNotification.addCancelAction(getId());
|
||||
uploadNotification = new UploadNotification(getDevice(), getId());
|
||||
|
||||
sendPacketStatusCallback = new SendPacketStatusCallback();
|
||||
}
|
||||
|
@@ -48,15 +48,16 @@ class ReceiveNotification {
|
||||
private final int notificationId;
|
||||
private NotificationCompat.Builder builder;
|
||||
private final Device device;
|
||||
private long currentJobId;
|
||||
private long jobId;
|
||||
|
||||
//https://documentation.onesignal.com/docs/android-customizations#section-big-picture
|
||||
private static final int bigImageWidth = 1440;
|
||||
private static final int bigImageHeight = 720;
|
||||
|
||||
public ReceiveNotification(Device device) {
|
||||
public ReceiveNotification(Device device, long jobId) {
|
||||
this.device = device;
|
||||
|
||||
this.jobId = jobId;
|
||||
notificationId = (int) System.currentTimeMillis();
|
||||
notificationManager = (NotificationManager) device.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
builder = new NotificationCompat.Builder(device.getContext(), NotificationHelper.Channels.FILETRANSFER)
|
||||
@@ -64,6 +65,7 @@ class ReceiveNotification {
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(true)
|
||||
.setProgress(100, 0, true);
|
||||
addCancelAction();
|
||||
}
|
||||
|
||||
public void show() {
|
||||
@@ -74,10 +76,8 @@ class ReceiveNotification {
|
||||
notificationManager.cancel(notificationId);
|
||||
}
|
||||
|
||||
public void addCancelAction(long jobId) {
|
||||
builder.mActions.clear();
|
||||
public void addCancelAction() {
|
||||
|
||||
currentJobId = jobId;
|
||||
Intent cancelIntent = new Intent(device.getContext(), ShareBroadcastReceiver.class);
|
||||
cancelIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
cancelIntent.setAction(SharePlugin.ACTION_CANCEL_SHARE);
|
||||
@@ -88,12 +88,6 @@ class ReceiveNotification {
|
||||
builder.addAction(R.drawable.ic_reject_pairing, device.getContext().getString(R.string.cancel), cancelPendingIntent);
|
||||
}
|
||||
|
||||
public long getCurrentJobId() { return currentJobId; }
|
||||
|
||||
public int getNotificationId() {
|
||||
return notificationId;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
builder.setContentTitle(title);
|
||||
builder.setTicker(title);
|
||||
|
@@ -153,7 +153,6 @@ public class ShareActivity extends AppCompatActivity {
|
||||
});
|
||||
} else {
|
||||
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
BackgroundService.RunCommand(this, service -> {
|
||||
service.onNetworkChange();
|
||||
service.addDeviceListChangedCallback("ShareActivity", this::updateComputerList);
|
||||
@@ -166,7 +165,6 @@ public class ShareActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onStop() {
|
||||
BackgroundService.RunCommand(this, service -> service.removeDeviceListChangedCallback("ShareActivity"));
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
|
@@ -39,9 +39,11 @@ class UploadNotification {
|
||||
private NotificationCompat.Builder builder;
|
||||
private final int notificationId;
|
||||
private final Device device;
|
||||
private long jobId;
|
||||
|
||||
UploadNotification(Device device) {
|
||||
UploadNotification(Device device, long jobId) {
|
||||
this.device = device;
|
||||
this.jobId = jobId;
|
||||
|
||||
notificationId = (int) System.currentTimeMillis();
|
||||
notificationManager = (NotificationManager) device.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
@@ -50,11 +52,10 @@ class UploadNotification {
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(true)
|
||||
.setProgress(100, 0, true);
|
||||
addCancelAction();
|
||||
}
|
||||
|
||||
void addCancelAction(long jobId) {
|
||||
builder.mActions.clear();
|
||||
|
||||
void addCancelAction() {
|
||||
Intent cancelIntent = new Intent(device.getContext(), ShareBroadcastReceiver.class);
|
||||
cancelIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
cancelIntent.setAction(SharePlugin.ACTION_CANCEL_SHARE);
|
||||
|
@@ -123,10 +123,9 @@ public class TelephonyPlugin extends Plugin {
|
||||
return;
|
||||
String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
|
||||
|
||||
final int finalIntState = intState;
|
||||
|
||||
if (finalIntState != lastState) {
|
||||
callBroadcastReceived(finalIntState, number);
|
||||
if (intState != lastState) {
|
||||
lastState = intState;
|
||||
callBroadcastReceived(intState, number);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +212,7 @@ public class TelephonyPlugin extends Plugin {
|
||||
}
|
||||
|
||||
//Emit a missed call notification if needed
|
||||
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
|
||||
if ("ringing".equals(lastPacket.getString("event", null))) {
|
||||
np.set("event", "missedCall");
|
||||
np.set("phoneNumber", lastPacket.getString("phoneNumber", null));
|
||||
np.set("contactName", lastPacket.getString("contactName", null));
|
||||
@@ -224,7 +223,6 @@ public class TelephonyPlugin extends Plugin {
|
||||
}
|
||||
|
||||
lastPacket = np;
|
||||
lastState = state;
|
||||
}
|
||||
|
||||
private void unmuteRinger() {
|
||||
|
@@ -127,18 +127,5 @@ public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
|
||||
return mDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
getDelegate().onStop();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -167,18 +167,6 @@ public class CustomDevicesActivity extends AppCompatActivity implements CustomDe
|
||||
return deserializeIpList(deviceListPrefs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomDeviceClicked(String customDevice) {
|
||||
editingDeviceAtPosition = customDeviceList.indexOf(customDevice);
|
||||
|
@@ -44,7 +44,7 @@ import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.NetworkHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.UserInterface.List.CustomItem;
|
||||
import org.kde.kdeconnect.UserInterface.List.PluginListHeaderItem;
|
||||
import org.kde.kdeconnect.UserInterface.List.FailedPluginListItem;
|
||||
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
|
||||
import org.kde.kdeconnect.UserInterface.List.PluginItem;
|
||||
@@ -71,6 +71,8 @@ public class DeviceFragment extends Fragment {
|
||||
private static final String ARG_DEVICE_ID = "deviceId";
|
||||
private static final String ARG_FROM_DEVICE_LIST = "fromDeviceList";
|
||||
|
||||
private static final String TAG = "KDE/DeviceFragment";
|
||||
|
||||
private View rootView;
|
||||
private String mDeviceId;
|
||||
private Device device;
|
||||
@@ -133,12 +135,10 @@ public class DeviceFragment extends Fragment {
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
//Log.e("DeviceFragment", "device: " + deviceId);
|
||||
|
||||
BackgroundService.RunCommand(mActivity, service -> {
|
||||
device = service.getDevice(mDeviceId);
|
||||
if (device == null) {
|
||||
Log.e("DeviceFragment", "Trying to display a device fragment but the device is not present");
|
||||
Log.e(TAG, "Trying to display a device fragment but the device is not present");
|
||||
mActivity.onDeviceSelected(null);
|
||||
return;
|
||||
}
|
||||
@@ -208,8 +208,6 @@ public class DeviceFragment extends Fragment {
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
|
||||
//Log.e("DeviceFragment", "onPrepareOptionsMenu");
|
||||
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
menu.clear();
|
||||
|
||||
@@ -231,7 +229,7 @@ public class DeviceFragment extends Fragment {
|
||||
}
|
||||
|
||||
menu.add(R.string.device_menu_plugins).setOnMenuItemClickListener(menuItem -> {
|
||||
Intent intent = new Intent(mActivity, DeviceSettingsActivity.class);
|
||||
Intent intent = new Intent(mActivity, PluginSettingsActivity.class);
|
||||
intent.putExtra("deviceId", mDeviceId);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
@@ -290,7 +288,6 @@ public class DeviceFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void refreshUI() {
|
||||
//Log.e("DeviceFragment", "refreshUI");
|
||||
|
||||
if (device == null || rootView == null) {
|
||||
return;
|
||||
@@ -355,7 +352,7 @@ public class DeviceFragment extends Fragment {
|
||||
} catch (IllegalStateException e) {
|
||||
//Ignore: The activity was closed while we were trying to update it
|
||||
} catch (ConcurrentModificationException e) {
|
||||
Log.e("DeviceActivity", "ConcurrentModificationException");
|
||||
Log.e(TAG, "ConcurrentModificationException");
|
||||
this.run(); //Try again
|
||||
}
|
||||
|
||||
@@ -404,31 +401,15 @@ public class DeviceFragment extends Fragment {
|
||||
};
|
||||
|
||||
private void createPluginsList(ConcurrentHashMap<String, Plugin> plugins, int headerText, FailedPluginListItem.Action action) {
|
||||
if (!plugins.isEmpty()) {
|
||||
if (plugins.isEmpty())
|
||||
return;
|
||||
|
||||
TextView header = new TextView(mActivity);
|
||||
header.setPadding(
|
||||
((int) (16 * getResources().getDisplayMetrics().density)),
|
||||
((int) (28 * getResources().getDisplayMetrics().density)),
|
||||
((int) (16 * getResources().getDisplayMetrics().density)),
|
||||
((int) (8 * getResources().getDisplayMetrics().density))
|
||||
);
|
||||
header.setOnClickListener(null);
|
||||
header.setOnLongClickListener(null);
|
||||
header.setText(headerText);
|
||||
|
||||
pluginListItems.add(new CustomItem(header));
|
||||
for (Map.Entry<String, Plugin> entry : plugins.entrySet()) {
|
||||
String pluginKey = entry.getKey();
|
||||
final Plugin plugin = entry.getValue();
|
||||
if (device.isPluginEnabled(pluginKey)) {
|
||||
if (plugin == null) {
|
||||
pluginListItems.add(new SmallEntryItem(pluginKey));
|
||||
} else {
|
||||
pluginListItems.add(new FailedPluginListItem(plugin, action));
|
||||
}
|
||||
}
|
||||
pluginListItems.add(new PluginListHeaderItem(headerText));
|
||||
for (Plugin plugin : plugins.values()) {
|
||||
if (!device.isPluginEnabled(plugin.getPluginKey())) {
|
||||
continue;
|
||||
}
|
||||
pluginListItems.add(new FailedPluginListItem(plugin, action));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,10 +53,10 @@ public class DeviceSettingsAlertDialogFragment extends AlertDialogFragment {
|
||||
setCallback(new Callback() {
|
||||
@Override
|
||||
public void onPositiveButtonClicked() {
|
||||
Intent intent = new Intent(requireActivity(), DeviceSettingsActivity.class);
|
||||
Intent intent = new Intent(requireActivity(), PluginSettingsActivity.class);
|
||||
|
||||
intent.putExtra(DeviceSettingsActivity.EXTRA_DEVICE_ID, deviceId);
|
||||
intent.putExtra(DeviceSettingsActivity.EXTRA_PLUGIN_KEY, pluginKey);
|
||||
intent.putExtra(PluginSettingsActivity.EXTRA_DEVICE_ID, deviceId);
|
||||
intent.putExtra(PluginSettingsActivity.EXTRA_PLUGIN_KEY, pluginKey);
|
||||
requireActivity().startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
@@ -15,32 +15,35 @@
|
||||
* 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/>.
|
||||
*/
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface.List;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class CustomItem implements ListAdapter.Item {
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
private final View view;
|
||||
public class PluginListHeaderItem implements ListAdapter.Item {
|
||||
|
||||
public CustomItem(View v) {
|
||||
private final int text;
|
||||
|
||||
if (v == null)
|
||||
throw new IllegalArgumentException("View must not be null");
|
||||
|
||||
this.view = v;
|
||||
public PluginListHeaderItem(int text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View inflateView(LayoutInflater layoutInflater) {
|
||||
return view;
|
||||
TextView v = (TextView) layoutInflater.inflate(R.layout.list_item_plugin_header, null);
|
||||
v.setText(text);
|
||||
v.setOnClickListener(null);
|
||||
v.setOnLongClickListener(null);
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
@@ -284,14 +284,12 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this, true);
|
||||
BackgroundService.RunCommand(this, service -> service.addDeviceListChangedCallback("MainActivity", this::updateDeviceList));
|
||||
updateDeviceList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
BackgroundService.RunCommand(this, service -> service.removeDeviceListChangedCallback("MainActivity"));
|
||||
super.onStop();
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
public class DeviceSettingsActivity
|
||||
public class PluginSettingsActivity
|
||||
extends AppCompatActivity
|
||||
implements PluginPreference.PluginPreferenceCallback {
|
||||
|
||||
@@ -47,7 +47,7 @@ public class DeviceSettingsActivity
|
||||
ThemeUtil.setUserPreferredTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_device_settings);
|
||||
setContentView(R.layout.activity_plugin_settings);
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
|
||||
@@ -68,7 +68,7 @@ public class DeviceSettingsActivity
|
||||
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentPlaceHolder);
|
||||
if (fragment == null) {
|
||||
if (pluginKey == null) {
|
||||
fragment = DeviceSettingsFragment.newInstance(deviceId);
|
||||
fragment = PluginSettingsListFragment.newInstance(deviceId);
|
||||
} else {
|
||||
Device device = BackgroundService.getInstance().getDevice(deviceId);
|
||||
Plugin plugin = device.getPlugin(pluginKey);
|
||||
@@ -96,17 +96,6 @@ public class DeviceSettingsActivity
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartPluginSettingsFragment(Plugin plugin) {
|
@@ -80,6 +80,6 @@ public class PluginSettingsFragment extends PreferenceFragmentCompat {
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return ((DeviceSettingsActivity)requireActivity()).getDeviceId();
|
||||
return ((PluginSettingsActivity)requireActivity()).getDeviceId();
|
||||
}
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class DeviceSettingsFragment extends PreferenceFragmentCompat {
|
||||
public class PluginSettingsListFragment extends PreferenceFragmentCompat {
|
||||
private static final String ARG_DEVICE_ID = "deviceId";
|
||||
private static final String KEY_RECYCLERVIEW_LAYOUTMANAGER_STATE = "RecyclerViewLayoutmanagerState";
|
||||
|
||||
@@ -50,8 +50,8 @@ public class DeviceSettingsFragment extends PreferenceFragmentCompat {
|
||||
*/
|
||||
private boolean stateSaved;
|
||||
|
||||
public static DeviceSettingsFragment newInstance(@NonNull String deviceId) {
|
||||
DeviceSettingsFragment fragment = new DeviceSettingsFragment();
|
||||
public static PluginSettingsListFragment newInstance(@NonNull String deviceId) {
|
||||
PluginSettingsListFragment fragment = new PluginSettingsListFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_DEVICE_ID, deviceId);
|
@@ -6,9 +6,9 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2014-11-23 22:02-0800\n"
|
||||
"PO-Revision-Date: 2014-11-23 22:02-0800\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-06-30 11:38+0200\n"
|
||||
"PO-Revision-Date: 2019-06-30 11:38+0200\n"
|
||||
"Last-Translator: Albert Vaca Cintora <albertvaka@gmail.com>\n"
|
||||
"Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
Reference in New Issue
Block a user