2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-31 22:25:08 +00:00

Compare commits

..

41 Commits

Author SHA1 Message Date
Albert Vaca Cintora
e37aa08dac Release 1.13.6 2020-01-05 22:34:07 +01:00
Erik Duisters
ad801f1db8 Make FindMyPhone plugin work on Android 10 2020-01-05 17:40:54 +00:00
Rishabh Sharma
d4f35d8bd6 added dark navigation bar for dark mode 2020-01-05 16:02:25 +01:00
l10n daemon script
5cf11c0e75 GIT_SILENT made messages (after extraction) 2019-12-23 02:41:01 +01:00
Erik Duisters
ef55d6d783 Certificate generation fails when locale is set to Arabic 2019-12-22 18:57:36 +00:00
l10n daemon script
f66263d05c GIT_SILENT made messages (after extraction) 2019-12-19 02:38:47 +01:00
l10n daemon script
c292639d36 GIT_SILENT made messages (after extraction) 2019-12-17 02:42:25 +01:00
l10n daemon script
01a8b84087 GIT_SILENT made messages (after extraction) 2019-12-04 02:39:45 +01:00
l10n daemon script
ffea85c740 GIT_SILENT made messages (after extraction) 2019-11-30 02:50:50 +01:00
Albert Vaca Cintora
f6df98d648 Fix NPE 2019-11-25 14:38:38 +01:00
Albert Vaca Cintora
5e37ffe7cd Release 1.13.5 2019-11-24 22:53:49 +01:00
Albert Vaca Cintora
5907517d91 Fix NPE
Apparently removeLink can be called when there are no links already
2019-11-24 22:52:47 +01:00
Albert Vaca Cintora
63d452908f Restrict this to even more version
Anyway, it only seems to be used since Android 10
2019-11-24 22:48:59 +01:00
Albert Vaca
ccda9d468b v1.13.4 2019-11-21 21:38:35 +01:00
Albert Vaca
c3d02adaa4 Fix IllegalArgumentException crashes 2019-11-21 21:38:25 +01:00
Albert Vaca Cintora
733dd604ba Release 1.13.3 2019-11-20 11:50:39 +01:00
Albert Vaca Cintora
f93a0e366f Bump gradle plugin version 2019-11-20 11:40:47 +01:00
Simon Redman
aa735c22b2 Remove Samsung compatibility mode 2019-11-18 22:42:57 -08:00
Ankit Bhardwaj
c78077a416 Fixed snackbar background color when darkmode is off 2019-11-17 23:06:50 +00:00
l10n daemon script
da074f9413 GIT_SILENT made messages (after extraction) 2019-11-14 02:43:15 +01:00
Krzysztof Dziembała
4a0c53610f Fix reading SMS/MMS on devices with no sub_id
Some (Xiaomi) devices running >= Android Lollipop (SDK 22+) don't
support `Telephony.Sms.SUBSCRIPTION_ID`.
This commit adds a verification step to ensure that only devices with
`"sub_id"` column include it in query.

* Address review comments

Check was moved to a separate helper function (boolean), it's
performed only on SDK 22+ and `Telephony.Sms.SUBSCRIPTION_ID`
is used in query (instead of null), so no NullPointerException
is thrown.

Also parseInt shouldn't now fail if `Message.SUBSCRIPTION_ID` key
exists in messageInfo, but value is null

* Return false if cursor is null

* Return true without checking column

If we got the cursor, the query won't fail when executed again, and the "sim_id" column must exist (because an exception wasn't thrown).
2019-11-09 11:27:54 -08:00
l10n daemon script
aa25372e91 GIT_SILENT made messages (after extraction) 2019-11-08 02:47:27 +01:00
Albert Vaca Cintora
125dd14b18 Remove redundant .create() 2019-10-27 23:43:42 +01:00
Simon Redman
6f81c67632 Refactor contacts-getting code to be either "everything" or "one"
Fixes bug from mailing list conversation dated 12 October 2019
2019-10-27 21:23:52 +00:00
Albert Vaca Cintora
1d5c280401 Update gradle plugin 2019-10-27 20:39:49 +01:00
Albert Vaca Cintora
432294c64c Broacast when we open the app but ratelimit broadcasts
Reviewed-by: Aleix Pol
2019-10-25 21:22:10 +02:00
Albert Vaca Cintora
d16293cca5 Add missing setEnabled(true)
The second time we entered the screen pull-to-refresh wasn't working

Reviewed-by: Aleix Pol
2019-10-25 20:18:46 +02:00
Albert Vaca Cintora
dd5fb954bc Don't use sender if not there
Reviewed-by: Aleix Pol
2019-10-25 20:09:26 +02:00
Simon Redman
b1c6df405c Delete broken getVCardsFast
This method does not work because the API doesn't provide the information we need.

If we decide to ressurect it, we can look this commit up later.

#TIMECAPSULE
2019-10-19 09:01:10 -07:00
Albert Vaca
418e1841f3 Actually read the "open" boolean
After sending a file, sending more was broken.
2019-10-13 21:41:31 +02:00
Albert Vaca Cintora
f2064aaef8 Honour FLAG_ONLY_ALERT_ONCE
Reviewed by Aleix Pol
2019-10-12 19:15:37 +02:00
Łukasz Patron
d1b892f368 Support ACTION_SEEK_TO in mpris media session 2019-10-12 14:55:50 +02:00
l10n daemon script
b5a1424206 GIT_SILENT made messages (after extraction) 2019-10-12 02:42:34 +02:00
l10n daemon script
b367e5d38e GIT_SILENT made messages (after extraction) 2019-10-10 02:43:06 +02:00
Simon Redman
a2ccafbdf8 Add information for bug reporting to README 2019-10-08 20:21:01 -07:00
l10n daemon script
da55b11c22 GIT_SILENT made messages (after extraction) 2019-10-06 02:38:36 +02:00
l10n daemon script
cf968a70ea GIT_SILENT made messages (after extraction) 2019-10-03 02:35:29 +02:00
l10n daemon script
7b78a4c78a GIT_SILENT made messages (after extraction) 2019-09-29 02:39:19 +02:00
l10n daemon script
9fcda1ec6f GIT_SILENT made messages (after extraction) 2019-09-27 02:37:00 +02:00
l10n daemon script
e359d59bdd GIT_SILENT made messages (after extraction) 2019-09-25 02:37:07 +02:00
l10n daemon script
ce7105ef89 GIT_SILENT made messages (after extraction) 2019-09-24 02:41:47 +02:00
42 changed files with 771 additions and 289 deletions

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.kde.kdeconnect_tp"
android:versionCode="11320"
android:versionName="1.13.2">
android:versionCode="11360"
android:versionName="1.13.6">
<supports-screens
android:anyDensity="true"
@@ -33,6 +34,7 @@
<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" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<application
android:icon="@drawable/icon"
@@ -40,7 +42,8 @@
android:supportsRtl="true"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/KdeConnectTheme">
android:theme="@style/KdeConnectTheme"
android:name="org.kde.kdeconnect.MyApplication">
<service
android:name="org.kde.kdeconnect.BackgroundService"
android:enabled="true" />
@@ -119,6 +122,12 @@
android:label="@string/findmyphone_title"
android:launchMode="singleInstance" />
<receiver android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneReceiver">
<intent-filter>
<action android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.foundIt" />
</intent-filter>
</receiver>
<!-- Plugin-related activities and services -->
<activity

View File

@@ -23,6 +23,8 @@ You can install this app from the [Play Store](https://play.google.com/store/app
A lot of useful information, including how to get started working on KDE Connect and how to connect with the current developers, is on our [KDE Community Wiki page](https://community.kde.org/KDEConnect)
For bug reporting, please use [KDE's Bugzilla](https://bugs.kde.org). Please do not use the issue tracker in GitLab since we want to keep everything in one place.
To contribute patches, use [KDE Connect's Gitlab](https://invent.kde.org/kde/kdeconnect-android/).
On Gitlab (as well as on our [old Phabricator](https://phabricator.kde.org/tag/kde_connect/)) you can find a task list with stuff to do and links to other relevant resources.
It is a good idea to also subscribe to the [KDE Connect mailing list](https://mail.kde.org/mailman/listinfo/kdeconnect).

View File

@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath 'com.android.tools.build:gradle:3.5.3'
}
}
@@ -82,12 +82,15 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.preference:preference:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.lifecycle:lifecycle-runtime:2.1.0'
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
implementation 'androidx.lifecycle:lifecycle-common-java8:2.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.jakewharton:disklrucache:2.0.2' //For caching album art bitmaps
implementation 'com.jaredrummler:android-device-names:1.1.9' //To get a human-friendly device name
implementation 'org.apache.sshd:sshd-core:0.14.0'
implementation 'org.apache.mina:mina-core:2.0.19' //For some reason, makes sshd-core:0.14.0 work without NIO, which isn't available until Android 8+
implementation 'org.apache.mina:mina-core:2.0.19' //For some reason, makes sshd-core:0.14.0 work without NIO, which isn't available until Android 8 (api 26)
//implementation('com.github.bright:slf4android:0.1.6') { transitive = true } // For org.apache.sshd debugging
implementation 'com.madgag.spongycastle:bcpkix-jdk15on:1.58.0.0' //For SSL certificate generation

View File

@@ -1,6 +1,6 @@
#Wed May 01 14:24:13 CEST 2019
#Sun Oct 27 20:27:45 CET 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

View File

@@ -108,6 +108,7 @@
</plurals>
<string name="received_file_text">Toca p\'abrir «%1s»</string>
<string name="cannot_create_file">Nun pue crease\'l ficheru %s</string>
<string name="tap_to_answer">Toca pa responder</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>
@@ -136,7 +137,7 @@
<string name="custom_device_list_help">Si\'l preséu nun se deteuta automáticamente, pues amestar la so direición IP o nome d\'agospiu calcando nel botón flotante d\'aición</string>
<string name="undo">Desfacer</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_notification_preference_summary">Fai que\'l teléfonu vibre y reproduza un soníu al recibir un ficheru</string>
<string name="share_destination_customize">Personalizar el direutoriu de destín</string>
<string name="share_destination_customize_summary_disabled">Los ficheros recibíos van apaecer en Descargues</string>
<string name="share_destination_customize_summary_enabled">Los ficheros van atroxase nel direutoriu d\'embaxo</string>
@@ -155,6 +156,7 @@
<string name="sftp_storage_preference_display_name">Nome</string>
<string name="sftp_storage_preference_display_name_already_used">Esti nome yá ta usándose</string>
<string name="sftp_storage_preference_display_name_cannot_be_empty">El nome nun pue tar baleru</string>
<string name="sftp_action_mode_menu_delete">Desaniciar</string>
<string name="sftp_no_storage_locations_configured">Nun se configuraron allugamientos d\'almacenamientu</string>
<string name="sftp_saf_permission_explanation">P\'acceder remotamente a los ficheros tienes de configurar allugamientos d\'almacenamientu</string>
<string name="no_players_connected">Nun s\'alcontraron reproductores</string>
@@ -164,6 +166,7 @@
<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="unreachable_description">Esti preséu empareyáu nun ye algamable. Asegúrate de que ta coneutáu a la mesma rede que tu.</string>
<string name="no_wifi">Nun tas coneutáu a una rede Wi-Fi polo que nun vas ser a ver dengún preséu. Calca equí p\'activar el Wi-Fi.</string>
<string name="no_file_browser">Nun hai dengún restolador de ficheros instaláu.</string>
<string name="pref_plugin_telepathy">Unviu de SMS</string>
@@ -181,10 +184,13 @@
<string name="addcommand_explanation">Nun hai comandos rexistraos.</string>
<string name="addcommand_explanation2">Pues amestar más nos axustes de KDE Connect del ordenador</string>
<string name="add_command_description">Pues amestar más comandos nel ordenador</string>
<string name="pref_plugin_mprisreceiver">Mandu pa reproductores multimedia</string>
<string name="pref_plugin_mprisreceiver_desc">Controla los reproductores multimedia d\'esti preséu dende otru</string>
<string name="notification_channel_default">Otros avisos</string>
<string name="notification_channel_persistent">Indicador permanente</string>
<string name="notification_channel_media_control">Mandu multimedia</string>
<string name="notification_channel_filetransfer">Tresferencia de ficheros</string>
<string name="copy_url_to_clipboard">Copiar la URL al cartafueyu</string>
<string name="clipboard_toast">Copióse al cartafueyu</string>
<string name="runcommand_noruncommandplugin">Esti preséu nun tien activáu\'l plugin Execución de comandos</string>
<string name="pref_plugin_findremotedevice_desc">Fai que\'l preséu remotu suene</string>
@@ -205,7 +211,8 @@
<string name="block_contents">Bloquiar el conteníu de los avisos</string>
<string name="block_images">Bloquiar les imáxenes de los avisos</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>
<string name="take_picture">Llanzamientu de la cámara</string>
<string name="plugin_photo_desc">Llanza l\'aplicación de la cámara p\'acenciellar la fechura y tresferencia de semeyes</string>
<string name="no_app_for_opening">Nun alcontró denguna aplicación afayadiza p\'abrir esti ficheru.</string>
<string name="remote_keyboard_service">Tecláu remotu de KDE Connect</string>
</resources>

View File

@@ -27,8 +27,8 @@
<string name="pref_plugin_ping_desc">Posílat a přijímat ping</string>
<string name="pref_plugin_notifications">Synchronizace upozornění</string>
<string name="pref_plugin_notifications_desc">Zpřístupněte si upozornění z jiných zařízení</string>
<string name="pref_plugin_receive_notifications">Přijímat oznáme</string>
<string name="pref_plugin_receive_notifications_desc">Přijímat oznámení z jiného zařízení a zobrazovat je v Androidu</string>
<string name="pref_plugin_receive_notifications">Přijímat upozorně</string>
<string name="pref_plugin_receive_notifications_desc">Přijímat upozornění z jiného zařízení a zobrazovat je v Androidu</string>
<string name="pref_plugin_sharereceiver">Sdílet a přijmout</string>
<string name="pref_plugin_sharereceiver_desc">Sdílet soubory a odkazy mezi zařízeními</string>
<string name="device_list_empty">Žádná zařízení</string>
@@ -36,7 +36,7 @@
<string name="cancel">Zrušit</string>
<string name="open_settings">Otevřít nastavení</string>
<string name="no_permissions">Pro zpřístupnění upozornění potřebujete oprávnění</string>
<string name="no_permission_mprisreceiver">Abyste byli schopni ovládat vaše přehrávače médií, musíte udělit přístup k oznámením</string>
<string name="no_permission_mprisreceiver">Abyste byli schopni ovládat vaše přehrávače médií, musíte udělit přístup k upozorněním</string>
<string name="no_permissions_remotekeyboard">Pro zachytávání stisků kláves je potřeba aktivovat vzdálenou klávesnici KDE Connect</string>
<string name="send_ping">Poslat ping</string>
<string name="open_mpris_controls">Ovládání multimédií</string>
@@ -254,7 +254,8 @@
<string name="addcommand_explanation2">Nové příkazy můžete přidat v nastavení systému KDE Connect</string>
<string name="add_command_description">V pracovním prostředí můžete přidat příkazy</string>
<string name="pref_plugin_mprisreceiver">Ovládání přehrávače médií</string>
<string name="notification_channel_default">Ostatní oznámení</string>
<string name="pref_plugin_mprisreceiver_desc">Ovládejte přehrávače médií na vašem telefonu z jiného zařízení</string>
<string name="notification_channel_default">Ostatní upozornění</string>
<string name="notification_channel_persistent">Stálý ukazatel</string>
<string name="notification_channel_media_control">Ovládání médií</string>
<string name="notification_channel_filetransfer">Přenos souboru</string>
@@ -283,9 +284,9 @@
<string name="extra_options">Další možnosti</string>
<string name="privacy_options">Možnosti soukromí</string>
<string name="set_privacy_options">Nastavte své možnosti soukromí</string>
<string name="block_contents">Blokovat obsah oznáme</string>
<string name="block_contents">Blokovat obsah upozorně</string>
<string name="block_images">Blokovat obrázky z upozornění</string>
<string name="notification_channel_receivenotification">Oznamování z ostatních zařízení</string>
<string name="notification_channel_receivenotification">Upozornění z ostatních zařízení</string>
<string name="take_picture">Spustit fotoaparát</string>
<string name="plugin_photo_desc">Spusťte aplikaci fotoaparátu pro snadné zachytávání s přenos obrázků</string>
<string name="no_app_for_opening">Pro otevření tohoto souboru nebyla nalezena vhodná aplikace</string>

View File

@@ -238,6 +238,7 @@
<string name="addcommand_explanation2">Puede añadir nuevas órdenes en las preferencias del sistema de KDE Connect</string>
<string name="add_command_description">Puede añadir órdenes en su escritorio</string>
<string name="pref_plugin_mprisreceiver">Control del reproductor de medios</string>
<string name="pref_plugin_mprisreceiver_desc">Controle los reproductores de medios de su teléfono desde otro dispositivo</string>
<string name="notification_channel_default">Otras notificaciones</string>
<string name="notification_channel_persistent">Indicador persistente</string>
<string name="notification_channel_media_control">Control multimedia</string>

View File

@@ -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">Pole ühendatud ühegi seadmega</string>
<string name="foreground_notification_devices">Ühendatud seadmega: %s</string>
<string name="pref_plugin_telephony">Telefoni märguanded</string>
<string name="pref_plugin_telephony_desc">Sisenevate kõnede märguannete saatmine</string>
<string name="pref_plugin_battery">Aku aruanne</string>
<string name="pref_plugin_battery_desc">Perioodiline aku olekust teavitamine</string>
<string name="pref_plugin_sftp">Failisüsteemi sirvimine</string>
@@ -9,10 +13,16 @@
<string name="pref_plugin_clipboard_desc">Lõikepuhvri sisu jagamine</string>
<string name="pref_plugin_mousepad">Kaugsisestus</string>
<string name="pref_plugin_mousepad_desc">Telefoni või tahvli kasutamine puuteplaadi ja klaviatuurina</string>
<string name="pref_plugin_presenter">Kaugslaidiseanss</string>
<string name="pref_plugin_presenter_desc">Seadme kasutamine esitluse slaidide vahetamiseks</string>
<string name="pref_plugin_remotekeyboard">Kaugklahvivajutuste vastuvõtmine</string>
<string name="pref_plugin_remotekeyboard_desc">Kaugseadmete klahvivajutuste vastuvõtmine</string>
<string name="pref_plugin_mpris">Multimeedia juhtimine</string>
<string name="pref_plugin_mpris_desc">Meediamängija kaugjuhtimise võimaldamine</string>
<string name="pref_plugin_runcommand">Käsu käivitamine</string>
<string name="pref_plugin_runcommand_desc">Telefonist või tahvlist kaugkäskude käivitamine</string>
<string name="pref_plugin_contacts">Kontaktide sünkroonimine</string>
<string name="pref_plugin_contacts_desc">Võimaldab sünkroonida seadme kontaktiloendit</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Pingide saatmine ja vastuvõtmine</string>
<string name="pref_plugin_notifications">Märguannete sünkroonimine</string>
@@ -26,12 +36,20 @@
<string name="cancel">Loobu</string>
<string name="open_settings">Ava seadistused</string>
<string name="no_permissions">Märguannete nägemiseks tuleb anda vastavad õigused</string>
<string name="no_permission_mprisreceiver">Meediamängija juhtimiseks tuleb lubada juurdepääs märguannetele</string>
<string name="no_permissions_remotekeyboard">Klahvivajutuste vastuvõtmiseks tuleb aktiveerida KDE Connecti kaugklaviatuur</string>
<string name="send_ping">Saada ping</string>
<string name="open_mpris_controls">Multimeedia juhtimine</string>
<string name="remotekeyboard_editing_only_title">Kaugklahvide käitlemine ainult redigeerimisel</string>
<string name="remotekeyboard_not_connected">Aktiivne kaugklaviatuuri ühendus puudub, pane see paika KDE Connectis</string>
<string name="remotekeyboard_connected">Kaugklaviatuuri ühendus on aktiivne</string>
<string name="remotekeyboard_multiple_connections">Kaugklaviatuuri ühendusi on üle ühe, palun vali seade, mida seadistada</string>
<string name="open_mousepad">Kaugsisestus</string>
<string name="mousepad_info">Hiirekursori liigutamiseks liiguta sõrme ekraanil. Koputa klõpsamiseks ja kasuta kaht või kolme sõrme parema ja keskmise nupu jaoks. Kahe sõrmega saab kerida. Pika vajutusega saab lohistada.</string>
<string name="mousepad_double_tap_settings_title">Kahe sõrmega koputamise toimingu määramine</string>
<string name="mousepad_triple_tap_settings_title">Kolme sõrmega koputamise toimingu määramine</string>
<string name="mousepad_sensitivity_settings_title">Puutepadja tundlikkuse määramine</string>
<string name="mousepad_acceleration_profile_settings_title">Osutusseadme kiirenduse määramine</string>
<string name="mousepad_scroll_direction_title">Vastupidi kerimise suund</string>
<string-array name="mousepad_tap_entries">
<item>Paremklõps</item>
@@ -46,12 +64,12 @@
<item>Kõige kiirem</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>Kiirendus puudub</item>
<item>Kõige nõrgem</item>
<item>Nõrgem</item>
<item>Keskmine</item>
<item>Tugev</item>
<item>Kõige tugevam</item>
</string-array>
<string name="category_connected_devices">Ühendatud seadmed</string>
<string name="category_not_paired_devices">Saadaolevad seadmed</string>
@@ -72,7 +90,40 @@
<string name="remote_device_fingerprint">Kaugseadme sertifikaadi SHA1 sõrmejälg on:</string>
<string name="pair_requested">Paardumise soov</string>
<string name="pairing_request_from">Paardumise soov seadmest %1s</string>
<plurals name="incoming_file_title">
<item quantity="one">Saadi %1$d fail seadmest %2$s</item>
<item quantity="other">Saadi %1$d faili seadmest %2$s</item>
</plurals>
<plurals name="incoming_files_text">
<item quantity="one">File: %1s</item>
<item quantity="other">(Fail %2$d / %3$d) : %1$s</item>
</plurals>
<plurals name="outgoing_file_title">
<item quantity="one">Saadeti %1$d fail seadmesse %2$s</item>
<item quantity="other">Saadeti %1$d faili seadmesse %2$s</item>
</plurals>
<plurals name="outgoing_files_text">
<item quantity="one">Fail: %1$s</item>
<item quantity="other">(Fail %2$d / %3$d) : %1$s</item>
</plurals>
<plurals name="received_files_title">
<item quantity="one">Saadi fail %1$s</item>
<item quantity="other">Saadi %2$d faili seadmest %1$s</item>
</plurals>
<plurals name="received_files_fail_title">
<item quantity="one">Faili saamine seadmest %1$s nurjus</item>
<item quantity="other">%2$d faili saamine %3$d failist seadmest %1$s nurjus</item>
</plurals>
<plurals name="sent_files_title">
<item quantity="one">Fail saadeti seadmesse %1$s</item>
<item quantity="other">%2$d faili saadeti seadmesse %1$s</item>
</plurals>
<plurals name="send_files_fail_title">
<item quantity="one">Faili saatmine seadmesse %1$s nurjus</item>
<item quantity="other">%2$d faili saamine %3$d failist seadmesse %1$s nurjus</item>
</plurals>
<string name="received_file_text">Koputa \"%1s\" avamiseks</string>
<string name="cannot_create_file">Faili %s loomine nurjus</string>
<string name="tap_to_answer">Koputa vastamiseks</string>
<string name="right_click">Saada paremklõps</string>
<string name="middle_click">Saada keskklõps</string>
@@ -81,13 +132,16 @@
<string name="request_pairing">Soovi paardumist</string>
<string name="pairing_accept">Nõustu</string>
<string name="pairing_reject">Keeldu</string>
<string name="settings">Seadistused</string>
<string name="mpris_play">Esita</string>
<string name="mpris_pause">Paus</string>
<string name="mpris_previous">Eelmine</string>
<string name="mpris_rew">Keri tagasi</string>
<string name="mpris_ff">Kiiresti edasi</string>
<string name="mpris_next">Järgmine</string>
<string name="mpris_volume">Helitugevus</string>
<string name="mpris_time_settings_title">Edasi-tagasikerimise nupud</string>
<string name="mpris_time_settings_summary">Kiire edasi-tagasikerimise aja kohandamine vajutamisel</string>
<string-array name="mpris_time_entries">
<item>10 sekundit</item>
<item>20 sekundit</item>
@@ -95,39 +149,131 @@
<item>1 minut</item>
<item>2 minutit</item>
</string-array>
<string name="mpris_notification_settings_title">Meedia juhtimise märguannete näitamine</string>
<string name="mpris_notification_settings_summary">Meediamängija juhtimise võimaldamine ilma KDE Connecti avamata</string>
<string name="share_to">Jaga ...</string>
<string name="protocol_version_newer">See seade kasutab uuemat protokolli versiooni</string>
<string name="plugin_settings_with_name">%s seadistused</string>
<string name="invalid_device_name">Vigane seadme nimi</string>
<string name="shareplugin_text_saved">Saadi tekst, salvestati lõikepuhvrisse</string>
<string name="custom_devices_settings">Kohandatud seadmete loend</string>
<string name="custom_device_list">Lisa seadmeid IP järgi</string>
<string name="custom_device_deleted">Kohandatud seade kustutati</string>
<string name="custom_device_list_help">Kui sinu seadet automaatselt ei tuvastatud, võib lisada selle IP-aadressi või masinanime nupule klõpsates</string>
<string name="custom_device_fab_hint">Lisa seade</string>
<string name="undo">Võta tagasi</string>
<string name="share_notification_preference">Mürarikkad märguanded</string>
<string name="share_notification_preference_summary">Vibreerimine ja heli esitamine faili saamisel</string>
<string name="share_destination_customize">Sihtkataloogi kohandamine</string>
<string name="share_destination_customize_summary_disabled">Saadud failid salvestatakse kataloogi Allalaaditud</string>
<string name="share_destination_customize_summary_enabled">Failid salvestatakse allmääratud kataloogi</string>
<string name="share_destination_folder_preference">Sihtkataloog</string>
<string name="share">Jaga</string>
<string name="share_received_file">Jaga \"%s\"</string>
<string name="title_activity_notification_filter">Märguannete filter</string>
<string name="filter_apps_info">Valitud rakenduste märguanded sünkroonitakse</string>
<string name="sftp_sdcard_num">SD-kaart %d</string>
<string name="sftp_sdcard">SD-kaart</string>
<string name="sftp_readonly">(kirjutuskaitstud)</string>
<string name="sftp_camera">Kaamera pildid</string>
<string name="add_device_dialog_title">Seadme lisamine</string>
<string name="add_device_hint">Masinanimi või IP-aadress</string>
<string name="sftp_preference_detected_sdcards">Tuvastatud SD-kaardid</string>
<string name="sftp_preference_edit_sdcard_title">SD-kaardi muutmine</string>
<string name="sftp_preference_configured_storage_locations">Seadistatud salvestuskohad</string>
<string name="sftp_preference_add_storage_location_title">Salvestuskoha lisamine</string>
<string name="sftp_preference_edit_storage_location">Salvestuskoha muutmine</string>
<string name="sftp_preference_add_camera_shortcut">Lisa kaamerakausta kiirviit</string>
<string name="sftp_preference_add_camera_shortcut_summary_on">Kaamerakausta kiirviida lisamine</string>
<string name="sftp_preference_add_camera_shortcut_summary_off">Kaamerakausta kiirviita ei lisata</string>
<string name="sftp_storage_preference_storage_location">Salvestuskoht</string>
<string name="sftp_storage_preference_storage_location_already_configured">See asukoht on juba seadistatud</string>
<string name="sftp_storage_preference_click_to_select">"klõpsa valimiseks "</string>
<string name="sftp_storage_preference_display_name">Näidatav nimi</string>
<string name="sftp_storage_preference_display_name_already_used">See nimi on juba kasutusel</string>
<string name="sftp_storage_preference_display_name_cannot_be_empty">Näidatav nimi ei tohi olla andmata</string>
<string name="sftp_action_mode_menu_delete">Kustuta</string>
<string name="sftp_no_sdcard_detected">Ühtegi SD-kaarti ei leitud</string>
<string name="sftp_no_storage_locations_configured">Ühtegi salvestuskohta pole seadistatud</string>
<string name="sftp_saf_permission_explanation">Ligipääsuks failidele eemalt tuleb seadistada salvestuskohad</string>
<string name="no_players_connected">Ühtegi mängijat ei leitud</string>
<string name="send_files">Saada faile</string>
<string name="pairing_title">KDE Connecti seadmed</string>
<string name="pairing_description">Siin näeb teisi seadmeid samas võrgus, kus töötab KDE Connect</string>
<string name="device_rename_title">Muuda seadme nime</string>
<string name="device_rename_confirm">Muuda nime</string>
<string name="device_rename_title">Seadme nime muutmine</string>
<string name="device_rename_confirm">Nime muutmine</string>
<string name="refresh">Värskenda</string>
<string name="unreachable_description">See paardunud seade pole saadaval. Kontrolli, kas see on ikka ühendatud sinuga samasse võrku.</string>
<string name="no_wifi">Sul puudub ühendus Wi-Fi võrguga, mistõttu sa ei näe ühtegi seadet. Klõpsa siia Wi-Fi sisselülitamiseks.</string>
<string name="no_file_browser">Ühtegi failisirvijat pole paigaldatud</string>
<string name="pref_plugin_telepathy">Saada SMS</string>
<string name="pref_plugin_telepathy_desc">Tekstisõnumite saatmine oma töölaualt</string>
<string name="findmyphone_title">Leia mu telefon</string>
<string name="findmyphone_title_tablet">Leia mu tahvel</string>
<string name="findmyphone_title_tv">Leia mu teler</string>
<string name="findmyphone_description">Seadmele helistamine, et see üles leida</string>
<string name="findmyphone_found">Leitud</string>
<string name="open">Ava</string>
<string name="close">Sulge</string>
<string name="plugins_need_permission">Mõned pluginad vajavad töötamiseks õigusi (koputa rohkema teabe saamiseks);</string>
<string name="permission_explanation">See plugin vajab töötamiseks õigusi</string>
<string name="optional_permission_explanation">Kõigi funktsioonide lubamiseks tuleb sul anda lisaõigusi</string>
<string name="plugins_need_optional_permission">Mõne plugina osa omadusi on keelatud õiguste puudumise tõttu (koputa rohkema teabe saamiseks):</string>
<string name="share_optional_permission_explanation">Failide jagamiseks telefoni ja töölau vahel tuleb anda telefonile ligipääs</string>
<string name="telepathy_permission_explanation">SMS-ide lugemiseks ja kirjutamiseks töölaual tuleb anda õigused SMS-ile</string>
<string name="telephony_permission_explanation">Kõnede nägemiseks töölaual tuleb anda õigused telefonikõnede logile ja telefoni olekule</string>
<string name="telephony_optional_permission_explanation">Telefoninumbri asemel kontakti nime nägemiseks tuleb anda õigused telefoni kontaktidele</string>
<string name="contacts_permission_explanation">Oma kontaktide jagamiseks töölauaga tuleb anda õigused kontaktidele</string>
<string name="select_ringtone">Vali helin</string>
<string name="telephony_pref_blocked_title">Blokitud numbrid</string>
<string name="telephony_pref_blocked_dialog_desc">Neilt numbritelt tulevaid kõnesid ja SMS-e ei näidata. Palun pane iga number kirja eraldi reale</string>
<string name="mpris_coverart_description">Aktiivse meedia kaanepilt</string>
<string name="device_icon_description">Seadme ikoon</string>
<string name="settings_icon_description">Seadistuste ikoon</string>
<string name="presenter_fullscreen">Täisekraan</string>
<string name="presenter_exit">Välju esitlusest</string>
<string name="presenter_lock_tip">Seade on võimalik lukku panna ning liikuda eelmisele/järgmisele slaidile helitugevuse klahvidega</string>
<string name="add_command">Lisa käsk</string>
<string name="addcommand_explanation">Ühtegi käsku pole registreeritud</string>
<string name="addcommand_explanation2">Uusi käske saab lisada Süsteemi seadistustes KDE Connecti all</string>
<string name="add_command_description">Käske saab lisada töölaual</string>
<string name="pref_plugin_mprisreceiver">Meediafailide mängija juhtimine</string>
<string name="pref_plugin_mprisreceiver_desc">Telefoni meediamängijate juhtimine teisest seadmest</string>
<string name="notification_channel_default">Muud märguanded</string>
<string name="notification_channel_persistent">Püsiindikaator</string>
<string name="notification_channel_media_control">Meedia juhtimine</string>
<string name="notification_channel_filetransfer">Failiülekanne</string>
<string name="mpris_stop">Peata aktiivne mängija</string>
<string name="copy_url_to_clipboard">Kopeeri URL lõikepuhvrisse</string>
<string name="clipboard_toast">Kopeeriti lõikepuhvrisse</string>
<string name="runcommand_notreachable">Seade pole saadaval</string>
<string name="runcommand_notpaired">Seade pole paaritatud</string>
<string name="runcommand_nosuchdevice">Sellist seadet ei ole</string>
<string name="runcommand_noruncommandplugin">Sel seadmel ei ole käsu käivitamise plugin sisse lülitatud</string>
<string name="pref_plugin_findremotedevice">Kaugseadme leidmine</string>
<string name="pref_plugin_findremotedevice_desc">Helistamine kaugseadmesse</string>
<string name="ring">Helista</string>
<string name="pref_plugin_systemvolume">Süsteemi helitugevus</string>
<string name="pref_plugin_systemvolume_desc">Kaugseadme helitugevuse juhtimine</string>
<string name="mute">Tumm</string>
<string name="all">Kõik</string>
<string name="devices">Seadmed</string>
<string name="settings_rename">Seadme nimi</string>
<string name="settings_dark_mode">Tume teema</string>
<string name="settings_more_settings_title">Rohkem seadistusi</string>
<string name="settings_more_settings_text">Seadmekaupa seadistusi leiab seadme \"Pluginate seadistuste \" all.</string>
<string name="setting_persistent_notification">Püsimärguannete näitamine</string>
<string name="setting_persistent_notification_oreo">Püsimärguanded</string>
<string name="setting_persistent_notification_description">Koputa märguannete seadistuste lubamiseks/keelamiseks</string>
<string name="extra_options">Erivalikud</string>
<string name="privacy_options">Privaatsuse valikud</string>
<string name="set_privacy_options">Privaatsusvalikute määramine</string>
<string name="block_contents">Märguannete sisu blokkimine</string>
<string name="block_images">Märguannete piltide blokkimine</string>
<string name="notification_channel_receivenotification">Märguanded teistest seadmetest</string>
<string name="take_picture">Käivita kaamera</string>
<string name="plugin_photo_desc">Kaamerarakenduse käivitamine piltide tegemiseks ja ülekandmiseks</string>
<string name="no_app_for_opening">Selle faili avamiseks ei leitud sobivat rakendust</string>
<string name="remote_keyboard_service">KDE Connecti kaugklaviatuur</string>
<string name="presenter_pointer">Osutusseade</string>
</resources>

View File

@@ -11,13 +11,14 @@
<string name="pref_plugin_sftp_desc">Gailu honen fitxategi-sistema urrunetik arakatzea ahalbidetzen du</string>
<string name="pref_plugin_clipboard">Arbelaren sinkronizazioa</string>
<string name="pref_plugin_clipboard_desc">Partekatu arbelaren edukia</string>
<string name="pref_plugin_mousepad">Urruneko sarrera</string>
<string name="pref_plugin_mousepad">Urrutiko sarrera</string>
<string name="pref_plugin_mousepad_desc">Erabili zure telefonoa edo tableta ukimen-sagu eta teklatu gisa</string>
<string name="pref_plugin_presenter">Diapositiba emanaldietarako telekomandoa</string>
<string name="pref_plugin_presenter_desc">Erabili zure gailua aurkezpen bateko diapositibak aldatzeko</string>
<string name="pref_plugin_remotekeyboard">Jaso urruneko tekla-sakatzeak</string>
<string name="pref_plugin_remotekeyboard_desc">Jaso tekla-sakatze gertaerak urruneko gailuetatik</string>
<string name="pref_plugin_mpris">Multimedia kontrolak</string>
<string name="pref_plugin_mpris_desc">Zure media jotzailearen urruneko kontrola ematen dizu</string>
<string name="pref_plugin_mpris_desc">Zure euskarri-jotzailearen urruneko kontrola ematen dizu</string>
<string name="pref_plugin_runcommand">Exekutatu agindua</string>
<string name="pref_plugin_runcommand_desc">Abiarazi urruneko aginduak zure telefono edo tabletatik</string>
<string name="pref_plugin_contacts">Kontaktuen sinkronizatzailea</string>
@@ -36,6 +37,7 @@
<string name="open_settings">Ireki ezarpenak</string>
<string name="no_permissions">Jakinarazpenak atzitzeko baimena eman behar duzu</string>
<string name="no_permission_mprisreceiver">Zure euskarri-jotzaileak kontrolatu ahal izateko jakinarazpenetara atzipena eman behar diozu</string>
<string name="no_permissions_remotekeyboard">Sakatzeak jasotzeko KDE Connecten urruneko teklatua aktibatu behar duzu</string>
<string name="send_ping">Bidali ping</string>
<string name="open_mpris_controls">Multimedia kontrola</string>
<string name="remotekeyboard_editing_only_title">Erabili urruneko teklak editatzean besterik ez</string>
@@ -96,6 +98,14 @@
<item quantity="one">Fitxategia: %1s</item>
<item quantity="other">(%3$d(e)tik %2$d fitxategia) : %1$s</item>
</plurals>
<plurals name="outgoing_file_title">
<item quantity="one">"%2$s(r)i %1$d fitxategi bidaltzea"</item>
<item quantity="other">"%2$s(r)i %1$d fitxategi bidaltzea"</item>
</plurals>
<plurals name="outgoing_files_text">
<item quantity="one">Fitxategia: %1$s</item>
<item quantity="other">(%3$d(e)tik %2$d. fitxategia) : %1$s</item>
</plurals>
<plurals name="received_files_title">
<item quantity="one">Fitxategi bat jaso da %1$s-tik</item>
<item quantity="other">%2$d fitxategi jaso dira %1$s-tik</item>
@@ -104,6 +114,14 @@
<item quantity="one">Huts egin du fitxategi bat %1$s-tik jasotzeak</item>
<item quantity="other">Huts egin du %2$d/%3$d fitxategi %1$s-tik jasotzeak</item>
</plurals>
<plurals name="sent_files_title">
<item quantity="one">Fitxategia %1$s(e)ra bidali da</item>
<item quantity="other">%2$d fitxategi %1$s(e)ra bidali dira</item>
</plurals>
<plurals name="send_files_fail_title">
<item quantity="one">Huts egin du fitxategia %1$s(e)ra bidaltzea</item>
<item quantity="other">"Huts egin du %3$d(e)tik %2$d fitxategi %1$s(e)ra bidaltzea"</item>
</plurals>
<string name="received_file_text">Tak egin \'%1s\' irekitzeko</string>
<string name="cannot_create_file">Ezin da sortu %s fitxategia</string>
<string name="tap_to_answer">Tak egin erantzuteko</string>
@@ -140,6 +158,10 @@
<string name="shareplugin_text_saved">Testua jaso da, arbelean kopiatu da</string>
<string name="custom_devices_settings">Gailuen zerrenda pertsonalizatua</string>
<string name="custom_device_list">Gehitu gailuak IP bidez</string>
<string name="custom_device_deleted">Norberak finkatutako gailua ezabatu da</string>
<string name="custom_device_list_help">Zure gailua ez bada automatikoki detektatzen bere IP helbidea edo ostalari-izena gehitu dezakezu ekintza botoi mugikorrean klik eginez</string>
<string name="custom_device_fab_hint">Gehitu gailu bat</string>
<string name="undo">Desegin</string>
<string name="share_notification_preference">Jakinarazpen zaratatsuak</string>
<string name="share_notification_preference_summary">Bibratu eta jo soinua fitxategia jasotzean</string>
<string name="share_destination_customize">Pertsonalizatu direktorio xedea</string>
@@ -154,7 +176,27 @@
<string name="sftp_sdcard">SD txartela</string>
<string name="sftp_readonly">(irakurri soilik)</string>
<string name="sftp_camera">Kamerako irudiak</string>
<string name="no_players_connected">Ez da jokalaririk aurkitu</string>
<string name="add_device_dialog_title">Gehitu gailua</string>
<string name="add_device_hint">Ostalari-izena edo IP helbidea</string>
<string name="sftp_preference_detected_sdcards">Detektatutako SD txartelak</string>
<string name="sftp_preference_edit_sdcard_title">Editatu SD txartela</string>
<string name="sftp_preference_configured_storage_locations">Konfiguratutako biltegiratze kokalekuak</string>
<string name="sftp_preference_add_storage_location_title">Gehitu biltegiratze kokalekua</string>
<string name="sftp_preference_edit_storage_location">Editatu biltegiratze kokalekua</string>
<string name="sftp_preference_add_camera_shortcut">Gehitu kamera karpetaren lasterbidea</string>
<string name="sftp_preference_add_camera_shortcut_summary_on">Gehitu lasterbide bat kamera karpetara</string>
<string name="sftp_preference_add_camera_shortcut_summary_off">Ez gehitu lasterbide bat kamera karpetara</string>
<string name="sftp_storage_preference_storage_location">Biltegiratze kokalekua</string>
<string name="sftp_storage_preference_storage_location_already_configured">Kokaleku hau jada konfiguratuta dago</string>
<string name="sftp_storage_preference_click_to_select">klik egin aukeratzeko</string>
<string name="sftp_storage_preference_display_name">Azaltzeko izena</string>
<string name="sftp_storage_preference_display_name_already_used">Azaltzeko izen hau jada erabilita dago</string>
<string name="sftp_storage_preference_display_name_cannot_be_empty">Azaltzeko izena ezin da hutsik egon</string>
<string name="sftp_action_mode_menu_delete">Ezabatu</string>
<string name="sftp_no_sdcard_detected">Ez da SD txartelik detektatu</string>
<string name="sftp_no_storage_locations_configured">Ez da biltegiratze kokalekurik konfiguratu</string>
<string name="sftp_saf_permission_explanation">Fitxategiak urrunetik atzitzeko biltegiratze kokalekuak konfiguratu behar dituzu</string>
<string name="no_players_connected">Ez da jotzailerik aurkitu</string>
<string name="send_files">Bidali fitxategiak</string>
<string name="pairing_title">KDE Connect gailuak</string>
<string name="pairing_description">KDE Connect darabilten sareko beste gailuak hemen agertu beharko lirateke.</string>
@@ -162,6 +204,7 @@
<string name="device_rename_confirm">Aldatu izena</string>
<string name="refresh">Freskatu</string>
<string name="unreachable_description">Parekatutako gailu hau ez dago eskuragarri. Egiaztatu sare berera konektatuta dagoela.</string>
<string name="no_wifi">Ez zaude Wi-Fi sare batera konektatuta, baliteke gailurik ez ikustea. Egin klik hemen Wi-Fia gaitzeko.</string>
<string name="no_file_browser">Ez dago fitxategi arakatzailerik instalatuta.</string>
<string name="pref_plugin_telepathy">Bidali SMSa</string>
<string name="pref_plugin_telepathy_desc">Bidali testu-mezuak zure mahaigainetik</string>
@@ -178,6 +221,7 @@
<string name="plugins_need_optional_permission">Plugin batzuek desgaitutako eginbideak dituzte baimenak faltan dituztelako (tak egin informazio gehiagorako):</string>
<string name="share_optional_permission_explanation">Zure telefonoa eta mahaigainaren artean fitxategiak partekatzeko telefonoaren biltegiratzea atzitzeko baimena eman behar duzu</string>
<string name="telepathy_permission_explanation">SMSak zure mahaigainetik bidali ahal izateko, SMSak erabiltzeko baimena eman behar duzu</string>
<string name="telephony_permission_explanation">Telefono deiak zure mahaigainetik ikusteko, telefono deien egunkarira eta telefonoaren egoerara baimena eman behar duzu</string>
<string name="telephony_optional_permission_explanation">Telefono zenbakiaren ordez kontaktuaren izena ikusteko telefonoko kontaktuak atzitzeko baimena eman behar duzu</string>
<string name="contacts_permission_explanation">Zure kontaktuen liburuak mahaigainarekin partekatzeko, kontaktuetara baimena eman behar duzu</string>
<string name="select_ringtone">Hautatu dei-tonu bat</string>
@@ -188,11 +232,13 @@
<string name="settings_icon_description">Ezarpenen ikonoa</string>
<string name="presenter_fullscreen">Pantaila-betea</string>
<string name="presenter_exit">Irten aurkezpenetik</string>
<string name="presenter_lock_tip">Zure gailua giltzatu dezakezu eta bolumen teklak botoi gisa erabili aurreko/hurrengo diapositibara joateko</string>
<string name="add_command">Gehitu komando bat</string>
<string name="addcommand_explanation">Ez dago komandorik erregistraturik</string>
<string name="addcommand_explanation2">Komando berriak gehitu ditzakezu KDE Connect sistemaren ezarpenetan</string>
<string name="add_command_description">Komandoak gehitu ditzakezu mahaigainean</string>
<string name="pref_plugin_mprisreceiver">Euskarri-jotzailearen kontrola</string>
<string name="pref_plugin_mprisreceiver_desc">Kontrolatu zure telefonoaren euskarri-jotzaileak beste gailu batetik</string>
<string name="notification_channel_default">Beste jakinarazpen batzuk</string>
<string name="notification_channel_persistent">Adierazle iraunkorra</string>
<string name="notification_channel_media_control">Euskarrien kontrola</string>
@@ -217,10 +263,17 @@
<string name="settings_more_settings_title">Ezarpen gehiago</string>
<string name="settings_more_settings_text">Gailu-bakoitzeko ezarpenak aurki daitezke \'Pluginen ezarpenak\' barruan.</string>
<string name="setting_persistent_notification">Erakutsi jakinarazpen iraunkorra</string>
<string name="setting_persistent_notification_oreo">Jakinarazpen iraunkorra</string>
<string name="setting_persistent_notification_description">Sakatu gaitzeko/desgaitzeko jakinarazpen ezarpenetan</string>
<string name="extra_options">Aukera gehigarriak</string>
<string name="privacy_options">Pribatutasun aukerak</string>
<string name="set_privacy_options">Ezarri zure pribatutasun aukerak</string>
<string name="block_contents">Oztopatu jakinarazpenen edukiak</string>
<string name="block_images">Oztopatu jakinarazpenen irudiak</string>
<string name="notification_channel_receivenotification">Beste gailu batzuen jakinarazpenak</string>
<string name="take_picture">Abiarazi kamera</string>
<string name="plugin_photo_desc">Abiarazi kamerako aplikazioa argazkiak hartzeko eta transferitzeko</string>
<string name="no_app_for_opening">Ez da fitxategi hau irekitzeko aplikazio egokirik aurkitu</string>
<string name="remote_keyboard_service">KDE Connect urruneko teklatua</string>
<string name="presenter_pointer">Erakuslea</string>
</resources>

View File

@@ -238,6 +238,7 @@
<string name="addcommand_explanation2">Vous pouvez ajouter de nouvelles commandes dans la configuration système de KDE Connect</string>
<string name="add_command_description">Vous pouvez ajouter des commandes sur votre ordinateur</string>
<string name="pref_plugin_mprisreceiver">Contrôle du lecteur multimédia</string>
<string name="pref_plugin_mprisreceiver_desc">Contrôlez les lecteurs multimédia de votre téléphone depuis un autre appareil</string>
<string name="notification_channel_default">Autres notifications</string>
<string name="notification_channel_persistent">Indicateur persistant</string>
<string name="notification_channel_media_control">Contrôle multimédia</string>

View File

@@ -3,7 +3,7 @@
<string name="kde_connect">KDE Connect</string>
<string name="foreground_notification_no_devices">Belum terkoneksi ke perangkat apa pun</string>
<string name="foreground_notification_devices">Terkoneksi ke: %s</string>
<string name="pref_plugin_telephony">Penotifikasi telepon</string>
<string name="pref_plugin_telephony">Penotifikasi ponsel</string>
<string name="pref_plugin_telephony_desc">Kirim notifikasi untuk panggilan yang masuk</string>
<string name="pref_plugin_battery">Laporan baterai</string>
<string name="pref_plugin_battery_desc">Status baterai laporkan secara berkala</string>
@@ -12,14 +12,14 @@
<string name="pref_plugin_clipboard">Sinkron 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_mousepad_desc">Gunakan ponsel atau tabletmu sebagai touchpad dan keyboard</string>
<string name="pref_plugin_presenter_desc">Gunakan perangkatmu untuk mengubah slide dalam sebuah presentasi</string>
<string name="pref_plugin_remotekeyboard">Terima penekanan tuts jarak jauh</string>
<string name="pref_plugin_remotekeyboard_desc">Terima peristiwa tekan-tuts dari perangkat jarak jauh</string>
<string name="pref_plugin_mpris">Kendalikan multimedia</string>
<string name="pref_plugin_mpris_desc">Menyediakan sebuah kendali jarak jauh untuk pemutar mediamu</string>
<string name="pref_plugin_runcommand">Jalankan Perintah</string>
<string name="pref_plugin_runcommand_desc">Pemicu perintah jarak jauh dari telepon dan tablet-mu</string>
<string name="pref_plugin_runcommand_desc">Pemicu perintah jarak jauh dari ponsel dan tablet-mu</string>
<string name="pref_plugin_contacts">Penyinkron Kontak</string>
<string name="pref_plugin_contacts_desc">Bolehkan menyinkronkan buku kontak pada perangkat</string>
<string name="pref_plugin_ping">Ping</string>
@@ -160,7 +160,7 @@
<string name="no_file_browser">Tidak adanya penelusur file yang terinstal.</string>
<string name="pref_plugin_telepathy">Kirim SMS</string>
<string name="pref_plugin_telepathy_desc">Kirim teks perpesanan dari desktopmu</string>
<string name="findmyphone_title">Temukan teleponku</string>
<string name="findmyphone_title">Temukan ponselku</string>
<string name="findmyphone_title_tablet">Temukan tabletku</string>
<string name="findmyphone_title_tv">Temukan TV-ku</string>
<string name="findmyphone_description">Deringkan perangkat ini sehingga kamu bisa menemukannya</string>
@@ -173,7 +173,8 @@
<string name="plugins_need_optional_permission">Beberapa plugin yang memiliki fitur dinonfungsikan karena kurangnya perizinan (ketuk untuk info selebihnya):</string>
<string name="share_optional_permission_explanation">Untuk membagikan file antara teleponmu dan desktopmu kamu harus memberikan akses ke penyimpanan teleponmu</string>
<string name="telepathy_permission_explanation">Untuk membaca dan menulis SMS dari desktopmu kamu harus memberikan perizinan untuk SMS</string>
<string name="telephony_optional_permission_explanation">Untuk melihat nama kontak alih-alih nomor telepon, kamu harus memberikan akses ke kontak telepon</string>
<string name="telephony_permission_explanation">Untuk melihat panggilan ponsel pada desktop kamu harus memberikan perizinan untuk log panggilan ponsel dan keadaan ponsel</string>
<string name="telephony_optional_permission_explanation">Untuk melihat nama kontak alih-alih nomor ponsel, kamu harus memberikan akses ke kontak ponsel</string>
<string name="contacts_permission_explanation">Untuk membagikan buku kontak dengan desktopmu, kamu harus memberikan perizinan kontak</string>
<string name="select_ringtone">Pilih sebuah ringtone</string>
<string name="telephony_pref_blocked_title">Nomor yang diblokir</string>
@@ -186,4 +187,9 @@
<string name="addcommand_explanation2">"Kamu bisa menambahkan perintah baru dalam System Settings KDE Connect "</string>
<string name="add_command_description">Kamu bisa menambahkan perintah pada desktop</string>
<string name="pref_plugin_mprisreceiver">Kendali Pemutar Media</string>
<string name="pref_plugin_mprisreceiver_desc">Kendalikan pemutar media ponselmu dari perangkat lainnya</string>
<string name="devices">Perangkat</string>
<string name="settings_rename">Nama perangkat</string>
<string name="settings_dark_mode">Tema gelap</string>
<string name="settings_more_settings_title">Pengaturan selebihnya</string>
</resources>

View File

@@ -230,6 +230,7 @@
<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="notification_channel_default">기타 알림</string>
<string name="notification_channel_persistent">항상 표시된 표시기</string>
<string name="notification_channel_media_control">미디어 제어</string>

View File

@@ -220,6 +220,7 @@
<string name="device_rename_confirm">Pervadinti</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="no_wifi">Nesate prisijungę prie belaidžio (Wi-Fi) tinklo, taigi, galite nematyti jokių įrenginių. Spustelėkite čia, norėdami įjungti belaidį (Wi-Fi).</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>
@@ -253,6 +254,7 @@
<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 telefono medijos leistuves iš kito įrenginio</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>

View File

@@ -259,7 +259,7 @@
<string name="all">Alles</string>
<string name="devices">Apparaten</string>
<string name="settings_rename">Apparaatnaam</string>
<string name="settings_dark_mode">Donker themea</string>
<string name="settings_dark_mode">Donker thema</string>
<string name="settings_more_settings_title">Meer instellingen</string>
<string name="settings_more_settings_text">Instellingen per apparaat kunnen gevonden worden onder \'Plug-in-instellingen\' vanuit een apparaat.</string>
<string name="setting_persistent_notification">Blijvende melding tonen</string>

View File

@@ -238,6 +238,7 @@
<string name="addcommand_explanation2">Du kan leggja til nye kommandoar i systeminnstillingane til KDE Connect</string>
<string name="add_command_description">Du kan leggja til kommandoar på skrivebordet</string>
<string name="pref_plugin_mprisreceiver">Mediespelarkontrollar</string>
<string name="pref_plugin_mprisreceiver_desc">Kontroller mediespelarar på telefonen din frå ei anna eining</string>
<string name="notification_channel_default">Andre varslingar</string>
<string name="notification_channel_persistent">Evigvarande varslingar</string>
<string name="notification_channel_media_control">Mediestyring</string>

View File

@@ -11,8 +11,8 @@
<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">Wykorzystuje ekran jako mysz i klawiaturę</string>
<string name="pref_plugin_mousepad">Sterowanie z urządzenia przenośnego</string>
<string name="pref_plugin_mousepad_desc">Telefon lub tablet służy jako gładzik i klawiatura</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>
@@ -29,8 +29,8 @@
<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ółdzieli pliki i adresy URL pomiędzy urządzeniami</string>
<string name="pref_plugin_sharereceiver">Udostępnianie i pobieranie</string>
<string name="pref_plugin_sharereceiver_desc">Udostępnia pliki i adresy URL pomiędzy urządzeniami</string>
<string name="device_list_empty">Brak urządzeń</string>
<string name="ok">OK</string>
<string name="cancel">Zaniechaj</string>
@@ -127,9 +127,9 @@
<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="one">Wysłano plik do %1$s</item>
<item quantity="few">Wysłano %2$d pliki do %1$s</item>
<item quantity="many">Wysłano %2$d plików do %1$s</item>
<item quantity="other"/>
</plurals>
<plurals name="send_files_fail_title">
@@ -213,7 +213,7 @@
<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="no_players_connected">Nie znaleziono żadnego odtwarzacza</string>
<string name="send_files">Wyślij pliki</string>
<string name="send_files">Wysyłanie plików</string>
<string name="pairing_title">Urządzenia KDE Connect</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_rename_title">Zmień nazwę urządzenia</string>
@@ -223,11 +223,11 @@
<string name="no_wifi">Brak połączenia z siecią Wi-Fi, więc może nie być widać urządzeń. Naciśnij tutaj, aby włączyć Wi-Fi.</string>
<string name="no_file_browser">Nie wgrano żadnych przeglądarek plików.</string>
<string name="pref_plugin_telepathy">Wysyłanie SMSów</string>
<string name="pref_plugin_telepathy_desc">Wysyła wiadomość tekstową z komputera</string>
<string name="findmyphone_title">Znajdź mój telefon</string>
<string name="findmyphone_title_tablet">Znajdź mój tablet</string>
<string name="findmyphone_title_tv">Znajdź mój telewizor</string>
<string name="findmyphone_description">Dzwoni na dane urządzenie, tak abyś mógł je znaleźć.</string>
<string name="pref_plugin_telepathy_desc">Wysyła wiadomości tekstowe z komputera</string>
<string name="findmyphone_title">Poszukiwania telefonu</string>
<string name="findmyphone_title_tablet">Poszukiwania tabletu</string>
<string name="findmyphone_title_tv">Poszukiwania telewizora</string>
<string name="findmyphone_description">Dzwoni na dane urządzenie, aby można je odnaleźć.</string>
<string name="findmyphone_found">Znaleziony</string>
<string name="open">Otwórz</string>
<string name="close">Zamknij</string>
@@ -266,8 +266,8 @@
<string name="runcommand_notpaired">Urządzenie jest niesparowane</string>
<string name="runcommand_nosuchdevice">Nie ma takiego urządzenia</string>
<string name="runcommand_noruncommandplugin">To urządzenie nie ma włączonej wtyczki wykonywania poleceń</string>
<string name="pref_plugin_findremotedevice">Znajdź swoje urządzenie zdalne</string>
<string name="pref_plugin_findremotedevice_desc">Zadzwoń na urządzenie zdalne</string>
<string name="pref_plugin_findremotedevice">Poszukiwania urządzenia przenośnego</string>
<string name="pref_plugin_findremotedevice_desc">Dzwoni na urządzenie przenośne</string>
<string name="ring">Zadzwoń</string>
<string name="pref_plugin_systemvolume">Głośność systemowa</string>
<string name="pref_plugin_systemvolume_desc">Sterowanie głośnością systemu zdalnego urządzenia</string>

View File

@@ -7,6 +7,7 @@
<style name="KdeConnectTheme.Dark.NoActionBar" parent="KdeConnectThemeBase.Dark.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:colorEdgeEffect">@color/darkGrey</item>
<item name="android:navigationBarColor">@android:color/black</item>
</style>
</resources>

View File

@@ -230,6 +230,7 @@
<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="notification_channel_default">其他通知</string>
<string name="notification_channel_persistent">持久性通知</string>
<string name="notification_channel_media_control">媒体控制</string>

View File

@@ -45,7 +45,7 @@
<string name="remotekeyboard_connected">遠端鍵盤連線為啟用狀態</string>
<string name="remotekeyboard_multiple_connections">這裡有兩個以上的遠端鍵盤連結,選擇一個裝置以設定。</string>
<string name="open_mousepad">遠端輸入</string>
<string name="mousepad_info">在您的智慧型手機的螢幕上移動手指頭,用來控制電腦螢幕的標。按一下表示滑鼠的左鍵,使用兩隻/三隻手指頭按一下來表示滑鼠的右鍵/中鍵。使用兩隻手指頭捲動。長按則表示要拖拉。</string>
<string name="mousepad_info">在您的智慧型手機的螢幕上移動手指頭,用來控制電腦螢幕的標。按一下表示滑鼠的左鍵,使用兩隻/三隻手指頭按一下來表示滑鼠的右鍵/中鍵。使用兩隻手指頭捲動。長按則表示要拖拉。</string>
<string name="mousepad_double_tap_settings_title">設定兩隻手指頭按一下的動作</string>
<string name="mousepad_triple_tap_settings_title">設定三隻手指頭按一下的動作</string>
<string name="mousepad_sensitivity_settings_title">設定觸碰板的靈敏度</string>
@@ -122,8 +122,8 @@
<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="pairing_accept">接受</string>
<string name="pairing_reject"></string>
<string name="settings">設定</string>
<string name="mpris_play">播放</string>
<string name="mpris_pause">暫停</string>

View File

@@ -264,7 +264,7 @@
<string name="findmyphone_title_tablet">Find my tablet</string>
<string name="findmyphone_title_tv">Find my TV</string>
<string name="findmyphone_description">Rings this device so you can find it</string>
<string name="findmyphone_found">Found</string>
<string name="findmyphone_found">Found it</string>
<string name="open">Open</string>
<string name="close">Close</string>
@@ -300,6 +300,7 @@
<string name="notification_channel_persistent">Persistent indicator</string>
<string name="notification_channel_media_control">Media control</string>
<string name="notification_channel_filetransfer">File transfer</string>
<string name="notification_channel_high_priority">High priority</string>
<string name="mpris_stop">Stop the current player</string>
<string name="copy_url_to_clipboard">Copy URL to clipboard</string>

View File

@@ -76,6 +76,9 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
private ServerSocket tcpServer;
private DatagramSocket udpServer;
private long lastBroadcast = 0;
private final static long delayBetweenBroadcasts = 500;
private boolean listening = false;
// To prevent infinte loop between Android < IceCream because both device can only broadcast identity package but cannot connect via TCP
@@ -355,6 +358,12 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
}
private void broadcastUdpPacket() {
if (System.currentTimeMillis() < lastBroadcast + delayBetweenBroadcasts) {
Log.i("LanLinkProvider", "broadcastUdpPacket: relax cowboy");
return;
}
lastBroadcast = System.currentTimeMillis();
new Thread(() -> {
ArrayList<String> iplist = CustomDevicesActivity
.getCustomDeviceList(PreferenceManager.getDefaultSharedPreferences(context));

View File

@@ -534,8 +534,10 @@ public class Device implements BaseLink.PacketReceiver {
Log.i("KDE/Device", "removeLink: " + link.getLinkProvider().getName() + " -> " + getName() + " active links: " + links.size());
if (links.isEmpty()) {
reloadPluginsFromSettings();
packetQueue.disconnected();
packetQueue = null;
if (packetQueue != null) {
packetQueue.disconnected();
packetQueue = null;
}
}
}

View File

@@ -33,8 +33,8 @@ import android.util.Base64OutputStream;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.collection.LongSparseArray;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -52,6 +52,7 @@ import java.util.Set;
public class ContactsHelper {
static final String LOG_TAG = "ContactsHelper";
/**
* Lookup the name and photoID of a contact given a phone number
@@ -103,7 +104,7 @@ public class ContactsHelper {
}
return encodedPhoto.toString();
} catch (Exception ex) {
Log.e("ContactsHelper", ex.toString());
Log.e(LOG_TAG, ex.toString());
return "";
}
}
@@ -140,7 +141,7 @@ public class ContactsHelper {
} else {
// Something went wrong with this contact
// If you are experiencing this, please open a bug report indicating how you got here
Log.e("ContactsHelper", "Got a contact which does not have a LOOKUP_KEY");
Log.e(LOG_TAG, "Got a contact which does not have a LOOKUP_KEY");
continue;
}
@@ -155,59 +156,7 @@ public class ContactsHelper {
}
/**
* Get VCards using the batch database query which requires Android API 21
*
* @param context android.content.Context running the request
* @param IDs collection of raw contact IDs to look up
* @param lookupKeys
* @return Mapping of raw contact IDs to corresponding VCard
*/
@SuppressWarnings("ALL") // Since this method is busted anyway
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@Deprecated
protected static Map<Long, VCardBuilder> getVCardsFast(Context context, Collection<Long> IDs, Map<Long, String> lookupKeys) {
LongSparseArray<VCardBuilder> toReturn = new LongSparseArray<>();
StringBuilder keys = new StringBuilder();
List<Long> orderedIDs = new ArrayList<>(IDs);
for (Long ID : orderedIDs) {
String key = lookupKeys.get(ID);
keys.append(key);
keys.append(':');
}
// Remove trailing ':'
keys.deleteCharAt(keys.length() - 1);
Uri vcardURI = Uri.withAppendedPath(
ContactsContract.Contacts.CONTENT_MULTI_VCARD_URI,
Uri.encode(keys.toString()));
;
StringBuilder vcardJumble = new StringBuilder();
try (InputStream input = context.getContentResolver().openInputStream(vcardURI)) {
BufferedReader bufferedInput = new BufferedReader(new InputStreamReader(input));
String line;
while ((line = bufferedInput.readLine()) != null) {
vcardJumble.append(line).append('\n');
}
} catch (IOException e) {
// If you are experiencing this, please open a bug report indicating how you got here
Log.e("Contacts", "Exception while fetching vcards", e);
}
// At this point we are screwed:
// There is no way to figure out, given the lookup we just made, which VCard belonges
// to which ID. They appear to be in the same order as the request was made, but this
// is (provably) unreliable. I am leaving this code in case it is useful, but unless
// Android improves their API there is nothing we can do with it
return null;
}
/**
* Get VCards using serial database lookups. This is tragically slow, but the faster method using
* Get VCards using serial database lookups. This is tragically slow, so call only when needed.
*
* There is a faster API specified using ContactsContract.Contacts.CONTENT_MULTI_VCARD_URI,
* but there does not seem to be a way to figure out which ID resulted in which VCard using that API
@@ -263,97 +212,110 @@ public class ContactsHelper {
}
/**
* Return a mapping of contact IDs to a map of the requested data from the Contacts database
* <p>
* If for some reason there is no row associated with the contact ID in the database,
* there will not be a corresponding field in the returned map
* Get the last-modified timestamp for every contact in the database
*
* @param context android.content.Context running the request
* @param IDs collection of contact uIDs to look up
* @param contactsProjection List of column names to extract, defined in ContactsContract.Contacts
* @param context android.content.Context running the request
* @return Mapping of contact uID to last-modified timestamp
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) // Need API 18 for contact timestamps
public static Map<uID, Long> getAllContactTimestamps(Context context) {
String[] projection = { uID.COLUMN, ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP };
Map<uID, Map<String, String>> databaseValues = accessContactsDatabase(context, projection, null, null, null);
Map<uID, Long> timestamps = new HashMap<>();
for (uID contactID : databaseValues.keySet()) {
Map<String, String> data = databaseValues.get(contactID);
timestamps.put(
contactID,
Long.parseLong(data.get(ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP))
);
}
return timestamps;
}
/**
* Get the last-modified timestamp for the specified contact
*
* @param context android.content.Context running the request
* @param contactID Contact uID to read
* @throws ContactNotFoundException If the given ID for some reason does not match a contact
* @return Last-modified timestamp of the contact
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) // Need API 18 for contact timestamps
public static Long getContactTimestamp(Context context, uID contactID) throws ContactNotFoundException {
String[] projection = { uID.COLUMN, ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP };
String selection = uID.COLUMN + " = ?";
String[] selectionArgs = { contactID.toString() };
Map<uID, Map<String, String>> databaseValue = accessContactsDatabase(context, projection, selection, selectionArgs, null);
if (databaseValue.size() == 0) {
throw new ContactNotFoundException("Querying for contact with id " + contactID + " returned no results.");
}
if (databaseValue.size() != 1) {
Log.w(LOG_TAG, "Received an improper number of return values from the database in getContactTimestamp: " + databaseValue.size());
}
Long timestamp = Long.parseLong(databaseValue.get(contactID).get(ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP));
return timestamp;
}
/**
* Return a mapping of contact IDs to a map of the requested data from the Contacts database.
*
* @param context android.content.Context running the request
* @param projection List of column names to extract, defined in ContactsContract.Contacts. Must contain uID.COLUMN
* @param selection Parameterizable filter to use with the ContentResolver query. May be null.
* @param selectionArgs Parameters for selection. May be null.
* @param sortOrder Sort order to request from the ContentResolver query. May be null.
* @return mapping of contact uIDs to desired values, which are a mapping of column names to the data contained there
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB) // Needed for Cursor.getType(..)
public static Map<uID, Map<String, Object>> getColumnsFromContactsForIDs(Context context, Collection<uID> IDs, String[] contactsProjection) {
HashMap<uID, Map<String, Object>> toReturn = new HashMap<>();
if (IDs.isEmpty()) {
return toReturn;
}
private static Map<uID, Map<String, String>> accessContactsDatabase(
@NonNull Context context,
@NonNull String[] projection,
@Nullable String selection,
@Nullable String[] selectionArgs,
@Nullable String sortOrder
) {
Uri contactsUri = ContactsContract.Contacts.CONTENT_URI;
// Regardless of whether it was requested, we need to look up the uID column
Set<String> lookupProjection = new HashSet<>(Arrays.asList(contactsProjection));
lookupProjection.add(uID.COLUMN);
// We need a selection which looks like "<column> IN(?,?,...?)" with one ? per ID
StringBuilder contactsSelection = new StringBuilder(uID.COLUMN);
contactsSelection.append(" IN(");
for (int i = 0; i < IDs.size(); i++) {
contactsSelection.append("?,");
}
// Remove trailing comma
contactsSelection.deleteCharAt(contactsSelection.length() - 1);
contactsSelection.append(")");
// We need selection arguments as simply a String representation of each ID
List<String> contactsArgs = new ArrayList<>();
for (uID ID : IDs) {
contactsArgs.add(ID.toString());
}
HashMap<uID, Map<String, String>> toReturn = new HashMap<>();
try (Cursor contactsCursor = context.getContentResolver().query(
contactsUri,
lookupProjection.toArray(new String[0]),
contactsSelection.toString(),
contactsArgs.toArray(new String[0]),
null
projection,
selection,
selectionArgs,
sortOrder
)) {
if (contactsCursor != null && contactsCursor.moveToFirst()) {
do {
Map<String, Object> requestedData = new HashMap<>();
Map<String, String> requestedData = new HashMap<>();
int lookupKeyIdx = contactsCursor.getColumnIndexOrThrow(uID.COLUMN);
String lookupKey = contactsCursor.getString(lookupKeyIdx);
int uIDIndex = contactsCursor.getColumnIndexOrThrow(uID.COLUMN);
uID uID = new uID(contactsCursor.getString(uIDIndex));
// For each column, collect the data from that column
for (String column : contactsProjection) {
for (String column : projection) {
int index = contactsCursor.getColumnIndex(column);
// Since we might be getting various kinds of data, Object is the best we can do
Object data;
int type;
String data;
if (index == -1) {
// This contact didn't have the requested column? Something is very wrong.
// If you are experiencing this, please open a bug report indicating how you got here
Log.e("ContactsHelper", "Got a contact which does not have a requested column");
Log.e(LOG_TAG, "Got a contact which does not have a requested column");
continue;
}
type = contactsCursor.getType(index);
switch (type) {
case Cursor.FIELD_TYPE_INTEGER:
data = contactsCursor.getInt(index);
break;
case Cursor.FIELD_TYPE_FLOAT:
data = contactsCursor.getFloat(index);
break;
case Cursor.FIELD_TYPE_STRING:
data = contactsCursor.getString(index);
break;
case Cursor.FIELD_TYPE_BLOB:
data = contactsCursor.getBlob(index);
break;
default:
Log.e("ContactsHelper", "Got an undefined type of column " + column);
continue;
}
data = contactsCursor.getString(index);
requestedData.put(column, data);
}
toReturn.put(new uID(lookupKey), requestedData);
toReturn.put(uID, requestedData);
} while (contactsCursor.moveToNext());
}
}
@@ -443,4 +405,17 @@ public class ContactsHelper {
return contactLookupKey.equals(other);
}
}
/**
* Exception to indicate that a specified contact was not found
*/
public static class ContactNotFoundException extends Exception {
public ContactNotFoundException(uID contactID) {
super("Unable to find contact with ID " + contactID);
}
public ContactNotFoundException(String message) {
super(message);
}
}
}

View File

@@ -18,6 +18,7 @@ public class NotificationHelper {
public final static String MEDIA_CONTROL = "media_control";
public final static String FILETRANSFER = "filetransfer";
public final static String RECEIVENOTIFICATION = "receive";
public final static String HIGHPRIORITY = "highpriority";
}
public static void notifyCompat(NotificationManager notificationManager, int notificationId, Notification notification) {
@@ -80,6 +81,8 @@ public class NotificationHelper {
NotificationManager.IMPORTANCE_DEFAULT)
);
NotificationChannel highPriority = new NotificationChannel(Channels.HIGHPRIORITY, context.getString(R.string.notification_channel_high_priority), NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(highPriority);
}

View File

@@ -114,8 +114,7 @@ public class SMSHelper {
// By my understanding, "simple=true" means we can't support multi-target messages.
// Go complain to Samsung about their annoying OS changes!
if ("Samsung".equalsIgnoreCase(Build.MANUFACTURER)) {
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");
Log.i("SMSHelper", "This appears to be a Samsung device. This may cause some features to not work properly.");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
@@ -187,6 +186,41 @@ public class SMSHelper {
}
}
/**
* Checks if device supports `Telephony.Sms.SUBSCRIPTION_ID` column in database with URI `uri`
*
* @param uri Uri indicating the messages database to check
* @param context android.content.Context running the request.
*/
private static boolean getSubscriptionIdSupport(@NonNull Uri uri, @NonNull Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
return false;
}
// Some (Xiaomi) devices running >= Android Lollipop (SDK 22+) don't support
// `Telephony.Sms.SUBSCRIPTION_ID`, so additional check is needed.
// It may be possible to use "sim_id" instead of "sub_id" on these devices
// https://stackoverflow.com/a/38152331/6509200
try (Cursor availableColumnsCursor = context.getContentResolver().query(
uri,
new String[] {Telephony.Sms.SUBSCRIPTION_ID},
null,
null,
null)
) {
if (availableColumnsCursor != null) {
return true; // if we got the cursor, the query shouldn't fail
}
return false;
} catch (SQLiteException e) {
// With uri content://mms-sms/conversations this query throws an exception if sub_id is not supported
String errMessage = e.getMessage();
if (errMessage != null && errMessage.contains(Telephony.Sms.SUBSCRIPTION_ID)) {
return false;
}
return true;
}
}
/**
* Gets messages which match the selection
*
@@ -215,7 +249,7 @@ public class SMSHelper {
Set<String> allColumns = new HashSet<>();
allColumns.addAll(Arrays.asList(Message.smsColumns));
allColumns.addAll(Arrays.asList(Message.mmsColumns));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
if (getSubscriptionIdSupport(uri, context)) {
allColumns.addAll(Arrays.asList(Message.multiSIMColumns));
}
@@ -372,7 +406,8 @@ public class SMSHelper {
int read = Integer.parseInt(messageInfo.get(Message.READ));
@NonNull ThreadID threadID = new ThreadID(Long.parseLong(messageInfo.get(Message.THREAD_ID)));
long uID = Long.parseLong(messageInfo.get(Message.U_ID));
int subscriptionID = Integer.parseInt(messageInfo.get(Message.SUBSCRIPTION_ID));
int subscriptionID = messageInfo.get(Message.SUBSCRIPTION_ID) != null ?
Integer.parseInt(messageInfo.get(Message.SUBSCRIPTION_ID)) : 0;
return new Message(
address,
@@ -404,7 +439,8 @@ public class SMSHelper {
int read = Integer.parseInt(messageInfo.get(Message.READ));
@NonNull ThreadID threadID = new ThreadID(Long.parseLong(messageInfo.get(Message.THREAD_ID)));
long uID = Long.parseLong(messageInfo.get(Message.U_ID));
int subscriptionID = Integer.parseInt(messageInfo.get(Message.SUBSCRIPTION_ID));
int subscriptionID = messageInfo.get(Message.SUBSCRIPTION_ID) != null ?
Integer.parseInt(messageInfo.get(Message.SUBSCRIPTION_ID)) : 0;
String[] columns = {
Telephony.Mms.Part._ID, // The content ID of this part

View File

@@ -22,6 +22,8 @@ package org.kde.kdeconnect.Helpers.SecurityHelpers;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Base64;
@@ -57,6 +59,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
@@ -115,6 +118,10 @@ public class SslHelper {
if (needsToGenerateCertificate) {
Log.i("KDE/SslHelper", "Generating a certificate");
try {
//Fix for https://issuetracker.google.com/issues/37095309
Locale initialLocale = Locale.getDefault();
setLocale(Locale.ENGLISH, context);
X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
nameBuilder.addRDN(BCStyle.CN, deviceId);
nameBuilder.addRDN(BCStyle.OU, "KDE Connect");
@@ -138,12 +145,22 @@ public class SslHelper {
SharedPreferences.Editor edit = settings.edit();
edit.putString("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
edit.apply();
setLocale(initialLocale, context);
} catch (Exception e) {
Log.e("KDE/initialiseCert", "Exception", e);
}
}
}
private static void setLocale(Locale locale, Context context) {
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration config = resources.getConfiguration();
config.locale = locale;
resources.updateConfiguration(config, resources.getDisplayMetrics());
}
public static boolean isCertificateStored(Context context, String deviceId) {
SharedPreferences devicePreferences = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
String cert = devicePreferences.getString("certificate", "");

View File

@@ -0,0 +1,41 @@
package org.kde.kdeconnect;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner;
public class MyApplication extends Application {
private static class LifecycleObserver implements DefaultLifecycleObserver {
private boolean inForeground = false;
@Override
public void onStart(@NonNull LifecycleOwner owner) {
inForeground = true;
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
inForeground = false;
}
boolean isInForeground() {
return inForeground;
}
}
private static final LifecycleObserver foregroundTracker = new LifecycleObserver();
@Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(foregroundTracker);
}
public static boolean isInForeground() {
return foregroundTracker.isInForeground();
}
}

View File

@@ -108,6 +108,13 @@ public class NetworkPacket {
return mBody.optInt(key, defaultValue);
}
public void set(String key, int value) {
try {
mBody.put(key, value);
} catch (Exception ignored) {
}
}
public long getLong(String key) {
return mBody.optLong(key, -1);
}
@@ -116,7 +123,7 @@ public class NetworkPacket {
return mBody.optLong(key, defaultValue);
}
public void set(String key, int value) {
public void set(String key, long value) {
try {
mBody.put(key, value);
} catch (Exception ignored) {

View File

@@ -26,12 +26,12 @@ package org.kde.kdeconnect.Plugins.ContactsPlugin;
import android.Manifest;
import android.annotation.TargetApi;
import android.os.Build;
import android.provider.ContactsContract;
import android.util.Log;
import org.kde.kdeconnect.Helpers.ContactsHelper;
import org.kde.kdeconnect.Helpers.ContactsHelper.VCardBuilder;
import org.kde.kdeconnect.Helpers.ContactsHelper.uID;
import org.kde.kdeconnect.Helpers.ContactsHelper.ContactNotFoundException;
import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.PluginFactory;
@@ -141,9 +141,10 @@ public class ContactsPlugin extends Plugin {
*
* @param vcard vcard to apply metadata to
* @param uID uID to which the vcard corresponds
* @throws ContactNotFoundException If the given ID for some reason does not match a contact
* @return The same VCard as was passed in, but now with KDE Connect-specific fields
*/
private VCardBuilder addVCardMetadata(VCardBuilder vcard, uID uID) {
private VCardBuilder addVCardMetadata(VCardBuilder vcard, uID uID) throws ContactNotFoundException {
// Append the device ID line
// Unclear if the deviceID forms a valid name per the vcard spec. Worry about that later..
vcard.appendLine("X-KDECONNECT-ID-DEV-" + device.getDeviceId(),
@@ -151,16 +152,9 @@ public class ContactsPlugin extends Plugin {
// Build the timestamp line
// Maybe one day this should be changed into the vcard-standard REV key
List<uID> uIDs = new ArrayList<>();
uIDs.add(uID);
final String[] contactsProjection = new String[]{
ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP
};
Map<uID, Map<String, Object>> timestamp = ContactsHelper.getColumnsFromContactsForIDs(context, uIDs, contactsProjection);
Long timestamp = ContactsHelper.getContactTimestamp(context, uID);
vcard.appendLine("X-KDECONNECT-TIMESTAMP",
timestamp.get(uID).get(ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP).toString());
timestamp.toString());
return vcard;
}
@@ -178,26 +172,19 @@ public class ContactsPlugin extends Plugin {
private boolean handleRequestAllUIDsTimestamps(@SuppressWarnings("unused") NetworkPacket np) {
NetworkPacket reply = new NetworkPacket(PACKET_TYPE_CONTACTS_RESPONSE_UIDS_TIMESTAMPS);
List<uID> uIDs = ContactsHelper.getAllContactContactIDs(context);
Map<uID, Long> uIDsToTimestamps = ContactsHelper.getAllContactTimestamps(context);
List<String> uIDsAsStrings = new ArrayList<>(uIDs.size());
int contactCount = uIDsToTimestamps.size();
for (uID uID : uIDs) {
uIDsAsStrings.add(uID.toString());
List<String> uIDs = new ArrayList<>(contactCount);
for (uID contactID : uIDsToTimestamps.keySet()) {
Long timestamp = uIDsToTimestamps.get(contactID);
reply.set(contactID.toString(), timestamp);
uIDs.add(contactID.toString());
}
final String[] contactsProjection = new String[]{
ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP
};
reply.set("uids", uIDsAsStrings);
// Add last-modified timestamps
Map<uID, Map<String, Object>> uIDsToTimestamps = ContactsHelper.getColumnsFromContactsForIDs(context, uIDs, contactsProjection);
for (uID ID : uIDsToTimestamps.keySet()) {
Map<String, Object> data = uIDsToTimestamps.get(ID);
reply.set(ID.toString(), (Integer) data.get(ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP));
}
reply.set("uids", uIDs);
device.sendPacket(reply);
@@ -230,12 +217,17 @@ public class ContactsPlugin extends Plugin {
for (uID uID : uIDsToVCards.keySet()) {
VCardBuilder vcard = uIDsToVCards.get(uID);
vcard = this.addVCardMetadata(vcard, uID);
try {
vcard = this.addVCardMetadata(vcard, uID);
// Store this as a valid uID
uIDsAsStrings.add(uID.toString());
// Add the uid -> vcard pairing to the packet
reply.set(uID.toString(), vcard.toString());
// Store this as a valid uID
uIDsAsStrings.add(uID.toString());
// Add the uid -> vcard pairing to the packet
reply.set(uID.toString(), vcard.toString());
} catch (ContactsHelper.ContactNotFoundException e) {
e.printStackTrace();
}
}
// Add the valid uIDs to the packet

View File

@@ -19,47 +19,37 @@
*/
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import androidx.appcompat.app.AppCompatActivity;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.UserInterface.ThemeUtil;
import org.kde.kdeconnect_tp.R;
public class FindMyPhoneActivity extends Activity {
public class FindMyPhoneActivity extends AppCompatActivity {
static final String EXTRA_DEVICE_ID = "deviceId";
private MediaPlayer mediaPlayer;
private int previousVolume;
private AudioManager audioManager;
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (mediaPlayer != null) {
// If this activity was already open and we received the ring packet again, just finish it
finish();
}
// otherwise the activity will become active again
}
private String deviceId;
private FindMyPhonePlugin plugin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setUserPreferredTheme(this);
setContentView(R.layout.activity_find_my_phone);
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (!getIntent().hasExtra(EXTRA_DEVICE_ID)) {
Log.e("FindMyPhoneActivity", "You must include the deviceId for which this activity is started as an intent EXTRA");
finish();
}
deviceId = getIntent().getStringExtra(EXTRA_DEVICE_ID);
plugin = BackgroundService.getInstance().getDevice(deviceId).getPlugin(FindMyPhonePlugin.class);
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
@@ -72,42 +62,19 @@ public class FindMyPhoneActivity extends Activity {
@Override
protected void onStart() {
super.onStart();
try {
// Make sure we are heard even when the phone is silent, restore original volume later
previousVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), 0);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Uri ringtone;
String ringtoneString = prefs.getString(getString(R.string.findmyphone_preference_key_ringtone), "");
if (ringtoneString.isEmpty()) {
ringtone = Settings.System.DEFAULT_RINGTONE_URI;
} else {
ringtone = Uri.parse(ringtoneString);
}
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(this, ringtone);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mediaPlayer.setLooping(true);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception e) {
Log.e("FindMyPhoneActivity", "Exception", e);
}
/*
For whatever reason when Android launches this activity as a SystemAlertWindow it calls:
onCreate(), onStart(), onResume(), onStop(), onStart(), onResume().
When using BackgroundService.RunWithPlugin we get into concurrency problems and sometimes no sound will be played
*/
plugin.startPlaying();
plugin.hideNotification();
}
@Override
protected void onStop() {
super.onStop();
if (mediaPlayer != null) {
mediaPlayer.stop();
}
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, previousVolume, 0);
plugin.stopPlaying();
}
}

View File

@@ -21,20 +21,46 @@
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import org.kde.kdeconnect.Helpers.DeviceHelper;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect.MyApplication;
import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.PluginFactory;
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
import org.kde.kdeconnect_tp.R;
import java.io.IOException;
import static android.content.Context.POWER_SERVICE;
@PluginFactory.LoadablePlugin
public class FindMyPhonePlugin extends Plugin {
public final static String PACKET_TYPE_FINDMYPHONE_REQUEST = "kdeconnect.findmyphone.request";
private NotificationManager notificationManager;
private int notificationId;
private AudioManager audioManager;
private MediaPlayer mediaPlayer;
private int previousVolume;
private PowerManager powerManager;
@Override
public String getDisplayName() {
switch (DeviceHelper.getDeviceType(context)) {
@@ -55,13 +81,122 @@ public class FindMyPhonePlugin extends Plugin {
}
@Override
public boolean onPacketReceived(NetworkPacket np) {
public boolean onCreate() {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationId = (int) System.currentTimeMillis();
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
powerManager = (PowerManager) context.getSystemService(POWER_SERVICE);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
Uri ringtone;
String ringtoneString = prefs.getString(context.getString(R.string.findmyphone_preference_key_ringtone), "");
if (ringtoneString.isEmpty()) {
ringtone = Settings.System.DEFAULT_RINGTONE_URI;
} else {
ringtone = Uri.parse(ringtoneString);
}
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(context, ringtone);
//TODO: Deprecated use setAudioAttributes for API > 21
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mediaPlayer.setLooping(true);
mediaPlayer.prepare();
} catch (Exception e) {
Log.e("FindMyPhoneActivity", "Exception", e);
return false;
}
Intent intent = new Intent(context, FindMyPhoneActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return true;
}
@Override
public void onDestroy() {
stopPlaying();
audioManager = null;
mediaPlayer.release();
mediaPlayer = null;
}
@Override
public boolean onPacketReceived(NetworkPacket np) {
if (Build.VERSION.SDK_INT < 29 || MyApplication.isInForeground()) {
Intent intent = new Intent(context, FindMyPhoneActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(FindMyPhoneActivity.EXTRA_DEVICE_ID, device.getDeviceId());
context.startActivity(intent);
} else {
if (powerManager.isInteractive()) {
startPlaying();
showBroadcastNotification();
} else {
showActivityNotification();
}
}
return true;
}
private void showBroadcastNotification() {
Intent intent = new Intent(context, FindMyPhoneReceiver.class);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.setAction(FindMyPhoneReceiver.ACTION_FOUND_IT);
intent.putExtra(FindMyPhoneReceiver.EXTRA_DEVICE_ID, device.getDeviceId());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
createNotification(pendingIntent);
}
private void showActivityNotification() {
Intent intent = new Intent(context, FindMyPhoneActivity.class);
intent.putExtra(FindMyPhoneActivity.EXTRA_DEVICE_ID, device.getDeviceId());
PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
createNotification(pi);
}
private void createNotification(PendingIntent pendingIntent) {
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NotificationHelper.Channels.HIGHPRIORITY);
notification
.setSmallIcon(R.drawable.ic_notification)
.setOngoing(false)
.setFullScreenIntent(pendingIntent, true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setContentTitle(context.getString(R.string.findmyphone_found));
notification.setGroup("BackgroundService");
notificationManager.notify(notificationId, notification.build());
}
void startPlaying() {
if (!mediaPlayer.isPlaying()) {
// Make sure we are heard even when the phone is silent, restore original volume later
previousVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), 0);
mediaPlayer.start();
}
}
void hideNotification() {
notificationManager.cancel(notificationId);
}
void stopPlaying() {
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, previousVolume, 0);
mediaPlayer.stop();
try {
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
boolean isPlaying() {
return mediaPlayer.isPlaying();
}
@Override

View File

@@ -0,0 +1,35 @@
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.kde.kdeconnect.BackgroundService;
public class FindMyPhoneReceiver extends BroadcastReceiver {
final static String ACTION_FOUND_IT = "org.kde.kdeconnect.Plugins.FindMyPhonePlugin.foundIt";
final static String EXTRA_DEVICE_ID = "deviceId";
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case ACTION_FOUND_IT:
foundIt(context, intent);
break;
default:
Log.d("ShareBroadcastReceiver", "Unhandled Action received: " + intent.getAction());
}
}
private void foundIt(Context context, Intent intent) {
if (!intent.hasExtra(EXTRA_DEVICE_ID)) {
Log.e("FindMyPhoneReceiver", "foundIt() - deviceId extra is not present, ignoring");
return;
}
String deviceId = intent.getStringExtra(EXTRA_DEVICE_ID);
BackgroundService.RunWithPlugin(context, deviceId, FindMyPhonePlugin.class, FindMyPhonePlugin::stopPlaying);
}
}

View File

@@ -116,6 +116,11 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
public void onStop() {
notificationPlayer.stop();
}
@Override
public void onSeekTo(long pos) {
notificationPlayer.setPosition((int) pos);
}
};
/**
@@ -425,6 +430,13 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
playbackActions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
++numActions;
}
// Documentation says that this was added in Lollipop (21) but it seems to cause crashes on < Pie (28)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (notificationPlayer.isSeekAllowed()) {
playbackActions |= PlaybackStateCompat.ACTION_SEEK_TO;
++numActions;
}
}
playbackState.setActions(playbackActions);
mediaSession.setPlaybackState(playbackState.build());

View File

@@ -199,7 +199,7 @@ public class NotificationFilterActivity extends AppCompatActivity {
compoundButton.isChecked()));
ad.cancel();
myBuilder.create().show();
myBuilder.show();
break;
}
});

View File

@@ -184,7 +184,8 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0
|| (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0
|| (notification.flags & Notification.FLAG_LOCAL_ONLY) != 0
|| (notification.flags & NotificationCompat.FLAG_GROUP_SUMMARY) != 0) //The notification that groups other notifications
|| (notification.flags & NotificationCompat.FLAG_GROUP_SUMMARY) != 0 //The notification that groups other notifications
)
{
//This is not a notification we want!
return;
@@ -237,6 +238,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
np.set("actions", extractActions(notification, key));
np.set("id", key);
np.set("silent", (notification.flags & NotificationCompat.FLAG_ONLY_ALERT_ONCE) != 0);
np.set("isClearable", statusBarNotification.isClearable());
np.set("appName", appName == null ? packageName : appName);
np.set("time", Long.toString(statusBarNotification.getPostTime()));
@@ -369,7 +371,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
for (Parcelable p : ms) {
Bundle m = (Bundle) p;
if (isGroupConversation) {
if (isGroupConversation && m.containsKey("sender")) {
messagesBuilder.append(m.get("sender"));
messagesBuilder.append(": ");
}

View File

@@ -107,7 +107,11 @@ public class RunCommandActivity extends AppCompatActivity {
deviceId = getIntent().getStringExtra("deviceId");
boolean canAddCommands = BackgroundService.getInstance().getDevice(deviceId).getPlugin(RunCommandPlugin.class).canAddCommand();
boolean canAddCommands = false;
try {
canAddCommands = BackgroundService.getInstance().getDevice(deviceId).getPlugin(RunCommandPlugin.class).canAddCommand();
} catch (Exception ignore) {
}
FloatingActionButton addCommandButton = findViewById(R.id.add_command_button);
if (canAddCommands) {
@@ -118,14 +122,12 @@ public class RunCommandActivity extends AppCompatActivity {
addCommandButton.setOnClickListener(v -> BackgroundService.RunWithPlugin(RunCommandActivity.this, deviceId, RunCommandPlugin.class, plugin -> {
plugin.sendSetupPacket();
AlertDialog dialog = new AlertDialog.Builder(RunCommandActivity.this)
new AlertDialog.Builder(RunCommandActivity.this)
.setTitle(R.string.add_command)
.setMessage(R.string.add_command_description)
.setPositiveButton(R.string.ok, null)
.create();
dialog.show();
.show();
}));
updateView();
}

View File

@@ -149,7 +149,7 @@ public class CompositeReceiveFileJob extends BackgroundJob<Device, Void> {
setProgress((int)prevProgressPercentage);
fileDocument = getDocumentFileFor(currentFileName, currentNetworkPacket.getBoolean("open"));
fileDocument = getDocumentFileFor(currentFileName, currentNetworkPacket.getBoolean("open", false));
if (currentNetworkPacket.hasPayload()) {
outputStream = new BufferedOutputStream(getDevice().getContext().getContentResolver().openOutputStream(fileDocument.getUri()));

View File

@@ -185,9 +185,9 @@ public class SharePlugin extends Plugin {
CompositeReceiveFileJob job;
boolean hasNumberOfFiles = np.has(KEY_NUMBER_OF_FILES);
boolean hasOpen = np.has("open");
boolean isOpen = np.getBoolean("open", false);
if (hasNumberOfFiles && !hasOpen && receiveFileJob != null) {
if (hasNumberOfFiles && !isOpen && receiveFileJob != null) {
job = receiveFileJob;
} else {
job = new CompositeReceiveFileJob(device, receiveFileJobCallback);
@@ -201,7 +201,7 @@ public class SharePlugin extends Plugin {
job.addNetworkPacket(np);
if (job != receiveFileJob) {
if (hasNumberOfFiles && !hasOpen) {
if (hasNumberOfFiles && !isOpen) {
receiveFileJob = job;
}
backgroundJobHandler.runJob(job);

View File

@@ -245,7 +245,7 @@ public class DeviceFragment extends Fragment {
builder.setMessage(context.getResources().getString(R.string.my_device_fingerprint) + "\n" + SslHelper.getCertificateHash(SslHelper.certificate) + "\n\n"
+ context.getResources().getString(R.string.remote_device_fingerprint) + "\n" + SslHelper.getCertificateHash(device.certificate));
}
builder.create().show();
builder.show();
return true;
});
}

View File

@@ -286,7 +286,10 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
@Override
protected void onStart() {
super.onStart();
BackgroundService.RunCommand(this, service -> service.addDeviceListChangedCallback("MainActivity", this::updateDeviceList));
BackgroundService.RunCommand(this, service -> {
service.onNetworkChange();
service.addDeviceListChangedCallback("MainActivity", this::updateDeviceList);
});
updateDeviceList();
}

View File

@@ -254,6 +254,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
@Override
public void onStart() {
super.onStart();
mSwipeRefreshLayout.setEnabled(true);
BackgroundService.RunCommand(mActivity, service -> service.addDeviceListChangedCallback("PairingFragment", this::updateDeviceList));
updateDeviceList();
}

View File

@@ -3,10 +3,12 @@ package org.kde.kdeconnect.UserInterface;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.view.View;
import com.google.android.material.snackbar.Snackbar;
@@ -52,7 +54,12 @@ public class SettingsFragment extends PreferenceFragmentCompat {
if (TextUtils.isEmpty(name)) {
if (getView() != null) {
Snackbar.make(getView(), R.string.invalid_device_name, Snackbar.LENGTH_LONG).show();
Snackbar snackbar = Snackbar.make(getView(), R.string.invalid_device_name, Snackbar.LENGTH_LONG);
if (!prefs.getBoolean("darkTheme", false)) {
// white color is set to the background of snackbar if dark mode is off
snackbar.getView().setBackgroundColor(Color.WHITE);
}
snackbar.show();
}
return false;
}