2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-09-01 22:55:10 +00:00

Compare commits

...

196 Commits

Author SHA1 Message Date
Albert Vaca
7dd4583a24 Increased version number to release 2018-02-17 10:07:57 +01:00
Nicolas Fella
c05f13afac Loop ringtone in FindMyPhonePlugin
Summary:
BUG: 368089

FindMyPhone does not loop ringtones, which makes problems with short ringtones. Additionally, it depends on the volume of the alarm channel, so if the alarms are muted, no
sound can be heard. This patch raises the alarm volume to max when the activity gets started and restores the previous value when it stops.

Test Plan: Trigger findmyphone, hear sound looping. Set alarm volume to zero and check if it gets restored.

Reviewers: #kde_connect, mtijink

Reviewed By: #kde_connect, mtijink

Subscribers: mtijink, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9947
2018-02-01 11:47:45 +01:00
Nicolas Fella
de7d944230 Get rid of MaxWidthImageButton
Summary: There is no need to implement a custom view for that. It is only used in MPRIS Activity, which looks almost the same now, except that the play button aligns with the buttons beneath, which is better IMHO.

Reviewers: #kde_connect, mtijink

Reviewed By: #kde_connect, mtijink

Subscribers: #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9520
2018-02-01 11:45:28 +01:00
l10n daemon script
b1daf1af0c GIT_SILENT made messages (after extraction) 2018-01-30 03:15:19 +01:00
l10n daemon script
baeec6afbf GIT_SILENT made messages (after extraction) 2018-01-29 03:17:09 +01:00
l10n daemon script
2187b273b9 GIT_SILENT made messages (after extraction) 2018-01-28 03:16:00 +01:00
l10n daemon script
1fa0585100 GIT_SILENT made messages (after extraction) 2018-01-27 03:15:25 +01:00
l10n daemon script
4e2460bf37 GIT_SILENT made messages (after extraction) 2018-01-25 03:18:02 +01:00
l10n daemon script
5e3e32d289 GIT_SILENT made messages (after extraction) 2018-01-23 03:18:45 +01:00
Albert Vaca
167f86affa Fix gradle deprecation warnings 2018-01-23 00:41:33 +01:00
Albert Vaca
53dfb299a7 Fix build from gradle's cli 2018-01-23 00:41:33 +01:00
l10n daemon script
c4e6c66809 GIT_SILENT made messages (after extraction) 2018-01-22 03:09:49 +01:00
l10n daemon script
1703276f37 GIT_SILENT made messages (after extraction) 2018-01-21 03:12:07 +01:00
Chris Holland
91ade6a846 Mention 2 fingers to scroll in mousepad_info
BUG: 389185

Differential Revision: https://phabricator.kde.org/D9977
2018-01-19 01:03:00 -05:00
Albert Vaca
1b62a5ae32 Use stringbuilder 2018-01-17 00:05:57 +01:00
Albert Vaca
4b21d67da0 Increased minor version to release 2018-01-16 22:53:49 +01:00
Philip Cohn-Cort
5c3fcb1423 Prevent Android 8.1 crash
Summary:
The SSL/TLS handshake code in LanLinkProvider is normally invoked in parallel, so that multiple incoming messages can be read at once. However, this logic causes an unusual crash in Android 8.1's native openssl library.

Sample logcat of crash is available at https://paste.kde.org/ptolqcpya

This patch mitigates the issue by making the `addLink` function in that class synchronized. I recommend future work to determine whether there are any other thread-safety concerns in the handshake code.

Test Plan:
1. Designate a test wi-fi network
2. Disconnect all KDE Connect devices from that network
3. Install build on disconnected Android 8.1 device
4. Clear KDE Connect app data (if present) on 8.1 device
5. Connect 8.1 device to test wi-fi network
6. Connect any other KDE Connect device to test wi-fi network

Reviewers: albertvaka

Reviewed By: albertvaka

Differential Revision: https://phabricator.kde.org/D9739
2018-01-16 20:08:16 +01:00
l10n daemon script
79a58e12a1 GIT_SILENT made messages (after extraction) 2018-01-08 03:04:36 +01:00
Albert Vaca
92300a7d63 Create destination directory in case it doesn't exist 2018-01-07 16:52:57 +01:00
Nicolas Fella
e94959f9c3 Show notifications that are present when pairing
Summary:
When the plugin is created all current notifications are sent to the other device. When the NotificationListener is not ready at that time this is delayed until it is. This was intended before, but did not work because the
requestAnswer flag was set on the network packages. The desktop ignored those packages. I see no purpose for the requestAnswer flag so I removed it.

Depends on D9622

Test Plan: Create some notifications. Restart the desktop or the app and look for the notifications on the desktop

Reviewers: #kde_connect, mtijink, albertvaka

Reviewed By: #kde_connect, mtijink, albertvaka

Subscribers: mtijink, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9558
2018-01-06 16:06:57 +01:00
Nicolas Fella
45bac893d9 Use getString instead of getCharsequence().toString()
Summary: Depends on D9621

Reviewers: #kde_connect, mtijink, albertvaka

Reviewed By: #kde_connect, mtijink, albertvaka

Subscribers: #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9622
2018-01-06 16:05:48 +01:00
Nicolas Fella
fdaa632a39 Delete general_preferences.xml
Summary: It doesnt seems to be useful any more

Test Plan: Android Studios Safe delete found no usage

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9623
2018-01-06 16:04:03 +01:00
Nicolas Fella
22696f7c97 Restrict access modifiers to the necessary
Summary:
Set access to (package) private where possible
Depends on D9620

Reviewers: #kde_connect, mtijink

Reviewed By: mtijink

Subscribers: mtijink, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9621
2018-01-03 21:09:28 +01:00
Nicolas Fella
7155042da0 Remove dead code
Summary:
Removed some dead code.

Depends on D9548

Reviewers: #kde_connect, mtijink

Reviewed By: mtijink

Subscribers: #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9620
2018-01-03 20:54:14 +01:00
Nicolas Fella
d218a10004 Use minSdk in NotificationsPlugin
Summary:
Depends on D9546
Depends on D9619

Make use of the new minSdk feature.

Reviewers: #kde_connect, mtijink

Reviewed By: mtijink

Subscribers: mtijink, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9548
2018-01-03 20:52:49 +01:00
Nicolas Fella
c9ca1f4906 Per Plugin minSdk Level
Summary:
Each plugin gets a minSdk level assigned. If this level isn't available the plugin doesn't get loaded. This can simplifie the plugin code by removing reccuring Sdk version checks.
Should we let the user know that a plugin is not available due to that or should it fail silently?

Actual Plugin adaptions come in follow-up patches.

Reviewers: #kde_connect, mtijink

Reviewed By: mtijink

Subscribers: mtijink, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9546
2018-01-03 20:50:02 +01:00
Matthijs Tijink
ea9a5459fd Remove minimum and target API versions from manifest.
Summary: They are provided by the gradle build file.

Test Plan: I checked the generated merged manifest file.

Reviewers: #kde_connect, nicolasfella

Reviewed By: #kde_connect, nicolasfella

Differential Revision: https://phabricator.kde.org/D9562
2018-01-03 20:40:53 +01:00
Nicolas Fella
9eda5bf072 Run Reformat Code on the notifications plugin
Summary: Bring law and order to the coding style

Reviewers: #kde_connect, mtijink

Reviewed By: mtijink

Subscribers: #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9619
2018-01-03 20:21:35 +01:00
l10n daemon script
8052994232 GIT_SILENT made messages (after extraction) 2018-01-03 04:54:08 +01:00
Nicolas Fella
8e2757ecf3 Fix context in layout files
Reviewers: #kde_connect, mtijink

Reviewed By: mtijink

Subscribers: #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9524
2018-01-02 18:18:31 +01:00
Nicolas Fella
52f2067e55 Silence a warning in preference_with_button.xml
Summary: Using @android:id instead of @+android:id silences two Code Inspection errors

Reviewers: #kde_connect, mtijink

Reviewed By: mtijink

Subscribers: #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D9523
2018-01-02 18:17:21 +01:00
Matthijs Tijink
56fc69b3de Add new encryption cipher for Android 2.3 (API 9+) support
Summary:
Arch linux recently updated libraries which dropped support for RC4, used for connections to Android before Android 3 Honeycomb. Other distributions may also be affected (or will be affected in the future).

This adds a new cipher, supported by Android API 9+.

Test Plan: With this change (and corresponding desktop change) the app can connect again.

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Differential Revision: https://phabricator.kde.org/D9449
2017-12-22 13:26:19 +01:00
Matthijs Tijink
8538121ed2 Receive MPRIS title, artist and album information
Summary: Receives the title, artist and album information from MPRIS, instead of a single "artist - title". The desktop counterpart is in D8957.

Test Plan: Works for me, both with and without D8957.

Reviewers: #kde_connect, nicolasfella

Reviewed By: #kde_connect, nicolasfella

Subscribers: nicolasfella

Differential Revision: https://phabricator.kde.org/D9083
2017-12-20 17:56:01 +01:00
Matthijs Tijink
c6746e38a0 Allow opening files shared to android using the notification
Summary:
Since Android Nougat, the previous way to open a file shared to android did not work anymore (using `file://` urls), as marked with a TODO.

This diff implements the new way of opening files: a content provider url (`content://`) allows opening files through the KDE Connect app. As an added benefit, apps without external files permission can now open files received by KDE Connect.

Test Plan: Works for me.

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka, nicolasfella

Differential Revision: https://phabricator.kde.org/D9331
2017-12-20 17:53:35 +01:00
Albert Vaca
90f03555c5 Updates for Android Studio 3.0 2017-12-09 15:36:21 +01:00
Albert Vaca
e9be9b9c87 Use appcompat libraries from maven instead of locally installed 2017-12-09 14:46:12 +01:00
Albert Vaca
ee854bf7ad Replace deprecated ActionBarActivity by AppCompatActivity 2017-12-09 14:31:40 +01:00
Albert Vaca
71106a3de3 Merge branch '1.x'
# Conflicts:
#	AndroidManifest.xml
#	res/values-da/strings.xml
#	res/values-eu/strings.xml
#	res/values-zh-rCN/strings.xml
2017-12-09 14:21:02 +01:00
l10n daemon script
0a841b8064 GIT_SILENT made messages (after extraction) 2017-12-09 02:57:06 +01:00
Matthijs Tijink
147d8510d5 Simplify MPRIS callback code
Summary:
Makes sure the MPRIS data is always up-to-date, so requesting updates
separately is never necessary. Also provides a way to remove callbacks.

Test Plan: All information still appears in the MPRIS activity and the controls still work.

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Differential Revision: https://phabricator.kde.org/D9084
2017-12-07 17:54:00 +01:00
Matthijs Tijink
044261ceb1 Use material icons in MPRIS activity
Summary: The previous icons were old (pre-Material, maybe even pre-Holo). The recommended practice now is to add the icons directly to your app, so I added the material icons. Note that the vector version is used; these are automatically converted to bitmaps for older android versions.

Reviewers: #kde_connect

Subscribers: apol

Differential Revision: https://phabricator.kde.org/D8955
2017-12-01 21:27:35 +01:00
Matthijs Tijink
cc8330a079 Make the player status a per-player object in the MPRIS plugin
Summary:
This directly fixes a couple of bugs (where the UI was not updated in all cases) and will allow different code parts to use different players without clashing with each other.

This is required for sensible behaviour while using the media control notification (which I plan to work on).

Reviewers: #kde_connect, thomasp, albertvaka

Reviewed By: #kde_connect, thomasp, albertvaka

Subscribers: albertvaka, apol, thomasp

Differential Revision: https://phabricator.kde.org/D8942
2017-12-01 00:36:43 +01:00
l10n daemon script
221c6b4fd7 GIT_SILENT made messages (after extraction) 2017-11-28 02:58:18 +01:00
l10n daemon script
a1c6921696 GIT_SILENT made messages (after extraction) 2017-11-27 03:06:41 +01:00
l10n daemon script
656268c42e GIT_SILENT made messages (after extraction) 2017-11-10 03:06:52 +01:00
l10n daemon script
3e229afea2 GIT_SILENT made messages (after extraction) 2017-11-08 05:45:51 +01:00
l10n daemon script
6c54a3d720 GIT_SILENT made messages (after extraction) 2017-11-06 03:02:52 +01:00
l10n daemon script
66a120d978 GIT_SILENT made messages (after extraction) 2017-11-02 03:05:21 +01:00
l10n daemon script
082543f749 GIT_SILENT made messages (after extraction) 2017-10-30 03:04:06 +01:00
l10n daemon script
bc1befcbb0 GIT_SILENT made messages (after extraction) 2017-10-20 03:00:08 +02:00
l10n daemon script
53cd5c71ab GIT_SILENT made messages (after extraction) 2017-10-15 03:17:25 +02:00
l10n daemon script
473e6c8d9c GIT_SILENT made messages (after extraction) 2017-10-13 03:19:46 +02:00
l10n daemon script
3fc88bb120 GIT_SILENT made messages (after extraction) 2017-10-10 03:17:38 +02:00
l10n daemon script
30afd0263b GIT_SILENT made messages (after extraction) 2017-10-09 03:22:38 +02:00
l10n daemon script
001755667a GIT_SILENT made messages (after extraction) 2017-09-20 06:11:38 +02:00
l10n daemon script
cf8aaa66e0 GIT_SILENT made messages (after extraction) 2017-09-11 03:14:20 +02:00
l10n daemon script
090815e7f7 GIT_SILENT made messages (after extraction) 2017-09-03 03:00:03 +02:00
Albert Vaca
45cb0cc393 Updated README 2017-09-02 12:01:21 +02:00
l10n daemon script
6859685dd0 GIT_SILENT made messages (after extraction) 2017-08-27 03:02:41 +02:00
Nicolas Fella
9338641a78 Fix bug while refreshing
Summary: Fix bug mentioned in https://phabricator.kde.org/T6583

Reviewers: #kde_connect, jeanv, albertvaka

Reviewed By: #kde_connect, jeanv, albertvaka

Subscribers: albertvaka, #kde_connect

Tags: #kde_connect

Maniphest Tasks: T6583

Differential Revision: https://phabricator.kde.org/D7372
2017-08-19 13:27:09 +02:00
l10n daemon script
de9aeb8416 GIT_SILENT made messages (after extraction) 2017-08-18 03:17:16 +02:00
l10n daemon script
d4e0386665 GIT_SILENT made messages (after extraction) 2017-08-15 03:32:00 +02:00
l10n daemon script
eba0a16df2 GIT_SILENT made messages (after extraction) 2017-08-09 06:55:09 +02:00
Albert Vaca
a54d9c98f7 Bumped version to release as beta 2017-08-06 18:47:02 +02:00
Albert Vaca
45b09a0461 Bumped version to release 2017-08-06 18:44:50 +02:00
Albert Vaca
8e3232fecc Detect data corruption caused by sshfs 3.x and abort transfer 2017-08-06 18:44:33 +02:00
Albert Vaca
83c8a30a71 Detect data corruption caused by sshfs 3.x and abort transfer 2017-08-06 18:09:55 +02:00
Albert Vaca
1cfddd409d Unused var 2017-08-01 22:24:25 +02:00
Albert Vaca
31e2d0b208 Match desktop buffer size 2017-08-01 22:23:18 +02:00
Albert Vaca
f630ea3e3f Fix progress not being displayed when 0% 2017-08-01 22:22:54 +02:00
Albert Vaca
407ce1ccb0 Make percentage be updated every 1% again, it seems to work. 2017-08-01 22:22:25 +02:00
Albert Vaca
7a097f7b27 Unused var 2017-08-01 22:21:44 +02:00
l10n daemon script
04e9a38a68 GIT_SILENT made messages (after extraction) 2017-07-30 03:16:05 +02:00
Nicolas Fella
bea90521c5 Direct Share
Summary:
Support Android 6 direct share.
BUG:362266
BackgroundService is a SIngleton now. This should only be used if strictly necessary.

Test Plan: Pick a random app with a share button, look for device entries in Sharing options (might not be there because other sharing options have higher priority)

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D6743
2017-07-29 11:33:45 +02:00
l10n daemon script
b68c159275 GIT_SILENT made messages (after extraction) 2017-07-27 03:23:21 +02:00
l10n daemon script
1109f6d728 GIT_SILENT Add new file (after extraction) 2017-07-26 09:27:24 +02:00
l10n daemon script
bbda044d73 GIT_SILENT made messages (after extraction) 2017-07-26 09:27:11 +02:00
l10n daemon script
fb315e3651 GIT_SILENT Add new file (after extraction) 2017-07-26 06:53:02 +02:00
Albert Vaca
2e1c91929e Oops, that was broken 2017-07-25 18:16:10 +02:00
Albert Vaca
df568ccad7 Coding style 2017-07-24 16:39:32 +02:00
l10n daemon script
23ff4bf64c GIT_SILENT made messages (after extraction) 2017-07-24 05:07:37 +02:00
l10n daemon script
4e3e0a1d5e GIT_SILENT made messages (after extraction) 2017-07-24 03:09:21 +02:00
l10n daemon script
d68fec2ab8 GIT_SILENT made messages (after extraction) 2017-07-23 05:04:56 +02:00
l10n daemon script
0c9f395c55 GIT_SILENT made messages (after extraction) 2017-07-23 03:11:21 +02:00
Albert Vaca
49ea4cdfe7 Fix Github links 2017-07-20 15:36:30 +02:00
l10n daemon script
8bd54ba153 GIT_SILENT made messages (after extraction) 2017-07-19 09:08:49 +02:00
l10n daemon script
afbcbb1f44 GIT_SILENT made messages (after extraction) 2017-07-19 06:40:45 +02:00
l10n daemon script
710dcf6c47 GIT_SILENT made messages (after extraction) 2017-07-18 03:12:33 +02:00
Nicolas Fella
2ffeab0c5e Fixed exception while handling notifications
Summary: An exception occurred while processing non-repliable notifications

Test Plan: Send a non-repliable notification, look in log for exception

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: apol, albertvaka, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D6740
2017-07-17 15:26:00 +02:00
l10n daemon script
c62a4bb4c4 GIT_SILENT made messages (after extraction) 2017-07-17 03:17:01 +02:00
l10n daemon script
4d989941b3 GIT_SILENT made messages (after extraction) 2017-07-16 03:11:34 +02:00
l10n daemon script
e53d3eaff8 GIT_SILENT made messages (after extraction) 2017-07-15 04:59:26 +02:00
Albert Vaca
29108894a2 Announce name changes
BUG: 364150
2017-07-14 03:30:32 +02:00
Albert Vaca
4e6dc31247 Noti never changes to finished if we spam too many noti updates
Can reproduce it 100% on my phone, but seems to work fine on others...
2017-07-14 03:20:12 +02:00
Albert Vaca
5d87675586 Disable animation on tap on the list header 2017-07-14 02:47:46 +02:00
Albert Vaca
109d2b4e41 Bump version to release as beta 2017-07-14 01:55:57 +02:00
Albert Vaca
9fb3aaa9e0 Oops 2017-07-14 01:45:28 +02:00
Albert Vaca
69249fe408 Merge branch '1.x' 2017-07-14 01:38:54 +02:00
Albert Vaca
5bef181c8f Merge branch '1.x' of git.kde.org:kdeconnect-android into 1.x 2017-07-14 01:38:45 +02:00
Albert Vaca
065d22ebda Merge branch '1.x'
# Conflicts:
#	src/org/kde/kdeconnect/Plugins/TelepathyPlugin/TelepathyPlugin.java
2017-07-14 01:38:37 +02:00
Albert Vaca
a8842b189c Merge branch 'master' into 1.x
# Conflicts:
#	AndroidManifest.xml
#	res/values-es/strings.xml
#	res/values-fr/strings.xml
#	res/values-ru/strings.xml
#	res/values-sr/strings.xml
#	src/org/kde/kdeconnect/Helpers/NetworkHelper.java
#	src/org/kde/kdeconnect/Plugins/SftpPlugin/SftpPlugin.java
#	src/org/kde/kdeconnect/Plugins/TelepathyPlugin/TelepathyPlugin.java
#	src/org/kde/kdeconnect/Plugins/TelephonyPlugin/TelephonyPlugin.java
2017-07-14 01:12:13 +02:00
l10n daemon script
55bc578374 GIT_SILENT made messages (after extraction) 2017-07-13 03:10:56 +02:00
Nicolas Fella
34c84051c9 Runtime Permissions: optional Permissions
Summary: Added support for optional Permissions. Also provided explanations why the permissions are needed

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D6094
2017-07-11 21:42:19 +02:00
Nicolas Fella
45f3311b70 SharePlugin refactoring
Summary:
Some refactoring in the Shareplugin:

Extracted some parts into separate methods
Extracted notification into separate class
Some optical tweaks on notifications

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D6613
2017-07-11 10:49:52 +02:00
Albert Vaca
7ffd7c2682 Bumped minor version of Android tools 2017-07-09 18:42:34 +02:00
Albert Vaca
8a7f7231b5 Do not swallow the exception, wrap it and let it crash.
Returning null did make it crash on NPE anyway, and we lost info.
2017-07-09 18:30:20 +02:00
l10n daemon script
17740c63ee GIT_SILENT made messages (after extraction) 2017-06-30 03:03:42 +02:00
l10n daemon script
1798fd71d1 GIT_SILENT made messages (after extraction) 2017-06-28 06:12:19 +02:00
l10n daemon script
6e08f2bddd GIT_SILENT made messages (after extraction) 2017-06-26 03:00:08 +02:00
l10n daemon script
3127cba4ee GIT_SILENT made messages (after extraction) 2017-06-21 06:47:38 +02:00
Albert Vaca
0ae3d487e3 Bumped version for release 2017-06-21 03:27:03 +02:00
Albert Vaca
37aab9a520 Ignore all exceptions from ContentResolver.query 2017-06-21 03:27:03 +02:00
Albert Vaca
c18dc3b724 Fix crash when trying to stop stfp while it was mounted 2017-06-21 03:23:29 +02:00
l10n daemon script
569ae488a0 GIT_SILENT Add new file (after extraction) 2017-06-20 03:02:09 +02:00
l10n daemon script
70a94a7e1d GIT_SILENT made messages (after extraction) 2017-06-13 05:10:21 +02:00
l10n daemon script
510000541c GIT_SILENT made messages (after extraction) 2017-06-11 03:04:13 +02:00
l10n daemon script
18a8f06ce4 GIT_SILENT made messages (after extraction) 2017-06-10 02:57:53 +02:00
Nicolas Fella
5886422d72 Fixed a bug in MousepadPlugin
Summary: Some values in the mousepad plugin had no default values because some strings were translated but shouldn't.

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D6097
2017-06-08 13:25:06 +02:00
l10n daemon script
09570ec34c GIT_SILENT made messages (after extraction) 2017-06-08 03:00:19 +02:00
l10n daemon script
b57c22468c GIT_SILENT made messages (after extraction) 2017-06-05 04:40:58 +02:00
l10n daemon script
1d7594d83b GIT_SILENT made messages (after extraction) 2017-06-05 02:53:14 +02:00
l10n daemon script
f223fe0812 GIT_SILENT made messages (after extraction) 2017-06-04 02:56:42 +02:00
l10n daemon script
d0482f1e81 GIT_SILENT made messages (after extraction) 2017-06-02 02:59:51 +02:00
Nicolas Fella
0b83cfe06d Implement Android 6 Runtime Permissions
Differential Revision: https://phabricator.kde.org/D5876
2017-05-31 15:53:31 +02:00
Albert Vaca
e13090066c Update the notification less often
Otherwise, for some reason it stops allowing further updates afterwards
and looks like the download never completed (even though it did).
2017-05-31 15:39:31 +02:00
Albert Vaca
07ec3f2132 Mark the notification as not ongoing when it's done 2017-05-31 15:39:31 +02:00
Albert Vaca
f8bb5d4dd4 Reuse the same builder 2017-05-31 15:39:31 +02:00
Julian Wolff
6d216b2766 reply to notifications
Summary: These changes allow replying to any notifications that offer quick reply text fields (like WhatsApp). Does work for WhatsApp. Does not work for Telegram.

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka

Maniphest Tasks: T4674

Differential Revision: https://phabricator.kde.org/D5991
2017-05-31 15:38:14 +02:00
Albert Vaca
05d728b846 Don't lose the stacktrace. 2017-05-31 00:05:26 +02:00
l10n daemon script
5c3607dde5 GIT_SILENT made messages (after extraction) 2017-05-30 04:50:50 +02:00
l10n daemon script
d0f3c8eb22 GIT_SILENT made messages (after extraction) 2017-05-30 02:56:10 +02:00
l10n daemon script
b9a366df09 GIT_SILENT Add new file (after extraction) 2017-05-27 04:52:01 +02:00
l10n daemon script
f392505d21 GIT_SILENT Add new file (after extraction) 2017-05-27 03:02:08 +02:00
Saikrishna Arcot
981685e926 Avoid NPE when pluginList is still getting updated, by starting the receiving thread after the pluginList is updated.
Also have the pluginList be initialized to an empty map.

REVIEW: 130140
2017-05-25 22:19:08 +02:00
l10n daemon script
63f8f86cd5 GIT_SILENT made messages (after extraction) 2017-05-25 02:58:42 +02:00
Àlex Fiestas
20455f74ab Add Bluetooth support
This is a ported version of the patch submited in review:
https://git.reviewboard.kde.org/r/128270

It is disabled by default.

REVIEW: 128270
2017-05-25 00:08:29 +02:00
Albert Vaca
cea712ced9 Bumped version for release 2017-05-24 00:29:41 +02:00
Albert Vaca
124a971a1f Never crash if there is a problem in isOnMobileNetwork 2017-05-24 00:29:33 +02:00
Albert Vaca
82b42fda67 Fix NPE 2017-05-24 00:23:57 +02:00
Albert Vaca
7c02f79c22 Attempt to fix NPE 2017-05-24 00:21:45 +02:00
Albert Vaca
23d54eaedf Fix crash on Android 5.1 when calling registerReceiver(null)
Plus small optimization by re-using the NetworkPackage.
2017-05-24 00:11:43 +02:00
Albert Vaca
7ad141bb6d Revert "Fixing sent SMS not appearing in the SMS app on old phones"
Doesn't seem to actually work.

This reverts commit 40c9b67033.
2017-05-23 23:00:31 +02:00
Albert Vaca
e68925c852 Bumped version to release in Beta 2017-05-17 23:14:21 +02:00
Albert Vaca
62cab267b4 Bumped gradle version 2017-05-17 23:13:43 +02:00
Albert Vaca
40c9b67033 Fixing sent SMS not appearing in the SMS app on old phones
BUG: 368069
2017-05-17 23:13:33 +02:00
Albert Vaca
23648a03e5 Bumped version to release 2017-05-16 21:05:17 +02:00
Simon Redman
3f188b5526 Add support for sending and receiving multipart SMSes
Summary:
The SMS protocol does not support sending a message longer than 160 characters. Android's SmsManager.sendTextMessage(..) fails to send in case the message is too long.
Instead of failing, check the message length. If it is longer than 160 characters, break it up and send it as several messages

On receive, collect the list of messages, then combine their bodies

Test Plan:
Send a long message via KDE Connect and verify that it is actually sent
Send a short message via KDE Connect and verify that it can also be sent
Ideally: Test sending a message which is the maximum length for an SMS (160 characters) and verify that it is sent as exactly one SMS (And billed properly)

Receive a long message and verify that it is delivered as a single long message, even though we all know that it was transmitted as a multi-part SMS
Receive a short message and verify that it is correctly delivered

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka

Differential Revision: https://phabricator.kde.org/D5848
2017-05-16 21:03:59 +02:00
Albert Vaca
2d35b04713 Fix IllegalStateException: Fragment not attached to Activity
BUG: 379873
2017-05-16 21:01:45 +02:00
Albert Vaca
9a5b03c423 Fixing crash, apparently info can be null (?) 2017-05-16 21:01:45 +02:00
l10n daemon script
ee336aa414 GIT_SILENT made messages (after extraction) 2017-05-15 05:02:35 +02:00
l10n daemon script
5d7b0a976a GIT_SILENT made messages (after extraction) 2017-05-15 03:14:09 +02:00
Albert Vaca
a81eba9ea1 Bumped version number to release 2017-05-06 14:29:24 +02:00
Nicholas Killewald
c5022358de Made getLocalIpAddress ignore rmnet-related interfaces.
Any interface with "rmnet" in it is an internal interface that has to do
with the device's cellular connection or USB tethering.  Since those
interfaces might give IPv4 addresses that are unreachable from any other
device, this change makes getLocalIpAddress ignore anything rmnet-related.

BUG: 337685
2017-05-06 14:26:55 +02:00
Albert Vaca
9d1734406b Bumped version number to release 2017-05-06 12:54:06 +02:00
Albert Vaca
2d49715891 Removed print 2017-05-06 12:47:51 +02:00
Albert Vaca
9e6a4938ed Added an extra check to be really sure we are on data. 2017-05-06 12:47:46 +02:00
Albert Vaca
cc4a196334 Make android version check lint happy 2017-05-06 12:46:52 +02:00
Albert Vaca
c39620e33c Update gradle plugin 2017-05-06 12:38:04 +02:00
Albert Vaca
0dd26e5729 Removed an if to check for access to "/" as it never helped 2017-05-06 12:19:36 +02:00
Nicolas Fella
2cdf743bba Added Notification icons
Some additional fields are transferred in a network package. This includes
the payloads MD5 checksum (which determines where the image file is stored)
and the notifications title and text (which allows more flexibility in the
desktop app, ticker is still transferred for compatibility)

REVIEW: 130033
2017-04-13 21:27:39 +02:00
Albert Vaca
dbf069cf85 Further refining the network detection 2017-03-18 02:16:00 +01:00
Zixing Liu
bf230509b8 Add swipe to refresh to device pairing activity
This makes it more conform to material design standard

REVIEW: 129980
2017-03-18 02:16:00 +01:00
Albert Vaca
09cbd444e6 Update gradle plugin 2017-03-18 02:15:00 +01:00
l10n daemon script
2ace4aaef1 GIT_SILENT made messages (after extraction) 2017-03-15 03:29:06 +01:00
l10n daemon script
86d0d3065c GIT_SILENT made messages (after extraction) 2017-03-14 19:05:45 +01:00
l10n daemon script
1f8f39a7f8 GIT_SILENT made messages (after extraction) 2017-03-09 06:56:51 +01:00
l10n daemon script
64b124aefd GIT_SILENT made messages (after extraction) 2017-03-09 03:53:11 +01:00
l10n daemon script
05ba2188de GIT_SILENT made messages (after extraction) 2017-03-05 08:01:12 +01:00
l10n daemon script
d64452bbb6 GIT_SILENT made messages (after extraction) 2017-03-05 04:52:02 +01:00
l10n daemon script
ba440bd5ea GIT_SILENT made messages (after extraction) 2017-03-04 07:13:18 +01:00
l10n daemon script
a94e082b68 GIT_SILENT made messages (after extraction) 2017-03-01 06:45:54 +01:00
l10n daemon script
e8a61e144a GIT_SILENT made messages (after extraction) 2017-03-01 03:45:22 +01:00
Albert Vaca
def0cad889 Further refining the network detection 2017-02-28 21:21:51 +01:00
Albert Vaca
c93e4400e2 Fix crash when fragment.getContext() was null 2017-02-25 21:42:34 +01:00
Albert Vaca
8935ab5d7f Fix crash when fragment.getContext() was null 2017-02-25 21:42:15 +01:00
Albert Vaca
c5a9e7e357 Merge branch '1.x' 2017-02-25 21:32:52 +01:00
Albert Vaca
9580154a13 Bumped version to release 2017-02-25 21:32:28 +01:00
Albert Vaca
48f5566326 Try a different approach to detect when on mobile data. 2017-02-25 21:25:06 +01:00
Albert Vaca
b24010a86e Try a different approach to detect when on mobile data. 2017-02-25 21:22:20 +01:00
Albert Vaca
e2a932558a Revert "Do not broadcast in 3G + info message"
As it couldn't be any other way, this broke somebody's workflow.

This reverts commit 440a12f86c.
2017-02-25 21:07:04 +01:00
Albert Vaca
732206ac13 Fix crash on Android < 12 2017-02-25 21:07:04 +01:00
Albert Vaca
3ea5d43b99 Revert "Do not broadcast in 3G + info message"
As it couldn't be any other way, this broke somebody's workflow.

This reverts commit 440a12f86c.
2017-02-25 21:06:40 +01:00
l10n daemon script
a172430c11 GIT_SILENT made messages (after extraction) 2017-02-23 07:12:52 +01:00
l10n daemon script
2a732645d2 GIT_SILENT made messages (after extraction) 2017-02-23 03:58:04 +01:00
l10n daemon script
c91d84b635 GIT_SILENT made messages (after extraction) 2017-02-22 03:45:42 +01:00
l10n daemon script
b4b7b58cb2 GIT_SILENT made messages (after extraction) 2017-02-21 13:33:16 +01:00
l10n daemon script
f9ca018e2a GIT_SILENT made messages (after extraction) 2017-02-21 08:45:31 +01:00
Albert Vaca
8d99de59fc Fix crash on Android < 12 2017-02-20 22:59:52 +01:00
Albert Vaca
8e36986ffb Merge branch '1.x' 2017-02-20 20:42:07 +01:00
Albert Vaca
337cdba68f Prepare beta release 2017-02-20 20:36:55 +01:00
l10n daemon script
40b1caaf3a GIT_SILENT made messages (after extraction) 2017-02-20 03:50:57 +01:00
l10n daemon script
c8469b06b5 GIT_SILENT made messages (after extraction) 2017-02-19 03:48:16 +01:00
Albert Vaca
7c0880124b Merge branch '1.x'
# Conflicts:
#	res/values-ast/strings.xml
#	res/values-zh-rCN/strings.xml
2017-02-18 19:15:28 +01:00
l10n daemon script
b73f5ad6a4 GIT_SILENT made messages (after extraction) 2017-02-11 03:47:01 +01:00
l10n daemon script
7e8edda808 GIT_SILENT made messages (after extraction) 2017-02-06 03:54:31 +01:00
Albert Vaca
48ffde66da OPEN_DOCUMENT_TREE needs lollipop 2017-02-05 21:39:49 +01:00
99 changed files with 3941 additions and 1422 deletions

3
.arcconfig Normal file
View File

@@ -0,0 +1,3 @@
{
"phabricator.uri" : "https://phabricator.kde.org/project/profile/159/"
}

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ gradlew
gradlew.bat
*.iml
*.keystore
.directory

View File

@@ -1,11 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kde.kdeconnect_tp"
android:versionCode="1610"
android:versionName="1.6.1">
<uses-sdk android:minSdkVersion="9"
android:targetSdkVersion="22" />
android:versionCode="1720"
android:versionName="1.7.2">
<supports-screens
android:anyDensity="true"
@@ -18,12 +15,15 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<!--<uses-permission android:name="android.permission.BLUETOOTH" />-->
<!--<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:required="false" />
<uses-permission android:name="android.permission.RECEIVE_SMS" android:required="false" />
<uses-permission android:name="android.permission.SEND_SMS" android:required="false" />
<uses-permission android:name="android.permission.READ_SMS" android:required="false" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -32,8 +32,8 @@
<application
android:allowBackup="true"
android:icon="@drawable/icon"
android:supportsRtl="true"
android:label="KDE Connect"
android:supportsRtl="true"
android:theme="@style/KdeConnectTheme"
>
@@ -42,8 +42,6 @@
android:enabled="true" >
</service>
<!--Commented here and in PluginFactory until we release a desktop version with this feature, so we don't get bad "feature not working" reviews-->
<!--
<service android:name="org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin.RemoteKeyboardService"
android:label="KDE Connect Remote Keyboard"
android:permission="android.permission.BIND_INPUT_METHOD">
@@ -52,7 +50,7 @@
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/remotekeyboardplugin_method" />
</service>
-->
<activity
android:name="org.kde.kdeconnect.UserInterface.MaterialActivity"
android:label="KDE Connect"
@@ -139,9 +137,9 @@
<activity
android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneActivity"
android:label="@string/findmyphone_title"
android:configChanges="orientation|screenSize"
android:excludeFromRecents="true"
android:label="@string/findmyphone_title"
android:launchMode="singleInstance">
</activity>
@@ -193,7 +191,19 @@
<data android:mimeType="*/*" />
</intent-filter>
<meta-data
android:name="android.service.chooser.chooser_target_service"
android:value="org.kde.kdeconnect.Plugins.SharePlugin.ShareChooserTargetService" />
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.kde.kdeconnect_tp.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/fileprovider_paths" />
</provider>
<service
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationReceiver"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
@@ -201,6 +211,13 @@
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service
android:name="org.kde.kdeconnect.Plugins.SharePlugin.ShareChooserTargetService"
android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
<intent-filter>
<action android:name="android.service.chooser.ChooserTargetService" />
</intent-filter>
</service>
<activity
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity"

View File

@@ -4,20 +4,24 @@ KDE Connect is a multi-platform app that allows your devices to communicate (eg:
## (Some) Features
- **Shared clipboard**: copy and paste between your phone and your computer (or any other device).
- **Notification sync**: Read your Android notifications from the desktop.
- **Notification sync**: Read and reply to your Android notifications from the desktop.
- **Share files and URLs** instantly from one device to another.
- **Multimedia remote control**: Use your phone as a remote for Linux media players.
- **Virtual touchpad**: Use your phone screen as your computer's touchpad.
- **Virtual touchpad**: Use your phone screen as your computer's touchpad and keyboard.
All this without wires, over the already existing WiFi network, and using a secure, encrypted protocol.
All this without wires, over the already existing WiFi network, and using TLS encryption.
## About this app
This is a native Android port of the KDE Connect Qt app. You will find a more complete readme about KDE Connect [here](https://github.com/albertvaka/kdeconnect-kde).
This is a native Android port of the KDE Connect Qt app. You will find a more complete readme about KDE Connect [here](https://github.com/KDE/kdeconnect-kde).
## How to install this app
You can install this app from the [Play Store](https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp) as well as [F-Droid](https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp). Note you will also need to install the [desktop app](https://github.com/albertvaka/kdeconnect-kde) for it to work.
You can install this app from the [Play Store](https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp) as well as [F-Droid](https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp). Note you will also need to install the [desktop app](https://github.com/KDE/kdeconnect-kde) for it to work.
## Contributing
To contribute patches, use [KDE Connect's Phabricator](https://phabricator.kde.org/project/profile/159/). There you can also 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).
## License
[GNU GPL v2](https://www.gnu.org/licenses/gpl-2.0.html) and [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html)

View File

@@ -1,20 +1,24 @@
buildscript {
repositories {
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
apply plugin: 'com.android.application'
android {
buildToolsVersion '25.0.2'
buildToolsVersion '26.0.2'
compileSdkVersion 25
defaultConfig {
minSdkVersion 9
targetSdkVersion 22 //Bumping to >22 means we have to support the new permissions model
targetSdkVersion 25
//multiDexEnabled true
//testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
}
@@ -57,7 +61,7 @@ android {
minifyEnabled false
useProguard false
}
release { //keep on 'releae', set to 'all' when testing to make sure proguard is not deleting important stuff
release { //keep on 'release', set to 'all' when testing to make sure proguard is not deleting important stuff
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
@@ -68,20 +72,25 @@ android {
dependencies {
repositories {
mavenCentral()
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
compile 'com.android.support:support-v4:25.1.1'
compile 'com.android.support:appcompat-v7:25.1.1'
compile 'com.android.support:design:25.1.1'
implementation 'com.android.support:support-v4:25.4.0'
implementation 'com.android.support:appcompat-v7:25.4.0'
implementation 'com.android.support:design:25.4.0'
compile 'org.apache.sshd:sshd-core:0.8.0' //0.9 seems to fail on Android 6 and 1.+ requires java.nio.file, which doesn't exist in Android
implementation 'org.apache.sshd:sshd-core:0.8.0' //0.9 seems to fail on Android 6 and 1.+ requires java.nio.file, which doesn't exist in Android
compile 'com.madgag.spongycastle:pkix:1.54.0.0' //For SSL certificate generation
implementation 'com.madgag.spongycastle:pkix:1.54.0.0' //For SSL certificate generation
// Testing
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'// Because mockito has some problems with dex environment
androidTestCompile 'org.skyscreamer:jsonassert:1.3.0'
androidTestImplementation 'org.mockito:mockito-core:1.10.19'
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.1'// Because mockito has some problems with dex environment
androidTestImplementation 'org.skyscreamer:jsonassert:1.3.0'
testImplementation 'junit:junit:4.12'
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
</vector>

View File

@@ -3,7 +3,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_vertical_margin"
tools:context=".DeviceFragment"
tools:context="org.kde.kdeconnect.UserInterface.DeviceFragment"
android:orientation="vertical">
<LinearLayout

View File

@@ -4,7 +4,7 @@
android:layout_height="match_parent"
android:paddingLeft="16dip"
android:paddingRight="16dip"
tools:context=".MainActivity"
tools:context="org.kde.kdeconnect.UserInterface.MaterialActivity"
android:id="@+id/listView1"
android:addStatesFromChildren="true"
android:orientation="vertical">

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/refresh_list_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dip"
android:paddingRight="16dip"
tools:context=".MainActivity"
android:id="@+id/listView1"
android:addStatesFromChildren="true"
android:orientation="vertical"/>
</android.support.v4.widget.SwipeRefreshLayout>

View File

@@ -41,12 +41,11 @@
android:layout_gravity="center"
/>
<org.kde.kdeconnect.UserInterface.MaxWidthImageButton
<ImageButton
android:layout_width="fill_parent"
android:layout_height="75dip"
app:maxWidth="300dip"
android:layout_height="75dp"
android:id="@+id/play_button"
android:src="@android:drawable/ic_media_play"
android:src="@drawable/ic_play_black"
android:contentDescription="@string/mpris_play"
android:layout_gravity="center"
android:layout_weight="0"
@@ -65,7 +64,7 @@
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/prev_button"
android:src="@android:drawable/ic_media_previous"
android:src="@drawable/ic_previous_black"
android:contentDescription="@string/mpris_previous"
android:layout_weight="0.25"
/>
@@ -74,7 +73,7 @@
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/rew_button"
android:src="@android:drawable/ic_media_rew"
android:src="@drawable/ic_rewind_black"
android:contentDescription="@string/mpris_rew"
android:layout_weight="0.25"
/>
@@ -83,7 +82,7 @@
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/ff_button"
android:src="@android:drawable/ic_media_ff"
android:src="@drawable/ic_fast_forward_black"
android:contentDescription="@string/mpris_ff"
android:layout_weight="0.25"
/>
@@ -92,7 +91,7 @@
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/next_button"
android:src="@android:drawable/ic_media_next"
android:src="@drawable/ic_next_black"
android:contentDescription="@string/mpris_next"
android:layout_weight="0.25"
/>
@@ -152,7 +151,7 @@
android:id="@+id/imageView"
android:layout_weight="0"
android:contentDescription="@string/mpris_volume"
android:src="@drawable/ic_volume"
android:src="@drawable/ic_volume_black"
/>

View File

@@ -29,7 +29,7 @@
android:background="?attr/selectableItemBackground">
<!-- Preference will place its actual preference widget here. -->
<LinearLayout android:id="@+android:id/widget_frame"
<LinearLayout android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
@@ -54,7 +54,7 @@
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
<TextView android:id="@+android:id/summary"
<TextView android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"

View File

@@ -9,14 +9,6 @@
android:title="@string/refresh"
/>
<item
android:id="@+id/menu_progress"
android:orderInCategory="200"
android:visible="false"
kdeconnect:showAsAction="ifRoom"
kdeconnect:actionViewClass="android.widget.ProgressBar"
/>
<item
android:id="@+id/menu_rename"
android:orderInCategory="300"

View File

@@ -5,16 +5,8 @@
android:id="@+id/menu_refresh"
android:icon="@drawable/ic_action_refresh"
android:orderInCategory="200"
kdeconnect:showAsAction="ifRoom"
kdeconnect:showAsAction="never"
android:title="@string/refresh"
/>
<item
android:id="@+id/menu_progress"
android:orderInCategory="200"
android:visible="false"
kdeconnect:showAsAction="ifRoom"
kdeconnect:actionViewClass="android.widget.ProgressBar"
/>
</menu>

View File

@@ -5,13 +5,23 @@
<string name="pref_plugin_battery">تقرير البطّاريّة</string>
<string name="pref_plugin_battery_desc">بلّغ عن حالة البطّاريّة دوريًّا</string>
<string name="pref_plugin_sftp">اكشف نظام الملفّات</string>
<string name="pref_plugin_sftp_desc">تسمح بتصفّح نظام ملفّات هذا الهاتف عن بعد</string>
<string name="pref_plugin_clipboard">مزامنة الحافظة</string>
<string name="pref_plugin_clipboard_desc">شارك محتوى الحافظة</string>
<string name="pref_plugin_mousepad">الدَّخل البعيد</string>
<string name="pref_plugin_mousepad">الدّخل البعيد</string>
<string name="pref_plugin_mousepad_desc">استخدم الهاتف أو اللوحيّ كفأرة ولوحة مفاتيح</string>
<string name="pref_plugin_mpris">تحكّمات الوسائط المتعدّدة</string>
<string name="pref_plugin_mpris_desc">توفّر تحكّمًا بعيدًا لمشغّل الوسائط</string>
<string name="pref_plugin_runcommand">شغّل أمرًا</string>
<string name="pref_plugin_runcommand_desc">تحفّز أوامر عن بعد من الهاتف أو اللوحيّ</string>
<string name="pref_plugin_ping">وخزة</string>
<string name="pref_plugin_ping_desc">أرسل واستقبل وخزات</string>
<string name="pref_plugin_notifications">مزامنة الإخطارات</string>
<string name="pref_plugin_notifications_desc">انفذ إلى إخطاراتك من أجهزة أخرى</string>
<string name="pref_plugin_receive_notifications">استقبل الإخطارات</string>
<string name="pref_plugin_receive_notifications_desc">استقبل الإخطارات من الجهاز الآخر واعرضها على أندرويد</string>
<string name="pref_plugin_sharereceiver">شارك واستقبل</string>
<string name="pref_plugin_sharereceiver_desc">شارك الملفّات والعناوين بين الجهازين</string>
<string name="plugin_not_available">هذه الميزة غير متوفّرة في إصدار أندرويد لديك</string>
<string name="device_list_empty">لا أجهزة</string>
<string name="ok">حسنًا</string>
@@ -19,24 +29,32 @@
<string name="open_settings">افتح الإعدادات</string>
<string name="no_permissions">عليك إعطاء التّطبيق صلاحيّات للنّفاذ إلى الإخطارات</string>
<string name="send_ping">أرسل وخزة</string>
<string name="open_mpris_controls">تحكّمات الوسائط المتعدّدة</string>
<string name="open_mousepad">الدّخل البعيد</string>
<string name="mousepad_double_tap_settings_title">اضبط إجراء اللمس بإصبعين</string>
<string name="mousepad_triple_tap_settings_title">اضبط إجراء اللمس بثلاث أصابع</string>
<string name="mousepad_sensitivity_settings_title">اضبط حساسيّة لوحة اللمس</string>
<string name="mousepad_scroll_direction_title">اعكس اتّجاه التّمرير</string>
<string-array name="mousepad_tap_entries">
<item/>
<item/>
<item>Nothing</item>
<item>النّقر باليمين</item>
<item>النّقر بالوسط</item>
<item>لا شيء</item>
</string-array>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
<item>الأبطأ</item>
<item>الأقل بطئًا</item>
<item>الافتراضيّ</item>
<item>الأسرع قليلًا</item>
<item>الأسرع</item>
</string-array>
<string name="category_connected_devices">الأجهزة المقترن بها</string>
<string name="category_not_paired_devices">الأجهزة المتوفّرة</string>
<string name="category_remembered_devices">الأجهزة المتذكَّرة</string>
<string name="plugins_failed_to_load">فشل تحميل الملحقات (المس لمعلومات اكثر):</string>
<string name="device_menu_unpair">أزل الاقتران</string>
<string name="device_menu_plugins">إعدادات الملحقة</string>
<string name="device_menu_unpair">ألغِ الاقتران</string>
<string name="device_not_reachable">الجهاز المقترن غير قابل الوصول</string>
<string name="pair_new_device">اقرن جهازًا جديدًا</string>
<string name="unknown_device">جهاز مجهول</string>
<string name="error_not_reachable">الجهاز غير قابل الوصول</string>
<string name="error_already_requested">طُلب الاقتران بالفعل</string>
@@ -46,14 +64,24 @@
<string name="error_canceled_by_user">ألغاه المستخدم</string>
<string name="error_canceled_by_other_peer">ألغاه ندّ آخر</string>
<string name="error_invalid_key">استُقبل مفتاح غير صالح</string>
<string name="encryption_info_title">معلومات التّعمية</string>
<string name="encryption_info_msg_no_ssl">لا يستخدم الجهاز الآخر إصدارة حديثة من «كدي المتّصل»، ستُستخدم طريقة التّعمية القديمة.</string>
<string name="my_device_fingerprint">بصمة SHA1 لشهادة جهازك هي:</string>
<string name="remote_device_fingerprint">بصمة SHA1 لشهادة الجهاز البعيد هي:</string>
<string name="pair_requested">طُلب الاقتران</string>
<string name="pairing_request_from">طلب اقتران من %1s</string>
<string name="received_url_title">استُلمت وصلة من %1s</string>
<string name="received_url_text">المس لفتح \'%1s\'</string>
<string name="incoming_file_title">ملفّ وارد من %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="received_file_title">استُلم ملفّ من %1s</string>
<string name="outgoing_file_title">يرسل ملفًّا إلى %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="received_file_title">استُقبل ملفّ من %1s</string>
<string name="received_file_fail_title">فشل استقبال الملفّ من %1s</string>
<string name="received_file_text">المس لفتح \'%1s\'</string>
<string name="sent_file_title">أرسل ملفًّا إلى %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">المس للإجابة</string>
<string name="reconnect">أعد الاتّصال</string>
<string name="right_click">أرسل نقرة باليمين</string>
@@ -74,6 +102,8 @@
<string name="mpris_next">التّالي</string>
<string name="mpris_volume">المستوى</string>
<string name="mpris_settings">إعدادات الوسائط المتعدّدة</string>
<string name="mpris_time_settings_title">زرّا التّقدّم والإرجاع</string>
<string name="mpris_time_settings_summary">اضبط الوقت عند نقر زرّيّ التّقديم أو الإرجاع.</string>
<string-array name="mpris_time_entries">
<item>10 ثوان</item>
<item>20 ثانية</item>
@@ -92,9 +122,13 @@
<string name="invalid_device_name">اسم جهاز غير صالح</string>
<string name="shareplugin_text_saved">استُقبل نصّ، حُفظ إلى الحافظة</string>
<string name="custom_devices_settings">قائمة أجهزة مخصّصة</string>
<string name="pair_device_action">اقرن جهازًا جديدًا</string>
<string name="unpair_device_action">ألغِ اقتران %s</string>
<string name="custom_device_list">أضف أجهزة بميفاق الإنترنت م​إ</string>
<string name="share_notification_preference">إخطارات مزعجة</string>
<string name="share_notification_preference_summary">اهتزّ وشغّل صوتًا عند استقبال ملفّ</string>
<string name="title_activity_notification_filter">مرشّح الإخطارات</string>
<string name="filter_apps_info">ستُزامن الإخطارات من التّطبيقات المحدّدة.</string>
<string name="sftp_internal_storage">التّخزين الدّاخليّ</string>
<string name="sftp_all_files">كلّ الملفّات</string>
<string name="sftp_sdcard_num">بطاقة SD %d</string>
@@ -102,7 +136,26 @@
<string name="sftp_readonly">(للقراءة فقط)</string>
<string name="sftp_camera">صور الكاميرا</string>
<string name="add_host">أضف مضيفًا/م​إ</string>
<string name="add_host_hint">اسم المضيف أو عنوان IP</string>
<string name="no_players_connected">لم يُعثر على مشغّلات</string>
<string name="custom_dev_list_help">استخدم هذا الخيار فقط إن لم يُكتَشف جهازك آليًّا. أدخِل عنوان م​إ أو اسم المضيف أدناه والمس الزرّ لإضافته إلى القائمة. المس عنصرًا موجودًا لإزالته من القائمة.</string>
<string name="mpris_player_on_device">%1$s على %2$s</string>
<string name="send_files">أرسل ملفّات</string>
<string name="pairing_title">أجهزة «كدي المتّصل»</string>
<string name="pairing_description">الأجهزة الأخرى التي تشغّل «كدي المتّصل» وعلى نفس الشّبكة ستظهر هنا.</string>
<string name="device_paired">اقتُرن الجهاز</string>
<string name="device_rename_title">أعد تسمية الجهاز</string>
<string name="device_rename_confirm">أعد التّسمية</string>
<string name="refresh">أنعش</string>
<string name="unreachable_description">الجهاز المقترن هذا لا يمكن الوصول إليه. تأكّد من اتّصاله بنفس الشّبكة.</string>
<string name="no_file_browser">لا متصفّحات ملفّات مثبّتة.</string>
<string name="pref_plugin_telepathy">أرسل SMS</string>
<string name="pref_plugin_telepathy_desc">أرسل رسائل نصّيّة من سطح المكتب</string>
<string name="plugin_not_supported">لا يدعم جهازك هذه الملحقة</string>
<string name="findmyphone_title">جِد جهازي</string>
<string name="findmyphone_title_tablet">جِد جهازي اللوحيّ</string>
<string name="findmyphone_description">يرّن هذا الجهاز لتجده</string>
<string name="findmyphone_found">وُجد</string>
<string name="open">افتح</string>
<string name="close">أغلق</string>
</resources>

View File

@@ -1,33 +1,39 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Notificador telefónicu</string>
<string name="pref_plugin_telephony">Avisador telefónicu</string>
<string name="pref_plugin_telephony_desc">Unvia avisos pa SMS y llamaes</string>
<string name="pref_plugin_battery">Informe de batería</string>
<string name="pref_plugin_battery_desc">Infoma davezu del estáu de la batería</string>
<string name="pref_plugin_battery_desc">Informe periódicu del estáu de la batería</string>
<string name="pref_plugin_sftp_desc">Permite restolar remotamente a esti preséu</string>
<string name="pref_plugin_clipboard">Sincronización del cartafueyu</string>
<string name="pref_plugin_clipboard_desc">Comparte\'l conteníu del cartafueyu</string>
<string name="pref_plugin_mousepad">Entrada remota</string>
<string name="pref_plugin_mpris">Controles remotos multimedia</string>
<string name="pref_plugin_mousepad_desc">Usa\'l to teléfonu o tableta como panel táutil y tecláu</string>
<string name="pref_plugin_remotekeyboard">Pulsaciones remotes</string>
<string name="pref_plugin_mpris">Controles multimedia</string>
<string name="pref_plugin_mpris_desc">Forne un control remotu pal to reproductor multimedia</string>
<string name="pref_plugin_runcommand">Execución de comandos</string>
<string name="pref_plugin_runcommand_desc">Aiciona comandos remotos del to teléfonu o tableta</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Unvia y recibi pings</string>
<string name="pref_plugin_ping_desc">Unvia y recibe pings</string>
<string name="pref_plugin_notifications">Sincronización d\'avisos</string>
<string name="pref_plugin_notifications_desc">Accede a los tos avisos dende otros preseos</string>
<string name="pref_plugin_sharereceiver">Unvia y recibi pings</string>
<string name="pref_plugin_notifications_desc">Accede a los tos avisos d\'otros preseos</string>
<string name="pref_plugin_receive_notifications">Recibir avisos</string>
<string name="pref_plugin_receive_notifications_desc">Recibe avisos d\'otros preseos y amuésalos n\'Android</string>
<string name="pref_plugin_sharereceiver">Compartir y recibir</string>
<string name="pref_plugin_sharereceiver_desc">Comparte ficheros y URLs ente preseos</string>
<string name="plugin_not_available">Esta carauterística nun ta disponible na to versión d\'Android</string>
<string name="device_list_empty">Ensin preseos</string>
<string name="ok">Aceutar</string>
<string name="cancel">Encaboxar</string>
<string name="open_settings">Abrir axustes</string>
<string name="no_permissions">Necesites garantizar l\'accesu a los avisos</string>
<string name="no_permissions">¡</string>
<string name="send_ping">Unviar ping</string>
<string name="open_mpris_controls">Controles multimedia</string>
<string name="open_mousepad">Entrada remota</string>
<string name="mousepad_info">Muevi un deu enriba la pantalla pa mover el mur. calca pa un clic y usa dos/tres deos pa los motones de drecha y mediu. Usa un primíu llargu pa arrastrar y soltar.</string>
<string name="open_mpris_controls">Control multimedia</string>
<string-array name="mousepad_tap_entries">
<item>Clic drechu</item>
<item>Clic d\'en mediu</item>
<item>Nada</item>
<item>Right click</item>
<item>Middle click</item>
<item>Nothing</item>
</string-array>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
@@ -36,101 +42,16 @@
<item>Above Default</item>
<item>Fastest</item>
</string-array>
<string name="category_connected_devices">Preseos coneutaos</string>
<string name="category_not_paired_devices">Preseos disponibles</string>
<string name="category_remembered_devices">Preseos recordaos</string>
<string name="device_not_reachable">El preséu empareyáu nun ye agamable</string>
<string name="unknown_device">Preséu desconocíu</string>
<string name="error_not_reachable">Nun ye algamable\'l preséu</string>
<string name="error_already_requested">Empareyamientu yá solicitáu</string>
<string name="error_already_paired">El preséu yá ta empareyáu</string>
<string name="error_could_not_send_package">Nun pudo unviase\'l paquete</string>
<string name="error_timed_out">Tiempu escosao</string>
<string name="error_canceled_by_user">Encaboxáu pol usuariu</string>
<string name="error_canceled_by_other_peer">Encaboxáu pola otra parte</string>
<string name="error_invalid_key">Recibióse una clave non válida</string>
<string name="pair_requested">Solicitóse l\'empareyamientu</string>
<string name="pairing_request_from">Solicitú d\'empareyamientu de %1s</string>
<string name="received_url_title">Recibióse l\'enllaz de %1s</string>
<string name="received_url_text">Calca p\'abrir «%1s»</string>
<string name="incoming_file_title">Ficheru entrante de %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Unviando ficheru a %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="received_file_title">Recibióse\'l ficheru de %1s</string>
<string name="received_file_fail_title">Fallu al recibir el ficheru de %1s</string>
<string name="received_file_text">Tap to open \'%1s\'</string>
<string name="sent_file_title">Unvióse\'l ficheru a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Calca pa responder</string>
<string name="reconnect">Reconeutar</string>
<string name="show_keyboard">Amosar tecláu</string>
<string name="device_not_paired">Preséu non empareyáu</string>
<string name="request_pairing">Solicitar empareyamientu</string>
<string name="pairing_accept">Aceutar</string>
<string name="pairing_reject">Refugar</string>
<string name="device">Preséu</string>
<string name="pair_device">Empareyar preséu</string>
<string name="remote_control">Control remotu</string>
<string name="settings">Axustes KDE Connect</string>
<string name="mpris_play">Reproducir</string>
<string name="mpris_previous">Anterior</string>
<string name="mpris_rew">Rebobinar</string>
<string name="mpris_ff">Avance rápidu</string>
<string name="mpris_next">Siguiente</string>
<string name="mpris_volume">Volume</string>
<string name="mpris_settings">Axustes multimedia</string>
<string name="mpris_time_settings_title">Botones d\'avanzar/rebobinar</string>
<string name="mpris_time_settings_summary">Axusta\'l tiempu p\'avanzar/rebobinar al primise</string>
<string name="error_timed_out">Escosó\'l tiempu</string>
<string-array name="mpris_time_entries">
<item>10 segundos</item>
<item>20 segundos</item>
<item>30 segundos</item>
<item>1 minutu</item>
<item>2 minutos</item>
<item>10 seconds</item>
<item>20 seconds</item>
<item>30 seconds</item>
<item>1 minute</item>
<item>2 minutes</item>
</string-array>
<string name="protocol_version_older">Esti preséu usa una versión vieya del protocolu</string>
<string name="protocol_version_newer">Esti preséu usa una versión anovada del protocolu</string>
<string name="general_settings">Axustes xenerales</string>
<string name="plugin_settings">Axustes</string>
<string name="plugin_settings_with_name">Axustes de %s</string>
<string name="device_name">Nome de preséu</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">Nome de preséu non válidu</string>
<string name="shareplugin_text_saved">Recibióse\'l testu y guardóse nel cartafueyu</string>
<string name="custom_devices_settings">Llista de preseos personalizada</string>
<string name="pair_device_action">Empareyar con un preséu nuevu</string>
<string name="unpair_device_action">Desempareyar %s</string>
<string name="custom_device_list">Amestar preseos pola IP</string>
<string name="share_notification_preference">Avisos sonoros</string>
<string name="share_notification_preference_summary">Fai vibrar y reproduz un soníu al recibir un ficheru</string>
<string name="title_activity_notification_filter">Peñera d\'avisos</string>
<string name="filter_apps_info">Los avisos sincronizaránse coles aplicaciones esbillaes.</string>
<string name="sftp_internal_storage">Almacenamientu internu</string>
<string name="sftp_all_files">Tolos ficheros</string>
<string name="sftp_sdcard_num">Tarxeta SD %d</string>
<string name="sftp_sdcard">Tarxeta SD</string>
<string name="sftp_readonly">(namai llectura)</string>
<string name="sftp_camera">Semeyes de cámara</string>
<string name="add_host">Amestar agospiu/IP</string>
<string name="add_host_hint">Nome d\'agospiu o IP</string>
<string name="no_players_connected">Nun s\'alcontraron reproductores</string>
<string name="custom_dev_list_help">Usa esta opción namái si\'l to preséu nun se deteuta automáticamente. Introduz la direición o\'l nome d\'agospiu y toca\'l botón p\'amestalu a la llista. Toca un elementu esistente pa desanicialu de la llista.</string>
<string name="mpris_player_on_device">%1$s en %2$s</string>
<string name="send_files">Unviar ficheros</string>
<string name="pairing_title">Preseos KDE Connect</string>
<string name="pairing_description">Deberíen apaecer equí otros preseos executando KDE Connect.</string>
<string name="device_paired">Preséu empareyáu</string>
<string name="device_rename_title">Renomar 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 que ta coneutáu a la to mesma rede.</string>
<string name="no_file_browser">Nun hai restoladores de ficheros instalaos.</string>
<string name="pref_plugin_telepathy">Unviar SMS</string>
<string name="no_file_browser">Nun hai restoladores de ficheros instalaos</string>
<string name="pref_plugin_telepathy_desc">Unvia mensaxes de testu dende\'l to escritoriu</string>
<string name="plugin_not_supported">Esti complementu nun ta sofitáu pol preséu</string>
<string name="findmyphone_found">Alcontrar</string>
<string name="open">Abrir</string>
<string name="close">Zarrar</string>
<string name="plugin_not_supported">Esti complementu nun lu sofita\'l preséu</string>
<string name="findmyphone_description">Fai sonar el teléfonu pa qu\'asina pueas alcontralu</string>
</resources>

View File

@@ -19,7 +19,6 @@
<string name="open_settings">Otvori postavke</string>
<string name="no_permissions">Morate odobriti dopuštenje da pristupite notifikacijama</string>
<string name="send_ping">Pošalji ping</string>
<string name="mousepad_info">Pomjerite prst na ekranu da opmjerite kursor miša. Tapnite za klik i koristite dva ili tri prsta za srednje i desno dugme. Koristite dugi pritisak za prevlačenje.</string>
<string name="mousepad_double_tap_settings_title">Postavite akciju tapa sa dva prsta</string>
<string name="mousepad_triple_tap_settings_title">Postavite akciju tapa sa tri prsta</string>
<string-array name="mousepad_tap_entries">
@@ -27,8 +26,6 @@
<item>Srednji klik</item>
<item>Ništa</item>
</string-array>
<string name="mousepad_double_default">desno</string>
<string name="mousepad_triple_default">Srednje</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>

View File

@@ -10,8 +10,8 @@
<string name="pref_plugin_clipboard_desc">Comparteix el contingut del porta-retalls</string>
<string name="pref_plugin_mousepad">Entrada remota</string>
<string name="pref_plugin_mousepad_desc">Usa el vostre telèfon o tauleta com un ratolí i un teclat</string>
<string name="pref_plugin_remotekeyboard">Rep les pulsacions de tecla remotes</string>
<string name="pref_plugin_remotekeyboard_desc">Rep els esdeveniments de pulsacions de tecla des de dispositius remots</string>
<string name="pref_plugin_remotekeyboard">S\'estan rebent pulsacions de tecla remotes</string>
<string name="pref_plugin_remotekeyboard_desc">S\'estan rebent esdeveniments de pulsacions de tecla des de dispositius remots</string>
<string name="pref_plugin_mpris">Controls multimèdia</string>
<string name="pref_plugin_mpris_desc">Proporciona un comandament a distància pel reproductor multimèdia</string>
<string name="pref_plugin_runcommand">Executa una ordre</string>
@@ -33,11 +33,11 @@
<string name="send_ping">Envia un ping</string>
<string name="open_mpris_controls">Control multimèdia</string>
<string name="remotekeyboard_editing_only_title">Fes servir les tecles remotes només en editar</string>
<string name="remotekeyboard_not_connected">No hi ha cap connexió activa amb el teclat remot, establiu-ne una al «kdeconnect»</string>
<string name="remotekeyboard_not_connected">No hi ha cap connexió activa amb el teclat remot, establiu-ne una al kde-connect</string>
<string name="remotekeyboard_connected">La connexió amb el teclat remot està activa</string>
<string name="remotekeyboard_multiple_connections">Hi ha més d\'una connexió amb un teclat remot, seleccioneu el dispositiu per configurar-lo</string>
<string name="open_mousepad">Entrada remota</string>
<string name="mousepad_info">Moveu un dit per la pantalla per a moure el cursor del ratolí. Toqueu per un clic, i empreu dos/tres dits pels botons dret i mig. Empreu un toc llarg per arrossegar i deixar anar.</string>
<string name="mousepad_info">Moveu un dit per la pantalla per a moure el cursor del ratolí. Toqueu per un clic, i empreu dos/tres dits pels botons dret i mig. Useu 2 dits per desplaçar. Empreu un toc llarg per arrossegar i deixar anar.</string>
<string name="mousepad_double_tap_settings_title">Estableix l\'acció de tocar amb dos dits</string>
<string name="mousepad_triple_tap_settings_title">Estableix l\'acció de tocar amb tres dits</string>
<string name="mousepad_sensitivity_settings_title">Estableix la sensibilitat del ratolí tàctil</string>
@@ -47,9 +47,6 @@
<item>Clic del mig</item>
<item>No fer res</item>
</string-array>
<string name="mousepad_double_default">dret</string>
<string name="mousepad_triple_default">mig</string>
<string name="mousepad_sensitivity_default">Predeterminada</string>
<string-array name="mousepad_sensitivity_entries">
<item>La més lenta</item>
<item>Lenta</item>
@@ -91,7 +88,7 @@
<string name="received_file_title">Fitxer rebut des de %1s</string>
<string name="received_file_fail_title">Ha fallat en rebre el fitxer des de %1s</string>
<string name="received_file_text">Puntegeu per obrir «%1s»</string>
<string name="sent_file_title">Envia el fitxer a %1s</string>
<string name="sent_file_title">Fitxer enviat a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Ha fallat en enviar el fitxer a %1s</string>
<string name="sent_file_failed_text">%1s</string>
@@ -142,7 +139,7 @@
<string name="share_notification_preference_summary">Vibra i reprodueix un so en rebre un fitxer</string>
<string name="share_destination_customize">Personalitza el directori de destinació</string>
<string name="share_destination_customize_summary_disabled">Els fitxers rebuts apareixeran a Baixades</string>
<string name="share_destination_customize_summary_enabled">Els fitxers seran emmagatzemats al directori de a sota</string>
<string name="share_destination_customize_summary_enabled">Els fitxers seran emmagatzemats al directori de sota</string>
<string name="share_destination_folder_preference">Directori de destinació</string>
<string name="title_activity_notification_filter">Filtre per a les notificacions</string>
<string name="filter_apps_info">Les notificacions se sincronitzaran per a les aplicacions seleccionades.</string>
@@ -176,4 +173,14 @@
<string name="findmyphone_found">L\'he trobat</string>
<string name="open">Obre</string>
<string name="close">Tanca</string>
<string name="no_permissions_storage">Us caldrà concedir permís per accedir a l\'emmagatzematge</string>
<string name="plugins_need_permission">Alguns connectors necessiten permisos per a funcionar (puntegeu per a més informació):</string>
<string name="permission_explanation">Aquest connector necessita permisos per a funcionar</string>
<string name="optional_permission_explanation">Us caldrà concedir permisos extres per accedir a totes les característiques</string>
<string name="plugins_need_optional_permission">Alguns connectors tenen característiques desactivades per la falta de permís (puntegeu per a més informació):</string>
<string name="sftp_permission_explanation">Per accedir als fitxers des del PC, l\'aplicació necessita permís per accedir a l\'emmagatzematge del telèfon</string>
<string name="share_optional_permission_explanation">Per a compartir fitxers entre el telèfon i l\'escriptori, haureu de donar accés a l\'emmagatzematge del telèfon</string>
<string name="telepathy_permission_explanation">Per a llegir i escriure SMS des de l\'escriptori, haureu de donar permís als SMS</string>
<string name="telephony_permission_explanation">Per a veure les trucades telefòniques i SMS des de l\'escriptori, haureu de donar permís a les trucades telefòniques i SMS</string>
<string name="telephony_optional_permission_explanation">Per a veure un nom de contacte en comptes d\'un número de telèfon, haureu de donar permís als contactes del telèfon</string>
</resources>

View File

@@ -22,7 +22,7 @@
<string name="pref_plugin_notifications_desc">Zpřístupněte si upozornění z jiných zařízení</string>
<string name="pref_plugin_receive_notifications">Přijímat oznámení</string>
<string name="pref_plugin_receive_notifications_desc">Přijímat oznámení z jiného zařízení a zobrazovat je v Androidu</string>
<string name="pref_plugin_sharereceiver">Sdílet s přijmnout</string>
<string name="pref_plugin_sharereceiver">Sdílet a přijmout</string>
<string name="pref_plugin_sharereceiver_desc">Sdílet soubory a odkazy mezi zařízeními</string>
<string name="plugin_not_available">Tato vlastnost není pro vaši verzi Androidu platná</string>
<string name="device_list_empty">Žádná zařízení</string>
@@ -37,7 +37,6 @@
<string name="remotekeyboard_connected">Vzdálené připojení klávesnice je aktivní</string>
<string name="remotekeyboard_multiple_connections">Je k dispozici více než jedno připojení klávesnice. Vyberte zařízení pro jeho nastavení.</string>
<string name="open_mousepad">Vzdálený vstup</string>
<string name="mousepad_info">Pohybujte prstem po obrazovce pro pohybování kurzorem myši. Ťukněte pro kliknutí a použijte dva/tři prsty jako pravé a prostřední tlačítko. Pro přetažení dlouze podržte.</string>
<string name="mousepad_double_tap_settings_title">Nastavit činnost pro ťuknutí dvěma prsty</string>
<string name="mousepad_triple_tap_settings_title">Nastavit činnost pro ťuknutí třemi prsty</string>
<string name="mousepad_sensitivity_settings_title">Nastavit citlivost touchpadu</string>
@@ -47,9 +46,6 @@
<item>Kliknutí prostředním tlačítkem myši</item>
<item>Nic</item>
</string-array>
<string name="mousepad_double_default">pravé</string>
<string name="mousepad_triple_default">prostřední</string>
<string name="mousepad_sensitivity_default">výchozí</string>
<string-array name="mousepad_sensitivity_entries">
<item>Nejpomalejší</item>
<item>Méně pomalý</item>
@@ -165,6 +161,7 @@
<string name="device_rename_confirm">Přejmenovat</string>
<string name="refresh">Obnovit</string>
<string name="unreachable_description">Toto spárované zařízení je nedosažitelné. Ujistěte se, že běží ve stejné síti.</string>
<string name="on_data_message">Vypadá to, že jste na mobilním internetovém připojení. KDE Connect funguje pouze na lokální síti.</string>
<string name="no_file_browser">Není nainstalován žádný prohlížeč souborů.</string>
<string name="pref_plugin_telepathy">Poslat SMS</string>
<string name="pref_plugin_telepathy_desc">Posílejte zprávy ze své pracovní plochy</string>
@@ -175,4 +172,14 @@
<string name="findmyphone_found">Nalezeno</string>
<string name="open">Otevřít</string>
<string name="close">Zavřít</string>
<string name="no_permissions_storage">Je potřeba povolit přístup k úložišti</string>
<string name="plugins_need_permission">Některé moduly potřebují pro práci povolení (ťukněte pro více informací):</string>
<string name="permission_explanation">Tento modul potřebuje pro práci povolení</string>
<string name="optional_permission_explanation">Pro zpřístupnění všech funkcí potřebujete další oprávnění</string>
<string name="plugins_need_optional_permission">Některé moduly mají vypnuté vlastnosti, kvůli nedostatečným oprávněním (ťukněte pro více informací):</string>
<string name="sftp_permission_explanation">Pro přístup k souborům z vašeho počítače aplikace potřebuje oprávnění k úložišti telefonu</string>
<string name="share_optional_permission_explanation">Pro sdílení souborů mezi telefonem a počítačem potřebujete udělit oprávnění k úložišti telefonu</string>
<string name="telepathy_permission_explanation">Pro čtení a psaní SMS z počítače musíte udělit oprávnění k SMS</string>
<string name="telephony_permission_explanation">Pro zobrazení telefonátů a SMS v počítači musíte udělit oprávnění k telefonování a SMS</string>
<string name="telephony_optional_permission_explanation">Pro zobrazení jména kontaktu u telefonního čísla je potřeba udělit oprávnění ke kontaktům v telefonu</string>
</resources>

View File

@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">Del indholdet af udklipsholderen</string>
<string name="pref_plugin_mousepad">Eksternt input</string>
<string name="pref_plugin_mousepad_desc">Brug din telefon eller tablet som mus og tastatur</string>
<string name="pref_plugin_remotekeyboard">Modtag eksterne tastetryk</string>
<string name="pref_plugin_remotekeyboard_desc">Modtag tastetryk-hændelser fra eksterne enheder</string>
<string name="pref_plugin_mpris">Multimediekontroller</string>
<string name="pref_plugin_mpris_desc">Giver en fjernbetjening til din medieafspiller</string>
<string name="pref_plugin_runcommand">Kør kommando</string>
@@ -30,8 +32,11 @@
<string name="no_permissions">Du skal give tilladelse for at tilgå bekendtgørelser</string>
<string name="send_ping">Send ping</string>
<string name="open_mpris_controls">Multimediekontrol</string>
<string name="remotekeyboard_editing_only_title">Håndtér kun eksterne tastetryk under redigering</string>
<string name="remotekeyboard_not_connected">Der er ingen aktiv ekstern tastaturforbindelse. Opret en i kdeconnect</string>
<string name="remotekeyboard_connected">Ekstern tastaturforbindelse er aktiv</string>
<string name="remotekeyboard_multiple_connections">Der er mere end en ekstern tastaturforbindelse, vælg den enhed der skal konfigureres</string>
<string name="open_mousepad">Eksternt input</string>
<string name="mousepad_info">Bevæg en finger på skærmen for at flytte musemarkøren. Tap for at klikke og brug to/tre-fingre for højre og midterste museknap. Brug et langt tryk til at trække og slippe.</string>
<string name="mousepad_double_tap_settings_title">Angiv handling for tap med to fingre</string>
<string name="mousepad_triple_tap_settings_title">Angiv handling for tap med tre fingre</string>
<string name="mousepad_sensitivity_settings_title">Angiv følsomhed for touchpad</string>
@@ -41,15 +46,12 @@
<item>Midterklik</item>
<item>Intet</item>
</string-array>
<string name="mousepad_double_default">højre</string>
<string name="mousepad_triple_default">midter</string>
<string name="mousepad_sensitivity_default">standard</string>
<string-array name="mousepad_sensitivity_entries">
<item>Mest langsom</item>
<item>Over mest langsom</item>
<item>Standard</item>
<item>Over standard</item>
<item>Hurtigste</item>
<item>Hurtigst</item>
</string-array>
<string name="category_connected_devices">Forbundne enheder</string>
<string name="category_not_paired_devices">Tilgængelig enheder</string>
@@ -79,12 +81,15 @@
<string name="incoming_file_title">Indkommende fil fra %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Sender fil til %1s</string>
<string name="outgoing_files_title">Sender filer til %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Sendte %1$d ud af %2$d filer</string>
<string name="received_file_title">Modtog fil fra %1s</string>
<string name="received_file_fail_title">Kunne ikke modtage fil fra %1s</string>
<string name="received_file_text">Tap for at åbne \"%1s\"</string>
<string name="sent_file_title">Fil sendt til %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Kunne ikke sende filen til %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tap for at svare</string>
<string name="reconnect">Forbind igen</string>
@@ -131,6 +136,10 @@
<string name="custom_device_list">Tilføj enheder via IP</string>
<string name="share_notification_preference">Støjende bekendtgørelser</string>
<string name="share_notification_preference_summary">Vibrér og afspil en lyd når en fil modtages</string>
<string name="share_destination_customize">Tilpas destinationsmappe</string>
<string name="share_destination_customize_summary_disabled">Modtagne filer vil dukke op i Downloads</string>
<string name="share_destination_customize_summary_enabled">Filer vil blive gemt i mappen nedenfor</string>
<string name="share_destination_folder_preference">Destinationsmappe</string>
<string name="title_activity_notification_filter">Bekendtgørelsesfilter</string>
<string name="filter_apps_info">Bekendtgørelser vil blive synkroniseret for de valgte apps.</string>
<string name="sftp_internal_storage">Intern lagring</string>
@@ -152,6 +161,7 @@
<string name="device_rename_confirm">Omdøb</string>
<string name="refresh">Genopfrisk</string>
<string name="unreachable_description">Denne parrede enhed kan ikke nås. Sørg for at den er forbundet til samme netværk som dig.</string>
<string name="on_data_message">Det lader til at du er på en mobil dataforbindelse. KDE Connect virker kun på lokale netværk.</string>
<string name="no_file_browser">Der er ingen filhåndtering installeret.</string>
<string name="pref_plugin_telepathy">Send SMS</string>
<string name="pref_plugin_telepathy_desc">Send SMS-beskeder fra din desktop</string>
@@ -162,4 +172,14 @@
<string name="findmyphone_found">Fundet</string>
<string name="open">Åbn</string>
<string name="close">Luk</string>
<string name="no_permissions_storage">Du skal give tilladelse for at tilgå datalagret</string>
<string name="plugins_need_permission">Nogle plugins kræver tilladelser for at virke (tap for mere info):</string>
<string name="permission_explanation">Dette plugin kræver tilladelser for at virke</string>
<string name="optional_permission_explanation">Du skal give ekstra tilladelser for at aktivere alle funktioner</string>
<string name="plugins_need_optional_permission">Nogle plugins har deaktiverede funktioner pga. manglende tilladelser (tap for mere info):</string>
<string name="sftp_permission_explanation">For at tilgå filerne fra din pc, skal app\'en have tilladelse til at til gå telefonens datalager</string>
<string name="share_optional_permission_explanation">For at dele filer mellem din telefon og din desktop skal du give adgang til telefonens datalager.</string>
<string name="telepathy_permission_explanation">For at læse og skrive sms\'er fra din desktop, skal du give tilladelse til sms</string>
<string name="telephony_permission_explanation">For at se telefonopkald og sms\'er fra desktoppen, skal du give tilladelse til telefonopkald og sms.</string>
<string name="telephony_optional_permission_explanation">For at se et kontaktnavn i stedet for et telefonnummer, skal du give adgang til telefonens kontakter</string>
</resources>

View File

@@ -9,15 +9,17 @@
<string name="pref_plugin_clipboard">Abgleich der Zwischenablage</string>
<string name="pref_plugin_clipboard_desc">Inhalt der Zwischenablage freigeben</string>
<string name="pref_plugin_mousepad">Ferneingabe</string>
<string name="pref_plugin_mousepad_desc">Verwendet Ihr Handy als Tablett, Touchpad und Tastatur</string>
<string name="pref_plugin_mousepad_desc">Verwendet Ihr Handy als Tablet, Touchpad und Tastatur</string>
<string name="pref_plugin_mpris">Multimedia-Bedienung</string>
<string name="pref_plugin_mpris_desc">Eine Fernbedienung für Ihre Medienwiedergabe</string>
<string name="pref_plugin_runcommand">Befehl ausführen</string>
<string name="pref_plugin_runcommand_desc">Von Ihrem Telefon oder Tablett Befehle auf anderen Geräten ausführen</string>
<string name="pref_plugin_runcommand_desc">Von Ihrem Telefon oder Tablet Befehle auf anderen Geräten ausführen</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Senden und Empfangen von Pings</string>
<string name="pref_plugin_notifications">Benachrichtigungs-Abgleich</string>
<string name="pref_plugin_notifications_desc">Zugriff auf Ihre Benachrichtigungen von anderen Geräten</string>
<string name="pref_plugin_receive_notifications">Benachrichtigungen empfangen</string>
<string name="pref_plugin_receive_notifications_desc">Empfangen und Anzeigen von Benachrichtigungen des anderen Geräts</string>
<string name="pref_plugin_sharereceiver">Veröffentlichen und Empfangen</string>
<string name="pref_plugin_sharereceiver_desc">Dateien und Adressen (URLs) zwischen Geräten teilen</string>
<string name="plugin_not_available">Diese Funktion ist in Ihrer Android-Version nicht verfügbar</string>
@@ -38,14 +40,11 @@
<item>Mittelklick</item>
<item>Nichts</item>
</string-array>
<string name="mousepad_double_default">Rechts</string>
<string name="mousepad_triple_default">Mitte</string>
<string name="mousepad_sensitivity_default">Standard</string>
<string-array name="mousepad_sensitivity_entries">
<item>Langsamste</item>
<item>Above Slowest</item>
<item>Langsam</item>
<item>Standard</item>
<item>Above Default</item>
<item>Schnell</item>
<item>Schnellste</item>
</string-array>
<string name="category_connected_devices">Verbundene Geräte</string>
@@ -66,19 +65,25 @@
<string name="error_canceled_by_other_peer">Abbruch durch Gegenstelle</string>
<string name="error_invalid_key">Ungültiger Schlüssel empfangen</string>
<string name="encryption_info_title">Verschlüsselungsinformationen</string>
<string name="encryption_info_msg_no_ssl">Das andere Gerät verwendet eine ältere Version von KDE-Connect, eine veraltete Verschlüsselungsmethode wird verwendet.</string>
<string name="my_device_fingerprint">Der SHA1-Fingerabdruck Ihres Gerätezertifikats lautet:</string>
<string name="remote_device_fingerprint">Der SHA1-Fingerabdruck des Gerätezertifikats der Gegenstelle lautet:</string>
<string name="pair_requested">Verbindung angefordert</string>
<string name="pairing_request_from">Verbindungsanfrage von %1s</string>
<string name="received_url_title">Verknüpfung von %1s erhalten</string>
<string name="received_url_text">Tippen um „%1s“ zu öffnen</string>
<string name="incoming_file_title">Eingehende Datei von %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Datei wird an %1s gesendet</string>
<string name="outgoing_files_title">Datei wird an %1s gesendet</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">%1$d von %2$d Dateien gesendet</string>
<string name="received_file_title">Datei von %1s erhalten</string>
<string name="received_file_fail_title">Der Empfang der Datei %1s ist fehlgeschlagen</string>
<string name="received_file_text">Tippen um „%1s“ zu öffnen</string>
<string name="sent_file_title">Datei an %1s gesendet</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Das Senden der Datei an %1s ist fehlgeschlagen</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tippen zum Antworten</string>
<string name="reconnect">Erneut verbinden</string>
@@ -86,7 +91,7 @@
<string name="middle_click">Mittelklick senden</string>
<string name="show_keyboard">Tastatur anzeigen</string>
<string name="device_not_paired">Das Gerät ist nicht verbunden</string>
<string name="request_pairing">Verbindung angefordert</string>
<string name="request_pairing">Verbindung anfordern</string>
<string name="pairing_accept">Annehmen</string>
<string name="pairing_reject">Ablehnen</string>
<string name="device">Gerät</string>
@@ -101,6 +106,7 @@
<string name="mpris_volume">Lautstärke</string>
<string name="mpris_settings">Multimedia-Einstellungen</string>
<string name="mpris_time_settings_title">Knöpfe Vorwärts/Rückwärts</string>
<string name="mpris_time_settings_summary">Sprungweite für Vorlauf/Rücklauf anpassen.</string>
<string-array name="mpris_time_entries">
<item>10 Sekunden</item>
<item>20 Sekunden</item>
@@ -121,9 +127,13 @@
<string name="custom_devices_settings">Benutzerdefinierte Geräteliste</string>
<string name="pair_device_action">Ein neues Gerät verbinden</string>
<string name="unpair_device_action">Verbindung %s trennen</string>
<string name="custom_device_list">Geräte nach IP hinzufügen</string>
<string name="custom_device_list">Geräte nach IP-Adresse hinzufügen</string>
<string name="share_notification_preference">Ausführliche Benachrichtigungen</string>
<string name="share_notification_preference_summary">Beim Empfang einer Datei vibrieren und einen Sound abspielen</string>
<string name="share_destination_customize">Zielverzeichnis anpassen</string>
<string name="share_destination_customize_summary_disabled">Empfangene Dateien werden in Downloads gespeichert</string>
<string name="share_destination_customize_summary_enabled">Dateien werden im folgenden Verzeichnis gespeichert</string>
<string name="share_destination_folder_preference">Zielverzeichnis</string>
<string name="title_activity_notification_filter">Benachrichtigungs-Filter</string>
<string name="filter_apps_info">Benachrichtigungen werden zwischen den ausgewählten Anwendungen abgeglichen.</string>
<string name="sftp_internal_storage">Interner Speicher</string>
@@ -132,24 +142,27 @@
<string name="sftp_sdcard">SD-Karte</string>
<string name="sftp_readonly">(Nur lesen)</string>
<string name="sftp_camera">Kamerabilder</string>
<string name="add_host">Rechner/IP hinzufügen</string>
<string name="add_host_hint">Rechnername oder IP</string>
<string name="add_host">Rechner/IP-Adresse hinzufügen</string>
<string name="add_host_hint">Rechnername oder IP-Adresse</string>
<string name="no_players_connected">Keine Medienspieler gefunden</string>
<string name="custom_dev_list_help">Benutzen Sie diese Funktion nur, wenn Ihr Gerät nicht automatisch erkannt wird. Geben hier Sie IP-Adresse oder Hostnamen ein und bestätigen Sie, um es zu der Liste hinzuzufügen. Tippen Sie ein bestehendes Gerät an, um es aus der Liste zu entfernen.</string>
<string name="mpris_player_on_device">%1$s auf %2$s</string>
<string name="send_files">Dateien senden</string>
<string name="pairing_title">KDE-Connect-Geräte</string>
<string name="pairing_description">Andere Geräte, auf denen KDE-Connect läuft im gleichen Netzwerk,sollte hier angezeigt werden.</string>
<string name="pairing_description">Andere Geräte im selben Netzwerk, auf denen KDE-Connect läuft, sollten hier angezeigt werden.</string>
<string name="device_paired">Gerät verbunden</string>
<string name="device_rename_title">Geräte umbenennen</string>
<string name="device_rename_confirm">Umbenennen</string>
<string name="refresh">Aktualisieren</string>
<string name="unreachable_description">Das verbundene Gerät ist nicht erreichbar. Stellen Sie sicher, dass es mit demselben Netzwerk verbunden ist.</string>
<string name="on_data_message">Sie benutzen anscheinend eine mobile Datenverbindung. KDE-Connect funktioniert nur in lokalen Netzwerken.</string>
<string name="no_file_browser">Es sind keine Dateiverwaltungsprogramme installiert.</string>
<string name="pref_plugin_telepathy">SMS senden</string>
<string name="pref_plugin_telepathy_desc">Text-Nachrichten von Ihrer Arbeitsfläche senden</string>
<string name="plugin_not_supported">Dieses Modul wird durch das Gerät nicht unterstützt</string>
<string name="findmyphone_title">Mein Telefon suchen</string>
<string name="findmyphone_title_tablet">Mein Tablett suchen</string>
<string name="findmyphone_description">Ruft dieses Gerät an, um es zu suchen.</string>
<string name="findmyphone_title_tablet">Mein Tablet suchen</string>
<string name="findmyphone_description">Ruft dieses Gerät an, damit sie es finden können</string>
<string name="findmyphone_found">Gefunden</string>
<string name="open">Öffnen</string>
<string name="close">Schließen</string>

View File

@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">Διαμοιρασμός περιεχομένου προχείρου</string>
<string name="pref_plugin_mousepad">Απομακρυσμένη είσοδος στοιχείων</string>
<string name="pref_plugin_mousepad_desc">Χρήση του τηλεφώνου ή της ταμπλέτας σας ως επιφάνεια αφής και πληκτρολόγιο</string>
<string name="pref_plugin_remotekeyboard">Λήψη απομακρυσμένων πληκτρολογήσεων</string>
<string name="pref_plugin_remotekeyboard_desc">Λήψη συμβάντων πληκτρολόγησης από απομακρυσμένες συσκευές</string>
<string name="pref_plugin_mpris">Κονσόλα πολυμέσων</string>
<string name="pref_plugin_mpris_desc">Παρέχει ένα τηλεχειριστήριο για την αναπαραγωγή πολυμέσων</string>
<string name="pref_plugin_runcommand">Εκτέλεση εντολής</string>
@@ -30,8 +32,11 @@
<string name="no_permissions">Απαιτείται παραχώρηση δικαιωμάτων για την πρόσβαση σε ειδοποιήσεις</string>
<string name="send_ping">Αποστολή ping</string>
<string name="open_mpris_controls">Έλεγχος πολυμέσων</string>
<string name="remotekeyboard_editing_only_title">Χειρισμός απομακρυσμένων πλήκτρων μόνο στην επεξεργασία</string>
<string name="remotekeyboard_not_connected">Δεν υπάρχει ενεργή σύνδεση με απομακρυσμένο πληκτρολόγιο, άνοιξε μία στο kdeconnect</string>
<string name="remotekeyboard_connected">Η σύνδεση με απομακρυσμένο πληκτρολόγιο είναι ενεργή</string>
<string name="remotekeyboard_multiple_connections">Υπάρχουν περισσότερες της μίας συνδέσεις με απομακρυσμένο πληκτρολόγιο, επιλέξτε ποια συσκευή θα διαμορφώσετε</string>
<string name="open_mousepad">Απομακρυσμένη είσοδος στοιχείων</string>
<string name="mousepad_info">Μετακινείστε το δάκτυλο στην οθόνη για να μετακινηθεί ο δρομέας του ποντικιού. Χτυπήστε για κλικ και χρησιμοποιήστε δύο/τρία δάκτυλα για δεξί και μεσαίο κλικ. Πιέστε με διάρκεια για μετακίνηση και απόθεση.</string>
<string name="mousepad_double_tap_settings_title">Ρύθμιση δύο δακτύλων για την ενέργεια χτυπήματος</string>
<string name="mousepad_triple_tap_settings_title">Ρύθμιση τριών δακτύλων για την ενέργεια χτυπήματος</string>
<string name="mousepad_sensitivity_settings_title">Ρύθμιση ευαισθησίας της οθόνης αφής</string>
@@ -41,9 +46,6 @@
<item>Μεσαίο κλικ</item>
<item>Τίποτα</item>
</string-array>
<string name="mousepad_double_default">δεξί</string>
<string name="mousepad_triple_default">μεσαίο</string>
<string name="mousepad_sensitivity_default">προκαθορισμένο</string>
<string-array name="mousepad_sensitivity_entries">
<item>Το πιο αργό</item>
<item>Πάνω από το πιο αργό</item>
@@ -79,12 +81,15 @@
<string name="incoming_file_title">Εισερχόμενο αρχείο από %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Αποστολή αρχείου σε %1s</string>
<string name="outgoing_files_title">Αποστολή αρχείων σε %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Εστάλησαν %1$d από %2$d αρχεία</string>
<string name="received_file_title">Ελήφθη αρχείο από %1s</string>
<string name="received_file_fail_title">Αποτυχία λήψης αρχείου από %1s</string>
<string name="received_file_text">Χτυπήστε για άνοιγμα \'%1s\'</string>
<string name="sent_file_title">Εστάλη αρχείο στο %1s</string>
<string name="sent_file_title">Εστάλη αρχείο σε %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Αποτυχία αποστολής αρχείου σε %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Χτυπήστε για να απαντήσετε</string>
<string name="reconnect">Επανασύνδεση</string>
@@ -131,6 +136,10 @@
<string name="custom_device_list">Προσθήκη συσκευών ανά IP</string>
<string name="share_notification_preference">Θορυβώδεις ειδοποιήσεις</string>
<string name="share_notification_preference_summary">Δόνηση και ηχητική ένδειξη με τη λήψη αρχείου</string>
<string name="share_destination_customize">Προσαρμογή καταλόγου προορισμού</string>
<string name="share_destination_customize_summary_disabled">Τα ληφθέντα αρχεία θα εμφανίζονται στις Λήψεις</string>
<string name="share_destination_customize_summary_enabled">Τα αρχεία θα αποθηκεύονται στον παρακάτω κατάλογο</string>
<string name="share_destination_folder_preference">Κατάλογος προορισμού</string>
<string name="title_activity_notification_filter">Φιλτράρισμα ειδοποιήσεων</string>
<string name="filter_apps_info">Οι ειδοποιήσεις θα συγχρονίζονται για επιλεγμένες εφαρμογές.</string>
<string name="sftp_internal_storage">Εσωτερικός αποθηκευτικός χώρος</string>
@@ -152,6 +161,7 @@
<string name="device_rename_confirm">Μετονομασία</string>
<string name="refresh">Ανανέωση</string>
<string name="unreachable_description">Αυτή η συζευγμένη συσκευή δεν είναι προσβάσιμη. Βεβαιωθείτε ότι είναι συνδεδεμένη στο δίκτυό σας.</string>
<string name="on_data_message">Φαίνεται ότι είστε σε σύνδεση δεδομένων από κινητό. Το KDE Connect λειτουργεί μόνο σε τοπικά δίκτυα.</string>
<string name="no_file_browser">Δεν υπάρχουν εγκατεστημένοι περιηγητές αρχείων.</string>
<string name="pref_plugin_telepathy">Αποστολή SMS</string>
<string name="pref_plugin_telepathy_desc">Αποστολή μηνυμάτων κειμένου από τον υπολογιστή σας</string>
@@ -162,4 +172,14 @@
<string name="findmyphone_found">Βρέθηκε</string>
<string name="open">Άνοιγμα</string>
<string name="close">Κλείσιμο</string>
<string name="no_permissions_storage">Απαιτείται παραχώρηση δικαιωμάτων για την πρόσβαση στον αποθηκευτικό χώρο</string>
<string name="plugins_need_permission">Κάποια πρόσθετα απαιτούν δικαιώματα για να λειτουργήσουν (χτυπήστε για περισσότερες πληροφορίες):</string>
<string name="permission_explanation">Αυτό το πρόσθετο χρειάζεται δικαιώματα για να λειτουργήσει</string>
<string name="optional_permission_explanation">Απαιτείται παραχώρηση επιπλέον δικαιωμάτων για την ενεργοποίηση όλων των λειτουργιών</string>
<string name="plugins_need_optional_permission">Κάποια πρόσθετα έχουν λειτουργίες ανενεργές εξαιτίας της απουσίας δικαιωμάτων (χτυπήστε για περισσότερες πληροφορίες):</string>
<string name="sftp_permission_explanation">Για την πρόσβαση στα αρχεία σας από τον υπολογιστή η εφαρμογή χρειάζεται δικαιώματα πρόσβασης στον αποθηκευτικό χώρο του κινητού σας</string>
<string name="share_optional_permission_explanation">Για το διαμοιρασμό αρχείων ανάμεσα στο τηλέφωνο και τον υπολογιστή σας χρειάζεται να παραχωρήσετε πρόσβαση στον αποθηκευτικό χώρο του τηλεφώνου σας</string>
<string name="telepathy_permission_explanation">Για να διαβάσετε και να γράψετε SMS από την επιφάνεια εργασίας, χρειάζεται να δώσετε δικαιώματα στο SMS</string>
<string name="telephony_permission_explanation">Για να δείτε τηλεφωνικές κλήσεις και SMS από την επιφάνεια εργασίας, χρειάζεται να παραχωρήσετε δικαιώματα σε τηλεφωνικές κλήσεις και SMS</string>
<string name="telephony_optional_permission_explanation">Για να δείτε το όνομα επαφής αντί για τον αριθμό κλήσης χρειάζεται να παραχωρήσετε πρόσβαση στις επαφές στο τηλέφωνο</string>
</resources>

View File

@@ -37,7 +37,6 @@
<string name="remotekeyboard_connected">Remote keyboard connection is active</string>
<string name="remotekeyboard_multiple_connections">There is more than one remote keyboard connection, select the device to configure</string>
<string name="open_mousepad">Remote input</string>
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
<string name="mousepad_sensitivity_settings_title">Set touchpad sensitivity</string>
@@ -47,9 +46,6 @@
<item>Middle click</item>
<item>Nothing</item>
</string-array>
<string name="mousepad_double_default">right</string>
<string name="mousepad_triple_default">middle</string>
<string name="mousepad_sensitivity_default">default</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
@@ -176,4 +172,14 @@
<string name="findmyphone_found">Found</string>
<string name="open">Open</string>
<string name="close">Close</string>
<string name="no_permissions_storage">You need to grant permissions to access the storage</string>
<string name="plugins_need_permission">Some Plugins need permissions to work (tap for more info):</string>
<string name="permission_explanation">This plugin needs permissions to work</string>
<string name="optional_permission_explanation">You need to grant extra permissions to enable all functions</string>
<string name="plugins_need_optional_permission">Some plugins have features disabled because of lack of permission (tap for more info):</string>
<string name="sftp_permission_explanation">To access your files from your PC the app needs permission to access your phone\'s storage</string>
<string name="share_optional_permission_explanation">To share files between your phone and your desktop you need to give access to the phone\'s storage</string>
<string name="telepathy_permission_explanation">To read and write SMS from your desktop you need to give permission to SMS</string>
<string name="telephony_permission_explanation">To see phone calls and SMS from the desktop you need to give permission to phone calls and SMS</string>
<string name="telephony_optional_permission_explanation">To see a contact name instead of a phone number you need to give access to the phone\'s contacts</string>
</resources>

View File

@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">Compartir el contenido del portapapeles</string>
<string name="pref_plugin_mousepad">Entrada remota</string>
<string name="pref_plugin_mousepad_desc">Usar su teléfono o tableta como teclado y teclado táctil</string>
<string name="pref_plugin_remotekeyboard">Recibir pulsaciones de teclas remotas</string>
<string name="pref_plugin_remotekeyboard_desc">Recibir eventos de pulsación de teclas desde dispositivos remotos</string>
<string name="pref_plugin_mpris">Controles multimedia</string>
<string name="pref_plugin_mpris_desc">Proporciona un control remoto para su reproductor de medios</string>
<string name="pref_plugin_runcommand">Ejecutar orden</string>
@@ -30,8 +32,12 @@
<string name="no_permissions">Debe otorgar permiso para acceder a las notificaciones</string>
<string name="send_ping">Enviar ping</string>
<string name="open_mpris_controls">Control multimedia</string>
<string name="remotekeyboard_editing_only_title">Manejar teclas remotas solo al editar</string>
<string name="remotekeyboard_not_connected">No hay ninguna conexión remota de teclado activa, establezca una en kdeconnect</string>
<string name="remotekeyboard_connected">La conexión remota de teclado está activa</string>
<string name="remotekeyboard_multiple_connections">Hay más de una conexión remota de teclado, seleccione el dispositivo a configurar</string>
<string name="open_mousepad">Entrada remota</string>
<string name="mousepad_info">Mueva un dedo sobre la pantalla para mover el cursor del ratón. Pulse para ejecutar un clic y use dos/tres dedos para emular los botones derecho y central. Use una pulsación larga para arrastrar y soltar.</string>
<string name="mousepad_info">Mueva un dedo sobre la pantalla para mover el cursor del ratón. Pulse para ejecutar un clic y use dos/tres dedos para emular los botones derecho y central. Use 2 dedos para desplazar las pantalla. Use una pulsación larga para arrastrar y soltar.</string>
<string name="mousepad_double_tap_settings_title">Establecer la acción al pulsar con dos dedos</string>
<string name="mousepad_triple_tap_settings_title">Establecer la acción al pulsar con tres dedos</string>
<string name="mousepad_sensitivity_settings_title">Establecer sensibilidad del panel táctil</string>
@@ -41,9 +47,6 @@
<item>Clic del botón central</item>
<item>Nada</item>
</string-array>
<string name="mousepad_double_default">derecho</string>
<string name="mousepad_triple_default">medio</string>
<string name="mousepad_sensitivity_default">por defecto</string>
<string-array name="mousepad_sensitivity_entries">
<item>Muy poco sensible</item>
<item>Poco sensible</item>
@@ -153,15 +156,16 @@
<string name="mpris_player_on_device">%1$s en %2$s</string>
<string name="send_files">Enviar archivos</string>
<string name="pairing_title">Dispositivos de KDE Connect</string>
<string name="pairing_description">Otros dispositivos ejecutando KDE Connect en su misma red deberían aparecer aquí.</string>
<string name="pairing_description">Cualquier otro dispositivo ejecutando KDE Connect en su misma red debería aparecer aquí.</string>
<string name="device_paired">Dispositivo vinculado</string>
<string name="device_rename_title">Renombrar dispositivo</string>
<string name="device_rename_confirm">Renombrar</string>
<string name="refresh">Actualizar</string>
<string name="unreachable_description">Este dispositivo vinculado no está disponible. Asegúrese que está conectado a su misma red.</string>
<string name="on_data_message">Parece que se encuentra en una conexión de datos móviles. KDE Connect solo funciona en redes locales.</string>
<string name="no_file_browser">No hay navegadores de archivos instalados.</string>
<string name="pref_plugin_telepathy">Enviar SMS</string>
<string name="pref_plugin_telepathy_desc">Enviar mensajes de texto desde el escritorio</string>
<string name="pref_plugin_telepathy_desc">Enviar mensajes de texto desde su escritorio</string>
<string name="plugin_not_supported">Este complemento no está permitido por el dispositivo</string>
<string name="findmyphone_title">Encontrar mi teléfono</string>
<string name="findmyphone_title_tablet">Encontrar mi tableta</string>
@@ -169,4 +173,14 @@
<string name="findmyphone_found">Encontrado</string>
<string name="open">Abrir</string>
<string name="close">Cerrar</string>
<string name="no_permissions_storage">Debe otorgar permisos para acceder al almacenamiento</string>
<string name="plugins_need_permission">Algunos complementos necesitan permisos para funcionar (pulse para más información):</string>
<string name="permission_explanation">Este complemento necesita permisos para funcionar</string>
<string name="optional_permission_explanation">Debe otorgar permisos extra para activar todas las funciones</string>
<string name="plugins_need_optional_permission">Algunos complementos tienen funcionalidades desactivadas por falta de permisos (pulse para más información):</string>
<string name="sftp_permission_explanation">Para acceder a sus archivos desde su equipo, la aplicación necesita permisos para acceder al almacenamiento de su teléfono</string>
<string name="share_optional_permission_explanation">Para compartir archivos entre su teléfono y su escritorio, necesita dar acceso al almacenamiento de su teléfono</string>
<string name="telepathy_permission_explanation">Para leer y escribir SMS desde su escritorio, necesita dar permisos para SMS</string>
<string name="telephony_permission_explanation">Para ver las llamadas telefónicas y SMS desde su escritorio, necesita dar permisos para llamadas telefónicas y SMS</string>
<string name="telephony_optional_permission_explanation">Para ver el nombre de un contacto en lugar de un número telefónico, necesita dar acceso a los contactos de su teléfono</string>
</resources>

View File

@@ -31,7 +31,6 @@
<string name="send_ping">Saada ping</string>
<string name="open_mpris_controls">Multimeedia juhtimine</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. 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>
@@ -41,9 +40,6 @@
<item>Keskklõps</item>
<item>Ei tee midagi</item>
</string-array>
<string name="mousepad_double_default">parem</string>
<string name="mousepad_triple_default">keskmine</string>
<string name="mousepad_sensitivity_default">vaikimisi</string>
<string-array name="mousepad_sensitivity_entries">
<item>Kõige aeglasem</item>
<item>Kõige aeglasemast kiirem</item>

185
res/values-eu/strings.xml Normal file
View File

@@ -0,0 +1,185 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Telefonia jakinarazlea</string>
<string name="pref_plugin_telephony_desc">Bidali jakinarazpenak SMSak eta deiak jasotzean</string>
<string name="pref_plugin_battery">Bateriaren txostena</string>
<string name="pref_plugin_battery_desc">Bidali bateriaren egoera aldiro</string>
<string name="pref_plugin_sftp">Fitxategi-sistemaren esposaketa</string>
<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_desc">Erabili zure telefonoa edo tableta ukimen-sagu eta teklatu gisa</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_runcommand">Exekutatu agindua</string>
<string name="pref_plugin_runcommand_desc">Abiarazi urruneko aginduak zure telefono edo tabletatik</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Bidali eta jaso pingak</string>
<string name="pref_plugin_notifications">Jakinarazpenen sinkronizazioa</string>
<string name="pref_plugin_notifications_desc">Atzitu zure jakinarazpenak beste gailuetatik</string>
<string name="pref_plugin_receive_notifications">Jaso jakinarazpenak</string>
<string name="pref_plugin_receive_notifications_desc">Jaso jakinarazpenak beste gailutik eta bistaratu Androiden</string>
<string name="pref_plugin_sharereceiver">Partekatu eta jaso</string>
<string name="pref_plugin_sharereceiver_desc">Partekatu fitxategiak eta URLak gailuen artean</string>
<string name="plugin_not_available">Ezaugarri hau ez dago erabilgarri zure Android bertsioan</string>
<string name="device_list_empty">Gailurik ez</string>
<string name="ok">Ados</string>
<string name="cancel">Utzi</string>
<string name="open_settings">Ireki ezarpenak</string>
<string name="no_permissions">Jakinarazpenak atzitzeko baimena eman 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>
<string name="remotekeyboard_not_connected">Ez dago urruneko teklatuarekin konexio aktiborik, ezarri bat kdeconnect erabiliz</string>
<string name="remotekeyboard_connected">Urruneko teklatuarekin konexioa aktibo dago</string>
<string name="remotekeyboard_multiple_connections">Urruneko teklatuekin konexio bat baino gehiago dago, hautatu konfiguratu beharreko gailua</string>
<string name="open_mousepad">Urruneko sarrera</string>
<string name="mousepad_double_tap_settings_title">Ezarri bi atzamarren ekintza</string>
<string name="mousepad_triple_tap_settings_title">Ezarri hiru atzamarren ekintza</string>
<string name="mousepad_sensitivity_settings_title">Ezarri ukimen-saguaren sentikortasuna</string>
<string name="mousepad_scroll_direction_title">Alderantzikatu korritzearen norabidea</string>
<string-array name="mousepad_tap_entries">
<item>Eskumako klik</item>
<item>Erdiko klik</item>
<item>Ezer ez</item>
</string-array>
<string-array name="mousepad_sensitivity_entries">
<item>Motelena</item>
<item>Motelena baino azkarrago</item>
<item>Lehenetsia</item>
<item>Batezbestekoa baino azkarrago</item>
<item>Azkarrena</item>
</string-array>
<string name="category_connected_devices">Konektatutako gailuak</string>
<string name="category_not_paired_devices">Gailu eskuragarriak</string>
<string name="category_remembered_devices">Gogoratutako gailuak</string>
<string name="plugins_failed_to_load">Pluginak kargatzen huts egin dute (sakatu informazio gehiagorako):</string>
<string name="device_menu_plugins">Pluginen ezarpenak</string>
<string name="device_menu_unpair">Desparekatu</string>
<string name="device_not_reachable">Parekatu gailua ez dago eskuragarri</string>
<string name="pair_new_device">Parekatu gailu berria</string>
<string name="unknown_device">Gailu ezezaguna</string>
<string name="error_not_reachable">Gailua ez dago eskuragarri</string>
<string name="error_already_requested">Parekatzea dagoeneko eskatu da</string>
<string name="error_already_paired">Gailua dagoeneko parekatuta</string>
<string name="error_could_not_send_package">Ezin izan da paketea bidali</string>
<string name="error_timed_out">Denbora-muga agortu da</string>
<string name="error_canceled_by_user">Erabiltzaileak utzita</string>
<string name="error_canceled_by_other_peer">Beste kideak utzita</string>
<string name="error_invalid_key">Baliogabeko gakoa jaso da</string>
<string name="encryption_info_title">Zifratze informazioa</string>
<string name="encryption_info_msg_no_ssl">Beste gailuak ez du oraintsuko KDE Connect bertsio bat erabiltzen, erabili aurreko bertsioetako metodoa.</string>
<string name="my_device_fingerprint">Zure gailuaren ziurtagiriaren SHA1 hatz-marka hau da:</string>
<string name="remote_device_fingerprint">Urruneko gailuaren ziurtagiriaren SHA1 hatz-marka hau da:</string>
<string name="pair_requested">Parekatzea eskatu da</string>
<string name="pairing_request_from">Parekatzeko eskaria %1s-tik</string>
<string name="received_url_title">Esteka jaso da %1s-tik</string>
<string name="received_url_text">Sakatu \'%1s\' irekitzeko</string>
<string name="incoming_file_title">Fitxategia jasotzen %1s-tik</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Fitxategia bidaltzen %1s-ra</string>
<string name="outgoing_files_title">Fitxategiak bidaltzen %1s-ra</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">%1$d / %2$d fitxategi bidalita</string>
<string name="received_file_title">Fitxategia jaso da %1s-tik</string>
<string name="received_file_fail_title">Huts egin du fitxategia jasotzea %1s-tik</string>
<string name="received_file_text">Sakatu \'%1s\' irekitzeko</string>
<string name="sent_file_title">Fitxategia bidalita %1s-ra</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Huts egin du fitxategia bidaltzea %1s-ra</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Sakatu erantzuteko</string>
<string name="reconnect">Birkonektatu</string>
<string name="right_click">Bidali eskumako klik</string>
<string name="middle_click">Bidali erdiko klik</string>
<string name="show_keyboard">Erakutsi teklatua</string>
<string name="device_not_paired">Gailua parekatu gabe</string>
<string name="request_pairing">Eskatu parekatzea</string>
<string name="pairing_accept">Onartu</string>
<string name="pairing_reject">Ukatu</string>
<string name="device">Gailua</string>
<string name="pair_device">Parekatu gailua</string>
<string name="remote_control">Urruneko kontrola</string>
<string name="settings">KDE Connect ezarpenak</string>
<string name="mpris_play">Jo</string>
<string name="mpris_previous">Aurrekoa</string>
<string name="mpris_rew">Atzera eraman</string>
<string name="mpris_ff">Aurrera eraman</string>
<string name="mpris_next">Hurrengoa</string>
<string name="mpris_volume">Bolumena</string>
<string name="mpris_settings">Multimedia ezarpenak</string>
<string name="mpris_time_settings_title">Atzera eraman / Aurrera eraman botoiak</string>
<string name="mpris_time_settings_summary">Doitu zenbat denbora eraman behar den aurrera / atzera sakatzean</string>
<string-array name="mpris_time_entries">
<item>10 segundo</item>
<item>20 segundo</item>
<item>30 segundo</item>
<item>minutu 1</item>
<item>2 minutu</item>
</string-array>
<string name="share_to">Partekatu honi...</string>
<string name="protocol_version_older">Gailu honek protokoloaren bertsio zahar bat erabiltzen du</string>
<string name="protocol_version_newer">Gailu honek protokoloaren bertsio berriago bat erabiltzen du</string>
<string name="general_settings">Ezarpen orokorrak</string>
<string name="plugin_settings">Ezarpenak</string>
<string name="plugin_settings_with_name">%s ezarpenak</string>
<string name="device_name">Gailuaren izena</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">Gailuaren izen baliogabea</string>
<string name="shareplugin_text_saved">Testua jaso da, arbelean kopiatu da</string>
<string name="custom_devices_settings">Gailuen zerrenda pertsonalizatua</string>
<string name="pair_device_action">Parekatu gailu berria</string>
<string name="unpair_device_action">Desparekatu %s</string>
<string name="custom_device_list">Gehitu gailuak IP bidez</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>
<string name="share_destination_customize_summary_disabled">Jasotako fitxategiak Deskargak karpetan agertuko dira</string>
<string name="share_destination_customize_summary_enabled">Fitxategiak beheko direktorioan gordeko dira</string>
<string name="share_destination_folder_preference">Direktorio xedea</string>
<string name="title_activity_notification_filter">Jakinarazpenen iragazkia</string>
<string name="filter_apps_info">Aukeratutako aplikazioen jakinarazpenak sinkronizatuko dira</string>
<string name="sftp_internal_storage">Barne biltegiratzea</string>
<string name="sftp_all_files">Fitxategi guztiak</string>
<string name="sftp_sdcard_num">%d SD txartela</string>
<string name="sftp_sdcard">SD txartela</string>
<string name="sftp_readonly">(irakurri soilik)</string>
<string name="sftp_camera">Kamerako irudiak</string>
<string name="add_host">Gehitu ostalaria/IP</string>
<string name="add_host_hint">Ostalaria edo IP</string>
<string name="no_players_connected">Ez da jokalaririk aurkitu</string>
<string name="custom_dev_list_help">Erabili aukera hau zure gailua automatikoki antzematen ez denean. Sartu IP helbidea edo ostalaria azpian eta ukitu botoia zerrendara gehitzeko. Ukitu badagoen elementu bat zerrendatik ezabatzeko.</string>
<string name="mpris_player_on_device">%1$s - %2$s</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>
<string name="device_paired">Gailu parekatua</string>
<string name="device_rename_title">Aldatu izena gailuari</string>
<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="on_data_message">Badirudi datu mugikorrak erabiliz konektatu zarela. KDE Connect sare lokalen bitartez besterik ez dabil.</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>
<string name="plugin_not_supported">Gailu honek ez du plugin honentzako euskarririk</string>
<string name="findmyphone_title">Bilatu nire telefonoa</string>
<string name="findmyphone_title_tablet">Bilatu nire tableta</string>
<string name="findmyphone_description">Gailuaren dei-doinua jotzen du aurki dezazun</string>
<string name="findmyphone_found">Aurkituta</string>
<string name="open">Ireki</string>
<string name="close">Itxi</string>
<string name="no_permissions_storage">Biltegiratzea atzitzeko baimena eman behar duzu</string>
<string name="plugins_need_permission">Plugin batzuk baimenak behar dituzte funtzionatzeko (sakatu informazio gehiagorako):</string>
<string name="permission_explanation">Plugin honek baimena behar du funtzionatzeko</string>
<string name="optional_permission_explanation">Baimen gehiago eman behar dituzu funtzio guztiak gaitzeko</string>
<string name="plugins_need_optional_permission">Plugin batzuk desgaitutako funtzioak dituzte baimenak faltan dituztelako (sakatu informazio gehiagorako):</string>
<string name="sftp_permission_explanation">Zure fitxategiak PCtik atzitzeko aplikazioak zure telefonoaren biltegiratzea atzitzeko baimena behar du</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 eta SMSak zure mahaigainetik ikusteko, telefono deiak eta SMSak erabiltzeko 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>
</resources>

View File

@@ -31,7 +31,6 @@
<string name="send_ping">Lähetä tiedustelupaketti</string>
<string name="open_mpris_controls">Multimedian ohjaus</string>
<string name="open_mousepad">Kauko-ohjaus</string>
<string name="mousepad_info">Liikuta hiiren osoitinta liikuttamalla sormeasi näytöllä. Napsauta napauttamalla yhdellä sormella, käytä oikeaa painiketta kahdella sormella ja keskipainiketta kolmella. Vedä ja pudota painamalla pitkään.</string>
<string name="mousepad_double_tap_settings_title">Aseta kahden sormen napautuksen toiminto</string>
<string name="mousepad_triple_tap_settings_title">Aseta kolmen sormen napautuksen toiminto</string>
<string name="mousepad_sensitivity_settings_title">Aseta kosketuslevyn herkkyys</string>
@@ -41,9 +40,6 @@
<item>Keskinapsautus</item>
<item>Ei toimintoa</item>
</string-array>
<string name="mousepad_double_default">Oikea painike</string>
<string name="mousepad_triple_default">Keskipainike</string>
<string name="mousepad_sensitivity_default">oletus</string>
<string-array name="mousepad_sensitivity_entries">
<item>Hitain</item>
<item>Hitainta suurempi</item>

View File

@@ -1,18 +1,27 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Notifications du téléphonie</string>
<string name="pref_plugin_telephony">Notifications de téléphonie</string>
<string name="pref_plugin_telephony_desc">Envoie des notifications pour les SMS et les appels</string>
<string name="pref_plugin_battery">Rapport sur la batterie</string>
<string name="pref_plugin_battery_desc">Rapport périodique sur l\'état de la batterie</string>
<string name="pref_plugin_sftp">Exposer le système de fichiers</string>
<string name="pref_plugin_sftp_desc">Permettre de parcourir le système de fichiers du périphérique à distance</string>
<string name="pref_plugin_clipboard">Synchronisation avec le presse-papiers</string>
<string name="pref_plugin_clipboard_desc">Partage le contenu du presse-papiers</string>
<string name="pref_plugin_mousepad">Contrôle distant</string>
<string name="pref_plugin_mousepad_desc">Utilisez votre téléphone ou tablette comme un pavé tactile et un clavier</string>
<string name="pref_plugin_remotekeyboard">Recevoir les appuis de touches distants</string>
<string name="pref_plugin_remotekeyboard_desc">Recevoir les appuis de touches des périphériques distants</string>
<string name="pref_plugin_mpris">Contrôles multimédia</string>
<string name="pref_plugin_mpris_desc">Fournit une télécommande pour votre lecteur multimédia</string>
<string name="pref_plugin_runcommand">Exécuter une commande</string>
<string name="pref_plugin_runcommand_desc">Exécuter des commandes à distance sur votre téléphone ou tablette</string>
<string name="pref_plugin_ping">Commande « Ping »</string>
<string name="pref_plugin_ping_desc">Envoie et reçoit des commandes « Ping »</string>
<string name="pref_plugin_notifications">Synchronisation des notifications</string>
<string name="pref_plugin_notifications_desc">Accédez à vos notifications depuis d\'autres périphériques</string>
<string name="pref_plugin_receive_notifications">Recevoir les notifications</string>
<string name="pref_plugin_receive_notifications_desc">Recevoir les notifications du périphérique et les afficher dans Android</string>
<string name="pref_plugin_sharereceiver">Partager et recevoir</string>
<string name="pref_plugin_sharereceiver_desc">Partagez des URLs et des fichiers entre périphériques</string>
<string name="plugin_not_available">Cette fonctionnalité n\'est pas disponible dans votre version de Android</string>
@@ -23,65 +32,76 @@
<string name="no_permissions">Vous devez accorder la permission d\'accéder aux notifications</string>
<string name="send_ping">Envoyer un « Ping »</string>
<string name="open_mpris_controls">Contrôles multimédia</string>
<string name="remotekeyboard_editing_only_title">Gérer les appuis de touches à distance uniquement lors de l\'édition</string>
<string name="remotekeyboard_not_connected">Aucune connexion active d\'un clavier sans fil disponible, établissez-en une dans KDE Connect</string>
<string name="remotekeyboard_connected">La connexion au clavier sans fil est active</string>
<string name="remotekeyboard_multiple_connections">Plusieurs connexions à des claviers sans fil sont disponibles, sélectionnez le périphérique à configurer</string>
<string name="open_mousepad">Contrôle distant</string>
<string name="mousepad_info">Déplacer le doigt sur l\'écran pour bouger le pointeur de la souris. Appuyez pour cliquer et utiliser deux/trois doigts pour les clic droit et centre. Appuyez longtemps pour faire un glisser déplacer.</string>
<string name="mousepad_double_tap_settings_title">Action pour l\'appui à deux doigts</string>
<string name="mousepad_triple_tap_settings_title">Action pour l\'appui à trois doigts</string>
<string name="mousepad_sensitivity_settings_title">Définir la sensibilité du pavé tactile</string>
<string name="mousepad_scroll_direction_title">Inverser la direction du défilement</string>
<string-array name="mousepad_tap_entries">
<item>Clic droit</item>
<item>Clic central</item>
<item>Rien</item>
</string-array>
<string name="mousepad_double_default">Droite</string>
<string name="mousepad_triple_default">Milieu</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
<item>Le plus lent</item>
<item>Assez lent</item>
<item>Par défaut</item>
<item>Assez rapide</item>
<item>Le plus rapide</item>
</string-array>
<string name="category_connected_devices">Périphériques connectés</string>
<string name="category_not_paired_devices">Périphériques disponibles</string>
<string name="category_remembered_devices">Périphériques mémorisés</string>
<string name="plugins_failed_to_load">Le chargement des modules externes a échoué (cliquez pour plus d\'informations) :</string>
<string name="device_menu_plugins">Paramètres du module externe</string>
<string name="device_menu_unpair">Désapparier</string>
<string name="device_menu_plugins">Paramètres des modules externes</string>
<string name="device_menu_unpair">Dissocier</string>
<string name="device_not_reachable">Périphérique inaccessible</string>
<string name="pair_new_device">Associer un nouveau périphérique</string>
<string name="unknown_device">Périphérique inconnu</string>
<string name="error_not_reachable">Périphérique inaccessible</string>
<string name="error_already_requested">L\'appariement a déjà été demandé</string>
<string name="error_already_paired">Périphérique déjà appar</string>
<string name="error_already_requested">L\'association a déjà été demandée</string>
<string name="error_already_paired">Périphérique déjà assoc</string>
<string name="error_could_not_send_package">Il est impossible d\'envoyer un paquet</string>
<string name="error_timed_out">Délai expiré</string>
<string name="error_canceled_by_user">Annulé par l\'utilisateur</string>
<string name="error_canceled_by_other_peer">Annulé par un autre homologue</string>
<string name="error_invalid_key">Clé reçue non valable</string>
<string name="encryption_info_title">Informations de chiffrement</string>
<string name="encryption_info_msg_no_ssl">Ce périphérique n\'utilise pas une version récente de KDE Connect qui utilise l\'ancienne méthode de chiffrement.</string>
<string name="my_device_fingerprint">L\'empreinte SHA1 du certificat de votre appareil est :</string>
<string name="remote_device_fingerprint">L\'empreinte SHA1 du certificat du périphérique distant est :</string>
<string name="pair_requested">Paire demandée</string>
<string name="pairing_request_from">Demande d\'appariement provenant de %1s</string>
<string name="pairing_request_from">Demande d\'association provenant de %1s</string>
<string name="received_url_title">Lien reçu de %1s</string>
<string name="received_url_text">Appuyez pour ouvrir %1s</string>
<string name="incoming_file_title">Réception d\'un fichier en cours depuis %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Envoi d\'un fichier à %1s</string>
<string name="outgoing_files_title">Envoi de fichiers à %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Envoi de %1$d sur %2$d fichiers</string>
<string name="received_file_title">Fichier reçu de %1s</string>
<string name="received_file_fail_title">Impossible de recevoir le fichier depuis : %1s</string>
<string name="received_file_text">Appuyez pour ouvrir %1s</string>
<string name="sent_file_title">Fichier envoyé à %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Impossible d\'envoyer le fichier à %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Cliquer pour répondre</string>
<string name="reconnect">Reconnecter</string>
<string name="right_click">Envoyer un clic droit</string>
<string name="middle_click">Envoyer un clic central</string>
<string name="show_keyboard">Afficher le clavier</string>
<string name="device_not_paired">Périphérique non appar</string>
<string name="request_pairing">Demande d\'appariement</string>
<string name="device_not_paired">Périphérique non assoc</string>
<string name="request_pairing">Demande d\'association</string>
<string name="pairing_accept">Accepter</string>
<string name="pairing_reject">Rejeter</string>
<string name="device">Périphérique</string>
<string name="pair_device">Apparier un périphérique</string>
<string name="pair_device">Associer un périphérique</string>
<string name="remote_control">Contrôle distant</string>
<string name="settings">Paramètres de connexion de KDE</string>
<string name="mpris_play">Lire</string>
@@ -111,9 +131,15 @@
<string name="invalid_device_name">Nom de périphérique non valable</string>
<string name="shareplugin_text_saved">Texte reçu et enregistré dans le presse-papiers</string>
<string name="custom_devices_settings">Liste personnalisée de périphériques</string>
<string name="pair_device_action">Associer un nouveau périphérique</string>
<string name="unpair_device_action">Dissocier %s</string>
<string name="custom_device_list">Ajouter des périphériques par IP</string>
<string name="share_notification_preference">Notifications sonores</string>
<string name="share_notification_preference_summary">Vibrer et jouer un son quand un fichier est reçu</string>
<string name="share_destination_customize">Personnaliser le dossier de destination</string>
<string name="share_destination_customize_summary_disabled">Les fichiers reçus apparaîtront dans le dossier de téléchargement</string>
<string name="share_destination_customize_summary_enabled">Les fichiers seront enregistrés dans le dossier ci-dessous</string>
<string name="share_destination_folder_preference">Dossier de destination</string>
<string name="title_activity_notification_filter">Filtre des notifications</string>
<string name="filter_apps_info">Les notifications seront synchronisées pour les applications sélectionnées.</string>
<string name="sftp_internal_storage">Stockage interne</string>
@@ -123,8 +149,37 @@
<string name="sftp_readonly">(lecture seule)</string>
<string name="sftp_camera">Images de l\'appareil photo</string>
<string name="add_host">Ajouter hôte/IP</string>
<string name="add_host_hint">Nom d\'hôte ou adresse IP </string>
<string name="add_host_hint">"Nom d\'hôte ou adresse IP "</string>
<string name="no_players_connected">Aucun lecteur trouvé</string>
<string name="custom_dev_list_help">N\'utilisez cette option que si votre périphérique n\'est pas détecté automatiquement. Saisissez l\'adresse IP ou le nom d\'hôte ci-dessous et appuyez sur le bouton pour l\'ajouter à la liste. Appuyez sur un élément existant pour le retirer de la liste.</string>
<string name="mpris_player_on_device">%1$s sur %2$s</string>
<string name="send_files">Envoyer des fichiers</string>
<string name="pairing_title">Périphériques KDE Connect</string>
<string name="pairing_description">Les autres périphériques utilisant KDE Connect dans votre réseau apparaissent ici.</string>
<string name="device_paired">Périphérique associé</string>
<string name="device_rename_title">Renommer le périphérique</string>
<string name="device_rename_confirm">Renommer</string>
<string name="refresh">Mettre à jour</string>
<string name="unreachable_description">Ce périphérique associé n\'est pas accessible. Assurez-vous qu\'il est bien connecté au même réseau.</string>
<string name="on_data_message">Il semble que vous utilisiez une connexion de données mobile. KDE Connect fonctionne uniquement sur un réseau local.</string>
<string name="no_file_browser">Aucun navigateur de fichiers installé.</string>
<string name="pref_plugin_telepathy">Envoyer un SMS</string>
<string name="pref_plugin_telepathy_desc">Envoyer des SMS depuis votre bureau</string>
<string name="plugin_not_supported">Ce module externe n\'est pas géré par le périphérique</string>
<string name="findmyphone_title">Trouver mon téléphone</string>
<string name="findmyphone_title_tablet">Trouver ma tablette</string>
<string name="findmyphone_description">Fait sonner le périphérique pour vous aider à le retrouver</string>
<string name="findmyphone_found">Trouvé</string>
<string name="open">Ouvrir</string>
<string name="close">Fermer</string>
<string name="no_permissions_storage">Vous devez accorder la permission d\'accéder à l\'espace de stockage</string>
<string name="plugins_need_permission">Certains modules externes nécessitent des permissions pour fonctionner (tapez pour plus d\'informations) :</string>
<string name="permission_explanation">Ce module externe nécessite des permissions pour fonctionner</string>
<string name="optional_permission_explanation">Vous devez accorder des permissions supplémentaires pour activer toutes les fonctionnalités</string>
<string name="plugins_need_optional_permission">Certaines fonctionnalités de modules externes sont désactivées faute de permissions suffisantes (tapez pour plus d\'informations) :</string>
<string name="sftp_permission_explanation">Pour accéder aux fichiers de votre ordinateur, l\'application requiert la permission d\'accéder à la mémoire de stockage de votre téléphone</string>
<string name="share_optional_permission_explanation">Pour partager des fichiers entre votre téléphone et votre ordinateur, veuillez permettre l\'accès à la mémoire de stockage du téléphone</string>
<string name="telepathy_permission_explanation">Pour lire et écrire des SMS depuis votre ordinateur, veuillez permettre l\'accès aux SMS</string>
<string name="telephony_permission_explanation">Pour voir les appels et les SMS depuis votre ordinateur, veuillez permettre l\'accès aux appels et aux SMS</string>
<string name="telephony_optional_permission_explanation">Pour voir le nom du contact au lieu du numéro de téléphone, veuillez permettre l\'accès aux contacts du téléphone</string>
</resources>

View File

@@ -5,15 +5,23 @@
<string name="pref_plugin_battery">Informe da batería</string>
<string name="pref_plugin_battery_desc">Envíe periodicamente un informe sobre o estado da batería.</string>
<string name="pref_plugin_sftp">Revelador do sistema de ficheiros</string>
<string name="pref_plugin_sftp_desc">Permite examinar o sistema de ficheiros do dispositivo remotamente.</string>
<string name="pref_plugin_clipboard">Sincronización do portapapeis</string>
<string name="pref_plugin_clipboard_desc">Comparta o contido do portapapeis.</string>
<string name="pref_plugin_mousepad">Entrada remota</string>
<string name="pref_plugin_mousepad_desc">Use o teléfono ou tableta como área táctil e teclado.</string>
<string name="pref_plugin_remotekeyboard">Recibir teclas premidas remotamente.</string>
<string name="pref_plugin_remotekeyboard_desc">Recibir eventos de teclas premidas de dispositivos remotos.</string>
<string name="pref_plugin_mpris">Controis multimedia</string>
<string name="pref_plugin_mpris_desc">Fornece un mando a distancia para o reprodutor.</string>
<string name="pref_plugin_runcommand">Executar unha orde</string>
<string name="pref_plugin_runcommand_desc">Provocar ordes remotas desde o teléfono ou tableta.</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Envíe e reciba pings.</string>
<string name="pref_plugin_notifications">Sincronización de notificacións</string>
<string name="pref_plugin_notifications_desc">Acceda ás súas notificacións desde outros dispositivos.</string>
<string name="pref_plugin_receive_notifications">Recibir notificacións</string>
<string name="pref_plugin_receive_notifications_desc">Recibir notificacións do outro dispositivo e mostralas en Android.</string>
<string name="pref_plugin_sharereceiver">Compartir e recibir</string>
<string name="pref_plugin_sharereceiver_desc">Comparta ficheiros e enderezos URL entre dispositivos.</string>
<string name="plugin_not_available">Esta funcionalidade non está dispoñíbel para a súa versión de Android.</string>
@@ -24,29 +32,33 @@
<string name="no_permissions">Debe conceder permisos para acceder ás notificacións.</string>
<string name="send_ping">Enviar un ping</string>
<string name="open_mpris_controls">Control multimedia</string>
<string name="remotekeyboard_editing_only_title">Xestionar teclas remotas só ao editar.</string>
<string name="remotekeyboard_not_connected">Non hai ningunha conexión de teclado remoto activa, estableza unha en kdeconnect.</string>
<string name="remotekeyboard_connected">A conexión de teclado remoto está activa.</string>
<string name="remotekeyboard_multiple_connections">Hai máis dunha conexión de teclado remoto, seleccione o dispositivo para configurar.</string>
<string name="open_mousepad">Entrada remota</string>
<string name="mousepad_info">Mova un dedo na pantalla para mover o cursor. Toque para facer clic, e use dous ou tres dedos para os botóns secundario e central. Prema durante un tempo para arrastrar e soltar.</string>
<string name="mousepad_info">Mova un dedo na pantalla para mover o cursor do rato. Toque para facer clic, e use dous ou tres dedos para os botóns secundario e central. Use dous dedos para desprazar. Prema durante un tempo para arrastrar e soltar.</string>
<string name="mousepad_double_tap_settings_title">Definir a acción de tocar con dous dedos</string>
<string name="mousepad_triple_tap_settings_title">Definir a acción de tocar con tres dedos</string>
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do punteiro táctil</string>
<string name="mousepad_scroll_direction_title">Inverter a dirección de desprazamento</string>
<string-array name="mousepad_tap_entries">
<item>Clic dereito</item>
<item>Clic central</item>
<item>Nada</item>
</string-array>
<string name="mousepad_double_default">dereita</string>
<string name="mousepad_triple_default">medio</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
<item>O máis lento</item>
<item>Lento</item>
<item>Predeterminado</item>
<item>Rápido</item>
<item>O máis rápido</item>
</string-array>
<string name="category_connected_devices">Dispositivos conectados</string>
<string name="category_not_paired_devices">Dispositivos dispoñíbeis</string>
<string name="category_remembered_devices">Dispositivos coñecidos</string>
<string name="plugins_failed_to_load">Non foi posíbel cargar os seguintes complementos (toque para obter máis información):</string>
<string name="device_menu_plugins">Configuración do engadido</string>
<string name="plugins_failed_to_load">Non se puideron cargar os seguintes complementos (toque para obter máis información):</string>
<string name="device_menu_plugins">Configuración do complemento</string>
<string name="device_menu_unpair">Desemparellarse</string>
<string name="device_not_reachable">O dispositivo emparellado está fóra do alcance.</string>
<string name="pair_new_device">Emparellar cun novo dispositivo</string>
@@ -54,11 +66,15 @@
<string name="error_not_reachable">Dispositivo fóra do alcance</string>
<string name="error_already_requested">Xa solicitou emparellarse.</string>
<string name="error_already_paired">O dispositivo xa está emparellado.</string>
<string name="error_could_not_send_package">Non foi posíbel enviar o paquete.</string>
<string name="error_could_not_send_package">Non se puido enviar o paquete.</string>
<string name="error_timed_out">Esgotouse o tempo límite</string>
<string name="error_canceled_by_user">Cancelouno o usuario.</string>
<string name="error_canceled_by_other_peer">Cancelouse remotamente</string>
<string name="error_invalid_key">Recibiuse unha clave incorrecta.</string>
<string name="encryption_info_title">Información do cifrado</string>
<string name="encryption_info_msg_no_ssl">O outro dispositivo non usa unha versión recente de KDE Connect, usarase un método obsoleto de cifrado.</string>
<string name="my_device_fingerprint">A pegada SHA1 do certificado do seu dispositivo é:</string>
<string name="remote_device_fingerprint">A pegada SHA1 do certificado do dispositivo remoto é:</string>
<string name="pair_requested">Solicitude de emparellamento</string>
<string name="pairing_request_from">Solicitude de emparellamento de %1s.</string>
<string name="received_url_title">Recibiuse unha ligazón de %1s</string>
@@ -66,12 +82,15 @@
<string name="incoming_file_title">Ficheiro entrande de %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Enviando un ficheiro a %1s</string>
<string name="outgoing_files_title">Enviando os ficheiros a %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Enviáronse %1$d de %2$d ficheiros.</string>
<string name="received_file_title">Recibiuse un ficheiro de %1s</string>
<string name="received_file_fail_title">Non foi posíbel recibir o ficheiro de %1s</string>
<string name="received_file_fail_title">A recepción do ficheiro de %1s fallou</string>
<string name="received_file_text">Toque para abrir «%1s».</string>
<string name="sent_file_title">Enviouse o ficheiro a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Non se puido enviar o ficheiro a %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Toque para contestar</string>
<string name="reconnect">Conectar de novo</string>
@@ -118,8 +137,12 @@
<string name="custom_device_list">Engadir dispositivos por IP</string>
<string name="share_notification_preference">Notificacións sonoras</string>
<string name="share_notification_preference_summary">Vibrar e reproducir un son ao recibir un ficheiro.</string>
<string name="share_destination_customize">Personalizar o directorio de destino</string>
<string name="share_destination_customize_summary_disabled">Os ficheiros recibidos aparecerán en «Descargas».</string>
<string name="share_destination_customize_summary_enabled">Os ficheiros almacenaranse no directorio de abaixo.</string>
<string name="share_destination_folder_preference">Directorio de destino</string>
<string name="title_activity_notification_filter">Filtro de notificacións</string>
<string name="filter_apps_info">As notificacións sincronizaranse para os seguintes programas.</string>
<string name="filter_apps_info">As notificacións sincronizaranse para os seguintes aplicativos.</string>
<string name="sftp_internal_storage">Almacenamento interno</string>
<string name="sftp_all_files">Todos os ficheiros</string>
<string name="sftp_sdcard_num">Tarxeta SD %d</string>
@@ -129,21 +152,35 @@
<string name="add_host">Engadir unha nome ou IP</string>
<string name="add_host_hint">Nome ou IP do servidor.</string>
<string name="no_players_connected">Non se atoparon reprodutores.</string>
<string name="custom_dev_list_help">Marque esta opción unicamente se o seu dispositivo non se detecta automaticamente. Escriba o enderezo IP ou o nome de servidor do dispositivo e toque o botón para engadilo á lista. Toque un elemento existente para retiralo da lista.</string>
<string name="custom_dev_list_help">Marque esta opción se o seu dispositivo non se detecta automaticamente. Insira o enderezo IP ou o nome de servidor do dispositivo e toque o botón para engadilo á lista. Toque un elemento existente para retiralo da lista.</string>
<string name="mpris_player_on_device">%1$s en %2$s</string>
<string name="send_files">Enviar ficheiros</string>
<string name="pairing_title">Dispositivos con KDE Connect</string>
<string name="pairing_description">Outros dispositivos que estean a executar KDE Connect na mesma rede deberían aparecer aquí.</string>
<string name="device_paired">Emparellouse co dispositivo</string>
<string name="device_rename_title">Cambiar o nome do dispositivo</string>
<string name="device_rename_confirm">Mudar o nome</string>
<string name="device_rename_title">Renomear o dispositivo</string>
<string name="device_rename_confirm">Renomear</string>
<string name="refresh">Actualizar</string>
<string name="unreachable_description">Este dispositivo emparellado está fóra do alcance. Asegúrese de que está conectado á mesma rede.</string>
<string name="on_data_message">Parece que está usando unha conexión de datos de móbil. KDE Connect só funciona en redes locais.</string>
<string name="no_file_browser">Non hai navegadores de ficheiros instalados.</string>
<string name="pref_plugin_telepathy">Enviar unha mensaxe de texto</string>
<string name="pref_plugin_telepathy_desc">Enviar mensaxes de texto desde un computador de escritorio.</string>
<string name="plugin_not_supported">O dispositivo non é compatíbel con este complemento.</string>
<string name="findmyphone_title">Atopar o móbil</string>
<string name="findmyphone_title_tablet">Atopar a tableta</string>
<string name="findmyphone_description">Reproduce un son de chamada no dispositivo para que poida atopalo.</string>
<string name="findmyphone_found">Atopado</string>
<string name="open">Abrir</string>
<string name="close">Pechar</string>
<string name="no_permissions_storage">Debe conceder permisos para acceder ao almacenamento.</string>
<string name="plugins_need_permission">Algúns complementos necesitan permisos para funcionar (toque para máis información):</string>
<string name="permission_explanation">Este complemento necesita permisos para funcionar.</string>
<string name="optional_permission_explanation">Ten que conceder permisos adicionais para activar todas as funcións.</string>
<string name="plugins_need_optional_permission">Algúns complementos teñen funcionalidades desactivadas por mor dunha falta de permisos (toque para máis información):</string>
<string name="sftp_permission_explanation">Para acceder aos seus ficheiros desde o computador o aplicativo necesita permiso para acceder ao almacenamento do teléfono.</string>
<string name="share_optional_permission_explanation">Para compartir ficheiros entre o teléfono e o escritorio ten que dar acceso ao almacenamento do teléfono.</string>
<string name="telepathy_permission_explanation">Para ler e escribir SMS desde o escritorio ten que dar permiso de SMS.</string>
<string name="telephony_permission_explanation">Para ver as chamadas de teléfono e os SMS desde o escritorio ten que dar permiso a chamadas de teléfono e a SMS.</string>
<string name="telephony_optional_permission_explanation">Para ver o nome dun contacto en vez dun número de teléfono ten que dar acceso aos contactos do teléfono.</string>
</resources>

View File

@@ -5,15 +5,23 @@
<string name="pref_plugin_battery">דיווח סוללה</string>
<string name="pref_plugin_battery_desc">מדווח על אחוז הסוללה למחשב</string>
<string name="pref_plugin_sftp">גישה לקבצים</string>
<string name="pref_plugin_clipboard">סנכנרון לוח העתקה</string>
<string name="pref_plugin_clipboard_desc">שתף בין המחשבים את מה שמועתק</string>
<string name="pref_plugin_sftp_desc">אפשר להתקן המרוחק לדפדף בקבצים של הפלאפון מרחוק</string>
<string name="pref_plugin_clipboard">סנכרון לוח העתקה</string>
<string name="pref_plugin_clipboard_desc">שתף בין המחשבים את כל מה שמועתק</string>
<string name="pref_plugin_mousepad">שליטה מרחוק</string>
<string name="pref_plugin_mousepad_desc">השתמש בפלאפון כדי לשלוט בעכבר ובמקלדת של ההתקן המרוחק</string>
<string name="pref_plugin_remotekeyboard">קבלת לחיצות מרחוק</string>
<string name="pref_plugin_remotekeyboard_desc">קבלת אירועי מקלדת מהתקן מרוחק</string>
<string name="pref_plugin_mpris">שליטה במדיה</string>
<string name="pref_plugin_mpris_desc">מספק שליטה מרוחקת על נגן המדיה שלך</string>
<string name="pref_plugin_runcommand">הרץ פקודה</string>
<string name="pref_plugin_runcommand_desc">הרץ פקודה במחשב מהמכשיר שלך</string>
<string name="pref_plugin_ping">פינג</string>
<string name="pref_plugin_ping_desc">שלח וקבל פינגים</string>
<string name="pref_plugin_notifications">סנכרון התראות</string>
<string name="pref_plugin_notifications_desc">הראה את ההתראות מהפלאפון בהתקן אחר</string>
<string name="pref_plugin_receive_notifications">קבלת התראות</string>
<string name="pref_plugin_receive_notifications_desc">קבל התראות מהתקן אחר והצג אותם במכשיר שלך</string>
<string name="pref_plugin_sharereceiver">שתף וקבל קבצים וכתובות</string>
<string name="pref_plugin_sharereceiver_desc">שתף וקבל קבצים וכתובת אינטרנט בין התקנים</string>
<string name="plugin_not_available">אפשרות זו אינה זמינה בגרסת האנדרואיד שלך</string>
@@ -24,8 +32,11 @@
<string name="no_permissions">אתה צריך לתת הרשאות לגישה להתראות</string>
<string name="send_ping">שלח פינג</string>
<string name="open_mpris_controls">שליטה על המדיה</string>
<string name="open_mousepad">שלוט על המחשב</string>
<string name="mousepad_info">הזז את האצבע על המסך כדי להזיז את סמן העכבר במחשב. לחץ כדי ללחוץ במחשב, השתמש בשנים או שלוש אצבעות כדי ללחוץ על המקש הימני או האמצעי. השתמש בליחצה ארוכה לגרירה ושחרור.</string>
<string name="remotekeyboard_editing_only_title">השתמש במקשים מרוחקים רק בעת עריכה</string>
<string name="remotekeyboard_not_connected">אין מקלדת מרוחקת מופעלת, הוסף אחת ל־kdeconnect</string>
<string name="remotekeyboard_connected">חיבור המקדלת המרוחקת פעיל</string>
<string name="remotekeyboard_multiple_connections">ישנם כמה מקלדות מרוחקות מחוברות, בחר את ההתקן להגדרה</string>
<string name="open_mousepad">שליטה מרחוק</string>
<string name="mousepad_double_tap_settings_title">הגדר פעולה ללחיצת שתי אצבעות</string>
<string name="mousepad_triple_tap_settings_title">הגדר פעולה ללחיצת שלוש אצבעות</string>
<string name="mousepad_sensitivity_settings_title">הגדר רגישות משטח המגע</string>
@@ -35,9 +46,6 @@
<item>לחיצה אצמעית (גלגלת)</item>
<item>שום דבר</item>
</string-array>
<string name="mousepad_double_default">ימין</string>
<string name="mousepad_triple_default">אמצע</string>
<string name="mousepad_sensitivity_default">ברירת מחדל</string>
<string-array name="mousepad_sensitivity_entries">
<item>הכי איטי</item>
<item>יותר מההכי איטי</item>
@@ -59,9 +67,9 @@
<string name="error_already_paired">ההתקן כבר מותאם</string>
<string name="error_could_not_send_package">לא יכול לשלוח חבילה</string>
<string name="error_timed_out">נגמר הזמן</string>
<string name="error_canceled_by_user">בוטל ע\"י המשתמש</string>
<string name="error_canceled_by_other_peer">בוטל ע\"י מישהו אחר</string>
<string name="error_invalid_key">התקבל מפתח לא חוקי</string>
<string name="error_canceled_by_user">בוטל על ידי המשתמש</string>
<string name="error_canceled_by_other_peer">בוטל על ידי מישהו אחר</string>
<string name="error_invalid_key">התקבל מפתח לא תקין</string>
<string name="encryption_info_title">פרטי הצפנה</string>
<string name="encryption_info_msg_no_ssl">ההתקן השני אינו משתמש בגרסה האחרונה של KDE Connect, משתמש בשיטת ההצפנה הישנה.</string>
<string name="my_device_fingerprint">טביעת האצבע SHA1 של ההתקן היא:</string>
@@ -69,16 +77,19 @@
<string name="pair_requested">בקשת התאמה</string>
<string name="pairing_request_from">בוקשה התאמה מ־%1s</string>
<string name="received_url_title">התקבל קישור מ־%1s</string>
<string name="received_url_text">לחץ כדי לפתוח את \'%1s\'</string>
<string name="incoming_file_title">התקבל קובץ ־%1s</string>
<string name="received_url_text">לחץ כדי לפתוח את \"%1s\"</string>
<string name="incoming_file_title">התקבל קובץ מאת %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">שולח קובץ ל־%1s</string>
<string name="outgoing_file_title">שולח קובץ אל %1s</string>
<string name="outgoing_files_title">שולח קובצים אל %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="received_file_title">התקבל קובץ מ־%1s</string>
<string name="received_file_fail_title">נכשל בקבלת קובץ מ־%1s</string>
<string name="received_file_text">לחץ כדי לפתוח את %1s</string>
<string name="sent_file_title">הקובץ נשלח ל־%1s</string>
<string name="outgoing_files_text">"שולח %1$d מתוך %2$d קבצים "</string>
<string name="received_file_title">התקבל קובץ מאת %1s</string>
<string name="received_file_fail_title">נכשל בקבלת קובץ מאת %1s</string>
<string name="received_file_text">לחץ כדי לפתוח את \"%1s\"</string>
<string name="sent_file_title">הקובץ נשלח אל %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">נכשל בשליחת הקובץ אל %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">לחץ כדי לענות</string>
<string name="reconnect">התחבר מחדש</string>
@@ -109,22 +120,26 @@
<item>דקה</item>
<item>שתי דקות</item>
</string-array>
<string name="share_to">שתף ל...</string>
<string name="share_to">שתף אל...</string>
<string name="protocol_version_older">ההתקן משתמש בגרסה ישנה יותר</string>
<string name="protocol_version_newer">ההתקן משתמש בגרסה חדשה יותר</string>
<string name="general_settings">הגדרות כלליות</string>
<string name="plugin_settings">הגדרות</string>
<string name="plugin_settings_with_name">הגדרות %s</string>
<string name="device_name">שם המכשיר</string>
<string name="device_name">שם ההתקן</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">שם המכשיר לא תקין</string>
<string name="invalid_device_name">שם ההתקן לא תקין</string>
<string name="shareplugin_text_saved">התקבל טקסט, נשמר ללוח העתקה</string>
<string name="custom_devices_settings">רשימת התקנים מותאמת אישית</string>
<string name="pair_device_action">התאם התקן חדש</string>
<string name="unpair_device_action">בטל את ההתאמה עם %s</string>
<string name="custom_device_list">הוסף התקן ע\"י כתובת IP</string>
<string name="custom_device_list">הוסף התקן על ידי כתובת IP</string>
<string name="share_notification_preference">התראות רועשות</string>
<string name="share_notification_preference_summary">רטוט ונגן צליל בעת קבלת קובץ</string>
<string name="share_destination_customize">שנה תקיית יעד</string>
<string name="share_destination_customize_summary_disabled">קבצים שהתקבלו יהיו בהורדות</string>
<string name="share_destination_customize_summary_enabled">קבצים יאוכסנו בתיקיה למטה</string>
<string name="share_destination_folder_preference">תיקית יעד</string>
<string name="title_activity_notification_filter">סנן התראות</string>
<string name="filter_apps_info">התראות יסונכרנו רק לאפליקציות נבחרות</string>
<string name="sftp_internal_storage">זיכרון פנימי</string>
@@ -133,11 +148,11 @@
<string name="sftp_sdcard">כרטיס זיכרון</string>
<string name="sftp_readonly">(לקריאה בלבד)</string>
<string name="sftp_camera">תמונות מצלמה</string>
<string name="add_host">הוסף כתובת שרת או IP</string>
<string name="add_host_hint">כתבות שרת או IP</string>
<string name="add_host">הוסף כתובת או IP</string>
<string name="add_host_hint">כתובת או IP</string>
<string name="no_players_connected">לא נמצא נגן</string>
<string name="custom_dev_list_help">השתמש באפשרות זו רק אם המכשיר שלך לא מזוהה באופן אוטומטי. הקלד את כתובת הIP או את כינוי ההתקן למטה ולחץ על הכפתור כדי להוסיף לרשימה. לחץ על פריט קיים כדי להסיר אותו מהרשימה.</string>
<string name="mpris_player_on_device">%1$s ב־%2$s</string>
<string name="mpris_player_on_device">%1$s אצל %2$s</string>
<string name="send_files">שלח קובץ</string>
<string name="pairing_title">מכשירי KDE Connect</string>
<string name="pairing_description">התקנים אחרים המריצים KDE Connect ברשת הנוכחית צריכים להופיע פה.</string>
@@ -145,12 +160,15 @@
<string name="device_rename_title">שנה שם התקן</string>
<string name="device_rename_confirm">שנה שם</string>
<string name="refresh">רענן</string>
<string name="unreachable_description">ההתקן המתואם לא זמין, וודא שהוא מחובר לאותה רשת אליה התקן זה מחובר.</string>
<string name="unreachable_description">ההתקן המתואם לא זמין, וודא שהוא מחובר לאותה רשת אליה אתה מחובר.</string>
<string name="on_data_message">נראה שאתה מחובר דרך הרשת הסלולרית. KDE Connect עובד רק עם רשתות מקומיות.</string>
<string name="no_file_browser">לא נמצאו מנהלי קבצים מותקנים במכשיר זה.</string>
<string name="pref_plugin_telepathy">שלח SMS</string>
<string name="pref_plugin_telepathy">שליחת הודעת SMS</string>
<string name="pref_plugin_telepathy_desc">שלח הודעות מהמחשב שלך</string>
<string name="plugin_not_supported">התוסף הזה לא נתמך ע\"י המכשיר שלך</string>
<string name="findmyphone_title">מצא את המכשיר שלי</string>
<string name="plugin_not_supported">תוסף הזה לא נתמך על ידי המכשיר שלך</string>
<string name="findmyphone_title">מצא את הפלאפון שלי</string>
<string name="findmyphone_title_tablet">מצא את הטבלט שלי</string>
<string name="findmyphone_description">מפעיל רעש במכשיר כדי שתוכל למצוא אותו.</string>
<string name="findmyphone_found">נמצא</string>
<string name="open">פתח</string>
<string name="close">סגור</string>

View File

@@ -37,7 +37,7 @@
<string name="remotekeyboard_connected">La connessione della tastiera remota è attiva</string>
<string name="remotekeyboard_multiple_connections">Ci sono più connessioni di tastiere remote, seleziona il dispositivo da configurare</string>
<string name="open_mousepad">Impulso remoto</string>
<string name="mousepad_info">Muovi un dito sullo schermo per spostare il puntatore del mouse. Tocca per un clic e usa due/tre dita per i pulsanti destro e centrale. Utilizza una pressione lunga per trascinare e rilasciare.</string>
<string name="mousepad_info">Muovi un dito sullo schermo per spostare il puntatore del mouse. Tocca per un clic e usa due/tre dita per i pulsanti destro e centrale. Utilizza 2 dita per scorrere. Utilizza una pressione lunga per trascinare e rilasciare.</string>
<string name="mousepad_double_tap_settings_title">Imposta azione per il tocco a due dita</string>
<string name="mousepad_triple_tap_settings_title">Imposta azione per il tocco a tre dita</string>
<string name="mousepad_sensitivity_settings_title">Imposta la sensibilità del touchpad</string>
@@ -47,9 +47,6 @@
<item>Clic centrale</item>
<item>Niente</item>
</string-array>
<string name="mousepad_double_default">destra</string>
<string name="mousepad_triple_default">centro</string>
<string name="mousepad_sensitivity_default">predefinita</string>
<string-array name="mousepad_sensitivity_entries">
<item>Minima</item>
<item>Più veloce</item>
@@ -165,6 +162,7 @@
<string name="device_rename_confirm">Rinomina</string>
<string name="refresh">Aggiorna</string>
<string name="unreachable_description">Questo dispositivo associato non è raggiungibile. Assicurati che sia connesso alla tua stessa rete.</string>
<string name="on_data_message">Sembra che tu stia utilizzando una connessione dati mobile. KDE Connect funziona solo su reti locali.</string>
<string name="no_file_browser">Non ci sono navigatori di file installati.</string>
<string name="pref_plugin_telepathy">Invia SMS</string>
<string name="pref_plugin_telepathy_desc">Invia messaggi di testo dal tuo desktop</string>
@@ -175,4 +173,14 @@
<string name="findmyphone_found">Trovato</string>
<string name="open">Apri</string>
<string name="close">Chiudi</string>
<string name="no_permissions_storage">Devi concedere i permessi per l\'accesso all\'archiviazione</string>
<string name="plugins_need_permission">Alcune estensioni hanno bisogno di permessi per funzionare (tocca per maggiori informazioni):</string>
<string name="permission_explanation">Questa estensione ha bisogno di permessi per funzionare</string>
<string name="optional_permission_explanation">Devi concedere permessi aggiuntivi per abilitare tutte le funzioni</string>
<string name="plugins_need_optional_permission">Alcune estensioni hanno funzioni disabilitate per una mancanza di permessi (tocca per maggiori informazioni):</string>
<string name="sftp_permission_explanation">Per accedere ai tuoi file dal tuo PC, l\'applicazione ha bisogno dell\'autorizzazione di accesso alla memoria del telefono</string>
<string name="share_optional_permission_explanation">Per condividere i file tra il telefono e il tuo desktop devi dare accesso alla memoria del telefono</string>
<string name="telepathy_permission_explanation">Per leggere e scrivere SMS dal tuo desktop, devi concedere l\'autorizzazione per SMS</string>
<string name="telephony_permission_explanation">Per vedere le chiamate telefoniche e gli SMS dal desktop devi dare l\'autorizzazione per telefonate e SMS</string>
<string name="telephony_optional_permission_explanation">Per vedere il nome di un contatto invece del numero di telefono devi dare accesso alla rubrica del telefono</string>
</resources>

View File

@@ -31,7 +31,6 @@
<string name="send_ping">핑 보내기</string>
<string name="open_mpris_controls">멀티미디어 제어</string>
<string name="open_mousepad">원격 입력</string>
<string name="mousepad_info">화면에서 손가락을 움직이면 마우스 커서를 움직입니다. 화면을 누르면 왼쪽 단추를 누르고, 두 손가락과 세 손가락으로 누르면 오른쪽/가운데 단추를 누릅니다. 드래그 앤 드롭을 사용하려면 길게 누르십시오.</string>
<string name="mousepad_double_tap_settings_title">두 손가락으로 눌렀을 때 동작 설정</string>
<string name="mousepad_triple_tap_settings_title">세 손가락으로 눌렀을 때 동작 설정</string>
<string name="mousepad_sensitivity_settings_title">터치패드 감도 설정</string>
@@ -41,9 +40,6 @@
<item>가운데 단추 누름</item>
<item>아무것도 안 함</item>
</string-array>
<string name="mousepad_double_default">오른쪽</string>
<string name="mousepad_triple_default">가운데</string>
<string name="mousepad_sensitivity_default">기본값</string>
<string-array name="mousepad_sensitivity_entries">
<item>느리게</item>
<item>느리게 이상</item>

View File

@@ -41,14 +41,11 @@
<string name="error_already_requested">Jau paprašyta suporuoti</string>
<string name="error_already_paired">Įrenginys jau suporuotas</string>
<string name="error_could_not_send_package">Nepavyksta išsiųsti paketo</string>
<string name="error_timed_out">Skirtasis laikas baigėsi</string>
<string name="error_canceled_by_user">Naudotojas atšaukė užduotį</string>
<string name="error_canceled_by_other_peer">Porininkas atšaukė užduotį</string>
<string name="error_invalid_key">Gautas netinkamas raktas</string>
<string name="pair_requested">Paprašyta suporuoti</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Norėdami atsakyti, palieskite</string>
<string name="reconnect">Prisijungti iš naujo</string>
<string name="show_keyboard">Rodyti klaviatūrą</string>
@@ -86,7 +83,6 @@
<string name="pair_device_action">Suporuoti naują įrenginį</string>
<string name="unpair_device_action">Atrišti %s</string>
<string name="custom_device_list">Pridėti įrenginį pagal IP</string>
<string name="sftp_internal_storage">Vidinė saugykla</string>
<string name="sftp_all_files">Visi failai</string>
<string name="sftp_sdcard_num">SD kortelė %d</string>
<string name="sftp_sdcard">SD kortelė</string>
@@ -100,9 +96,12 @@
<string name="pairing_description">Čia turėtų pasirodyti to kiti paties tinklo įrenginiai, kuriuose veikia „KDE Connect“</string>
<string name="device_paired">Įrenginys suporuotas</string>
<string name="device_rename_title">Pervadinti įrenginį</string>
<string name="device_rename_confirm">Pervadinti</string>
<string name="refresh">Atnaujinti</string>
<string name="unreachable_description">Šis suporuotas įrenginys nepasiekiamas. Patikrinkite, ar jis prisijungęs prie to paties tinklo.</string>
<string name="pref_plugin_telepathy">Siųsti SMS</string>
<string name="plugin_not_supported">Telefonas nepalaiko šio papildinio</string>
<string name="findmyphone_found">Radau</string>
<string name="open">Atverti</string>
<string name="close">Užverti</string>
</resources>

View File

@@ -37,7 +37,7 @@
<string name="remotekeyboard_connected">Verbinding met toetsenbord op afstand is actief</string>
<string name="remotekeyboard_multiple_connections">Er is meer dan een verbinding met een toetsenbord op afstand, selecteer het te configureren apparaat</string>
<string name="open_mousepad">Invoer op afstand</string>
<string name="mousepad_info">Veeg met een vinger op het scherm om de muiscursor te verplaatsen. Tik om te klikken en gebruik twee/drie vingers voor rechter en middelste knop. Druk lang voor slepen en loslaten.</string>
<string name="mousepad_info">Veeg met een vinger op het scherm om de muiscursor te verplaatsen. Tik om te klikken en gebruik twee/drie vingers voor rechter en middelste knop. Twee vingers gebruiken voor schuiven. Druk lang voor slepen en loslaten.</string>
<string name="mousepad_double_tap_settings_title">Tikactie met twee vingers instellen</string>
<string name="mousepad_triple_tap_settings_title">Tikactie met drie vingers instellen</string>
<string name="mousepad_sensitivity_settings_title">Gevoeligheid van touchpad instellen</string>
@@ -47,9 +47,6 @@
<item>Middelste muisklik</item>
<item>Niets</item>
</string-array>
<string name="mousepad_double_default">rechts</string>
<string name="mousepad_triple_default">midden</string>
<string name="mousepad_sensitivity_default">standaard</string>
<string-array name="mousepad_sensitivity_entries">
<item>Langzaamst</item>
<item>Langzaam</item>
@@ -67,7 +64,7 @@
<string name="pair_new_device">Nieuw apparaat paren</string>
<string name="unknown_device">Onbekend apparaat</string>
<string name="error_not_reachable">Apparaat niet bereikbaar</string>
<string name="error_already_requested">Paar maken is al gevraagd</string>
<string name="error_already_requested">Paarvorming is al gevraagd</string>
<string name="error_already_paired">Apparaat is al gepaard</string>
<string name="error_could_not_send_package">Kon pakket niet verzenden</string>
<string name="error_timed_out">Tijdslimiet overschreden</string>
@@ -78,22 +75,22 @@
<string name="encryption_info_msg_no_ssl">Het andere apparaat gebruikt geen recente versie van KDE Connect, de verouderde versleutelingsmethode zal worden gebruikt.</string>
<string name="my_device_fingerprint">De SHA1 vingerafdruk van het certificaat van uw apparaat is:</string>
<string name="remote_device_fingerprint">De SHA1 vingerafdruk van het certificaat van het apparaat op afstand is:</string>
<string name="pair_requested">Paar gevraagd</string>
<string name="pair_requested">Paarvorming gevraagd</string>
<string name="pairing_request_from">Verzoek om een paar te maken van %1s</string>
<string name="received_url_title">Ontvangen koppeling van %1s</string>
<string name="received_url_text">Tap om \'%1s\' te openen</string>
<string name="incoming_file_title">Inkomend bestand van %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Bezig bestand te verzenden naar %1s</string>
<string name="outgoing_files_title">Bestanden verzenden naar %1s</string>
<string name="outgoing_files_title">Bezig bestanden te verzenden naar %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Verzonden %1$d van %2$d bestanden</string>
<string name="outgoing_files_text">Verzonden %1$d uit %2$d bestanden</string>
<string name="received_file_title">Bestand ontvangen van %1s</string>
<string name="received_file_fail_title">Bestand ontvangen van %1s is mislukt</string>
<string name="received_file_text">Tap om \'%1s\' te openen</string>
<string name="sent_file_title">Bestand verzonden naar %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Verzenden van bestanden naar %1s is mislukt</string>
<string name="sent_file_failed_title">Verzenden van bestand naar %1s is mislukt</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tap om te antwoorden</string>
<string name="reconnect">Opnieuw verbinden</string>
@@ -140,7 +137,7 @@
<string name="custom_device_list">Voeg apparaten toe per IP-adres</string>
<string name="share_notification_preference">Luidruchtige meldingen</string>
<string name="share_notification_preference_summary">Vibreer en speel een geluidje bij ontvangen van een bestand</string>
<string name="share_destination_customize">Pas bestemmingsmap aan</string>
<string name="share_destination_customize">De bestemmingsmap aanpassen</string>
<string name="share_destination_customize_summary_disabled">Ontvangen bestanden zullen in Downloads verschijnen</string>
<string name="share_destination_customize_summary_enabled">Bestanden zullen opgeslagen worden in de onderstaande map</string>
<string name="share_destination_folder_preference">Bestemmingsmap</string>
@@ -165,6 +162,7 @@
<string name="device_rename_confirm">Hernoemen</string>
<string name="refresh">Verversen</string>
<string name="unreachable_description">Dit gepaarde apparaat is niet bereikbaar. Ga na dat het is verbonden met uw zelfde netwerk.</string>
<string name="on_data_message">Het lijkt of op een mobiele gegevensverbinding zit. KDE Connect werkt alleen op locale netwerken.</string>
<string name="no_file_browser">Er zijn geen bestandsbrowsers geïnstalleerd.</string>
<string name="pref_plugin_telepathy">SMS verzenden</string>
<string name="pref_plugin_telepathy_desc">Stuur tekstberichten van uw bureaublad</string>
@@ -175,4 +173,14 @@
<string name="findmyphone_found">Gevonden</string>
<string name="open">Openen</string>
<string name="close">Sluiten</string>
<string name="no_permissions_storage">U moet toestemming geven voor toegang tot de opslag</string>
<string name="plugins_need_permission">Sommige plug-ins hebben toestemming nodig om te werken (tik voor meer informatie):</string>
<string name="permission_explanation">Deze plug-in heeft toestemming nodig om te werken</string>
<string name="optional_permission_explanation">U moet toestemming geven om alle functies in te schakelen</string>
<string name="plugins_need_optional_permission">Sommige plug-ins hebben functies uitgeschakeld vanwege ontbrekende toestemming (tik voor meer informatie):</string>
<string name="sftp_permission_explanation">"Om toegang tot uw bestanden te krijgen vanuit uw PC heeft de app toestemming nodig voor toegang tot de opslag van uw telefoon "</string>
<string name="share_optional_permission_explanation">Om bestanden tussen uw telefoon en uw bureaublad te delen moet u toegang geven tot de opslag van uw telefoon</string>
<string name="telepathy_permission_explanation">Om een SMS te lezen of te schrijven vanaf uw bureaublad moet u toestemming geven tot SMS</string>
<string name="telephony_permission_explanation">Om telefoonoproepen en SMS te zien vanaf het bureaublad moet u toestemming geven tot telefoonoproepen en SMS</string>
<string name="telephony_optional_permission_explanation">Om een naam van een contactpersoon te zien in plaats van een telefoonnummer moet u toegang geven tot de contacten in uw telefoon</string>
</resources>

View File

@@ -9,13 +9,15 @@
<string name="pref_plugin_clipboard">Synkroniser utklippstavle</string>
<string name="pref_plugin_clipboard_desc">Del innhaldet på utklippstavla</string>
<string name="pref_plugin_mousepad">Fjernstyring</string>
<string name="pref_plugin_mousepad_desc">Bruk telefonen eller nettbrettet som styrepute og tastatur</string>
<string name="pref_plugin_mousepad_desc">Bruk telefonen eller nettbrettet som styreplate og tastatur</string>
<string name="pref_plugin_remotekeyboard">Ta imot eksterne tastetrykk</string>
<string name="pref_plugin_remotekeyboard_desc">Ta imot tastetrykk frå eksterne einingar</string>
<string name="pref_plugin_mpris">Mediekontrollar</string>
<string name="pref_plugin_mpris_desc">Gjev fjernkontroll til mediespelarar</string>
<string name="pref_plugin_mpris_desc">Gje fjernkontroll til mediespelarar</string>
<string name="pref_plugin_runcommand">Køyr kommando</string>
<string name="pref_plugin_runcommand_desc">Utløys fjernkommandoar frå telefonen eller nettbrettet</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Send og ta imot ping-signal</string>
<string name="pref_plugin_ping_desc">Send og ta imot pingsignal</string>
<string name="pref_plugin_notifications">Varslingssynkronisering</string>
<string name="pref_plugin_notifications_desc">Få tilgang til varslingar frå andre einingar</string>
<string name="pref_plugin_receive_notifications">Få varslingar</string>
@@ -30,20 +32,21 @@
<string name="no_permissions">Du må gje tilgang til lesing av varslingar</string>
<string name="send_ping">Send pingsignal</string>
<string name="open_mpris_controls">Mediekontroll</string>
<string name="remotekeyboard_editing_only_title">Handter eksterne tastetrykk berre ved redigering</string>
<string name="remotekeyboard_not_connected">Det finst ikkje noko verksamt tastatursamband (må setjast opp i KDE Connect)</string>
<string name="remotekeyboard_connected">Eksternt tastatursamband er verksamt</string>
<string name="remotekeyboard_multiple_connections">Det finst meir enn eitt eksternt tastatursamband (vel eining å setja opp)</string>
<string name="open_mousepad">Fjernstyring</string>
<string name="mousepad_info">Dra ein finger over skjermen for å flytta peikaren på datamaskina. Trykk for å klikka, og bruk to eller tre fingrar for høvesvis høgre- og midtknappen. Trykk og hald for å dra og sleppa.</string>
<string name="mousepad_info">Dra ein finger over skjermen for å flytta peikaren på datamaskina. Trykk for å klikka, og bruk to eller tre fingrar for høvesvis høgre- og midtknappen. Bruk to fingrar for å rulla. Trykk lenge for å dra og sleppa.</string>
<string name="mousepad_double_tap_settings_title">Vel handling for tofingertrykk</string>
<string name="mousepad_triple_tap_settings_title">Vel handling for trefingertrykk</string>
<string name="mousepad_sensitivity_settings_title">Vel følsemd for styrepute</string>
<string name="mousepad_sensitivity_settings_title">Vel følsemd for styreplate</string>
<string name="mousepad_scroll_direction_title">Omvend rulleretning</string>
<string-array name="mousepad_tap_entries">
<item>Høgreklikk</item>
<item>Midtklikk</item>
<item>Ingenting</item>
</string-array>
<string name="mousepad_double_default">høgre</string>
<string name="mousepad_triple_default">midt</string>
<string name="mousepad_sensitivity_default">standard</string>
<string-array name="mousepad_sensitivity_entries">
<item>Saktast</item>
<item>Raskare enn saktast</item>
@@ -55,7 +58,7 @@
<string name="category_not_paired_devices">Tilgjengelege einingar</string>
<string name="category_remembered_devices">Hugs einingar</string>
<string name="plugins_failed_to_load">Klarte ikkje lasta programtillegg (trykk for meir informasjon):</string>
<string name="device_menu_plugins">Innstillingar for programtillegg</string>
<string name="device_menu_plugins">Programtillegg-oppsett</string>
<string name="device_menu_unpair">Løys paring</string>
<string name="device_not_reachable">Får ikkje kontakt med para eining</string>
<string name="pair_new_device">Par ny eining</string>
@@ -70,8 +73,8 @@
<string name="error_invalid_key">Fekk ugyldig nøkkel</string>
<string name="encryption_info_title">Krypteringsinfo</string>
<string name="encryption_info_msg_no_ssl">Den andre eininga brukar ein gammal versjon av KDE Connect, med ein utdatert krypteringsmetode.</string>
<string name="my_device_fingerprint">SHA-fingeravtrykk av einingssertifikatet er:</string>
<string name="remote_device_fingerprint">SHA-fingeravtrykk av fjerneiningssertifikatet er:</string>
<string name="my_device_fingerprint">SHA-fingeravtrykket til einingssertifikatet er:</string>
<string name="remote_device_fingerprint">SHA-fingeravtrykket fjerneiningssertifikatet er:</string>
<string name="pair_requested">Paringsførespurnad</string>
<string name="pairing_request_from">Paringsførespurnad frå %1s</string>
<string name="received_url_title">Fekk lenkje frå %1s</string>
@@ -79,12 +82,15 @@
<string name="incoming_file_title">Får fil frå %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Sender fil til %1s</string>
<string name="outgoing_files_title">Sender filer til %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Sende %1$d av %2$d filer</string>
<string name="received_file_title">Fekk fil frå %1s</string>
<string name="received_file_fail_title">Klarte ikkje ta imot fil frå %1s</string>
<string name="received_file_text">Trykk for å opna «%1s»</string>
<string name="sent_file_title">Send fil til %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Klarte ikkje senda fil til %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Trykk for å svara</string>
<string name="reconnect">Kopla til på nytt</string>
@@ -107,7 +113,7 @@
<string name="mpris_volume">Lydstyrke</string>
<string name="mpris_settings">Medieinnstillingar</string>
<string name="mpris_time_settings_title">Spoleknappar</string>
<string name="mpris_time_settings_summary">Juster tida for spoling ved trykking.</string>
<string name="mpris_time_settings_summary">Juster tida for spoling ved trykking</string>
<string-array name="mpris_time_entries">
<item>10 sekund</item>
<item>20 sekund</item>
@@ -131,6 +137,10 @@
<string name="custom_device_list">Legg til eining basert på IP</string>
<string name="share_notification_preference">Lydvarsling</string>
<string name="share_notification_preference_summary">Vibrer og spel ein lyd ved mottak av fil</string>
<string name="share_destination_customize">Sjølvvald målmappe</string>
<string name="share_destination_customize_summary_disabled">Mottekne filer vert lagra i nedlastingsmappa</string>
<string name="share_destination_customize_summary_enabled">Mottekne filer vert lagra i mappa nedanfor</string>
<string name="share_destination_folder_preference">Målmappe</string>
<string name="title_activity_notification_filter">Varslingsfilter</string>
<string name="filter_apps_info">Varslingar vert synkroniserte for dei valde appane.</string>
<string name="sftp_internal_storage">Intern lagring</string>
@@ -152,14 +162,25 @@
<string name="device_rename_confirm">Endra namn</string>
<string name="refresh">Oppdater</string>
<string name="unreachable_description">Får ikkje kontakt med den para eininga. Sjå til at ho er kopla til same nettverk.</string>
<string name="on_data_message">Det ser ut til at er kopla til eit mobilt samband. KDE Connect verkar berre på lokale nettverk.</string>
<string name="no_file_browser">Ingen filhandsamarar er installerte.</string>
<string name="pref_plugin_telepathy">Send SMS</string>
<string name="pref_plugin_telepathy_desc">Send tekstmeldingar frå datamaskina</string>
<string name="plugin_not_supported">Dette tillegget er ikkje støtta av eininga</string>
<string name="findmyphone_title">Finn telefonen min</string>
<string name="findmyphone_title_tablet">Finn nettbrettet mitt</string>
<string name="findmyphone_description">Ring til eininga, slik at du kan finna ho</string>
<string name="findmyphone_description">Spel av lydsignal på eininga, slik at du lett kan finna ho</string>
<string name="findmyphone_found">Fann</string>
<string name="open">Opna</string>
<string name="close">Lukk</string>
<string name="no_permissions_storage">Du må gje KDE Connect løyve til å få tilgang til lagringsområdet</string>
<string name="plugins_need_permission">Nokre av tillegga treng utvida løyva for å fungera (trykk på dei for meir informasjon):</string>
<string name="permission_explanation">Dette tillegget treng utvida løyve for å fungera</string>
<string name="optional_permission_explanation">Du må gje utvida løyve for at alle funksjonane skal fungera</string>
<string name="plugins_need_optional_permission">På grunn av manglande løyve har nokre av tillegga funksjonar slåtte av (trykk på dei for meir informasjon):</string>
<string name="sftp_permission_explanation">For å gje tilgang til filene frå datamaskina treng appen leseløyve til lagringsområdet på telefonen</string>
<string name="share_optional_permission_explanation">For å kunna dela filer mellom telefonen og datamaskina må du gje appen lese- og skriveløyve til lagringsområdet på telefonen</string>
<string name="telepathy_permission_explanation">For å kunna lesa og skriva tekstmeldingar frå datamaskina må du gje appen tilgang til SMS</string>
<string name="telephony_permission_explanation">For å kunna sjå telefonsamtalar og tekstmeldingar frå datamaskina må du gje appen tilgang til telefon- og SMS-funksjonar</string>
<string name="telephony_optional_permission_explanation">For å kunna sjå namn på kontaktar i staden for berre telefonnummeret må du gje appen tilgang til kontaktlista di</string>
</resources>

View File

@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">Udostępnij zawartość schowka</string>
<string name="pref_plugin_mousepad">Zdalne sterowanie</string>
<string name="pref_plugin_mousepad_desc">Użyj swojego telefonu lub tabletu jako myszy i klawiatury</string>
<string name="pref_plugin_remotekeyboard">Odbieraj zdalne naciśnięcia klawiszy</string>
<string name="pref_plugin_remotekeyboard_desc">Odbieraj naciśnięcia klawiszy od urządzeń zdalnych</string>
<string name="pref_plugin_mpris">Sterowanie multimediami</string>
<string name="pref_plugin_mpris_desc">Zapewnia zdalne sterowanie twoim odtwarzaczem multimedialnym</string>
<string name="pref_plugin_runcommand">Wykonaj polecenie</string>
@@ -30,8 +32,12 @@
<string name="no_permissions">Musisz przydzielić uprawnienia, aby uzyskać dostęp do powiadomień</string>
<string name="send_ping">Wyślij ping</string>
<string name="open_mpris_controls">Sterowanie multimediami</string>
<string name="remotekeyboard_editing_only_title">Obsługuj zdalne naciśnięcia klawiszy tylko podczas edycji</string>
<string name="remotekeyboard_not_connected">Nie istnieje połączenie zdalnej klawiatury, nawiąż takie połączenie w kdeconnect</string>
<string name="remotekeyboard_connected">Połączenie zdalnej klawiatury jest nawiązane</string>
<string name="remotekeyboard_multiple_connections">Nawiązano więcej niż jedno połączenie zdalnej klawiatury, wybierz urządzenie do ustawienia</string>
<string name="open_mousepad">Zdalne sterowanie</string>
<string name="mousepad_info">Przesuń palcem po ekranie, aby przesunąć wskaźnik myszy. Stuknij, aby wywołać naciśniecie lewym przyciskiem myszy i użyj dwóch/trzech palców, aby wywołać naciśniecie prawym i środkowym przyciskiem myszy. Przyciśnij na dłużej, aby przeciągnąć i upuścić.</string>
<string name="mousepad_info">Przesuń palcem po ekranie, aby przesunąć wskaźnik myszy. Stuknij, aby wywołać naciśniecie lewym przyciskiem myszy i użyj dwóch/trzech palców, aby wywołać naciśniecie prawym i środkowym przyciskiem myszy. Przewijaj przy użyciu dwóch palców. Przyciśnij na dłużej, aby przeciągnąć i upuścić.</string>
<string name="mousepad_double_tap_settings_title">Ustaw działanie po dwukrotnym stuknięciu palcem</string>
<string name="mousepad_triple_tap_settings_title">Ustaw działanie po trzykrotnym stuknięciu palcem</string>
<string name="mousepad_sensitivity_settings_title">Ustaw czułość gładzika</string>
@@ -41,9 +47,6 @@
<item>Kliknięcie środkowym</item>
<item>Nic</item>
</string-array>
<string name="mousepad_double_default">prawo</string>
<string name="mousepad_triple_default">środek</string>
<string name="mousepad_sensitivity_default">domyślne</string>
<string-array name="mousepad_sensitivity_entries">
<item>Najmniejsza</item>
<item>Ponad najmniejszą</item>
@@ -170,4 +173,14 @@
<string name="findmyphone_found">Znaleziony</string>
<string name="open">Otwórz</string>
<string name="close">Zamknij</string>
<string name="no_permissions_storage">Musisz nadać uprawnienia, aby uzyskać dostęp do pamięci masowej</string>
<string name="plugins_need_permission">Niektóre z wtyczek wymagają uprawnień do działania (stuknij po więcej informacji)</string>
<string name="permission_explanation">Ta wtyczka wymaga uprawnień do działania</string>
<string name="optional_permission_explanation">Musisz przydzielić dodatkowe uprawnienia, aby włączyć wszystkie funkcje</string>
<string name="plugins_need_optional_permission">Niektóre z wtyczek mają ograniczone możliwości ze względu na ograniczone uprawnienia (stuknij po więcej informacji)</string>
<string name="sftp_permission_explanation">Aby uzyskać dostęp do plików z twojego PC aplikacja ta potrzebuje uprawnień do dostępu do pamięci twojego telefonu</string>
<string name="share_optional_permission_explanation">Aby udostępniać pliki z twojego telefonu na twoim komputerze musisz pozowolić na dostęp do pamięci telefonu</string>
<string name="telepathy_permission_explanation">Aby odczytywać i pisać SMSy z twojego komputera musisz nadać uprawnienia do SMSów</string>
<string name="telephony_permission_explanation">Aby widzieć rozmowy telefoniczne i SMSy z twojego komputera musisz nadać uprawnienia na rozmowy telefoniczne i SMSy</string>
<string name="telephony_optional_permission_explanation">Aby widzieć nazwę kontaktu zamiast numeru telefonu musisz pozwolić na dostęp do kontaktów telefonu</string>
</resources>

View File

@@ -29,7 +29,6 @@
<string name="send_ping">Enviar ping</string>
<string name="open_mpris_controls">Controle multimídia</string>
<string name="open_mousepad">Introdução de dados remota</string>
<string name="mousepad_info">Mova um dedo pela tela para mover o ponteiro do mouse. Dê um toque para clicar e use dois/três dedos para os botões da direita e do meio. Use uma pressão longa para arrastar e soltar.</string>
<string name="mousepad_double_tap_settings_title">Definir a ação do toque com dois dedos</string>
<string name="mousepad_triple_tap_settings_title">Definir a ação do toque com três dedos</string>
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do touchpad</string>
@@ -39,9 +38,6 @@
<item>Botão do meio</item>
<item>Nada</item>
</string-array>
<string name="mousepad_double_default">direita</string>
<string name="mousepad_triple_default">meio</string>
<string name="mousepad_sensitivity_default">padrão</string>
<string-array name="mousepad_sensitivity_entries">
<item>Mais lento</item>
<item>Ainda mais lento</item>

View File

@@ -47,9 +47,6 @@
<item>Botão do meio</item>
<item>Nada</item>
</string-array>
<string name="mousepad_double_default">direita</string>
<string name="mousepad_triple_default">meio</string>
<string name="mousepad_sensitivity_default">predefinição</string>
<string-array name="mousepad_sensitivity_entries">
<item>Mais Lento</item>
<item>Ainda Mais Lento</item>
@@ -176,4 +173,14 @@
<string name="findmyphone_found">Encontrado</string>
<string name="open">Abrir</string>
<string name="close">Fechar</string>
<string name="no_permissions_storage">Precisa de dar permissões de acesso ao armazenamento</string>
<string name="plugins_need_permission">Alguns \'plugins\' precisam de permissões para funcionar (toque para mais informações):</string>
<string name="permission_explanation">Este \'plugin\' precisa de permissões para funcionar</string>
<string name="optional_permission_explanation">Precisa de dar permissões extra para activar todas as funcionalidades</string>
<string name="plugins_need_optional_permission">Alguns \'plugins\' têm funcionalidades desactivadas devido à falta de permissões (toque para obter mais informações):</string>
<string name="sftp_permission_explanation">Para aceder aos seus ficheiros a partir do seu PC, a aplicação precisa de permissão para aceder ao armazenamento do seu telemóvel</string>
<string name="share_optional_permission_explanation">Para partilhar ficheiros entre o seu telemóvel e o seu ambiente de trabalho, precisa de permissão para aceder ao armazenamento do seu telemóvel</string>
<string name="telepathy_permission_explanation">Para ler e escrever SMS\'s a partir do seu ambiente de trabalho, precisa de dar permissões para os SMS\'s</string>
<string name="telephony_permission_explanation">Para ver as chamadas e os SMS\'s a partir do seu ambiente de trabalho, precisa de dar permissões para as chamadas telefónicas e SMS\'s</string>
<string name="telephony_optional_permission_explanation">Para ver o nome de um contacto em vez do seu número de telefone, precisa de dar acesso aos contactos do telemóvel</string>
</resources>

View File

@@ -5,15 +5,23 @@
<string name="pref_plugin_battery">Состояние батареи</string>
<string name="pref_plugin_battery_desc">Периодическое информирование о состоянии батареи</string>
<string name="pref_plugin_sftp">Просмотр файловой системы</string>
<string name="pref_plugin_sftp_desc">Позволяет удалённо просматривать файловую систему устройства</string>
<string name="pref_plugin_clipboard">Синхронизация буфера обмена</string>
<string name="pref_plugin_clipboard_desc">Использование общего буфера обмена</string>
<string name="pref_plugin_mousepad">Удалённый ввод</string>
<string name="pref_plugin_mousepad_desc">Использование телефона или планшета в качестве сенсорной панели и клавиатуры</string>
<string name="pref_plugin_remotekeyboard">Получение удалённых нажатий клавиш</string>
<string name="pref_plugin_remotekeyboard_desc">Получение нажатий клавиш с удалённых устройств</string>
<string name="pref_plugin_mpris">Управление воспроизведением</string>
<string name="pref_plugin_mpris_desc">Обеспечивает дистанционное управление медиапроигрывателем</string>
<string name="pref_plugin_runcommand">Запуск команд</string>
<string name="pref_plugin_runcommand_desc">Удалённый запуск команд с телефона или планшета</string>
<string name="pref_plugin_ping">Пинг</string>
<string name="pref_plugin_ping_desc">Отправка и получение тестовых сигналов</string>
<string name="pref_plugin_notifications">Синхронизация уведомлений</string>
<string name="pref_plugin_notifications_desc">Доступ к уведомлениям с других устройств</string>
<string name="pref_plugin_receive_notifications">Получение уведомлений</string>
<string name="pref_plugin_receive_notifications_desc">Получение уведомлений с другого устройства и показ их на Android</string>
<string name="pref_plugin_sharereceiver">Отправка и приём данных</string>
<string name="pref_plugin_sharereceiver_desc">Пересылка файлов и адресов URL между устройствами</string>
<string name="plugin_not_available">Эта функциональность недоступна в вашей версии Android</string>
@@ -24,23 +32,26 @@
<string name="no_permissions">Нужно разрешить доступ к уведомлениям</string>
<string name="send_ping">Отправить тестовый сигнал</string>
<string name="open_mpris_controls">Управление воспроизведением</string>
<string name="remotekeyboard_editing_only_title">Обрабатывать удалённые нажатия только при редактировании</string>
<string name="remotekeyboard_not_connected">Нет активного соединения с удалённой клавиатурой, установите его в KDE Connect</string>
<string name="remotekeyboard_connected">Соединение с удалённой клавиатурой активно</string>
<string name="remotekeyboard_multiple_connections">Подключено более одной удалённой клавиатуры, выберите устройство для настройки</string>
<string name="open_mousepad">Удалённый ввод</string>
<string name="mousepad_info">Перемещайте палец по экрану для перемещения курсора мыши. Коснитесь для нажатия, используйте два/три пальца для правой и средней кнопок. Используйте долгое нажатие для перетаскивания.</string>
<string name="mousepad_double_tap_settings_title">Действие при нажатии двумя пальцами</string>
<string name="mousepad_triple_tap_settings_title">Действие при нажатии тремя пальцами</string>
<string name="mousepad_sensitivity_settings_title">Чувствительность сенсорной панели</string>
<string name="mousepad_scroll_direction_title">Инвертировать направление прокрутки</string>
<string-array name="mousepad_tap_entries">
<item>Нажатие правой кнопки</item>
<item>Нажатие средней кнопки</item>
<item>Ничего не делать</item>
</string-array>
<string name="mousepad_double_default">Нажатие правой кнопки</string>
<string name="mousepad_triple_default">Нажатие средней кнопки</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
<item>Самая низкая</item>
<item>Низкая</item>
<item>Обычная</item>
<item>Высокая</item>
<item>Самая высокая</item>
</string-array>
<string name="category_connected_devices">Подключённые устройства</string>
<string name="category_not_paired_devices">Доступные устройства</string>
@@ -49,15 +60,20 @@
<string name="device_menu_plugins">Настройка модулей</string>
<string name="device_menu_unpair">Снять сопряжение</string>
<string name="device_not_reachable">Сопряжённое устройство недоступно</string>
<string name="pair_new_device">Подключить новое устройство</string>
<string name="unknown_device">Неизвестное устройство</string>
<string name="error_not_reachable">Устройство недоступно</string>
<string name="error_already_requested">Запрос на сопряжение уже был сделан</string>
<string name="error_already_paired">Устройство уже сопряжено</string>
<string name="error_could_not_send_package">Не удалось отправить пакет.</string>
<string name="error_could_not_send_package">Не удалось отправить пакет</string>
<string name="error_timed_out">Истекло время ожидания</string>
<string name="error_canceled_by_user">Отменено пользователем</string>
<string name="error_canceled_by_other_peer">Отменено другим участником</string>
<string name="error_invalid_key">Получен недопустимый ключ</string>
<string name="encryption_info_title">Информация о шифровании</string>
<string name="encryption_info_msg_no_ssl">На другом устройстве используется старая версия KDE Connect, используется старый метод шифрования.</string>
<string name="my_device_fingerprint">Отпечаток SHA-1 сертификата вашего устройства:</string>
<string name="remote_device_fingerprint">Отпечаток SHA-1 сертификата удалённого устройства:</string>
<string name="pair_requested">Запрошено сопряжение</string>
<string name="pairing_request_from">Запрос на сопряжение от %1s</string>
<string name="received_url_title">Получена ссылка от %1s</string>
@@ -65,12 +81,15 @@
<string name="incoming_file_title">Входящий файл с %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Отправка файла на %1s</string>
<string name="outgoing_files_title">Отправка файлов на %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Отправлено %1$d из %2$d файлов</string>
<string name="received_file_title">Получен файл с %1s</string>
<string name="received_file_fail_title">Не удалось получить файл с %1s</string>
<string name="received_file_text">Нажмите, чтобы открыть «%1s»</string>
<string name="sent_file_title">Файл отправлен на %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Не удалось отправить файл на %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Нажмите, чтобы ответить</string>
<string name="reconnect">Подключить заново</string>
@@ -102,8 +121,8 @@
<item>2 минуты</item>
</string-array>
<string name="share_to">Отправить на...</string>
<string name="protocol_version_older">Это устройство использует старую версию протокола.</string>
<string name="protocol_version_newer">Это устройство использует более новую версию протокола.</string>
<string name="protocol_version_older">Это устройство использует старую версию протокола</string>
<string name="protocol_version_newer">Это устройство использует более новую версию протокола</string>
<string name="general_settings">Общие параметры</string>
<string name="plugin_settings">Настройка</string>
<string name="plugin_settings_with_name">Настройка %s</string>
@@ -116,7 +135,11 @@
<string name="unpair_device_action">Снять сопряжение с %s</string>
<string name="custom_device_list">Добавить устройства по IP</string>
<string name="share_notification_preference">Звуковые уведомления</string>
<string name="share_notification_preference_summary">Использовать звуковой сигнал и вибрацию при получении файла.</string>
<string name="share_notification_preference_summary">Использовать вибрацию и звуковой сигнал при получении файла</string>
<string name="share_destination_customize">Задать целевой каталог</string>
<string name="share_destination_customize_summary_disabled">Полученные файлы появятся в каталоге Загрузки</string>
<string name="share_destination_customize_summary_enabled">Файлы будут сохранены в указанном ниже каталоге</string>
<string name="share_destination_folder_preference">Целевой каталог</string>
<string name="title_activity_notification_filter">Фильтр уведомлений</string>
<string name="filter_apps_info">Уведомления будут синхронизированы для выбранных приложений.</string>
<string name="sftp_internal_storage">Встроенная память</string>
@@ -138,11 +161,25 @@
<string name="device_rename_confirm">Переименовать</string>
<string name="refresh">Обновить</string>
<string name="unreachable_description">Это сопряжённое устройство недоступно. Проверьте, что оно подключено к той же локальной сети.</string>
<string name="on_data_message">Похоже, вы подключены к мобильной сети. KDE Connect работает только в локальных сетях.</string>
<string name="no_file_browser">Не удалось открыть диалог выбора файла.</string>
<string name="pref_plugin_telepathy">Отправка SMS</string>
<string name="pref_plugin_telepathy_desc">Отправка SMS-сообщений с вашего компьютера</string>
<string name="plugin_not_supported">Этот модуль не поддерживается устройством</string>
<string name="findmyphone_title">Поиск телефона</string>
<string name="findmyphone_title_tablet">Поиск планшета</string>
<string name="findmyphone_description">Подача звукового сигнала на устройстве, чтобы вы могли его найти</string>
<string name="findmyphone_found">Найден</string>
<string name="open">Открыть</string>
<string name="close">Закрыть</string>
<string name="no_permissions_storage">Необходимо предоставить разрешения на доступ к хранилищу</string>
<string name="plugins_need_permission">Некоторым модулям нужны разрешения для работы (нажмите для просмотра подробностей):</string>
<string name="permission_explanation">Этому модулю нужны разрешения для работы</string>
<string name="optional_permission_explanation">Необходимо предоставить дополнительные разрешения для включения всех функций</string>
<string name="plugins_need_optional_permission">Некоторые функции модулей отключены из-за отсутствия необходимых разрешений (нажмите для просмотра подробностей):</string>
<string name="sftp_permission_explanation">Для доступа к файлам с вашего компьютера приложению необходимо разрешение на доступ к встроенной памяти телефона</string>
<string name="share_optional_permission_explanation">Чтобы обмениваться файлами между телефоном и компьютером, необходимо предоставить доступ к встроенной памяти телефона</string>
<string name="telepathy_permission_explanation">Чтобы читать и писать SMS с компьютера, вам необходимо дать разрешение на доступ к SMS</string>
<string name="telephony_permission_explanation">Чтобы видеть телефонные звонки и SMS на компьютере, необходимо дать разрешение на телефонные звонки и SMS</string>
<string name="telephony_optional_permission_explanation">Чтобы видеть имя контакта вместо номера телефона, необходимо предоставить доступ к контактам</string>
</resources>

View File

@@ -10,8 +10,6 @@
<string name="pref_plugin_clipboard_desc">Zdieľať obsah schránky</string>
<string name="pref_plugin_mousepad">Vzdialený vstup</string>
<string name="pref_plugin_mousepad_desc">Použiť váš telefón alebo tablet ako touchpad a klávesnicu</string>
<string name="pref_plugin_remotekeyboard">Prijímať vzdialené stlačenia klávesov</string>
<string name="pref_plugin_remotekeyboard_desc">Prijímať udalosti stlačení klávesov od vzdialených zariadení</string>
<string name="pref_plugin_mpris">Multimediálne ovládače</string>
<string name="pref_plugin_mpris_desc">Poskytuje vzdialené ovládanie pre váš prehrávač médií</string>
<string name="pref_plugin_runcommand">Spustiť príkaz</string>
@@ -32,12 +30,7 @@
<string name="no_permissions">Musíte povoliť oprávnenia na prístup k pripomienkam</string>
<string name="send_ping">Poslať ping</string>
<string name="open_mpris_controls">Multimediálny ovládač</string>
<string name="remotekeyboard_editing_only_title">Spracúva vzdialené klávesy len pri editácii</string>
<string name="remotekeyboard_not_connected">Nie sú žiadne aktívne pripojenia vzdialenej klávesnice, vytvorte nejaké v Kdeconnect</string>
<string name="remotekeyboard_connected">Vzdialené pripojenie klávesnice je aktívne</string>
<string name="remotekeyboard_multiple_connections">Je viac ako jedno vzdialené pripojenie klávesnice, vyberte zariadenie na nastavenie</string>
<string name="open_mousepad">Vzdialený vstup</string>
<string name="mousepad_info">Posúvajte prst na obrazovke na posun kurzora. Ťuknutie vyvolá klik a použite dva/tri prsty pre pravé a stredné tlačidlo. Použite dlhé stlačenie pre drag and drop.</string>
<string name="mousepad_double_tap_settings_title">Nastaviť akciu dvoch prstov</string>
<string name="mousepad_triple_tap_settings_title">Nastaviť akciu troch prstov</string>
<string name="mousepad_sensitivity_settings_title">Nastaviť citlivosť touchpadu</string>
@@ -47,9 +40,6 @@
<item>Stredný klik</item>
<item>Nič</item>
</string-array>
<string name="mousepad_double_default">vpravo</string>
<string name="mousepad_triple_default">stred</string>
<string name="mousepad_sensitivity_default">predvolené</string>
<string-array name="mousepad_sensitivity_entries">
<item>Najpomalšie</item>
<item>Nad najpomalším</item>
@@ -85,15 +75,12 @@
<string name="incoming_file_title">Prichádzajúci súbor od %s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Posielam súbor pre %1s</string>
<string name="outgoing_files_title">Posielam súbor pre %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Poslať %1$d z %2$d súborov</string>
<string name="received_file_title">Prijatý súbor od %1s</string>
<string name="received_file_fail_title">Zlyhalo prijatie súboru od %1s</string>
<string name="received_file_text">Ťuknite na otvorenie \'%1s\'</string>
<string name="sent_file_title">Poslať súbor pre %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Zlyhalo poslanie súboru %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tapnite na odpoveď</string>
<string name="reconnect">Znovu pripojiť</string>
@@ -140,10 +127,6 @@
<string name="custom_device_list">Pridať zariadenia podľa IP</string>
<string name="share_notification_preference">Hlučné pripomienky</string>
<string name="share_notification_preference_summary">Vibrovať a prehrať zvuk pri prijatí súboru</string>
<string name="share_destination_customize">Prispôsobiť cieľový adresár</string>
<string name="share_destination_customize_summary_disabled">Prijaté súbory sa objavia v Preberaniach</string>
<string name="share_destination_customize_summary_enabled">Súbory sa uložia v adresári dolu</string>
<string name="share_destination_folder_preference">Cieľový adresár</string>
<string name="title_activity_notification_filter">Filter upozornení</string>
<string name="filter_apps_info">Upozornenia budú synchronizované pre vybrané aplikácie.</string>
<string name="sftp_internal_storage">Interné úložisko</string>
@@ -165,7 +148,6 @@
<string name="device_rename_confirm">Premenovať</string>
<string name="refresh">Obnoviť</string>
<string name="unreachable_description">Toto spárované zariadenie nie je dosiahnuteľné. Prosím, uistite sa, že je pripojené do rovnakej siete.</string>
<string name="on_data_message">Zdá sa, že ste na mobilom dátovom pripojení. KDE Connect funguje iba na lokálnej sieti.</string>
<string name="no_file_browser">Nie sú nainštalované žiadne prehliadače.</string>
<string name="pref_plugin_telepathy">Poslať SMS</string>
<string name="pref_plugin_telepathy_desc">Posielať textové správy z vášho počítača</string>

185
res/values-sr/strings.xml Normal file
View File

@@ -0,0 +1,185 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Обавештења телефона</string>
<string name="pref_plugin_telephony_desc">Шаље обавештења за СМС и позиве</string>
<string name="pref_plugin_battery">Извештај о батерији</string>
<string name="pref_plugin_battery_desc">Периодично извештава о стању батерије</string>
<string name="pref_plugin_sftp">Приступ фајл систему</string>
<string name="pref_plugin_sftp_desc">Дозвољава даљински приступ фајл систему уређаја</string>
<string name="pref_plugin_clipboard">Усклађени клипборд</string>
<string name="pref_plugin_clipboard_desc">Дељење садржаја клипборда</string>
<string name="pref_plugin_mousepad">Даљински унос</string>
<string name="pref_plugin_mousepad_desc">Користите телефон или таблет као додирник и тастатуру</string>
<string name="pref_plugin_remotekeyboard">Пријем даљинских тастера</string>
<string name="pref_plugin_remotekeyboard_desc">Примање тастерских догађаја са удаљених уређаја</string>
<string name="pref_plugin_mpris">Управљање мултимедијом</string>
<string name="pref_plugin_mpris_desc">Омогућава даљинско управљање медија плејером</string>
<string name="pref_plugin_runcommand">Извршавање наредбе</string>
<string name="pref_plugin_runcommand_desc">Даљински окида наредбе са телефона или таблета</string>
<string name="pref_plugin_ping">Пинг</string>
<string name="pref_plugin_ping_desc">Шаље и прима пингове</string>
<string name="pref_plugin_notifications">Усклађена обавештења</string>
<string name="pref_plugin_notifications_desc">Приступа вашим обавештењима са другог уређаја</string>
<string name="pref_plugin_receive_notifications">Пријем обавештења</string>
<string name="pref_plugin_receive_notifications_desc">Прима обавештења са других уређаја и приказује их на Андроиду</string>
<string name="pref_plugin_sharereceiver">Дели и примај</string>
<string name="pref_plugin_sharereceiver_desc">Дели фајлове и УРЛ‑ове између уређаја</string>
<string name="plugin_not_available">Ова могућност није доступна на вашој верзији Андроида</string>
<string name="device_list_empty">Нема уређаја</string>
<string name="ok">У реду</string>
<string name="cancel">Откажи</string>
<string name="open_settings">Отвори поставке</string>
<string name="no_permissions">Морате дати дозволу за приступ обавештењима</string>
<string name="send_ping">Пошаљи пинг</string>
<string name="open_mpris_controls">Контрола мултимедије</string>
<string name="remotekeyboard_editing_only_title">Користи даљинске дугмиће само при уређивању</string>
<string name="remotekeyboard_not_connected">Нема активне везе даљинске тастатуре. Успоставите је у КДЕ‑конекцији</string>
<string name="remotekeyboard_connected">Веза даљинске тастатуре је активна</string>
<string name="remotekeyboard_multiple_connections">Постоји више од једне везе даљинске тастатуре. Изаберите уређај да бисте подесили</string>
<string name="open_mousepad">Даљински унос</string>
<string name="mousepad_double_tap_settings_title">Радња за додир са два прста</string>
<string name="mousepad_triple_tap_settings_title">Радња за додир са три прста</string>
<string name="mousepad_sensitivity_settings_title">Постави осетљивост додирника</string>
<string name="mousepad_scroll_direction_title">Обрни смер клизања</string>
<string-array name="mousepad_tap_entries">
<item>десни клик</item>
<item>средњи клик</item>
<item>ништа</item>
</string-array>
<string-array name="mousepad_sensitivity_entries">
<item>најспорије</item>
<item>мало спорије</item>
<item>подразумевано</item>
<item>мало брже</item>
<item>најбрже</item>
</string-array>
<string name="category_connected_devices">Повезани уређаји</string>
<string name="category_not_paired_devices">Доступни уређаји</string>
<string name="category_remembered_devices">Упамћени уређаји</string>
<string name="plugins_failed_to_load">Неуспело учитавање прикључка (тапните за више информација):</string>
<string name="device_menu_plugins">Поставке прикључака</string>
<string name="device_menu_unpair">Распари</string>
<string name="device_not_reachable">Упарени уређај није доступан</string>
<string name="pair_new_device">Упари нов уређај</string>
<string name="unknown_device">Непознат уређај</string>
<string name="error_not_reachable">Уређај није доступан</string>
<string name="error_already_requested">Упаривање је већ тражено</string>
<string name="error_already_paired">Уређај је већ упарен</string>
<string name="error_could_not_send_package">Не могу да пошаљем пакет</string>
<string name="error_timed_out">Истекло је време</string>
<string name="error_canceled_by_user">Корисник отказао</string>
<string name="error_canceled_by_other_peer">Отказала друга страна</string>
<string name="error_invalid_key">Примљен је неисправан кључ</string>
<string name="encryption_info_title">Подаци о шифровању</string>
<string name="encryption_info_msg_no_ssl">Друга страна не користи најновију верзију, стога се користи старији метод шифровања.</string>
<string name="my_device_fingerprint">СХА1 отисак сертификата вашег уређаја је:</string>
<string name="remote_device_fingerprint">СХА1 отисак сертификата удаљеног уређаја је:</string>
<string name="pair_requested">Упаривање је тражено</string>
<string name="pairing_request_from">Захтев за упаривање са %1s</string>
<string name="received_url_title">Примљена веза са %1s</string>
<string name="received_url_text">Тапните да отворите „%1s“</string>
<string name="incoming_file_title">Долазни фајл са %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Шаљем фајл на %1s</string>
<string name="outgoing_files_title">Шаљем фајлове на %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Послато %1$d од %2$d фајлова</string>
<string name="received_file_title">Примљен фајл са %1s</string>
<string name="received_file_fail_title">Неуспео пријем фајла са %1s</string>
<string name="received_file_text">Тапните да отворите „%1s“</string>
<string name="sent_file_title">Послат фајл на %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Неуспело слање фајла на %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Тапните да одговорите</string>
<string name="reconnect">Поново повежи</string>
<string name="right_click">Пошаљи десни клик</string>
<string name="middle_click">Пошаљи средњи клик</string>
<string name="show_keyboard">Прикажи тастатуру</string>
<string name="device_not_paired">Уређај није упарен</string>
<string name="request_pairing">Тражи упаривање</string>
<string name="pairing_accept">Прихвати</string>
<string name="pairing_reject">Одбаци</string>
<string name="device">Уређај</string>
<string name="pair_device">Упари уређај</string>
<string name="remote_control">Даљинско управљање</string>
<string name="settings">Поставке за КДЕ‑конекцију</string>
<string name="mpris_play">Пусти</string>
<string name="mpris_previous">Претходно</string>
<string name="mpris_rew">Премотај</string>
<string name="mpris_ff">Брзо унапред</string>
<string name="mpris_next">Следеће</string>
<string name="mpris_volume">Јачина</string>
<string name="mpris_settings">Поставке мултимедије</string>
<string name="mpris_time_settings_title">Напред/назад дугмад</string>
<string name="mpris_time_settings_summary">Подесите време прескакања за напред/назад дугмад.</string>
<string-array name="mpris_time_entries">
<item>10 секунди</item>
<item>20 секунди</item>
<item>30 секунди</item>
<item>1 минут</item>
<item>2 минута</item>
</string-array>
<string name="share_to">Дели...</string>
<string name="protocol_version_older">Овај уређај користи стару верзију протокола</string>
<string name="protocol_version_newer">Овај уређај користи новију верзију протокола</string>
<string name="general_settings">Опште поставке</string>
<string name="plugin_settings">Поставке</string>
<string name="plugin_settings_with_name">%s — поставке</string>
<string name="device_name">Назив уређаја</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">Неисправан назив уређаја</string>
<string name="shareplugin_text_saved">Примљен текст, сачуван у клипборд</string>
<string name="custom_devices_settings">Списак посебних уређаја</string>
<string name="pair_device_action">Упари нови уређај</string>
<string name="unpair_device_action">Распари %s</string>
<string name="custom_device_list">Додај уређај по ИП адреси</string>
<string name="share_notification_preference">Бучна обавештења</string>
<string name="share_notification_preference_summary">Вибрирај и пусти звук кад примаш фајл</string>
<string name="share_destination_customize">Прилагоди одредишну фасциклу</string>
<string name="share_destination_customize_summary_disabled">Фајлови се смештају у Downloads</string>
<string name="share_destination_customize_summary_enabled">Фајлови се смештају у фасциклу испод</string>
<string name="share_destination_folder_preference">Одредишна фасцикла</string>
<string name="title_activity_notification_filter">Филтер обавештења</string>
<string name="filter_apps_info">Обавештења ће се синхронизовати за изабране апликације.</string>
<string name="sftp_internal_storage">Унутрашња меморија</string>
<string name="sftp_all_files">сви фајлови</string>
<string name="sftp_sdcard_num">СД картица %d</string>
<string name="sftp_sdcard">СД картица</string>
<string name="sftp_readonly">(само за читање)</string>
<string name="sftp_camera">Слике са камере</string>
<string name="add_host">Додај домаћина/ИП</string>
<string name="add_host_hint">Име домаћина или ИП</string>
<string name="no_players_connected">Нисам нашао плејере</string>
<string name="custom_dev_list_help">Користите ову опцију само ако се ваши уређаји не приказују аутоматски. Унесите ИП адресу или име домаћина и додирните дугме да га додате на листу. Додирните постојећу ставку да бисте је уклонили.</string>
<string name="mpris_player_on_device">%1$s на %2$s</string>
<string name="send_files">Пошаљи фајлове</string>
<string name="pairing_title">Уређаји КДЕ‑конекције</string>
<string name="pairing_description">Други уређаји на вашој мрежи на којима ради КДЕ‑конекција, појавиће се овде.</string>
<string name="device_paired">Уређај упарен</string>
<string name="device_rename_title">Преименовање уређаја</string>
<string name="device_rename_confirm">Преименуј</string>
<string name="refresh">Освежи</string>
<string name="unreachable_description">Овај упарени уређај није доступан. Проверите да ли је повезан на исту мрежу.</string>
<string name="on_data_message">Чини се да сте на мобилној мрежи. КДЕ‑конекција ради само на локалној мрежи.</string>
<string name="no_file_browser">Нема инсталираних прегледача фајлова.</string>
<string name="pref_plugin_telepathy">Шаљи СМС</string>
<string name="pref_plugin_telepathy_desc">Шаљите текстуалне поруке помоћу рачунара</string>
<string name="plugin_not_supported">Уређај не подржава овај прикључак</string>
<string name="findmyphone_title">Нађи мој телефон</string>
<string name="findmyphone_title_tablet">Нађи мој таблет</string>
<string name="findmyphone_description">Активира звоно уређаја како бисте га пронашли</string>
<string name="findmyphone_found">Нађен</string>
<string name="open">Отвори</string>
<string name="close">Затвори</string>
<string name="no_permissions_storage">Морате дати дозволе за приступ унутрашњој меморији.</string>
<string name="plugins_need_permission">Неки прикључци траже дозволе да би радили (тапните за више информација):</string>
<string name="permission_explanation">Овај прикључак тражи дозволе да би радио.</string>
<string name="optional_permission_explanation">Морате дати допунске дозволе за активирање свих функција.</string>
<string name="plugins_need_optional_permission">Неки прикључци имају деактивиране могућности због недостатка дозвола (тапните за више информација):</string>
<string name="sftp_permission_explanation">Програм захтева дозволе да би са рачунара приступио фајловима на телефону.</string>
<string name="share_optional_permission_explanation">За дељење фајлова између телефона и рачунара морате дати приступ складишту телефона.</string>
<string name="telepathy_permission_explanation">За читање и писање СМС‑ова на рачунару морате дати дозволу за СМС.</string>
<string name="telephony_permission_explanation">Да бисте са рачунара видели телефонске позиве и СМС‑ове морате дати дозволу за позиве и СМС‑ове.</string>
<string name="telephony_optional_permission_explanation">Да бисте видели име контакта уместо броја телефона морате дати приступ за контакте на телефону.</string>
</resources>

View File

@@ -8,10 +8,10 @@
<string name="pref_plugin_sftp_desc">Gör det möjligt att bläddra i apparatens filsystem från annan apparat</string>
<string name="pref_plugin_clipboard">Synkronisera klippbord</string>
<string name="pref_plugin_clipboard_desc">Dela klippbordets innehåll</string>
<string name="pref_plugin_mousepad">Fjärrinmatning</string>
<string name="pref_plugin_mousepad">Extern inmatning</string>
<string name="pref_plugin_mousepad_desc">Använd telefonen eller surfplattan som mus och tangentbord</string>
<string name="pref_plugin_remotekeyboard">Ta emot fjärrtangentnedtryckningar</string>
<string name="pref_plugin_remotekeyboard_desc">Ta emot tangentnedtryckningar från fjärrenheter</string>
<string name="pref_plugin_remotekeyboard">Ta emot externa tangentnedtryckningar</string>
<string name="pref_plugin_remotekeyboard_desc">Ta emot tangentnedtryckningar från externa enheter</string>
<string name="pref_plugin_mpris">Multimediakontroller</string>
<string name="pref_plugin_mpris_desc">Tillhandahåller en fjärrkontroll för mediaspelaren</string>
<string name="pref_plugin_runcommand">Kör kommando</string>
@@ -32,12 +32,12 @@
<string name="no_permissions">Du måste ge rättighet att komma åt underrättelser</string>
<string name="send_ping">Skicka ping</string>
<string name="open_mpris_controls">Kontroll av multimedia</string>
<string name="remotekeyboard_editing_only_title">Hantera bara fjärrtangenter vid redigering</string>
<string name="remotekeyboard_not_connected">Det finns ingen aktiv fjärrtangentbordsanslutning, upprätta en i KDE-anslut</string>
<string name="remotekeyboard_connected">Fjärrtangentbordsanslutning är aktiv</string>
<string name="remotekeyboard_multiple_connections">Det finns mer än en fjärrtangentbordsanslutning, välj enhet att anpassa</string>
<string name="open_mousepad">Fjärrinmatning</string>
<string name="mousepad_info">Flytta fingret på skärmen för att röra muspekaren. Rör för att klicka, och använd två eller tre fingrar för höger- och mittenknapparna. Använd en längre beröring för drag och släpp.</string>
<string name="remotekeyboard_editing_only_title">Hantera bara externa tangenter vid redigering</string>
<string name="remotekeyboard_not_connected">Det finns ingen aktiv anslutning till externt tangentbord, upprätta en i KDE-anslut</string>
<string name="remotekeyboard_connected">Anslutning till externt tangentbord är aktiv</string>
<string name="remotekeyboard_multiple_connections">Det finns mer än en anslutning till externt tangentbord, välj enhet att anpassa</string>
<string name="open_mousepad">Extern inmatning</string>
<string name="mousepad_info">Flytta fingret på skärmen för att röra muspekaren. Rör för att klicka, och använd två eller tre fingrar för höger- och mittenknapparna. Använd två fingrar för att panorera. Använd en längre beröring för drag och släpp.</string>
<string name="mousepad_double_tap_settings_title">Ställ in åtgärd vid två fingerberöringar</string>
<string name="mousepad_triple_tap_settings_title">Ställ in åtgärd vid tre fingerberöringar</string>
<string name="mousepad_sensitivity_settings_title">Ställ in tryckplattans känslighet</string>
@@ -47,9 +47,6 @@
<item>Mittenklick</item>
<item>Ingenting</item>
</string-array>
<string name="mousepad_double_default">höger</string>
<string name="mousepad_triple_default">mitten</string>
<string name="mousepad_sensitivity_default">normal</string>
<string-array name="mousepad_sensitivity_entries">
<item>Långsammaste</item>
<item>Ovanför långsammaste</item>
@@ -176,4 +173,14 @@
<string name="findmyphone_found">Hittade den</string>
<string name="open">Öppna</string>
<string name="close">Stäng</string>
<string name="no_permissions_storage">Du måste ge rättighet att komma åt lagringen</string>
<string name="plugins_need_permission">Vissa insticksprogram kräver rättigheter för att fungera (rör för mer information):</string>
<string name="permission_explanation">Insticksprogrammet behöver rättigheter för att fungera</string>
<string name="optional_permission_explanation">Du måste ge extra rättigheter för att aktivera alla funktioner</string>
<string name="plugins_need_optional_permission">Vissa insticksprogram har inaktiverade funktioner på grund av att rättigheter saknas (rör för mer information):</string>
<string name="sftp_permission_explanation">För att komma åt filerna från din dator behöver applikationen rättighet att komma åt telefonens lagringsutrymme</string>
<string name="share_optional_permission_explanation">För att dela filer mellan telefonen och skrivbordet behöver du ge tillgång till telefonens lagringsutrymme</string>
<string name="telepathy_permission_explanation">För att läsa och skriva SMS från skrivbordet måste du ge rättigheter för SMS</string>
<string name="telephony_permission_explanation">För att se telefonsamtal och SMS från skrivbordet måste du ge rättigheter för telefonsamtal och SMS</string>
<string name="telephony_optional_permission_explanation">För att se ett kontaktnamn istället för ett telefonnummer måste du ge tillgång till telefonens kontakter</string>
</resources>

185
res/values-tr/strings.xml Normal file
View File

@@ -0,0 +1,185 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Telefon bildiricisi</string>
<string name="pref_plugin_telephony_desc">SMS ve çağrılar için bildirimler yolla</string>
<string name="pref_plugin_battery">Batarya raporu</string>
<string name="pref_plugin_battery_desc">Batarya durumunu belirli aralıklarla raporla</string>
<string name="pref_plugin_sftp">Dosya sistemi gösterme</string>
<string name="pref_plugin_sftp_desc">Bu aıygıtın dosya sistemine uzaktan gözatılmasına izin verir</string>
<string name="pref_plugin_clipboard">Pano eşitleme</string>
<string name="pref_plugin_clipboard_desc">Pano içeriğini paylaş</string>
<string name="pref_plugin_mousepad">Uzak girdi</string>
<string name="pref_plugin_mousepad_desc">Telefonunuzu veya tabletinizi, dokunmatik veya klavye olarak kullanın</string>
<string name="pref_plugin_remotekeyboard">Uzak tuşa basmaları getir</string>
<string name="pref_plugin_remotekeyboard_desc">Tuş basma eylemlerini, uzak aygıtlardan getir</string>
<string name="pref_plugin_mpris">Çoklu ortam denetimleri</string>
<string name="pref_plugin_mpris_desc">Ortam oynatıcınız için uzak denetim sağlar</string>
<string name="pref_plugin_runcommand">Komut Çalıştır</string>
<string name="pref_plugin_runcommand_desc">Uzak komutları, telefon veya tabletinizden tetikler</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Ping gönder ve al</string>
<string name="pref_plugin_notifications">Bildirim eşitleme</string>
<string name="pref_plugin_notifications_desc">Bildirimlerinize, diğer aygıtlardan erişin</string>
<string name="pref_plugin_receive_notifications">Bildirimleri al</string>
<string name="pref_plugin_receive_notifications_desc">Bildirimleri diğer aygıtlardan al ve Android üzerinde göster</string>
<string name="pref_plugin_sharereceiver">Paylaş ve al</string>
<string name="pref_plugin_sharereceiver_desc">Dosyaları ve URL\'leri aygıtlar arasında paylaş</string>
<string name="plugin_not_available">Bu özellik, sahip olduğunuz Android sürümünde kullanılabilir değil</string>
<string name="device_list_empty">Aygıt yok</string>
<string name="ok">Tamam</string>
<string name="cancel">İptal</string>
<string name="open_settings">Ayarları</string>
<string name="no_permissions">Bildirimler erişebilmek için izine ihtiyacınız var</string>
<string name="send_ping">Ping gönder</string>
<string name="open_mpris_controls">Çoklu ortam denetimi</string>
<string name="remotekeyboard_editing_only_title">Uzak tuşları, sadece düzenleme yaparken işle</string>
<string name="remotekeyboard_not_connected">Etkin bir uzak klavye bağlantısı yok, kdeconnect ile bir bağlantı kurun</string>
<string name="remotekeyboard_connected">Uzak klavye bağlantısı etkin</string>
<string name="remotekeyboard_multiple_connections">Birden çok uzak klavye bağlantısı mevcut, yapılandırmak istediğiniz aygıtı seçin</string>
<string name="open_mousepad">Girdi sil</string>
<string name="mousepad_double_tap_settings_title">İki parmak dokunma eylemini ayarla</string>
<string name="mousepad_triple_tap_settings_title">Üç parmak dokunma eylemini ayarla</string>
<string name="mousepad_sensitivity_settings_title">Dokunmatik yüzey hassasiyetini ayarla</string>
<string name="mousepad_scroll_direction_title">Ters Kaydırma Yönü</string>
<string-array name="mousepad_tap_entries">
<item>Sağ tık</item>
<item>Orta tık</item>
<item>Hiçbiri</item>
</string-array>
<string-array name="mousepad_sensitivity_entries">
<item>En Yavaş</item>
<item>En Yavaşın Üstü</item>
<item>Varsayıla</item>
<item>Varsayılan Üstü</item>
<item>En Hızlı</item>
</string-array>
<string name="category_connected_devices">Bağlı aygıtlar</string>
<string name="category_not_paired_devices">Kullanılabilir aygıtlar</string>
<string name="category_remembered_devices">Hatırlanan aygıtlar</string>
<string name="plugins_failed_to_load">Eklentiler yüklenemedi (daha fazla bilgi için dokunun):</string>
<string name="device_menu_plugins">Eklenti ayarları</string>
<string name="device_menu_unpair">Ayır</string>
<string name="device_not_reachable">Eşleşmiş aygıt ulaşılabilir değil</string>
<string name="pair_new_device">Yeni bir aygıt eşleştir</string>
<string name="unknown_device">Bİlinmeyen aygıt</string>
<string name="error_not_reachable">Aygıt ulaşılabilir değil</string>
<string name="error_already_requested">Eşleşme zaten talep edilmiş</string>
<string name="error_already_paired">Aygıt zaten eşleşmiş</string>
<string name="error_could_not_send_package">Paket gönderilemedi</string>
<string name="error_timed_out">Zaman aşımı</string>
<string name="error_canceled_by_user">Kullanıcı tarafından iptal edildi</string>
<string name="error_canceled_by_other_peer">Diğer eş tarafından iptal edildi</string>
<string name="error_invalid_key">Geçersiz anahtar alındı</string>
<string name="encryption_info_title">Şifreleme Bilgisi</string>
<string name="encryption_info_msg_no_ssl">Diğer aygıt, KDE Connect\'in son sürümünü kullanmıyor, eski şifreleme yöntemini kullanıyor.</string>
<string name="my_device_fingerprint">Aygıt sertifikanızın SHA1 parmak izi:</string>
<string name="remote_device_fingerprint">Uzak aygıt sertifikanızın SHA1 parmak izi:</string>
<string name="pair_requested">Eşleşme talep edildi</string>
<string name="pairing_request_from">%1s için eşleşme talebi</string>
<string name="received_url_title">%1s üzerinden bağlantı alındı</string>
<string name="received_url_text">\'%1s\' açmak için dokunun</string>
<string name="incoming_file_title">%1s üzerinden gelen dosya</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Dosya şuraya gönderiliyor, %1s</string>
<string name="outgoing_files_title">Dosyalar şuraya gönderiliyor, %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">%2$d dosyadan %1$d dosya gönderildi</string>
<string name="received_file_title">Şuradan dosya alındı, %1s</string>
<string name="received_file_fail_title">Şuradan dosya alma başarısız, %1s</string>
<string name="received_file_text">\'%1s\' açmak için dokunun</string>
<string name="sent_file_title">Dosyayı şuraya gönder, %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Dosyayı şuraya gönderme başarısız, %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Cevap için dokunun</string>
<string name="reconnect">Yeniden Bağlan</string>
<string name="right_click">Sağ Tık Gönder</string>
<string name="middle_click">Orta Tık Gönder</string>
<string name="show_keyboard">Klavyeyi Göster</string>
<string name="device_not_paired">Aygıt eşleşmemiş</string>
<string name="request_pairing">Eşleşme isteği</string>
<string name="pairing_accept">Onayla</string>
<string name="pairing_reject">Reddet</string>
<string name="device">Aygıt</string>
<string name="pair_device">Aygıt eşleştir</string>
<string name="remote_control">Uzak denetim</string>
<string name="settings">KDE Connect Ayarları</string>
<string name="mpris_play">Oynat</string>
<string name="mpris_previous">Önceki</string>
<string name="mpris_rew">Geri Sar</string>
<string name="mpris_ff">Hızlı İleri Sar</string>
<string name="mpris_next">Sonraki</string>
<string name="mpris_volume">Ses</string>
<string name="mpris_settings">Çoklu Ortam Ayarları</string>
<string name="mpris_time_settings_title">İleri/geri düğmeleri</string>
<string name="mpris_time_settings_summary">Basıldığında kullanılacak ileri/geri zamanını ayarlayın.</string>
<string-array name="mpris_time_entries">
<item>10 saniye</item>
<item>20 saniye</item>
<item>30 saniye</item>
<item>1 dakika</item>
<item>2 dakika</item>
</string-array>
<string name="share_to">Paylaş...</string>
<string name="protocol_version_older">Bu aygıt, eski bir protokol sürümü kullanıyor</string>
<string name="protocol_version_newer">Bu aygıt, daha yeni bir protokol sürümü kullanıyor</string>
<string name="general_settings">Genel Ayarlar</string>
<string name="plugin_settings">Ayarlar</string>
<string name="plugin_settings_with_name">%s ayarları</string>
<string name="device_name">Aygıt adı</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">Geçersiz aygıt adı</string>
<string name="shareplugin_text_saved">Gelen ileti, panoya kaydet</string>
<string name="custom_devices_settings">Özel aygıt listesi</string>
<string name="pair_device_action">Yeni bir aygıt eşleştir</string>
<string name="unpair_device_action">Ayır %s</string>
<string name="custom_device_list">IP\'ye göre aygıtları ekle</string>
<string name="share_notification_preference">Sesli bildirimler</string>
<string name="share_notification_preference_summary">Bir dosya alırken, ses çıkar ve titret</string>
<string name="share_destination_customize">Hedef dizini özelleştir</string>
<string name="share_destination_customize_summary_disabled">Gelen dosyalar İndirilenler\'de gözükecektir</string>
<string name="share_destination_customize_summary_enabled">Dosyalar aşağıdaki dizinden depolanacaktır</string>
<string name="share_destination_folder_preference">Hedef dizin</string>
<string name="title_activity_notification_filter">Bildirim süzgeci</string>
<string name="filter_apps_info">Bildirimler, seçili uygulamalar için eşitlenecektir.</string>
<string name="sftp_internal_storage">Harici depolama</string>
<string name="sftp_all_files">Tüm dosyalar</string>
<string name="sftp_sdcard_num">SD kart %d</string>
<string name="sftp_sdcard">SD kart</string>
<string name="sftp_readonly">(salt okunur)</string>
<string name="sftp_camera">Kamera resimleri</string>
<string name="add_host">Makine/IP ekle</string>
<string name="add_host_hint">Makine adı veya IP</string>
<string name="no_players_connected">Onatıcı bulunamadı</string>
<string name="custom_dev_list_help">Bu seçeneği, sadece aygıtınız otomatik bulunamadıysa kullanın. Aşağıya IP adresini veya makine adının girin ve listeye eklemek için düğmeye dokunun. Listeden bir ögeyi silmek için, mevcut ögeye tıklayın.</string>
<string name="mpris_player_on_device">%2$s üzerindeki %1$s</string>
<string name="send_files">Dosyaları gönder</string>
<string name="pairing_title">KDE Connect Aygıtları</string>
<string name="pairing_description">KDE Connect\'te çalışan, aynı ağdaki diğer aygıtlar burada gözükmelidir.</string>
<string name="device_paired">Aygıt eşleştirildi</string>
<string name="device_rename_title">Aygıtı yeniden adlandır</string>
<string name="device_rename_confirm">Yeniden adlandır</string>
<string name="refresh">Tazele</string>
<string name="unreachable_description">Eşleştirilmiş aygıt ulaşılabilir değil. Aynı ağa bağlı olduğundan emin olun.</string>
<string name="on_data_message">Mobil veri bağlantısında olduğunuz gözüküyor. KDE Connect sadece yerel ağlarda çalışır.</string>
<string name="no_file_browser">Yüklü bir dosya tarayıcısı yok.</string>
<string name="pref_plugin_telepathy">SMS Gönder</string>
<string name="pref_plugin_telepathy_desc">Masaüstünden metin iletisi gönder</string>
<string name="plugin_not_supported">Eklenti, aygıt tarafından desteklenmiyor</string>
<string name="findmyphone_title">Telefonumu bul</string>
<string name="findmyphone_title_tablet">Tabletimi bul</string>
<string name="findmyphone_description">Aygıtı bulmak için onu çaldır</string>
<string name="findmyphone_found">Bulundu</string>
<string name="open"></string>
<string name="close">Kapat</string>
<string name="no_permissions_storage">Depolamaya erişim için izne ihtiyacınız var</string>
<string name="plugins_need_permission">Bazı Eklentiler çalışmak için izne ihtiyaç duyar (daha fazla bilgi için dokunun):</string>
<string name="permission_explanation">Bu eklenti, çalışmak için izne ihtiyaç duyuyor</string>
<string name="optional_permission_explanation">Tüm işlevleri etkinleştirmek için daha fazla yetkiye ihtiyacınız var</string>
<string name="plugins_need_optional_permission">Bazı eklentilerin özellikleri, izin yetersizliğinden kapalı gelmektedir (daha fazla bilgi için dokunun):</string>
<string name="sftp_permission_explanation">Bilgisayarınızdaki dosyalara erişmek için, uygulama telefonunuzun depolama alanına erişim izni olmalıdır</string>
<string name="share_optional_permission_explanation">Telefon ve masaüstünüz arasında dosya paylaşılabilmesi için, telefonun depolama alanına erişim izni olmalıdır</string>
<string name="telepathy_permission_explanation">Masaüstünde SMS yazma ve okuma yapmak için SMS izni gereklidir</string>
<string name="telephony_permission_explanation">Masaüstünden telefon çağrılarını ve SMS görebilmek için izin gereklidir</string>
<string name="telephony_optional_permission_explanation">Telefon numarası yerine kişi ismi görebilmek için telefonun kişilerine erişim gereklidir</string>
</resources>

View File

@@ -37,7 +37,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>
@@ -47,9 +47,6 @@
<item>Клацання середньою</item>
<item>Нічого</item>
</string-array>
<string name="mousepad_double_default">права</string>
<string name="mousepad_triple_default">середня</string>
<string name="mousepad_sensitivity_default">типва</string>
<string-array name="mousepad_sensitivity_entries">
<item>Найповільніший</item>
<item>Швидший за найповільніший</item>
@@ -176,4 +173,14 @@
<string name="findmyphone_found">Знайдено</string>
<string name="open">Відкрити</string>
<string name="close">Закрити</string>
<string name="no_permissions_storage">Для доступу до сховища даних вам слід надати програмі права доступу</string>
<string name="plugins_need_permission">Для роботи деяких додатків потрібні додаткові права доступу (натисніть, щоб дізнатися більше):</string>
<string name="permission_explanation">Для роботи цього додатка потрібні додаткові права доступу</string>
<string name="optional_permission_explanation">Щоб уможливити використання усіх функцій, вам слід надати програмі додаткові права доступу</string>
<string name="plugins_need_optional_permission">Можливості деяких додатків вимкнено, оскільки програмі не вистачає прав доступу (натисніть, щоб дізнатися більше):</string>
<string name="sftp_permission_explanation">Для доступу до ваших файлі із персонального комп’ютера програмі потрібні права доступу до сховища даних вашого телефону</string>
<string name="share_optional_permission_explanation">Щоб спільного використовувати файли на вашому телефоні і робочому комп’ютері, вам слід надати програмі доступ до сховища даних вашого телефону</string>
<string name="telepathy_permission_explanation">Щоб читати і писати SMS з вашого робочого комп’ютера, вам слід надати програмі доступ до SMS</string>
<string name="telephony_permission_explanation">"Щоб переглядати дзвінки і SMS з робочого комп’ютера, вам слід надати програмі доступ до дзвінків і SMS"</string>
<string name="telephony_optional_permission_explanation">Щоб бачити ім’я контакту замість номеру телефону, вам слід надати програмі доступ до записів контактів на телефоні</string>
</resources>

View File

@@ -19,7 +19,7 @@
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">发送和接受ping</string>
<string name="pref_plugin_notifications">通知同步</string>
<string name="pref_plugin_notifications_desc">从其他设备访问的通知</string>
<string name="pref_plugin_notifications_desc">从其他设备访问的通知</string>
<string name="pref_plugin_receive_notifications">接收通知</string>
<string name="pref_plugin_receive_notifications_desc">从其他设备接收通知并显示在 Android 上</string>
<string name="pref_plugin_sharereceiver">分享和接收</string>
@@ -29,7 +29,7 @@
<string name="ok">确认</string>
<string name="cancel">取消</string>
<string name="open_settings">开启设置</string>
<string name="no_permissions">需要授予权限以便访问通知</string>
<string name="no_permissions">需要授予权限以便访问通知</string>
<string name="send_ping">发送ping</string>
<string name="open_mpris_controls">多媒体控制</string>
<string name="remotekeyboard_editing_only_title">只有在编辑时才接受远程按键</string>
@@ -37,7 +37,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>
@@ -47,9 +47,6 @@
<item>中键点击</item>
<item></item>
</string-array>
<string name="mousepad_double_default"></string>
<string name="mousepad_triple_default"></string>
<string name="mousepad_sensitivity_default">默认</string>
<string-array name="mousepad_sensitivity_entries">
<item>最慢</item>
<item>高于最慢</item>
@@ -155,7 +152,7 @@
<string name="add_host">增加主机/IP</string>
<string name="add_host_hint">主机名或IP</string>
<string name="no_players_connected">未找到播放器</string>
<string name="custom_dev_list_help">仅当的设备没有被自动检测出时再使用本选项。在下方输入IP地址或主机名然后点击按钮以添加其到列表中。点击已有条目来从列表中删除它。</string>
<string name="custom_dev_list_help">仅当的设备没有被自动检测出时再使用本选项。在下方输入IP地址或主机名然后点击按钮以添加其到列表中。点击已有条目来从列表中删除它。</string>
<string name="mpris_player_on_device">%2$s上的%1$s</string>
<string name="send_files">发送文件</string>
<string name="pairing_title">KDE Connect 设备</string>
@@ -170,6 +167,19 @@
<string name="pref_plugin_telepathy_desc">从桌面发送短消息</string>
<string name="plugin_not_supported">设备不支持此插件</string>
<string name="findmyphone_title">找到我的手机</string>
<string name="findmyphone_title_tablet">找到我的平板电脑</string>
<string name="findmyphone_description">让设备响铃从而找到它</string>
<string name="findmyphone_found">找到</string>
<string name="open">打开</string>
<string name="close">关闭</string>
<string name="no_permissions_storage">您需要授予权限以访问存储</string>
<string name="plugins_need_permission">某些插件需要权限才能工作 (点击以获取更多信息)</string>
<string name="permission_explanation">这个插件需要权限才能工作</string>
<string name="optional_permission_explanation">您需要授予额外权限以启用全部功能</string>
<string name="plugins_need_optional_permission">因缺少权限,某些插件的一些功能已禁用(点击以查看更多信息):</string>
<string name="sftp_permission_explanation">此应用需要手机存储权限才能从您的 PC 访问手机内的文件</string>
<string name="share_optional_permission_explanation">您需要给予访问手机存储的权限才能在手机和桌面计算机之间分享文件</string>
<string name="telepathy_permission_explanation">从计算机桌面读取、写入短消息需要向应用程序授予 SMS 权限</string>
<string name="telephony_permission_explanation">您必须给予访问手机通话和短信的权限才能从桌面计算机查看通话记录和短信</string>
<string name="telephony_optional_permission_explanation">要查看联系人姓名而非电话号码,您需要授予访问手机通讯录的权限</string>
</resources>

View File

@@ -31,7 +31,6 @@
<string name="send_ping">傳送Ping回應封包</string>
<string name="open_mpris_controls">多媒體控制</string>
<string name="open_mousepad">遠端輸入</string>
<string name="mousepad_info">在您的智慧型手機的螢幕上移動手指頭,用來控制電腦螢幕的鼠標。點擊表示滑鼠的左鍵,使用兩隻/三隻手指頭點擊來表示滑鼠的右鍵/中鍵。長按則表示要拖拉。</string>
<string name="mousepad_double_tap_settings_title">設定兩隻手指頭點擊的動作</string>
<string name="mousepad_triple_tap_settings_title">設定三隻手指頭點擊的動作</string>
<string name="mousepad_sensitivity_settings_title">設定觸碰板的靈敏度</string>
@@ -41,9 +40,6 @@
<item>中鍵點擊</item>
<item></item>
</string-array>
<string name="mousepad_double_default"></string>
<string name="mousepad_triple_default"></string>
<string name="mousepad_sensitivity_default">預設</string>
<string-array name="mousepad_sensitivity_entries">
<item></item>
<item>最慢</item>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MaxWidthImageButton">
<attr name="maxWidth" format="dimension" />
</declare-styleable>
</resources>

View File

@@ -39,7 +39,7 @@
<string name="remotekeyboard_connected" translatable="true">Remote keyboard connection is active</string>
<string name="remotekeyboard_multiple_connections" translatable="true">There is more than one remote keyboard connection, select the device to configure</string>
<string name="open_mousepad">Remote input</string>
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use 2 fingers to scroll. Use a long press to drag\'n drop.</string>
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
<string name="mousepad_sensitivity_settings_title">Set touchpad sensitivity</string>
@@ -53,9 +53,9 @@
<item>Middle click</item>
<item>Nothing</item>
</string-array>
<string name="mousepad_double_default">right</string>
<string name="mousepad_triple_default">middle</string>
<string name="mousepad_sensitivity_default">default</string>
<string name="mousepad_default_double" translatable="false">right</string>
<string name="mousepad_default_triple" translatable="false">middle</string>
<string name="mousepad_default_sensitivity" translatable="false">default</string>
<string-array name="mousepad_tap_values" translatable="false">
<item>right</item>
<item>middle</item>
@@ -206,4 +206,15 @@
<string name="open">Open</string>
<string name="close">Close</string>
<string name="no_permissions_storage">You need to grant permissions to access the storage</string>
<string name="plugins_need_permission">Some Plugins need permissions to work (tap for more info):</string>
<string name="permission_explanation">This plugin needs permissions to work</string>
<string name="optional_permission_explanation">You need to grant extra permissions to enable all functions</string>
<string name="plugins_need_optional_permission">Some plugins have features disabled because of lack of permission (tap for more info):</string>
<string name="sftp_permission_explanation">To access your files from your PC the app needs permission to access your phone\'s storage</string>
<string name="share_optional_permission_explanation">To share files between your phone and your desktop you need to give access to the phone\'s storage</string>
<string name="telepathy_permission_explanation">To read and write SMS from your desktop you need to give permission to SMS</string>
<string name="telephony_permission_explanation">To see phone calls and SMS from the desktop you need to give permission to phone calls and SMS</string>
<string name="telephony_optional_permission_explanation">To see a contact name instead of a phone number you need to give access to the phone\'s contacts</string>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="." />
</paths>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/general_settings">
<EditTextPreference
android:key="device_name_preference"
android:title="@string/device_name"
android:summary=""
android:dialogTitle="@string/device_name"
android:singleLine="true" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -5,30 +5,30 @@
<ListPreference
android:id="@+id/mousepad_double_tap_preference"
android:key="@string/mousepad_double_tap_key"
android:title="@string/mousepad_double_tap_settings_title"
android:summary="%s"
android:defaultValue="@string/mousepad_default_double"
android:entries="@array/mousepad_tap_entries"
android:entryValues="@array/mousepad_tap_values"
android:defaultValue="@string/mousepad_double_default" />
android:key="@string/mousepad_double_tap_key"
android:summary="%s"
android:title="@string/mousepad_double_tap_settings_title"/>
<ListPreference
android:id="@+id/mousepad_triple_tap_preference"
android:key="@string/mousepad_triple_tap_key"
android:title="@string/mousepad_triple_tap_settings_title"
android:summary="%s"
android:defaultValue="@string/mousepad_default_triple"
android:entries="@array/mousepad_tap_entries"
android:entryValues="@array/mousepad_tap_values"
android:defaultValue="@string/mousepad_triple_default" />
android:key="@string/mousepad_triple_tap_key"
android:summary="%s"
android:title="@string/mousepad_triple_tap_settings_title"/>
<ListPreference
android:id="@+id/mousepad_sensitivity_preference"
android:key="@string/mousepad_sensitivity_key"
android:title="@string/mousepad_sensitivity_settings_title"
android:summary="%s"
android:defaultValue="@string/mousepad_default_sensitivity"
android:entries="@array/mousepad_sensitivity_entries"
android:entryValues="@array/mousepad_sensitivity_values"
android:defaultValue="@string/mousepad_sensitivity_default" />
android:key="@string/mousepad_sensitivity_key"
android:summary="%s"
android:title="@string/mousepad_sensitivity_settings_title"/>
<CheckBoxPreference
android:id="@+id/mousepad_scroll_preference"

View File

@@ -0,0 +1,248 @@
/*
* Copyright 2016 Saikrishna Arcot <saiarcot895@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.Backends.BluetoothBackend;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import org.kde.kdeconnect.Backends.BaseLink;
import org.kde.kdeconnect.Backends.BasePairingHandler;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
import org.kde.kdeconnect.NetworkPackage;
import java.io.*;
import java.nio.charset.Charset;
import java.security.PublicKey;
import java.util.UUID;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class BluetoothLink extends BaseLink {
private final BluetoothSocket socket;
private final BluetoothLinkProvider linkProvider;
private boolean continueAccepting = true;
private Thread receivingThread = new Thread(new Runnable() {
@Override
public void run() {
StringBuilder sb = new StringBuilder();
try {
Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8");
char[] buf = new char[512];
while (continueAccepting) {
while (sb.indexOf("\n") == -1 && continueAccepting) {
int charsRead;
if ((charsRead = reader.read(buf)) > 0) {
sb.append(buf, 0, charsRead);
}
}
int endIndex = sb.indexOf("\n");
if (endIndex != -1) {
String message = sb.substring(0, endIndex + 1);
sb.delete(0, endIndex + 1);
processMessage(message);
}
}
} catch (IOException e) {
Log.e("BluetoothLink/receiving", "Connection to " + socket.getRemoteDevice().getAddress() + " likely broken.", e);
disconnect();
}
}
private void processMessage(String message) {
NetworkPackage np;
try {
np = NetworkPackage.unserialize(message);
} catch (JSONException e) {
Log.e("BluetoothLink/receiving", "Unable to parse message.", e);
return;
}
if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_ENCRYPTED)) {
try {
np = RsaHelper.decrypt(np, privateKey);
} catch(Exception e) {
Log.e("BluetoothLink/receiving", "Exception decrypting the package", e);
}
}
if (np.hasPayloadTransferInfo()) {
BluetoothSocket transferSocket = null;
try {
UUID transferUuid = UUID.fromString(np.getPayloadTransferInfo().getString("uuid"));
transferSocket = socket.getRemoteDevice().createRfcommSocketToServiceRecord(transferUuid);
transferSocket.connect();
np.setPayload(transferSocket.getInputStream(), np.getPayloadSize());
} catch (Exception e) {
if (transferSocket != null) {
try { transferSocket.close(); } catch(IOException ignored) { }
}
Log.e("BluetoothLink/receiving", "Unable to get payload", e);
}
}
packageReceived(np);
}
});
public BluetoothLink(Context context, BluetoothSocket socket, String deviceId, BluetoothLinkProvider linkProvider) {
super(context, deviceId, linkProvider);
this.socket = socket;
this.linkProvider = linkProvider;
}
public void startListening() {
this.receivingThread.start();
}
@Override
public String getName() {
return "BluetoothLink";
}
@Override
public BasePairingHandler getPairingHandler(Device device, BasePairingHandler.PairingHandlerCallback callback) {
return new BluetoothPairingHandler(device, callback);
}
public void disconnect() {
if (socket == null) {
return;
}
continueAccepting = false;
try {
socket.close();
} catch (IOException e) {
}
linkProvider.disconnectedLink(this, getDeviceId(), socket);
}
private void sendMessage(NetworkPackage np) throws JSONException, IOException {
byte[] message = np.serialize().getBytes(Charset.forName("UTF-8"));
OutputStream socket = this.socket.getOutputStream();
Log.i("BluetoothLink","Beginning to send message");
socket.write(message);
Log.i("BluetoothLink","Finished sending message");
}
@Override
public boolean sendPackage(NetworkPackage np, Device.SendPackageStatusCallback callback) {
return sendPackageInternal(np, callback, null);
}
@Override
public boolean sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
return sendPackageInternal(np, callback, key);
}
private boolean sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) {
/*if (!isConnected()) {
Log.e("BluetoothLink", "sendPackageEncrypted failed: not connected");
callback.sendFailure(new Exception("Not connected"));
return;
}*/
try {
BluetoothServerSocket serverSocket = null;
if (np.hasPayload()) {
UUID transferUuid = UUID.randomUUID();
serverSocket = BluetoothAdapter.getDefaultAdapter()
.listenUsingRfcommWithServiceRecord("KDE Connect Transfer", transferUuid);
JSONObject payloadTransferInfo = new JSONObject();
payloadTransferInfo.put("uuid", transferUuid.toString());
np.setPayloadTransferInfo(payloadTransferInfo);
}
if (key != null) {
try {
np = RsaHelper.encrypt(np, key);
} catch (Exception e) {
callback.onFailure(e);
return false;
}
}
sendMessage(np);
if (serverSocket != null) {
BluetoothSocket transferSocket = serverSocket.accept();
try {
serverSocket.close();
int idealBufferLength = 4096;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& transferSocket.getMaxReceivePacketSize() > 0) {
idealBufferLength = transferSocket.getMaxReceivePacketSize();
}
byte[] buffer = new byte[idealBufferLength];
int bytesRead;
long progress = 0;
InputStream stream = np.getPayload();
while ((bytesRead = stream.read(buffer)) != -1) {
progress += bytesRead;
transferSocket.getOutputStream().write(buffer, 0, bytesRead);
if (np.getPayloadSize() > 0) {
callback.onProgressChanged((int) (100 * progress / np.getPayloadSize()));
}
}
transferSocket.getOutputStream().flush();
stream.close();
} catch (Exception e) {
callback.onFailure(e);
return false;
} finally {
try { transferSocket.close(); } catch (IOException ignored) { }
}
}
callback.onSuccess();
return true;
} catch (Exception e) {
callback.onFailure(e);
return false;
}
}
@Override
public boolean linkShouldBeKeptAlive() {
return receivingThread.isAlive();
}
/*
public boolean isConnected() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
return socket.isConnected();
} else {
return true;
}
}
*/
}

View File

@@ -0,0 +1,378 @@
/*
* Copyright 2016 Saikrishna Arcot <saiarcot895@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.Backends.BluetoothBackend;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothServerSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Parcelable;
import android.util.Log;
import org.kde.kdeconnect.Backends.BaseLinkProvider;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.NetworkPackage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.Set;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class BluetoothLinkProvider extends BaseLinkProvider {
private static final UUID SERVICE_UUID = UUID.fromString("185f3df4-3268-4e3f-9fca-d4d5059915bd");
private static final int REQUEST_ENABLE_BT = 48;
private final Context context;
private final Map<String, BluetoothLink> visibleComputers = new HashMap<>();
private final Map<BluetoothDevice, BluetoothSocket> sockets = new HashMap<>();
private BluetoothAdapter bluetoothAdapter = null;
private ServerRunnable serverRunnable;
private ClientRunnable clientRunnable;
private void addLink(NetworkPackage identityPackage, BluetoothLink link) {
String deviceId = identityPackage.getString("deviceId");
Log.i("BluetoothLinkProvider","addLink to "+deviceId);
BluetoothLink oldLink = visibleComputers.get(deviceId);
if (oldLink == link) {
Log.e("BluetoothLinkProvider", "oldLink == link. This should not happen!");
return;
}
visibleComputers.put(deviceId, link);
connectionAccepted(identityPackage, link);
link.startListening();
if (oldLink != null) {
Log.i("BluetoothLinkProvider","Removing old connection to same device");
oldLink.disconnect();
}
}
public BluetoothLinkProvider(Context context) {
this.context = context;
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Log.e("BluetoothLinkProvider","No bluetooth adapter found.");
}
}
@Override
public void onStart() {
if (bluetoothAdapter == null) {
return;
}
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
Log.e("BluetoothLinkProvider","Bluetooth adapter not enabled.");
// TODO: next line needs to be called from an existing activity, so move it?
// startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
// TODO: Check result of the previous command, whether the user allowed bluetooth or not.
return;
}
//This handles the case when I'm the existing device in the network and receive a hello package
clientRunnable = new ClientRunnable();
new Thread(clientRunnable).start();
// I'm on a new network, let's be polite and introduce myself
serverRunnable = new ServerRunnable();
new Thread(serverRunnable).start();
}
@Override
public void onNetworkChange() {
onStop();
onStart();
}
@Override
public void onStop() {
if (bluetoothAdapter == null || clientRunnable == null || serverRunnable == null) {
return;
}
clientRunnable.stopProcessing();
serverRunnable.stopProcessing();
}
@Override
public String getName() {
return "BluetoothLinkProvider";
}
public void disconnectedLink(BluetoothLink link, String deviceId, BluetoothSocket socket) {
sockets.remove(socket.getRemoteDevice());
visibleComputers.remove(deviceId);
connectionLost(link);
}
private class ServerRunnable implements Runnable {
private boolean continueProcessing = true;
private BluetoothServerSocket serverSocket;
void stopProcessing() {
continueProcessing = false;
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
try {
serverSocket = bluetoothAdapter
.listenUsingRfcommWithServiceRecord("KDE Connect", SERVICE_UUID);
} catch (IOException e) {
e.printStackTrace();
return;
}
if (continueProcessing) {
try {
BluetoothSocket socket = serverSocket.accept();
connect(socket);
} catch (Exception ignored) {
}
}
}
private void connect(BluetoothSocket socket) throws Exception {
//socket.connect();
OutputStream outputStream = socket.getOutputStream();
if (sockets.containsKey(socket.getRemoteDevice())) {
Log.i("BTLinkProvider/Server", "Received duplicate connection from " + socket.getRemoteDevice().getAddress());
socket.close();
return;
} else {
sockets.put(socket.getRemoteDevice(), socket);
}
Log.i("BTLinkProvider/Server", "Received connection from " + socket.getRemoteDevice().getAddress());
NetworkPackage np = NetworkPackage.createIdentityPackage(context);
byte[] message = np.serialize().getBytes("UTF-8");
outputStream.write(message);
Log.i("BTLinkProvider/Server", "Sent identity package");
// Listen for the response
StringBuilder sb = new StringBuilder();
Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8");
int charsRead;
char[] buf = new char[512];
while(sb.lastIndexOf("\n") == -1 && (charsRead = reader.read(buf)) != -1) {
sb.append(buf, 0, charsRead);
}
String response = sb.toString();
final NetworkPackage identityPackage = NetworkPackage.unserialize(response);
if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
Log.e("BTLinkProvider/Server", "2 Expecting an identity package");
return;
}
Log.i("BTLinkProvider/Server", "Received identity package");
BluetoothLink link = new BluetoothLink(context, socket,
identityPackage.getString("deviceId"), BluetoothLinkProvider.this);
addLink(identityPackage, link);
}
}
private class ClientRunnable extends BroadcastReceiver implements Runnable {
private boolean continueProcessing = true;
private Map<BluetoothDevice, Thread> connectionThreads = new HashMap<>();
void stopProcessing() {
continueProcessing = false;
}
@Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_UUID);
context.registerReceiver(this, filter);
}
while (continueProcessing) {
connectToDevices();
try {
Thread.sleep(15000);
} catch (InterruptedException ignored) {
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
context.unregisterReceiver(this);
}
}
private void connectToDevices() {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
Log.i("BluetoothLinkProvider", "Bluetooth adapter paired devices: " + pairedDevices.size());
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
if (sockets.containsKey(device)) {
continue;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
device.fetchUuidsWithSdp();
} else {
connectToDevice(device);
}
}
}
@Override
@TargetApi(value=Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(BluetoothDevice.ACTION_UUID)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Parcelable[] activeUuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
if (sockets.containsKey(device)) {
return;
}
if (activeUuids == null) {
return;
}
for (Parcelable uuid: activeUuids) {
if (uuid.toString().equals(SERVICE_UUID.toString())) {
connectToDevice(device);
return;
}
}
}
}
private void connectToDevice(BluetoothDevice device) {
if (!connectionThreads.containsKey(device) || !connectionThreads.get(device).isAlive()) {
Thread connectionThread = new Thread(new ClientConnect(device));
connectionThread.start();
connectionThreads.put(device, connectionThread);
}
}
}
private class ClientConnect implements Runnable {
private final BluetoothDevice device;
public ClientConnect(BluetoothDevice device) {
this.device = device;
}
@Override
public void run() {
connectToDevice();
}
private void connectToDevice() {
BluetoothSocket socket;
try {
socket = device.createRfcommSocketToServiceRecord(SERVICE_UUID);
socket.connect();
sockets.put(device, socket);
} catch (IOException e) {
Log.e("BTLinkProvider/Client", "Could not connect to KDE Connect service on " + device.getAddress(), e);
return;
}
Log.i("BTLinkProvider/Client", "Connected to " + device.getAddress());
try {
int character;
StringBuilder sb = new StringBuilder();
while(sb.lastIndexOf("\n") == -1 && (character = socket.getInputStream().read()) != -1) {
sb.append((char)character);
}
String message = sb.toString();
final NetworkPackage identityPackage = NetworkPackage.unserialize(message);
if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
Log.e("BTLinkProvider/Client", "1 Expecting an identity package");
socket.close();
return;
}
Log.i("BTLinkProvider/Client", "Received identity package");
String myId = NetworkPackage.createIdentityPackage(context).getString("deviceId");
if (identityPackage.getString("deviceId").equals(myId)) {
// Probably won't happen, but just to be safe
socket.close();
return;
}
if (visibleComputers.containsKey(identityPackage.getString("deviceId"))) {
return;
}
Log.i("BTLinkProvider/Client", "Identity package received, creating link");
final BluetoothLink link = new BluetoothLink(context, socket,
identityPackage.getString("deviceId"), BluetoothLinkProvider.this);
NetworkPackage np2 = NetworkPackage.createIdentityPackage(context);
link.sendPackage(np2,new Device.SendPackageStatusCallback() {
@Override
public void onSuccess() {
addLink(identityPackage, link);
}
@Override
public void onFailure(Throwable e) {
}
});
} catch (Exception e) {
Log.e("BTLinkProvider/Client", "Connection lost/disconnected on " + device.getAddress(), e);
}
}
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright 2015 Vineet Garg <grg.vineet@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.Backends.BluetoothBackend;
import android.util.Log;
import org.kde.kdeconnect.Backends.BasePairingHandler;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect_tp.R;
import java.util.Timer;
import java.util.TimerTask;
public class BluetoothPairingHandler extends BasePairingHandler {
Timer mPairingTimer;
public BluetoothPairingHandler(Device device, final PairingHandlerCallback callback) {
super(device, callback);
if (device.isPaired()) {
mPairStatus = PairStatus.Paired;
} else {
mPairStatus = PairStatus.NotPaired;
}
}
// @Override
public NetworkPackage createPairPackage() {
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
np.set("pair", true);
return np;
}
@Override
public void packageReceived(NetworkPackage np) throws Exception{
boolean wantsPair = np.getBoolean("pair");
if (wantsPair == isPaired()) {
if (mPairStatus == PairStatus.Requested) {
//Log.e("Device","Unpairing (pair rejected)");
mPairStatus = PairStatus.NotPaired;
hidePairingNotification();
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer));
}
return;
}
if (wantsPair) {
if (mPairStatus == PairStatus.Requested) { //We started pairing
hidePairingNotification();
pairingDone();
} else {
// If device is already paired, accept pairing silently
if (mDevice.isPaired()) {
acceptPairing();
return;
}
// Pairing notifications are still managed by device as there is no other way to
// know about notificationId to cancel notification when PairActivity is started
// Even putting notificationId in intent does not work because PairActivity can be
// started from MainActivity too, so then notificationId cannot be set
hidePairingNotification();
mDevice.displayPairingNotification();
mPairingTimer = new Timer();
mPairingTimer.schedule(new TimerTask() {
@Override
public void run() {
Log.w("KDE/Device","Unpairing (timeout B)");
mPairStatus = PairStatus.NotPaired;
hidePairingNotification();
}
}, 25*1000); //Time to show notification, waiting for user to accept (peer will timeout in 30 seconds)
mPairStatus = PairStatus.RequestedByPeer;
mCallback.incomingRequest();
}
} else {
Log.i("KDE/Pairing", "Unpair request");
if (mPairStatus == PairStatus.Requested) {
hidePairingNotification();
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer));
} else if (mPairStatus == PairStatus.Paired) {
mCallback.unpaired();
}
mPairStatus = PairStatus.NotPaired;
}
}
@Override
public void requestPairing() {
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
@Override
public void onSuccess() {
hidePairingNotification(); //Will stop the pairingTimer if it was running
mPairingTimer = new Timer();
mPairingTimer.schedule(new TimerTask() {
@Override
public void run() {
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_timed_out));
Log.w("KDE/Device","Unpairing (timeout A)");
mPairStatus = PairStatus.NotPaired;
}
}, 30*1000); //Time to wait for the other to accept
mPairStatus = PairStatus.Requested;
}
@Override
public void onFailure(Throwable e) {
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_could_not_send_package));
}
};
mDevice.sendPackage(createPairPackage(), statusCallback);
}
public void hidePairingNotification() {
mDevice.hidePairingNotification();
if (mPairingTimer != null) {
mPairingTimer .cancel();
}
}
@Override
public void acceptPairing() {
hidePairingNotification();
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
@Override
public void onSuccess() {
pairingDone();
}
@Override
public void onFailure(Throwable e) {
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_not_reachable));
}
};
mDevice.sendPackage(createPairPackage(), statusCallback);
}
@Override
public void rejectPairing() {
hidePairingNotification();
mPairStatus = PairStatus.NotPaired;
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
np.set("pair", false);
mDevice.sendPackage(np);
}
//@Override
public void pairingDone() {
// Store device information needed to create a Device object in a future
//Log.e("KDE/PairingDone", "Pairing Done");
mPairStatus = PairStatus.Paired;
mCallback.pairingDone();
}
@Override
public void unpair() {
mPairStatus = PairStatus.NotPaired;
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
np.set("pair", false);
mDevice.sendPackage(np);
}
}

View File

@@ -265,7 +265,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
}
private void addLink(final NetworkPackage identityPackage, Socket socket, LanLink.ConnectionStarted connectionOrigin) throws IOException {
private synchronized void addLink(final NetworkPackage identityPackage, Socket socket, LanLink.ConnectionStarted connectionOrigin) throws IOException {
String deviceId = identityPackage.getString("deviceId");
LanLink currentLink = visibleComputers.get(deviceId);

View File

@@ -26,11 +26,13 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import org.kde.kdeconnect.Backends.BaseLink;
import org.kde.kdeconnect.Backends.BaseLinkProvider;
//import org.kde.kdeconnect.Backends.BluetoothBackend.BluetoothLinkProvider;
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
@@ -44,6 +46,8 @@ import java.util.concurrent.locks.ReentrantLock;
public class BackgroundService extends Service {
private static BackgroundService instance;
public interface DeviceListChangedCallback {
void onDeviceListChanged();
}
@@ -56,6 +60,10 @@ public class BackgroundService extends Service {
private final HashSet<Object> discoveryModeAcquisitions = new HashSet<>();
public static BackgroundService getInstance(){
return instance;
}
public boolean acquireDiscoveryMode(Object key) {
boolean wasEmpty = discoveryModeAcquisitions.isEmpty();
discoveryModeAcquisitions.add(key);
@@ -140,11 +148,11 @@ public class BackgroundService extends Service {
}
private void registerLinkProviders() {
//linkProviders.add(new LoopbackLinkProvider(this));
linkProviders.add(new LanLinkProvider(this));
// linkProviders.add(new LoopbackLinkProvider(this));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// linkProviders.add(new BluetoothLinkProvider(this));
}
}
public ArrayList<BaseLinkProvider> getLinkProviders() {
@@ -248,6 +256,8 @@ public class BackgroundService extends Service {
public void onCreate() {
super.onCreate();
instance = this;
// Register screen on listener
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
registerReceiver(new KdeConnectBroadcastReceiver(), filter);

View File

@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
@@ -82,7 +83,9 @@ public class Device implements BaseLink.PackageReceiver {
private List<String> m_supportedPlugins = new ArrayList<>();
private final ConcurrentHashMap<String, Plugin> plugins = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Plugin> failedPlugins = new ConcurrentHashMap<>();
private Map<String, ArrayList<String>> pluginsByIncomingInterface;
private final ConcurrentHashMap<String, Plugin> pluginsWithoutPermissions = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Plugin> pluginsWithoutOptionalPermissions = new ConcurrentHashMap<>();
private Map<String, ArrayList<String>> pluginsByIncomingInterface = new HashMap<>();
private final SharedPreferences settings;
@@ -691,7 +694,20 @@ public class Device implements BaseLink.PackageReceiver {
private synchronized boolean addPlugin(final String pluginKey) {
Plugin existing = plugins.get(pluginKey);
if (existing != null) {
if (existing.getMinSdk() > Build.VERSION.SDK_INT) {
Log.i("KDE/addPlugin", "Min API level not fulfilled " + pluginKey);
return false;
}
//Log.w("KDE/addPlugin","plugin already present:" + pluginKey);
if (existing.checkOptionalPermissions()) {
Log.i("KDE/addPlugin", "Optional Permissions OK " + pluginKey);
pluginsWithoutOptionalPermissions.remove(pluginKey);
} else {
Log.e("KDE/addPlugin", "No optional permission " + pluginKey);
pluginsWithoutOptionalPermissions.put(pluginKey, existing);
}
return true;
}
@@ -703,6 +719,11 @@ public class Device implements BaseLink.PackageReceiver {
return false;
}
if (plugin.getMinSdk() > Build.VERSION.SDK_INT) {
Log.i("KDE/addPlugin", "Min API level not fulfilled" + pluginKey);
return false;
}
boolean success;
try {
success = plugin.onCreate();
@@ -722,6 +743,24 @@ public class Device implements BaseLink.PackageReceiver {
failedPlugins.put(pluginKey, plugin);
}
if(!plugin.checkRequiredPermissions()){
Log.e("KDE/addPlugin", "No permission " + pluginKey);
plugins.remove(pluginKey);
pluginsWithoutPermissions.put(pluginKey, plugin);
success = false;
} else {
Log.i("KDE/addPlugin", "Permissions OK " + pluginKey);
pluginsWithoutPermissions.remove(pluginKey);
if (plugin.checkOptionalPermissions()) {
Log.i("KDE/addPlugin", "Optional Permissions OK " + pluginKey);
pluginsWithoutOptionalPermissions.remove(pluginKey);
} else {
Log.e("KDE/addPlugin", "No optional permission " + pluginKey);
pluginsWithoutOptionalPermissions.put(pluginKey, plugin);
}
}
return success;
}
@@ -812,6 +851,14 @@ public class Device implements BaseLink.PackageReceiver {
return failedPlugins;
}
public ConcurrentHashMap<String, Plugin> getPluginsWithoutPermissions() {
return pluginsWithoutPermissions;
}
public ConcurrentHashMap<String,Plugin> getPluginsWithoutOptionalPermissions() {
return pluginsWithoutOptionalPermissions;
}
public void addPluginsChangedListener(PluginsChangedListener listener) {
pluginsChangedListeners.add(listener);
}

View File

@@ -59,7 +59,7 @@ public class ContactsHelper {
, PhoneLookup.ID */
},
null, null, null);
} catch (IllegalArgumentException e) {
} catch (Exception e) {
return contactInfo;
}

View File

@@ -2,17 +2,57 @@ package org.kde.kdeconnect.Helpers;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.util.Log;
import java.io.FileReader;
import java.io.LineNumberReader;
public class NetworkHelper {
public static boolean isOnMobileNetwork(Context context) {
return false; //This looks a bit dangerous and I prefer not to use it in the next stable release.
/*final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connMgr.getActiveNetworkInfo();
return (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE);
*/
if (context == null) {
return false;
}
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
return false; //No good way to know it
}
try {
boolean mobile = false;
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] networks = connMgr.getAllNetworks();
for (Network network : networks) {
NetworkInfo info = connMgr.getNetworkInfo(network);
if (info == null) {
continue;
}
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
mobile = info.isConnected();
continue;
}
//Log.e(info.getTypeName(),""+info.isAvailable());
if (info.isAvailable()) return false; //We are connected to at least one non-mobile network
}
if (mobile) { //We suspect we are on a mobile net
try {
//Check the number of network neighbours, on data it should be 0
LineNumberReader is = new LineNumberReader(new FileReader("/proc/net/arp"));
is.skip(Long.MAX_VALUE);
//Log.e("NetworkHelper", "procnetarp has " + is.getLineNumber() + " lines");
if (is.getLineNumber() > 1) { //The first line are the headers
return false; //I have neighbours, so this doesn't look like a mobile network
}
} catch (Exception e) {
Log.e("NetworkHelper", "Exception reading procnetarp");
e.printStackTrace();
}
}
} catch(Exception e) {
e.printStackTrace();
Log.d("isOnMobileNetwork", "Something went wrong, but this is non-critical.");
}
return false;
}
}

View File

@@ -220,6 +220,7 @@ public class SslHelper {
// Following ciphers are for and due to old devices
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA"); // API 9+
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5"); // API 9+
supportedCiphers.add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA"); // API 9+
}
socket.setEnabledCipherSuites(supportedCiphers.toArray(new String[supportedCiphers.size()]));

View File

@@ -40,7 +40,7 @@ public class BatteryPlugin extends Plugin {
private static final int THRESHOLD_EVENT_NONE= 0;
private static final int THRESHOLD_EVENT_BATTERY_LOW = 1;
private NetworkPackage lastInfo = null;
private NetworkPackage batteryInfo = new NetworkPackage(PACKAGE_TYPE_BATTERY);
@Override
public String getDisplayName() {
@@ -56,18 +56,18 @@ public class BatteryPlugin extends Plugin {
@Override
public void onReceive(Context context, Intent batteryIntent) {
Intent batteryChargeIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int level = batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
int currentCharge = level*100 / scale;
boolean isCharging = (0 != batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
int plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
int currentCharge = (level == -1)? batteryInfo.getInt("currentCharge") : level*100 / scale;
boolean isCharging = (plugged == -1)? batteryInfo.getBoolean("isCharging") : (0 != plugged);
boolean lowBattery = Intent.ACTION_BATTERY_LOW.equals(batteryIntent.getAction());
int thresholdEvent = lowBattery? THRESHOLD_EVENT_BATTERY_LOW : THRESHOLD_EVENT_NONE;
if (lastInfo != null
&& isCharging == lastInfo.getBoolean("isCharging")
&& currentCharge == lastInfo.getInt("currentCharge")
&& thresholdEvent == lastInfo.getInt("thresholdEvent")
if (isCharging == batteryInfo.getBoolean("isCharging")
&& currentCharge == batteryInfo.getInt("currentCharge")
&& thresholdEvent == batteryInfo.getInt("thresholdEvent")
) {
//Do not send again if nothing has changed
@@ -75,12 +75,10 @@ public class BatteryPlugin extends Plugin {
} else {
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_BATTERY);
np.set("currentCharge", currentCharge);
np.set("isCharging", isCharging);
np.set("thresholdEvent", thresholdEvent);
device.sendPackage(np);
lastInfo = np;
batteryInfo.set("currentCharge", currentCharge);
batteryInfo.set("isCharging", isCharging);
batteryInfo.set("thresholdEvent", thresholdEvent);
device.sendPackage(batteryInfo);
}
@@ -89,8 +87,10 @@ public class BatteryPlugin extends Plugin {
@Override
public boolean onCreate() {
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_LOW));
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
context.registerReceiver(receiver, intentFilter);
return true;
}
@@ -104,9 +104,7 @@ public class BatteryPlugin extends Plugin {
public boolean onPackageReceived(NetworkPackage np) {
if (np.getBoolean("request")) {
if (lastInfo != null) {
device.sendPackage(lastInfo);
}
device.sendPackage(batteryInfo);
}
return true;

View File

@@ -1,10 +1,10 @@
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
@@ -16,13 +16,16 @@ import android.view.WindowManager;
import org.kde.kdeconnect_tp.R;
public class FindMyPhoneActivity extends Activity {
Ringtone ringtone;
private MediaPlayer mediaPlayer;
private int previousVolume;
private AudioManager audioManager;
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(ringtone != null) {
if (mediaPlayer != null) {
// If this activity was already open and we received the ring packet again, just finish it
finish();
}
@@ -34,10 +37,12 @@ public class FindMyPhoneActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find_my_phone);
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() {
@Override
@@ -51,36 +56,37 @@ public class FindMyPhoneActivity extends Activity {
protected void onStart() {
super.onStart();
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
if (ringtone == null) {
ringtoneUri = RingtoneManager.getValidRingtoneUri(getApplicationContext());
if (ringtoneUri == null) {
Log.e("FindMyPhone", "Could not find a ringtone to play!");
return;
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);
Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
if (alert == null) {
alert = RingtoneManager.getValidRingtoneUri(getApplicationContext());
}
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(this, alert);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mediaPlayer.setLooping(true);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception e) {
Log.e("FindMyPhoneActivity", "Exception", e);
}
if (android.os.Build.VERSION.SDK_INT >= 21) {
AudioAttributes.Builder b = new AudioAttributes.Builder();
b.setUsage(AudioAttributes.USAGE_ALARM);
ringtone.setAudioAttributes(b.build());
} else {
ringtone.setStreamType(AudioManager.STREAM_ALARM);
}
ringtone.play();
}
@Override
protected void onStop() {
super.onStop();
if(ringtone != null) {
ringtone.stop();
ringtone = null;
if (mediaPlayer != null) {
mediaPlayer.stop();
}
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, previousVolume, 0);
}
}

View File

@@ -25,7 +25,7 @@ import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.HapticFeedbackConstants;
import android.view.Menu;
@@ -39,7 +39,7 @@ import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect_tp.R;
public class MousePadActivity extends ActionBarActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MousePadGestureDetector.OnGestureListener {
public class MousePadActivity extends AppCompatActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MousePadGestureDetector.OnGestureListener {
String deviceId;
private final static float MinDistanceToSendScroll = 2.5f; // touch gesture scroll
@@ -97,11 +97,11 @@ public class MousePadActivity extends ActionBarActivity implements GestureDetect
scrollDirection = 1;
}
String doubleTapSetting = prefs.getString(getString(R.string.mousepad_double_tap_key),
getString(R.string.mousepad_double_default));
getString(R.string.mousepad_default_double));
String tripleTapSetting = prefs.getString(getString(R.string.mousepad_triple_tap_key),
getString(R.string.mousepad_triple_default));
getString(R.string.mousepad_default_triple));
String sensitivitySetting = prefs.getString(getString(R.string.mousepad_sensitivity_key),
getString(R.string.mousepad_sensitivity_default));
getString(R.string.mousepad_default_sensitivity));
doubleTapAction = ClickType.fromString(doubleTapSetting);
tripleTapAction = ClickType.fromString(tripleTapSetting);

View File

@@ -26,7 +26,7 @@ import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -46,12 +46,12 @@ import org.kde.kdeconnect_tp.R;
import java.util.List;
public class MprisActivity extends ActionBarActivity {
public class MprisActivity extends AppCompatActivity {
private String deviceId;
private final Handler positionSeekUpdateHandler = new Handler();
private Runnable positionSeekUpdateRunnable = null;
private String targetPlayer = null;
private MprisPlugin.MprisPlayer targetPlayer = null;
private static String milisToProgress(long milis) {
int length = (int)(milis / 1000); //From milis to seconds
@@ -69,7 +69,7 @@ public class MprisActivity extends ActionBarActivity {
text.append(seconds);
return text.toString();
}
protected void connectToPlugin() {
protected void connectToPlugin(final String targetPlayerName) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
@Override
@@ -81,6 +81,7 @@ public class MprisActivity extends ActionBarActivity {
Log.e("MprisActivity", "device has no mpris plugin!");
return;
}
targetPlayer = mpris.getPlayerStatus(targetPlayerName);
mpris.setPlayerStatusUpdatedHandler("activity", new Handler() {
@Override
@@ -88,49 +89,7 @@ public class MprisActivity extends ActionBarActivity {
runOnUiThread(new Runnable() {
@Override
public void run() {
String song = mpris.getCurrentSong();
TextView nowPlaying = (TextView) findViewById(R.id.now_playing_textview);
if (!nowPlaying.getText().toString().equals(song)) {
nowPlaying.setText(song);
}
//Hacks for Spotify because it reports incorrect info about what it supports
boolean isSpotify = "spotify".equals(mpris.getPlayer().toLowerCase());
if (mpris.getLength() > -1 && mpris.getPosition() > -1 && !isSpotify) {
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(mpris.getLength()));
SeekBar positionSeek = (SeekBar)findViewById(R.id.positionSeek);
positionSeek.setMax((int)(mpris.getLength()));
positionSeek.setProgress((int)(mpris.getPosition()));
findViewById(R.id.progress_slider).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.progress_slider).setVisibility(View.GONE);
}
int volume = mpris.getVolume();
((SeekBar) findViewById(R.id.volume_seek)).setProgress(volume);
boolean isPlaying = mpris.isPlaying();
if (isPlaying) {
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_pause);
findViewById(R.id.play_button).setVisibility(mpris.isPauseAllowed() ? View.VISIBLE : View.GONE);
} else {
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_play);
findViewById(R.id.play_button).setVisibility(mpris.isPlayAllowed() ? View.VISIBLE : View.GONE);
}
if (isSpotify) {
findViewById(R.id.volume_layout).setVisibility(View.INVISIBLE);
findViewById(R.id.rew_button).setVisibility(View.GONE);
findViewById(R.id.ff_button).setVisibility(View.GONE);
} else {
findViewById(R.id.volume_layout).setVisibility(View.VISIBLE);
findViewById(R.id.rew_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
findViewById(R.id.ff_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
}
findViewById(R.id.next_button).setVisibility(mpris.isGoNextAllowed() ? View.VISIBLE : View.GONE);
findViewById(R.id.prev_button).setVisibility(mpris.isGoPreviousAllowed() ? View.VISIBLE : View.GONE);
updatePlayerStatus(mpris);
}
});
}
@@ -169,36 +128,28 @@ public class MprisActivity extends ActionBarActivity {
if (pos >= playerList.size()) return;
String player = playerList.get(pos);
if (player.equals(mpris.getPlayer())) {
if (targetPlayer != null && player.equals(targetPlayer.getPlayer())) {
return; //Player hasn't actually changed
}
mpris.setPlayer(player);
//Clear values from previous player
((TextView) findViewById(R.id.now_playing_textview)).setText("");
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(0));
((SeekBar)findViewById(R.id.positionSeek)).setMax(0);
targetPlayer = mpris.getPlayerStatus(player);
updatePlayerStatus(mpris);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
mpris.setPlayer(null);
targetPlayer = null;
}
});
if (targetPlayer != null) {
int targetIndex = adapter.getPosition(targetPlayer);
int targetIndex = adapter.getPosition(targetPlayer.getPlayer());
if (targetIndex >= 0) {
spinner.setSelection(targetIndex);
}
targetPlayer = null;
} else {
// restore last selected player
int position = adapter.getPosition(mpris.getPlayer());
if (position >= 0) {
spinner.setSelection(position);
} else {
targetPlayer = null;
}
}
updatePlayerStatus(mpris);
}
});
}
@@ -212,7 +163,7 @@ public class MprisActivity extends ActionBarActivity {
private final BaseLinkProvider.ConnectionReceiver connectionReceiver = new BaseLinkProvider.ConnectionReceiver() {
@Override
public void onConnectionReceived(NetworkPackage identityPackage, BaseLink link) {
connectToPlugin();
connectToPlugin(null);
}
@Override
@@ -232,14 +183,59 @@ public class MprisActivity extends ActionBarActivity {
});
}
private void updatePlayerStatus(MprisPlugin mpris) {
MprisPlugin.MprisPlayer playerStatus = targetPlayer;
if (playerStatus == null) {
//No player with that name found, just display "empty" data
playerStatus = mpris.getEmptyPlayer();
}
String song = playerStatus.getCurrentSong();
TextView nowPlaying = (TextView) findViewById(R.id.now_playing_textview);
if (!nowPlaying.getText().toString().equals(song)) {
nowPlaying.setText(song);
}
if (playerStatus.isSeekAllowed()) {
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(playerStatus.getLength()));
SeekBar positionSeek = (SeekBar)findViewById(R.id.positionSeek);
positionSeek.setMax((int)(playerStatus.getLength()));
positionSeek.setProgress((int)(playerStatus.getPosition()));
findViewById(R.id.progress_slider).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.progress_slider).setVisibility(View.GONE);
}
int volume = playerStatus.getVolume();
((SeekBar) findViewById(R.id.volume_seek)).setProgress(volume);
boolean isPlaying = playerStatus.isPlaying();
if (isPlaying) {
((ImageButton) findViewById(R.id.play_button)).setImageResource(R.drawable.ic_pause_black);
findViewById(R.id.play_button).setVisibility(playerStatus.isPauseAllowed() ? View.VISIBLE : View.GONE);
} else {
((ImageButton) findViewById(R.id.play_button)).setImageResource(R.drawable.ic_play_black);
findViewById(R.id.play_button).setVisibility(playerStatus.isPlayAllowed() ? View.VISIBLE : View.GONE);
}
findViewById(R.id.volume_layout).setVisibility(playerStatus.isSetVolumeAllowed() ? View.VISIBLE : View.INVISIBLE);
findViewById(R.id.rew_button).setVisibility(playerStatus.isSeekAllowed() ? View.VISIBLE : View.GONE);
findViewById(R.id.ff_button).setVisibility(playerStatus.isSeekAllowed() ? View.VISIBLE : View.GONE);
findViewById(R.id.next_button).setVisibility(playerStatus.isGoNextAllowed() ? View.VISIBLE : View.GONE);
findViewById(R.id.prev_button).setVisibility(playerStatus.isGoPreviousAllowed() ? View.VISIBLE : View.GONE);
}
/**
* Change current volume with provided step.
*
* @param mpris multimedia controller
* @param step step size volume change
*/
private void updateVolume(MprisPlugin mpris, int step) {
final int currentVolume = mpris.getVolume();
private void updateVolume(int step) {
if (targetPlayer == null) {
return;
}
final int currentVolume = targetPlayer.getVolume();
if(currentVolume < 100 || currentVolume > 0) {
int newVolume = currentVolume + step;
if(newVolume > 100) {
@@ -247,7 +243,7 @@ public class MprisActivity extends ActionBarActivity {
} else if (newVolume <0 ) {
newVolume = 0;
}
mpris.setVolume(newVolume);
targetPlayer.setVolume(newVolume);
}
}
@@ -255,26 +251,10 @@ public class MprisActivity extends ActionBarActivity {
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
updateVolume(mpris, 5);
}
});
updateVolume(5);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
updateVolume(mpris, -5);
}
});
updateVolume(-5);
return true;
default:
return super.onKeyDown(keyCode, event);
@@ -298,7 +278,7 @@ public class MprisActivity extends ActionBarActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.mpris_control);
targetPlayer = getIntent().getStringExtra("player");
final String targetPlayerName = getIntent().getStringExtra("player");
getIntent().removeExtra("player");
deviceId = getIntent().getStringExtra("deviceId");
@@ -313,7 +293,7 @@ public class MprisActivity extends ActionBarActivity {
service.addConnectionListener(connectionReceiver);
}
});
connectToPlugin();
connectToPlugin(targetPlayerName);
findViewById(R.id.play_button).setOnClickListener(new View.OnClickListener() {
@Override
@@ -321,10 +301,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
mpris.sendAction("PlayPause");
if (targetPlayer == null) return;
targetPlayer.playPause();
}
});
}
@@ -336,10 +314,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
mpris.sendAction("Previous");
if (targetPlayer == null) return;
targetPlayer.previous();
}
});
}
@@ -351,10 +327,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
mpris.Seek(interval_time * -1);
if (targetPlayer == null) return;
targetPlayer.seek(interval_time * -1);
}
});
}
@@ -366,10 +340,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
mpris.Seek(interval_time);
if (targetPlayer == null) return;
targetPlayer.seek(interval_time);
}
});
}
@@ -381,10 +353,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
mpris.sendAction("Next");
if (targetPlayer == null) return;
targetPlayer.next();
}
});
}
@@ -404,10 +374,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) return;
mpris.setVolume(seekBar.getProgress());
if (targetPlayer == null) return;
targetPlayer.setVolume(seekBar.getProgress());
}
});
}
@@ -421,12 +389,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
if (device != null) {
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris != null) {
positionSeek.setProgress((int) (mpris.getPosition()));
}
if (targetPlayer != null) {
positionSeek.setProgress((int) (targetPlayer.getPosition()));
}
positionSeekUpdateHandler.removeCallbacks(positionSeekUpdateRunnable);
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 1000);
@@ -453,10 +417,8 @@ public class MprisActivity extends ActionBarActivity {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris != null) {
mpris.setPosition(seekBar.getProgress());
if (targetPlayer != null) {
targetPlayer.setPosition(seekBar.getProgress());
}
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 200);
}

View File

@@ -33,29 +33,161 @@ import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class MprisPlugin extends Plugin {
public class MprisPlayer {
private String player = "";
private boolean playing = false;
private String currentSong = "";
private String title = "";
private String artist = "";
private String album = "";
private int volume = 50;
private long length = -1;
private long lastPosition = 0;
private long lastPositionTime;
private boolean playAllowed = true;
private boolean pauseAllowed = true;
private boolean goNextAllowed = true;
private boolean goPreviousAllowed = true;
private boolean seekAllowed = true;
public MprisPlayer() {
lastPositionTime = System.currentTimeMillis();
}
public String getCurrentSong() {
return currentSong;
}
public String getTitle() {
return title;
}
public String getArtist() {
return artist;
}
public String getAlbum() {
return album;
}
public String getPlayer() {
return player;
}
private boolean isSpotify() {
return getPlayer().toLowerCase().equals("spotify");
}
public int getVolume() {
return volume;
}
public long getLength(){ return length; }
public boolean isPlaying() {
return playing;
}
public boolean isPlayAllowed() {
return playAllowed;
}
public boolean isPauseAllowed() {
return pauseAllowed;
}
public boolean isGoNextAllowed() {
return goNextAllowed;
}
public boolean isGoPreviousAllowed() {
return goPreviousAllowed;
}
public boolean isSeekAllowed() {
return seekAllowed && getLength() >= 0 && getPosition() >= 0 && !isSpotify();
}
public boolean isSetVolumeAllowed() {
return !isSpotify();
}
public long getPosition(){
if(playing) {
return lastPosition + (System.currentTimeMillis() - lastPositionTime);
} else {
return lastPosition;
}
}
public void playPause() {
if (isPauseAllowed() || isPlayAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "action", "PlayPause");
}
}
public void play() {
if (isPlayAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "action", "Play");
}
}
public void pause() {
if (isPauseAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "action", "Pause");
}
}
public void stop() {
MprisPlugin.this.sendCommand(getPlayer(), "action", "Stop");
}
public void previous() {
if (isGoPreviousAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "action", "Previous");
}
}
public void next() {
if (isGoNextAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "action", "Next");
}
}
public void setVolume(int volume) {
if (isSetVolumeAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "setVolume", volume);
}
}
public void setPosition(int position) {
if (isSeekAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "SetPosition", position);
lastPosition = position;
lastPositionTime = System.currentTimeMillis();
}
}
public void seek(int offset) {
if (isSeekAllowed()) {
MprisPlugin.this.sendCommand(getPlayer(), "Seek", offset);
}
}
}
public final static String PACKAGE_TYPE_MPRIS = "kdeconnect.mpris";
public final static String PACKAGE_TYPE_MPRIS_REQUEST = "kdeconnect.mpris.request";
private String player = "";
private boolean playing = false;
private String currentSong = "";
private int volume = 50;
private long length = -1;
private long lastPosition;
private long lastPositionTime;
private boolean playAllowed = true;
private boolean pauseAllowed = true;
private boolean goNextAllowed = true;
private boolean goPreviousAllowed = true;
private boolean seekAllowed = true;
private HashMap<String, MprisPlayer> players = new HashMap<>();
private HashMap<String,Handler> playerStatusUpdated = new HashMap<>();
private List<String> playerList = new ArrayList<>();
private HashMap<String,Handler> playerListUpdated = new HashMap<>();
@Override
@@ -81,66 +213,54 @@ public class MprisPlugin extends Plugin {
@Override
public boolean onCreate() {
requestPlayerList();
lastPositionTime = System.currentTimeMillis();
//Always request the player list so the data is up-to-date
requestPlayerList();
return true;
}
@Override
public void onDestroy() {
playerList.clear();
players.clear();
}
public void sendAction(String player, String action) {
private void sendCommand(String player, String method, String value) {
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
np.set("player", player);
np.set("action", action);
device.sendPackage(np);
}
public void sendAction(String action) {
sendAction(player, action);
}
public void setVolume(int volume) {
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
np.set("player", player);
np.set("setVolume",volume);
np.set(method, value);
device.sendPackage(np);
}
public void setPosition(int position) {
private void sendCommand(String player, String method, int value) {
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
np.set("player", player);
np.set("SetPosition", position);
device.sendPackage(np);
this.lastPosition = position;
this.lastPositionTime = System.currentTimeMillis();
}
public void Seek(int offset) {
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
np.set("player", player);
np.set("Seek", offset);
np.set(method, value);
device.sendPackage(np);
}
@Override
public boolean onPackageReceived(NetworkPackage np) {
if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") || np.has("pos")) {
if (np.getString("player").equals(player)) {
currentSong = np.getString("nowPlaying", currentSong);
volume = np.getInt("volume", volume);
length = np.getLong("length", length);
MprisPlayer playerStatus = players.get(np.getString("player"));
if (playerStatus != null) {
playerStatus.currentSong = np.getString("nowPlaying", playerStatus.currentSong);
//Note: title, artist and album will not be available for all desktop clients
playerStatus.title = np.getString("title", playerStatus.title);
playerStatus.artist = np.getString("artist", playerStatus.artist);
playerStatus.album = np.getString("album", playerStatus.album);
playerStatus.volume = np.getInt("volume", playerStatus.volume);
playerStatus.length = np.getLong("length", playerStatus.length);
if(np.has("pos")){
lastPosition = np.getLong("pos", lastPosition);
lastPositionTime = System.currentTimeMillis();
playerStatus.lastPosition = np.getLong("pos", playerStatus.lastPosition);
playerStatus.lastPositionTime = System.currentTimeMillis();
}
playing = np.getBoolean("isPlaying", playing);
playAllowed = np.getBoolean("canPlay", playAllowed);
pauseAllowed = np.getBoolean("canPause", pauseAllowed);
goNextAllowed = np.getBoolean("canGoNext", goNextAllowed);
goPreviousAllowed = np.getBoolean("canGoPrevious", goPreviousAllowed);
seekAllowed = np.getBoolean("canSeek", seekAllowed);
playerStatus.playing = np.getBoolean("isPlaying", playerStatus.playing);
playerStatus.playAllowed = np.getBoolean("canPlay", playerStatus.playAllowed);
playerStatus.pauseAllowed = np.getBoolean("canPause", playerStatus.pauseAllowed);
playerStatus.goNextAllowed = np.getBoolean("canGoNext", playerStatus.goNextAllowed);
playerStatus.goPreviousAllowed = np.getBoolean("canGoPrevious", playerStatus.goPreviousAllowed);
playerStatus.seekAllowed = np.getBoolean("canSeek", playerStatus.seekAllowed);
for (String key : playerStatusUpdated.keySet()) {
try {
playerStatusUpdated.get(key).dispatchMessage(new Message());
@@ -155,18 +275,37 @@ public class MprisPlugin extends Plugin {
List<String> newPlayerList = np.getStringList("playerList");
if (newPlayerList != null) {
boolean equals = false;
if (newPlayerList.size() == playerList.size()) {
equals = true;
for (int i=0; i<newPlayerList.size(); i++) {
if (!newPlayerList.get(i).equals(playerList.get(i))) {
equals = false;
boolean equals = true;
for (String newPlayer : newPlayerList) {
if (!players.containsKey(newPlayer)) {
equals = false;
MprisPlayer player = new MprisPlayer();
player.player = newPlayer;
players.put(newPlayer, player);
//Immediately ask for the data of this player
requestPlayerStatus(newPlayer);
}
}
Iterator<HashMap.Entry<String, MprisPlayer>> iter = players.entrySet().iterator();
while (iter.hasNext()) {
String oldPlayer = iter.next().getKey();
boolean found = false;
for (String newPlayer : newPlayerList) {
if (newPlayer.equals(oldPlayer)) {
found = true;
break;
}
}
if (!found) {
iter.remove();
equals = false;
}
}
if (!equals) {
playerList = newPlayerList;
for (String key : playerListUpdated.keySet()) {
try {
playerListUpdated.get(key).dispatchMessage(new Message());
@@ -196,95 +335,34 @@ public class MprisPlugin extends Plugin {
playerStatusUpdated.put(id, h);
h.dispatchMessage(new Message());
}
//Get the status if this is the first handler we have
if (playerListUpdated.size() == 1) {
requestPlayerStatus();
}
public void removePlayerStatusUpdatedHandler(String id) {
playerStatusUpdated.remove(id);
}
public void setPlayerListUpdatedHandler(String id, Handler h) {
playerListUpdated.put(id,h);
h.dispatchMessage(new Message());
//Get the status if this is the first handler we have
if (playerListUpdated.size() == 1) {
requestPlayerList();
}
}
public void setPlayer(String player) {
if (player == null || player.equals(this.player)) return;
this.player = player;
currentSong = "";
volume = 50;
playing = false;
playAllowed = true;
pauseAllowed = true;
goNextAllowed = true;
goPreviousAllowed = true;
seekAllowed = true;
for (String key : playerStatusUpdated.keySet()) {
try {
playerStatusUpdated.get(key).dispatchMessage(new Message());
} catch(Exception e) {
e.printStackTrace();
Log.e("MprisControl","Exception");
playerStatusUpdated.remove(key);
}
}
requestPlayerStatus();
public void removePlayerListUpdatedHandler(String id) {
playerListUpdated.remove(id);
}
public List<String> getPlayerList() {
return playerList;
List<String> playerlist = new ArrayList<>(players.keySet());
Collections.sort(playerlist);
return playerlist;
}
public String getCurrentSong() {
return currentSong;
public MprisPlayer getPlayerStatus(String player) {
return players.get(player);
}
public String getPlayer() {
return player;
}
public int getVolume() {
return volume;
}
public long getLength(){ return length; }
public boolean isPlaying() {
return playing;
}
public boolean isPlayAllowed() {
return playAllowed;
}
public boolean isPauseAllowed() {
return pauseAllowed;
}
public boolean isGoNextAllowed() {
return goNextAllowed;
}
public boolean isGoPreviousAllowed() {
return goPreviousAllowed;
}
public boolean isSeekAllowed() {
return seekAllowed;
}
public long getPosition(){
if(playing) {
return lastPosition + (System.currentTimeMillis() - lastPositionTime);
} else {
return lastPosition;
}
public MprisPlayer getEmptyPlayer() {
return new MprisPlayer();
}
private void requestPlayerList() {
@@ -293,9 +371,9 @@ public class MprisPlugin extends Plugin {
device.sendPackage(np);
}
private void requestPlayerStatus() {
private void requestPlayerStatus(String player) {
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
np.set("player",player);
np.set("player", player);
np.set("requestNowPlaying",true);
np.set("requestVolume",true);
device.sendPackage(np);

View File

@@ -28,32 +28,33 @@ import android.database.sqlite.SQLiteOpenHelper;
import java.util.HashSet;
public class AppDatabase {
class AppDatabase {
static final private HashSet<String> disabledByDefault = new HashSet<>();
static {
disabledByDefault.add("com.android.messaging"); //We already have sms notifications in the telephony plugin
disabledByDefault.add("com.google.android.googlequicksearchbox"); //Google Now notifications re-spawn every few minutes
}
static final String KEY_PACKAGE_NAME = "packageName";
static final String KEY_IS_ENABLED = "isEnabled";
private static final String KEY_PACKAGE_NAME = "packageName";
private static final String KEY_IS_ENABLED = "isEnabled";
static final String DATABASE_NAME = "Applications";
static final String DATABASE_TABLE = "Applications";
static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "Applications";
private static final String DATABASE_TABLE = "Applications";
private static final int DATABASE_VERSION = 2;
final Context ourContext;
SQLiteDatabase ourDatabase;
DbHelper ourHelper;
private final Context ourContext;
private SQLiteDatabase ourDatabase;
private DbHelper ourHelper;
public AppDatabase(Context c) {
AppDatabase(Context c) {
ourContext = c;
}
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@@ -64,7 +65,7 @@ public class AppDatabase {
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i2) {
db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE);
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
@@ -79,14 +80,14 @@ public class AppDatabase {
ourHelper.close();
}
public void setEnabled(String packageName, boolean isEnabled) {
String[] columns = new String []{KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
void setEnabled(String packageName, boolean isEnabled) {
String[] columns = new String[]{KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ", new String[]{packageName}, null, null, null);
ContentValues cv = new ContentValues();
cv.put(KEY_IS_ENABLED, isEnabled?"true":"false");
cv.put(KEY_IS_ENABLED, isEnabled ? "true" : "false");
if (res.getCount() > 0) {
ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?",new String[]{packageName});
ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?", new String[]{packageName});
} else {
cv.put(KEY_PACKAGE_NAME, packageName);
ourDatabase.insert(DATABASE_TABLE, null, cv);
@@ -94,9 +95,9 @@ public class AppDatabase {
res.close();
}
public boolean isEnabled(String packageName) {
String[] columns = new String []{KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
boolean isEnabled(String packageName) {
String[] columns = new String[]{KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ", new String[]{packageName}, null, null, null);
boolean result;
if (res.getCount() > 0) {
res.moveToFirst();

View File

@@ -28,7 +28,7 @@ import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -45,9 +45,9 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class NotificationFilterActivity extends ActionBarActivity {
public class NotificationFilterActivity extends AppCompatActivity {
AppDatabase appDatabase;
private AppDatabase appDatabase;
static class AppListInfo {
String pkg;
@@ -56,7 +56,7 @@ public class NotificationFilterActivity extends ActionBarActivity {
boolean isEnabled;
}
AppListInfo[] apps;
private AppListInfo[] apps;
class AppListAdapter extends BaseAdapter {
@@ -80,10 +80,10 @@ public class NotificationFilterActivity extends ActionBarActivity {
LayoutInflater inflater = getLayoutInflater();
view = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null, true);
}
CheckedTextView checkedTextView = (CheckedTextView)view;
CheckedTextView checkedTextView = (CheckedTextView) view;
checkedTextView.setText(apps[position].name);
checkedTextView.setCompoundDrawablesWithIntrinsicBounds(apps[position].icon, null, null, null);
checkedTextView.setCompoundDrawablePadding((int)(8*getResources().getDisplayMetrics().density));
checkedTextView.setCompoundDrawablePadding((int) (8 * getResources().getDisplayMetrics().density));
return view;
}
@@ -134,7 +134,7 @@ public class NotificationFilterActivity extends ActionBarActivity {
}
void displayAppList() {
private void displayAppList() {
final ListView listView = (ListView) findViewById(R.id.lvFilterApps);
AppListAdapter adapter = new AppListAdapter();
@@ -151,7 +151,7 @@ public class NotificationFilterActivity extends ActionBarActivity {
}
});
for (int i = 0 ; i < apps.length; i++) {
for (int i = 0; i < apps.length; i++) {
listView.setItemChecked(i, apps[i].isEnabled);
}
@@ -172,11 +172,11 @@ public class NotificationFilterActivity extends ActionBarActivity {
BackgroundService.removeGuiInUseCounter(this);
}
Drawable resizeIcon(Drawable icon, int maxSize) {
private Drawable resizeIcon(Drawable icon, int maxSize) {
Resources res = getResources();
//Convert to display pixels
maxSize = (int)(maxSize*res.getDisplayMetrics().density);
maxSize = (int) (maxSize * res.getDisplayMetrics().density);
Bitmap bitmap = Bitmap.createBitmap(maxSize, maxSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);

View File

@@ -23,18 +23,26 @@ package org.kde.kdeconnect.Plugins.NotificationsPlugin;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.support.annotation.RequiresApi;
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotificationReceiver extends NotificationListenerService {
private boolean connected;
public interface NotificationListener {
void onNotificationPosted(StatusBarNotification statusBarNotification);
void onNotificationRemoved(StatusBarNotification statusBarNotification);
void onListenerConnected(NotificationReceiver service);
}
private final ArrayList<NotificationListener> listeners = new ArrayList<>();
@@ -42,6 +50,7 @@ public class NotificationReceiver extends NotificationListenerService {
public void addListener(NotificationListener listener) {
listeners.add(listener);
}
public void removeListener(NotificationListener listener) {
listeners.remove(listener);
}
@@ -49,21 +58,36 @@ public class NotificationReceiver extends NotificationListenerService {
@Override
public void onNotificationPosted(StatusBarNotification statusBarNotification) {
//Log.e("NotificationReceiver.onNotificationPosted","listeners: " + listeners.size());
for(NotificationListener listener : listeners) {
for (NotificationListener listener : listeners) {
listener.onNotificationPosted(statusBarNotification);
}
}
@Override
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
for(NotificationListener listener : listeners) {
for (NotificationListener listener : listeners) {
listener.onNotificationRemoved(statusBarNotification);
}
}
@Override
public void onListenerConnected() {
super.onListenerConnected();
for (NotificationListener listener : listeners) {
listener.onListenerConnected(this);
}
connected = true;
}
@Override
public void onListenerDisconnected() {
super.onListenerDisconnected();
connected = false;
}
public boolean isConnected() {
return connected;
}
//To use the service from the outer (name)space

View File

@@ -24,12 +24,16 @@ import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.support.annotation.RequiresApi;
import android.util.Log;
import org.kde.kdeconnect.Helpers.AppsHelper;
@@ -39,15 +43,22 @@ import org.kde.kdeconnect.UserInterface.MaterialActivity;
import org.kde.kdeconnect.UserInterface.SettingsActivity;
import org.kde.kdeconnect_tp.R;
import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class NotificationsPlugin extends Plugin implements NotificationReceiver.NotificationListener {
public final static String PACKAGE_TYPE_NOTIFICATION = "kdeconnect.notification";
public final static String PACKAGE_TYPE_NOTIFICATION_REQUEST = "kdeconnect.notification.request";
private final static String PACKAGE_TYPE_NOTIFICATION = "kdeconnect.notification";
private final static String PACKAGE_TYPE_NOTIFICATION_REQUEST = "kdeconnect.notification.request";
private final static String PACKAGE_TYPE_NOTIFICATION_REPLY = "kdeconnect.notification.reply";
/*
private boolean sendIcons = false;
*/
private Map<String, RepliableNotification> pendingIntents;
private boolean serviceReady;
@Override
public String getDisplayName() {
@@ -81,45 +92,51 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
@Override
public boolean onCreate() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (hasPermission()) {
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
@Override
public void onServiceStart(NotificationReceiver service) {
try {
service.addListener(NotificationsPlugin.this);
StatusBarNotification[] notifications = service.getActiveNotifications();
for (StatusBarNotification notification : notifications) {
sendNotification(notification, true);
}
} catch (Exception e) {
Log.e("NotificationsPlugin", "Exception");
e.printStackTrace();
}
}
});
} else {
return false;
if (!hasPermission()) return false;
pendingIntents = new HashMap<>();
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
@Override
public void onServiceStart(NotificationReceiver service) {
service.addListener(NotificationsPlugin.this);
serviceReady = service.isConnected();
if (serviceReady) {
sendCurrentNotifications(service);
}
}
}
});
return true;
}
@Override
public void onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
@Override
public void onServiceStart(NotificationReceiver service) {
service.removeListener(NotificationsPlugin.this);
}
});
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
@Override
public void onServiceStart(NotificationReceiver service) {
service.removeListener(NotificationsPlugin.this);
}
});
}
@Override
public void onListenerConnected(NotificationReceiver service) {
serviceReady = true;
sendCurrentNotifications(service);
}
@Override
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
if (statusBarNotification == null) {
Log.w("onNotificationRemoved", "notification is null");
return;
}
String id = getNotificationKeyCompat(statusBarNotification);
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
np.set("id", id);
@@ -129,10 +146,10 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
@Override
public void onNotificationPosted(StatusBarNotification statusBarNotification) {
sendNotification(statusBarNotification, false);
sendNotification(statusBarNotification);
}
public void sendNotification(StatusBarNotification statusBarNotification, boolean requestAnswer) {
private void sendNotification(StatusBarNotification statusBarNotification) {
Notification notification = statusBarNotification.getNotification();
AppDatabase appDatabase = new AppDatabase(context);
@@ -145,7 +162,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
}
appDatabase.open();
if (!appDatabase.isEnabled(statusBarNotification.getPackageName())){
if (!appDatabase.isEnabled(statusBarNotification.getPackageName())) {
return;
// we dont want notification from this app
}
@@ -155,6 +172,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
String packageName = statusBarNotification.getPackageName();
String appName = AppsHelper.appNameLookup(context, packageName);
if ("com.facebook.orca".equals(packageName) &&
(statusBarNotification.getId() == 10012) &&
"Messenger".equals(appName) &&
@@ -164,51 +182,181 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
}
if ("com.android.systemui".equals(packageName) &&
"low_battery".equals(statusBarNotification.getTag()))
{
"low_battery".equals(statusBarNotification.getTag())) {
//HACK: Android low battery notification are posted again every few seconds. Ignore them, as we already have a battery indicator.
return;
}
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
if (packageName.equals("org.kde.kdeconnect_tp"))
{
if (packageName.equals("org.kde.kdeconnect_tp")) {
//Make our own notifications silent :)
np.set("silent", true);
np.set("requestAnswer", true); //For compatibility with old desktop versions of KDE Connect that don't support "silent"
}
/*
if (sendIcons) {
try {
Drawable drawableAppIcon = AppsHelper.appIconLookup(context, packageName);
Bitmap appIcon = ImagesHelper.drawableToBitmap(drawableAppIcon);
try {
Bitmap appIcon = notification.largeIcon;
if (appIcon != null) {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
if (appIcon.getWidth() > 128) {
appIcon = Bitmap.createScaledBitmap(appIcon, 96, 96, true);
}
appIcon.compress(Bitmap.CompressFormat.PNG, 90, outStream);
byte[] bitmapData = outStream.toByteArray();
np.setPayload(bitmapData);
} catch (Exception e) {
e.printStackTrace();
Log.e("NotificationsPlugin", "Error retrieving icon");
np.set("payloadHash", getChecksum(bitmapData));
}
}
*/
np.set("id", key);
np.set("appName", appName == null? packageName : appName);
np.set("isClearable", statusBarNotification.isClearable());
np.set("ticker", getTickerText(notification));
np.set("time", Long.toString(statusBarNotification.getPostTime()));
if (requestAnswer) {
np.set("requestAnswer", true);
np.set("silent", true);
} catch (Exception e) {
e.printStackTrace();
Log.e("NotificationsPlugin", "Error retrieving icon");
}
RepliableNotification rn = extractRepliableNotification(statusBarNotification);
if (rn.pendingIntent != null) {
np.set("requestReplyId", rn.id);
pendingIntents.put(rn.id, rn);
}
np.set("id", key);
np.set("appName", appName == null ? packageName : appName);
np.set("isClearable", statusBarNotification.isClearable());
np.set("ticker", getTickerText(notification));
np.set("title", getNotificationTitle(notification));
np.set("text", getNotificationText(notification));
np.set("time", Long.toString(statusBarNotification.getPostTime()));
device.sendPackage(np);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
private void replyToNotification(String id, String message) {
if (pendingIntents.isEmpty() || !pendingIntents.containsKey(id)) {
Log.e("NotificationsPlugin", "No such notification");
return;
}
RepliableNotification repliableNotification = pendingIntents.get(id);
if (repliableNotification == null) {
Log.e("NotificationsPlugin", "No such notification");
return;
}
RemoteInput[] remoteInputs = new RemoteInput[repliableNotification.remoteInputs.size()];
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle localBundle = new Bundle();
int i = 0;
for (RemoteInput remoteIn : repliableNotification.remoteInputs) {
getDetailsOfNotification(remoteIn);
remoteInputs[i] = remoteIn;
localBundle.putCharSequence(remoteInputs[i].getResultKey(), message);
i++;
}
RemoteInput.addResultsToIntent(remoteInputs, localIntent, localBundle);
try {
repliableNotification.pendingIntent.send(context, 0, localIntent);
} catch (PendingIntent.CanceledException e) {
Log.e("NotificationPlugin", "replyToNotification error: " + e.getMessage());
}
pendingIntents.remove(id);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
private void getDetailsOfNotification(RemoteInput remoteInput) {
//Some more details of RemoteInput... no idea what for but maybe it will be useful at some point
String resultKey = remoteInput.getResultKey();
String label = remoteInput.getLabel().toString();
Boolean canFreeForm = remoteInput.getAllowFreeFormInput();
if (remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
String[] possibleChoices = new String[remoteInput.getChoices().length];
for (int i = 0; i < remoteInput.getChoices().length; i++) {
possibleChoices[i] = remoteInput.getChoices()[i].toString();
}
}
}
private String getNotificationTitle(Notification notification) {
final String TITLE_KEY = "android.title";
final String TEXT_KEY = "android.text";
String title = "";
if (notification != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Bundle extras = notification.extras;
title = extras.getString(TITLE_KEY);
} catch (Exception e) {
Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText);
e.printStackTrace();
}
}
}
//TODO Add compat for under Kitkat devices
return title;
}
private RepliableNotification extractRepliableNotification(StatusBarNotification statusBarNotification) {
RepliableNotification repliableNotification = new RepliableNotification();
if (statusBarNotification != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
Boolean reply = false;
//works for WhatsApp, but not for Telegram
if (statusBarNotification.getNotification().actions != null) {
for (Notification.Action act : statusBarNotification.getNotification().actions) {
if (act != null && act.getRemoteInputs() != null) {
repliableNotification.remoteInputs.addAll(Arrays.asList(act.getRemoteInputs()));
repliableNotification.pendingIntent = act.actionIntent;
reply = true;
break;
}
}
repliableNotification.packageName = statusBarNotification.getPackageName();
repliableNotification.tag = statusBarNotification.getTag();//TODO find how to pass Tag with sending PendingIntent, might fix Hangout problem
}
} catch (Exception e) {
Log.w("NotificationPlugin", "problem extracting notification wear for " + statusBarNotification.getNotification().tickerText);
e.printStackTrace();
}
}
}
return repliableNotification;
}
private String getNotificationText(Notification notification) {
final String TEXT_KEY = "android.text";
String text = "";
if (notification != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Bundle extras = notification.extras;
Object extraTextExtra = extras.get(TEXT_KEY);
if (extraTextExtra != null) text = extraTextExtra.toString();
} catch (Exception e) {
Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText);
e.printStackTrace();
}
}
}
//TODO Add compat for under Kitkat devices
return text;
}
/**
* Returns the ticker text of the notification.
@@ -220,90 +368,72 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
final String TEXT_KEY = "android.text";
String ticker = "";
if(notification != null) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (notification != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Bundle extras = notification.extras;
String extraTitle = extras.getCharSequence(TITLE_KEY).toString();
String extraTitle = extras.getString(TITLE_KEY);
String extraText = null;
Object extraTextExtra = extras.get(TEXT_KEY);
if (extraTextExtra != null) extraText = extraTextExtra.toString();
if (extraTitle != null && extraText != null && !extraText.isEmpty()) {
ticker = extraTitle + " " + extraText;
ticker = extraTitle + ": " + extraText;
} else if (extraTitle != null) {
ticker = extraTitle;
} else if (extraText != null) {
ticker = extraText;
}
} catch(Exception e) {
Log.w("NotificationPlugin","problem parsing notification extras for " + notification.tickerText);
} catch (Exception e) {
Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText);
e.printStackTrace();
}
}
if (ticker.isEmpty()) {
ticker = (notification.tickerText != null)? notification.tickerText.toString() : "";
ticker = (notification.tickerText != null) ? notification.tickerText.toString() : "";
}
}
return ticker;
}
private void sendCurrentNotifications(NotificationReceiver service) {
StatusBarNotification[] notifications = service.getActiveNotifications();
for (StatusBarNotification notification : notifications) {
sendNotification(notification);
}
}
@Override
public boolean onPackageReceived(final NetworkPackage np) {
/*
if (np.getBoolean("sendIcons")) {
sendIcons = true;
}
*/
if (np.getBoolean("request")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
private void sendCurrentNotifications(NotificationReceiver service) {
StatusBarNotification[] notifications = service.getActiveNotifications();
for (StatusBarNotification notification : notifications) {
sendNotification(notification, true);
}
}
@Override
public void onServiceStart(final NotificationReceiver service) {
try {
//If service just started, this call will throw an exception because the answer is not ready yet
sendCurrentNotifications(service);
} catch(Exception e) {
Log.e("onPackageReceived","Error when answering 'request': Service failed to start. Retrying in 100ms...");
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
Log.e("onPackageReceived","Error when answering 'request': Service failed to start. Retrying...");
sendCurrentNotifications(service);
} catch (Exception e) {
Log.e("onPackageReceived","Error when answering 'request': Service failed to start twice!");
e.printStackTrace();
}
}
}).start();
}
}
});
} else if (np.has("cancel")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
if (serviceReady) {
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
@Override
public void onServiceStart(NotificationReceiver service) {
String dismissedId = np.getString("cancel");
cancelNotificationCompat(service, dismissedId);
sendCurrentNotifications(service);
}
});
}
} else if (np.has("cancel")) {
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
@Override
public void onServiceStart(NotificationReceiver service) {
String dismissedId = np.getString("cancel");
cancelNotificationCompat(service, dismissedId);
}
});
} else if (np.has("requestReplyId") && np.has("message")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
replyToNotification(np.getString("requestReplyId"), np.getString("message"));
}
}
@@ -314,41 +444,29 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
@Override
public AlertDialog getErrorDialog(final Activity deviceActivity) {
if (Build.VERSION.SDK_INT < 18) {
return new AlertDialog.Builder(deviceActivity)
.setTitle(R.string.pref_plugin_notifications)
.setMessage(R.string.plugin_not_available)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
return new AlertDialog.Builder(deviceActivity)
.setTitle(R.string.pref_plugin_notifications)
.setMessage(R.string.no_permissions)
.setPositiveButton(R.string.open_settings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
deviceActivity.startActivityForResult(intent, MaterialActivity.RESULT_NEEDS_RELOAD);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//Do nothing
}
})
.create();
}
})
.create();
} else {
return new AlertDialog.Builder(deviceActivity)
.setTitle(R.string.pref_plugin_notifications)
.setMessage(R.string.no_permissions)
.setPositiveButton(R.string.open_settings, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
deviceActivity.startActivityForResult(intent, MaterialActivity.RESULT_NEEDS_RELOAD);
}
})
.setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//Do nothing
}
})
.create();
}
}
@Override
public String[] getSupportedPackageTypes() {
return new String[]{PACKAGE_TYPE_NOTIFICATION_REQUEST};
return new String[]{PACKAGE_TYPE_NOTIFICATION_REQUEST, PACKAGE_TYPE_NOTIFICATION_REPLY};
}
@Override
@@ -357,13 +475,13 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
}
//For compat with API<21, because lollipop changed the way to cancel notifications
public static void cancelNotificationCompat(NotificationReceiver service, String compatKey) {
private static void cancelNotificationCompat(NotificationReceiver service, String compatKey) {
if (Build.VERSION.SDK_INT >= 21) {
service.cancelNotification(compatKey);
} else {
int first = compatKey.indexOf(':');
if (first == -1) {
Log.e("cancelNotificationCompa","Not formated like a notification key: "+ compatKey);
Log.e("cancelNotificationCompa", "Not formated like a notification key: " + compatKey);
return;
}
int last = compatKey.lastIndexOf(':');
@@ -381,7 +499,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
}
}
public static String getNotificationKeyCompat(StatusBarNotification statusBarNotification) {
private static String getNotificationKeyCompat(StatusBarNotification statusBarNotification) {
String result;
// first check if it's one of our remoteIds
String tag = statusBarNotification.getTag();
@@ -398,4 +516,33 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
}
return result;
}
private String getChecksum(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data);
return bytesToHex(md.digest());
} catch (NoSuchAlgorithmException e) {
Log.e("KDEConnect", "Error while generating checksum", e);
}
return null;
}
private static String bytesToHex(byte[] bytes) {
char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars).toLowerCase();
}
@Override
public int getMinSdk() {
return Build.VERSION_CODES.JELLY_BEAN_MR2;
}
}

View File

@@ -0,0 +1,14 @@
package org.kde.kdeconnect.Plugins.NotificationsPlugin;
import android.app.PendingIntent;
import java.util.ArrayList;
import java.util.UUID;
class RepliableNotification {
String id = UUID.randomUUID().toString();
PendingIntent pendingIntent;
ArrayList<android.app.RemoteInput> remoteInputs = new ArrayList<>();
String packageName;
String tag;
}

View File

@@ -20,23 +20,35 @@
package org.kde.kdeconnect.Plugins;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.StringRes;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.UserInterface.MaterialActivity;
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
import org.kde.kdeconnect.UserInterface.SettingsActivity;
import org.kde.kdeconnect_tp.R;
public abstract class Plugin {
protected Device device;
protected Context context;
protected int permissionExplanation = R.string.permission_explanation;
protected int optionalPermissionExplanation = R.string.optional_permission_explanation;
public final void setContext(Context context, Device device) {
this.device = device;
@@ -167,14 +179,6 @@ public abstract class Plugin {
*/
public boolean onPackageReceived(NetworkPackage np) { return false; }
/**
* If onCreate returns false, should create a dialog explaining
* the problem (and how to fix it, if possible) to the user.
*/
public AlertDialog getErrorDialog(Activity deviceActivity) {
return null;
}
/**
* Should return the list of NetworkPackage types that this plugin can handle
*/
@@ -205,4 +209,79 @@ public abstract class Plugin {
return b;
}
public String[] getRequiredPermissions() {
return new String[0];
}
public String[] getOptionalPermissions() {
return new String[0];
}
//Permission from Manifest.permission.*
protected boolean isPermissionGranted(String permission) {
int result = ContextCompat.checkSelfPermission(context, permission);
return (result == PackageManager.PERMISSION_GRANTED);
}
protected boolean arePermissionsGranted(String[] permissions) {
for(String permission: permissions){
if(!isPermissionGranted(permission)){
return false;
}
}
return true;
}
protected AlertDialog requestPermissionDialog(Activity activity, String permissions, @StringRes int reason) {
return requestPermissionDialog(activity, new String[]{permissions}, reason);
}
protected AlertDialog requestPermissionDialog(final Activity activity, final String[] permissions, @StringRes int reason){
return new AlertDialog.Builder(activity)
.setTitle(getDisplayName())
.setMessage(reason)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCompat.requestPermissions(activity, permissions, 0);
}
})
.setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//Do nothing
}
})
.create();
}
/**
* If onCreate returns false, should create a dialog explaining
* the problem (and how to fix it, if possible) to the user.
*/
public AlertDialog getErrorDialog(Activity deviceActivity) {
return null;
}
public AlertDialog getPermissionExplanationDialog(Activity deviceActivity) {
return requestPermissionDialog(deviceActivity,getRequiredPermissions(), permissionExplanation);
}
public AlertDialog getOptionalPermissionExplanationDialog(Activity deviceActivity) {
return requestPermissionDialog(deviceActivity,getOptionalPermissions(), optionalPermissionExplanation);
}
public boolean checkRequiredPermissions(){
return arePermissionsGranted(getRequiredPermissions());
}
public boolean checkOptionalPermissions(){
return arePermissionsGranted(getOptionalPermissions());
}
public int getMinSdk() {
return Build.VERSION_CODES.BASE;
}
}

View File

@@ -125,8 +125,7 @@ public class PluginFactory {
PluginFactory.registerPlugin(TelepathyPlugin.class);
PluginFactory.registerPlugin(FindMyPhonePlugin.class);
PluginFactory.registerPlugin(RunCommandPlugin.class);
//Commented here and in AndroidManifest until we release a desktop version with this feature, so we don't get bad "feature not working" reviews
//PluginFactory.registerPlugin(RemoteKeyboardPlugin.class);
PluginFactory.registerPlugin(RemoteKeyboardPlugin.class);
}
public static PluginInfo getPluginInfo(Context context, String pluginKey) {
@@ -147,7 +146,7 @@ public class PluginFactory {
} catch(Exception e) {
Log.e("PluginFactory","getPluginInfo exception");
e.printStackTrace();
return null;
throw new RuntimeException(e);
}
}

View File

@@ -22,7 +22,7 @@
package org.kde.kdeconnect.Plugins.RunCommandPlugin;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
@@ -39,7 +39,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class RunCommandActivity extends ActionBarActivity {
public class RunCommandActivity extends AppCompatActivity {
private String deviceId;

View File

@@ -20,8 +20,16 @@
package org.kde.kdeconnect.Plugins.SftpPlugin;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import org.json.JSONException;
import org.kde.kdeconnect.Helpers.StorageHelper;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
@@ -38,6 +46,8 @@ public class SftpPlugin extends Plugin {
private static final SimpleSftpServer server = new SimpleSftpServer();
private int sftpPermissionExplanation = R.string.sftp_permission_explanation;
@Override
public String getDisplayName() {
return context.getResources().getString(R.string.pref_plugin_sftp);
@@ -51,6 +61,7 @@ public class SftpPlugin extends Plugin {
@Override
public boolean onCreate() {
server.init(context, device);
permissionExplanation = sftpPermissionExplanation;
return true;
}
@@ -75,50 +86,48 @@ public class SftpPlugin extends Plugin {
//Kept for compatibility, in case "multiPaths" is not possible or the other end does not support it
np2.set("path", Environment.getExternalStorageDirectory().getAbsolutePath());
File root = new File("/");
if (root.canExecute() && root.canRead()) {
List<StorageHelper.StorageInfo> storageList = StorageHelper.getStorageList();
ArrayList<String> paths = new ArrayList<>();
ArrayList<String> pathNames = new ArrayList<>();
List<StorageHelper.StorageInfo> storageList = StorageHelper.getStorageList();
ArrayList<String> paths = new ArrayList<>();
ArrayList<String> pathNames = new ArrayList<>();
for (StorageHelper.StorageInfo storage : storageList) {
paths.add(storage.path);
StringBuilder res = new StringBuilder();
for (StorageHelper.StorageInfo storage : storageList) {
paths.add(storage.path);
StringBuilder res = new StringBuilder();
if (storageList.size() > 1) {
if (!storage.removable) {
res.append(context.getString(R.string.sftp_internal_storage));
} else if (storage.number > 1) {
res.append(context.getString(R.string.sftp_sdcard_num, storage.number));
} else {
res.append(context.getString(R.string.sftp_sdcard));
}
if (storageList.size() > 1) {
if (!storage.removable) {
res.append(context.getString(R.string.sftp_internal_storage));
} else if (storage.number > 1) {
res.append(context.getString(R.string.sftp_sdcard_num, storage.number));
} else {
res.append(context.getString(R.string.sftp_all_files));
res.append(context.getString(R.string.sftp_sdcard));
}
String pathName = res.toString();
if (storage.readonly) {
res.append(" ");
res.append(context.getString(R.string.sftp_readonly));
}
pathNames.add(res.toString());
} else {
res.append(context.getString(R.string.sftp_all_files));
}
String pathName = res.toString();
if (storage.readonly) {
res.append(" ");
res.append(context.getString(R.string.sftp_readonly));
}
pathNames.add(res.toString());
//Shortcut for users that only want to browse camera pictures
String dcim = storage.path + "/DCIM/Camera";
if (new File(dcim).exists()) {
paths.add(dcim);
if (storageList.size() > 1) {
pathNames.add(context.getString(R.string.sftp_camera) + "(" + pathName + ")");
} else {
pathNames.add(context.getString(R.string.sftp_camera));
}
//Shortcut for users that only want to browse camera pictures
String dcim = storage.path + "/DCIM/Camera";
if (new File(dcim).exists()) {
paths.add(dcim);
if (storageList.size() > 1) {
pathNames.add(context.getString(R.string.sftp_camera) + "(" + pathName + ")");
} else {
pathNames.add(context.getString(R.string.sftp_camera));
}
}
}
if (paths.size() > 0) {
np2.set("multiPaths", paths);
np2.set("pathNames", pathNames);
if (paths.size() > 0) {
np2.set("multiPaths", paths);
np2.set("pathNames", pathNames);
}
}
device.sendPackage(np2);
@@ -129,6 +138,12 @@ public class SftpPlugin extends Plugin {
return false;
}
@Override
public String[] getRequiredPermissions() {
String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE};
return perms;
}
@Override
public String[] getSupportedPackageTypes() {
return new String[]{PACKAGE_TYPE_SFTP_REQUEST};

View File

@@ -48,7 +48,10 @@ import org.kde.kdeconnect.Helpers.RandomHelper;
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
@@ -125,7 +128,7 @@ class SimpleSftpServer {
public void stop() {
try {
started = false;
sshd.stop();
sshd.stop(true);
} catch (Exception e) {
e.printStackTrace();
}
@@ -144,6 +147,17 @@ class SimpleSftpServer {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
// Anything with rmnet is related to cellular connections or USB
// tethering mechanisms. See:
//
// https://android.googlesource.com/kernel/msm/+/android-msm-flo-3.4-kitkat-mr1/Documentation/usb/gadget_rmnet.txt
//
// If we run across an interface that has this, we can safely
// ignore it. In fact, it's much safer to do. If we don't, we
// might get invalid IP adddresses out of it.
if(intf.getDisplayName().contains("rmnet")) continue;
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
@@ -204,6 +218,32 @@ class SimpleSftpServer {
this.file = file;
}
@Override
public OutputStream createOutputStream(long offset) throws IOException {
if (!isWritable()) {
throw new IOException("No write permission : " + file.getName());
}
final RandomAccessFile raf = new RandomAccessFile(file, "rw");
try {
if (offset < raf.length()) {
throw new IOException("Your SSHFS is bugged"); //SSHFS 3.0 and 3.2 cause data corruption, abort the transfer if this happens
}
raf.setLength(offset);
raf.seek(offset);
return new FileOutputStream(raf.getFD()) {
public void close() throws IOException {
super.close();
raf.close();
}
};
} catch (IOException e) {
raf.close();
throw e;
}
}
@Override
public boolean delete() {
//Log.e("Sshd", "deleting file");

View File

@@ -74,6 +74,9 @@ class NotificationUpdateCallback extends Device.SendPackageStatusCallback {
public void onFailure(Throwable e) {
updateDone(false);
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
if (e != null) {
e.printStackTrace();
}
}
private void updateText() {
@@ -114,8 +117,7 @@ class NotificationUpdateCallback extends Device.SendPackageStatusCallback {
.setContentTitle(title)
.setContentText(text)
.setSmallIcon(icon)
.setProgress(progress, progress, false); //setting progress to 0 out of 0 remove the progress bar
.setProgress(0, 0, false); //setting progress to 0 out of 0 remove the progress bar
}
}

View File

@@ -26,7 +26,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;
@@ -37,7 +37,7 @@ import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
public class SendFileActivity extends ActionBarActivity {
public class SendFileActivity extends AppCompatActivity {
String mDeviceId;

View File

@@ -23,8 +23,9 @@ package org.kde.kdeconnect.Plugins.SharePlugin;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -32,6 +33,7 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
@@ -46,15 +48,14 @@ import java.util.ArrayList;
import java.util.Collection;
public class ShareActivity extends ActionBarActivity {
public class ShareActivity extends AppCompatActivity {
private MenuItem menuProgress;
private SwipeRefreshLayout mSwipeRefreshLayout;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.refresh, menu);
menuProgress = menu.findItem(R.id.menu_progress);
return true;
}
@@ -62,28 +63,7 @@ public class ShareActivity extends ActionBarActivity {
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_refresh:
updateComputerList();
BackgroundService.RunCommand(ShareActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
}
});
item.setVisible(false);
menuProgress.setVisible(true);
new Thread(new Runnable() {
@Override
public void run() {
try { Thread.sleep(1500); } catch (InterruptedException e) { }
runOnUiThread(new Runnable() {
@Override
public void run() {
menuProgress.setVisible(false);
item.setVisible(true);
}
});
}
}).start();
updateComputerListAction();
break;
default:
break;
@@ -91,6 +71,30 @@ public class ShareActivity extends ActionBarActivity {
return true;
}
private void updateComputerListAction() {
updateComputerList();
BackgroundService.RunCommand(ShareActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
}
});
mSwipeRefreshLayout.setRefreshing(true);
new Thread(new Runnable() {
@Override
public void run() {
try { Thread.sleep(1500); } catch (InterruptedException ignored) { }
runOnUiThread(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
}
});
}
}).start();
}
private void updateComputerList() {
final Intent intent = getIntent();
@@ -128,58 +132,7 @@ public class ShareActivity extends ActionBarActivity {
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
Bundle extras = intent.getExtras();
if (extras != null) {
if (extras.containsKey(Intent.EXTRA_STREAM)) {
try {
ArrayList<Uri> uriList;
if (!Intent.ACTION_SEND.equals(intent.getAction())) {
uriList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
} else {
Uri uri = extras.getParcelable(Intent.EXTRA_STREAM);
uriList = new ArrayList<>();
uriList.add(uri);
}
SharePlugin.queuedSendUriList(getApplicationContext(), device, uriList);
} catch (Exception e) {
Log.e("ShareActivity", "Exception");
e.printStackTrace();
}
} else if (extras.containsKey(Intent.EXTRA_TEXT)) {
String text = extras.getString(Intent.EXTRA_TEXT);
String subject = extras.getString(Intent.EXTRA_SUBJECT);
//Hack: Detect shared youtube videos, so we can open them in the browser instead of as text
if (subject != null && subject.endsWith("YouTube")) {
int index = text.indexOf(": http://youtu.be/");
if (index > 0) {
text = text.substring(index + 2); //Skip ": "
}
}
boolean isUrl;
try {
new URL(text);
isUrl = true;
} catch (Exception e) {
isUrl = false;
}
NetworkPackage np = new NetworkPackage(SharePlugin.PACKAGE_TYPE_SHARE_REQUEST);
if (isUrl) {
np.set("url", text);
} else {
np.set("text", text);
}
device.sendPackage(np);
}
}
SharePlugin.share(intent, device);
finish();
}
});
@@ -193,35 +146,65 @@ public class ShareActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
setContentView(R.layout.activity_refresh_list);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
setContentView(R.layout.activity_list);
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_list_layout);
mSwipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateComputerListAction();
}
}
);
if (actionBar != null) {
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
}
}
@Override
protected void onStart() {
super.onStart();
BackgroundService.addGuiInUseCounter(this);
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
service.addDeviceListChangedCallback("ShareActivity", new BackgroundService.DeviceListChangedCallback() {
@Override
public void onDeviceListChanged() {
updateComputerList();
final Intent intent = getIntent();
final String deviceId = intent.getStringExtra("deviceId");
if (deviceId!=null) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback(){
@Override
public void onServiceStart(BackgroundService service) {
Log.d("DirectShare", "sharing to "+service.getDevice(deviceId).getName());
Device device = service.getDevice(deviceId);
if (device.isReachable() && device.isPaired()) {
SharePlugin.share(intent, device);
}
});
}
});
updateComputerList();
finish();
}
});
} else {
BackgroundService.addGuiInUseCounter(this);
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
service.addDeviceListChangedCallback("ShareActivity", new BackgroundService.DeviceListChangedCallback() {
@Override
public void onDeviceListChanged() {
updateComputerList();
}
});
}
});
updateComputerList();
}
}
@Override
protected void onStop() {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2017 Nicolas Fella <nicolas.fella@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.Plugins.SharePlugin;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.IntentFilter;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.service.chooser.ChooserTarget;
import android.service.chooser.ChooserTargetService;
import android.util.Log;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
import java.util.List;
@TargetApi(23)
public class ShareChooserTargetService extends ChooserTargetService {
@Override
public List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
Log.d("DirectShare", "invoked");
final List<ChooserTarget> targets = new ArrayList<>();
for(Device d: BackgroundService.getInstance().getDevices().values()){
if(d.isReachable() && d.isPaired()) {
Log.d("DirectShare", d.getName());
final String targetName = d.getName();
final Icon targetIcon = Icon.createWithResource(this, R.drawable.icon);
final float targetRanking = 1;
final ComponentName targetComponentName = new ComponentName(getPackageName(),
ShareActivity.class.getCanonicalName());
final Bundle targetExtras = new Bundle();
targetExtras.putString("deviceId", d.getDeviceId());
targets.add(new ChooserTarget(
targetName, targetIcon, targetRanking, targetComponentName, targetExtras
));
}
}
return targets;
}
}

View File

@@ -0,0 +1,123 @@
package org.kde.kdeconnect.Plugins.SharePlugin;
/*
* Copyright 2017 Nicolas Fella <nicolas.fella@gmx.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.FileProvider;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect_tp.R;
import java.io.File;
public class ShareNotification {
private final String filename;
private NotificationManager notificationManager;
private int notificationId;
private NotificationCompat.Builder builder;
private Device device;
public ShareNotification(Device device, String filename) {
this.device = device;
this.filename = filename;
notificationId = (int) System.currentTimeMillis();
notificationManager = (NotificationManager) device.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
builder = new NotificationCompat.Builder(device.getContext())
.setContentTitle(device.getContext().getResources().getString(R.string.incoming_file_title, device.getName()))
.setContentText(device.getContext().getResources().getString(R.string.incoming_file_text, filename))
.setTicker(device.getContext().getResources().getString(R.string.incoming_file_title, device.getName()))
.setSmallIcon(android.R.drawable.stat_sys_download)
.setAutoCancel(true)
.setOngoing(true)
.setProgress(100, 0, true);
}
public void show() {
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
}
public int getId() {
return notificationId;
}
public void setProgress(int progress) {
builder.setProgress(100, progress, false)
.setContentTitle(device.getContext().getResources().getString(R.string.incoming_file_title, device.getName())+" ("+progress+"%)");
}
public void setFinished(boolean success) {
String message = success ? device.getContext().getResources().getString(R.string.received_file_title, device.getName()) : device.getContext().getResources().getString(R.string.received_file_fail_title, device.getName());
builder = new NotificationCompat.Builder(device.getContext());
builder.setContentTitle(message)
.setTicker(message)
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setAutoCancel(true)
.setOngoing(false);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(device.getContext());
if (prefs.getBoolean("share_notification_preference", true)) {
builder.setDefaults(Notification.DEFAULT_ALL);
}
}
public void setURI(Uri destinationUri, String mimeType) {
/*
* We only support file URIs (because sending a content uri to another app does not work for security reasons).
* In effect, that means only the default download folder currently works.
*
* TODO: implement our own content provider (instead of support-v4's FileProvider). It should:
* - Proxy to real files (in case of the default download folder)
* - Proxy to the underlying content uri (in case of a custom download folder)
*/
if (!"file".equals(destinationUri.getScheme())) {
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= 24) {
//Nougat and later require "content://" uris instead of "file://" uris
File file = new File(destinationUri.getPath());
Uri contentUri = FileProvider.getUriForFile(device.getContext(), "org.kde.kdeconnect_tp.fileprovider", file);
intent.setDataAndType(contentUri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
intent.setDataAndType(destinationUri, mimeType);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(device.getContext());
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentText(device.getContext().getResources().getString(R.string.received_file_text, filename))
.setContentIntent(resultPendingIntent);
}
}

View File

@@ -20,6 +20,7 @@
package org.kde.kdeconnect.Plugins.SharePlugin;
import android.Manifest;
import android.app.Activity;
import android.app.DownloadManager;
import android.app.Notification;
@@ -29,12 +30,12 @@ import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
@@ -53,17 +54,26 @@ import org.kde.kdeconnect.UserInterface.SettingsActivity;
import org.kde.kdeconnect_tp.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
public class SharePlugin extends Plugin {
//public final static String PACKAGE_TYPE_SHARE = "kdeconnect.share";
public final static String PACKAGE_TYPE_SHARE_REQUEST = "kdeconnect.share.request";
final static boolean openUrlsDirectly = true;
private int sharePermissionExplanation = R.string.share_optional_permission_explanation;
@Override
public boolean onCreate() {
optionalPermissionExplanation = sharePermissionExplanation;
return true;
}
@Override
public String getDisplayName() {
return context.getResources().getString(R.string.pref_plugin_sharereceiver);
@@ -108,180 +118,168 @@ public class SharePlugin extends Plugin {
if (np.hasPayload()) {
Log.i("SharePlugin", "hasPayload");
final InputStream input = np.getPayload();
final long fileLength = np.getPayloadSize();
final String originalFilename = np.getString("filename", Long.toString(System.currentTimeMillis()));
//We need to check for already existing files only when storing in the default path.
//User-defined paths use the new Storage Access Framework that already handles this.
final boolean customDestination = ShareSettingsActivity.isCustomDestinationEnabled(context);
final String defaultPath = ShareSettingsActivity.getDefaultDestinationDirectory().getAbsolutePath();
final String filename = customDestination? originalFilename : FilesHelper.findNonExistingNameForNewFile(defaultPath, originalFilename);
String displayName = FilesHelper.getFileNameWithoutExt(filename);
final String mimeType = FilesHelper.getMimeTypeFromFile(filename);
if ("*/*".equals(mimeType)) {
displayName = filename;
if (isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
receiveFile(np);
} else {
Log.i("SharePlugin", "no Permission for Storage");
}
final DocumentFile destinationFolderDocument = ShareSettingsActivity.getDestinationDirectory(context);
final DocumentFile destinationDocument = destinationFolderDocument.createFile(mimeType, displayName);
final OutputStream destinationOutput = context.getContentResolver().openOutputStream(destinationDocument.getUri());
final Uri destinationUri = destinationDocument.getUri();
final int notificationId = (int)System.currentTimeMillis();
Resources res = context.getResources();
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(res.getString(R.string.incoming_file_title, device.getName()))
.setContentText(res.getString(R.string.incoming_file_text, filename))
.setTicker(res.getString(R.string.incoming_file_title, device.getName()))
.setSmallIcon(android.R.drawable.stat_sys_download)
.setAutoCancel(true)
.setOngoing(true)
.setProgress(100,0,true);
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationHelper.notifyCompat(notificationManager,notificationId, builder.build());
new Thread(new Runnable() {
@Override
public void run() {
boolean successful = true;
try {
byte data[] = new byte[1024];
long progress = 0, prevProgressPercentage = 0;
int count;
while ((count = input.read(data)) >= 0) {
progress += count;
destinationOutput.write(data, 0, count);
if (fileLength > 0) {
if (progress >= fileLength) break;
long progressPercentage = (progress * 100 / fileLength);
if (progressPercentage != prevProgressPercentage) {
prevProgressPercentage = progressPercentage;
builder.setProgress(100, (int) progressPercentage, false);
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
}
}
//else Log.e("SharePlugin", "Infinite loop? :D");
}
destinationOutput.flush();
} catch (Exception e) {
successful = false;
Log.e("SharePlugin", "Receiver thread exception");
e.printStackTrace();
} finally {
try { destinationOutput.close(); } catch (Exception e) {}
try { input.close(); } catch (Exception e) {}
}
try {
Log.i("SharePlugin", "Transfer finished: "+destinationUri.getPath());
//Update the notification and allow to open the file from it
Resources res = context.getResources();
String message = successful? res.getString(R.string.received_file_title, device.getName()) : res.getString(R.string.received_file_fail_title, device.getName());
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle(message)
.setTicker(message)
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setAutoCancel(true);
if (successful) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(destinationUri, mimeType);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(intent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentText(res.getString(R.string.received_file_text, destinationDocument.getName()))
.setContentIntent(resultPendingIntent);
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.getBoolean("share_notification_preference", true)) {
builder.setDefaults(Notification.DEFAULT_ALL);
}
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
if (successful) {
if (!customDestination) {
Log.i("SharePlugin","Adding to downloads");
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
manager.addCompletedDownload(destinationUri.getLastPathSegment(), device.getName(), true, mimeType, destinationUri.getPath(), fileLength, false);
} else {
//Make sure it is added to the Android Gallery anyway
MediaStoreHelper.indexFile(context, destinationUri);
}
}
} catch (Exception e) {
Log.e("SharePlugin", "Receiver thread exception");
e.printStackTrace();
}
}
}).start();
} else if (np.has("text")) {
Log.i("SharePlugin", "hasText");
String text = np.getString("text");
if(android.os.Build.VERSION.SDK_INT >= 11) {
ClipboardManager cm = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
cm.setText(text);
} else {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}
Toast.makeText(context, R.string.shareplugin_text_saved, Toast.LENGTH_LONG).show();
receiveText(np);
} else if (np.has("url")) {
String url = np.getString("url");
Log.i("SharePlugin", "hasUrl: "+url);
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (openUrlsDirectly) {
context.startActivity(browserIntent);
} else {
Resources res = context.getResources();
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(browserIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
Notification noti = new NotificationCompat.Builder(context)
.setContentTitle(res.getString(R.string.received_url_title, device.getName()))
.setContentText(res.getString(R.string.received_url_text, url))
.setContentIntent(resultPendingIntent)
.setTicker(res.getString(R.string.received_url_title, device.getName()))
.setSmallIcon(R.drawable.ic_notification)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationHelper.notifyCompat(notificationManager, (int) System.currentTimeMillis(), noti);
}
receiveUrl(np);
} else {
Log.e("SharePlugin", "Error: Nothing attached!");
}
} catch(Exception e) {
Log.e("SharePlugin","Exception");
} catch (Exception e) {
Log.e("SharePlugin", "Exception");
e.printStackTrace();
}
return true;
}
private void receiveUrl(NetworkPackage np) {
String url = np.getString("url");
Log.i("SharePlugin", "hasUrl: " + url);
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (openUrlsDirectly) {
context.startActivity(browserIntent);
} else {
Resources res = context.getResources();
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(browserIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
Notification noti = new NotificationCompat.Builder(context)
.setContentTitle(res.getString(R.string.received_url_title, device.getName()))
.setContentText(res.getString(R.string.received_url_text, url))
.setContentIntent(resultPendingIntent)
.setTicker(res.getString(R.string.received_url_title, device.getName()))
.setSmallIcon(R.drawable.ic_notification)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationHelper.notifyCompat(notificationManager, (int) System.currentTimeMillis(), noti);
}
}
private void receiveText(NetworkPackage np) {
String text = np.getString("text");
if (Build.VERSION.SDK_INT >= 11) {
ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
cm.setText(text);
} else {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}
Toast.makeText(context, R.string.shareplugin_text_saved, Toast.LENGTH_LONG).show();
}
private void receiveFile(NetworkPackage np) {
final InputStream input = np.getPayload();
final long fileLength = np.getPayloadSize();
final String originalFilename = np.getString("filename", Long.toString(System.currentTimeMillis()));
//We need to check for already existing files only when storing in the default path.
//User-defined paths use the new Storage Access Framework that already handles this.
final boolean customDestination = ShareSettingsActivity.isCustomDestinationEnabled(context);
final String defaultPath = ShareSettingsActivity.getDefaultDestinationDirectory().getAbsolutePath();
final String filename = customDestination ? originalFilename : FilesHelper.findNonExistingNameForNewFile(defaultPath, originalFilename);
String displayName = FilesHelper.getFileNameWithoutExt(filename);
final String mimeType = FilesHelper.getMimeTypeFromFile(filename);
if ("*/*".equals(mimeType)) {
displayName = filename;
}
final DocumentFile destinationFolderDocument = ShareSettingsActivity.getDestinationDirectory(context);
final DocumentFile destinationDocument = destinationFolderDocument.createFile(mimeType, displayName);
final OutputStream destinationOutput;
try {
destinationOutput = context.getContentResolver().openOutputStream(destinationDocument.getUri());
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
final Uri destinationUri = destinationDocument.getUri();
final ShareNotification notification = new ShareNotification(device, filename);
notification.show();
new Thread(new Runnable() {
@Override
public void run() {
try {
byte data[] = new byte[4096];
long progress = 0, prevProgressPercentage = -1;
int count;
while ((count = input.read(data)) >= 0) {
progress += count;
destinationOutput.write(data, 0, count);
if (fileLength > 0) {
if (progress >= fileLength) break;
long progressPercentage = (progress * 100 / fileLength);
if (progressPercentage != prevProgressPercentage) {
prevProgressPercentage = progressPercentage;
notification.setProgress((int) progressPercentage);
notification.show();
}
}
//else Log.e("SharePlugin", "Infinite loop? :D");
}
destinationOutput.flush();
Log.i("SharePlugin", "Transfer finished: " + destinationUri.getPath());
//Update the notification and allow to open the file from it
notification.setFinished(true);
notification.setURI(destinationUri, mimeType);
notification.show();
if (!customDestination && Build.VERSION.SDK_INT >= 12) {
Log.i("SharePlugin", "Adding to downloads");
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
manager.addCompletedDownload(destinationUri.getLastPathSegment(), device.getName(), true, mimeType, destinationUri.getPath(), fileLength, false);
} else {
//Make sure it is added to the Android Gallery anyway
MediaStoreHelper.indexFile(context, destinationUri);
}
} catch (Exception e) {
Log.e("SharePlugin", "Receiver thread exception");
e.printStackTrace();
notification.setFinished(false);
notification.show();
} finally {
try {
destinationOutput.close();
} catch (Exception e) {
}
try {
input.close();
} catch (Exception e) {
}
}
}
}).start();
}
@Override
public void startPreferencesActivity(SettingsActivity parentActivity) {
Intent intent = new Intent(parentActivity, ShareSettingsActivity.class);
@@ -310,7 +308,7 @@ public class SharePlugin extends Plugin {
for (NetworkPackage np : toSend) {
boolean success = device.sendPackageBlocking(np, notificationUpdateCallback);
if (!success) {
Log.e("SharePlugin","Error sending files");
Log.e("SharePlugin", "Error sending files");
return;
}
}
@@ -340,24 +338,24 @@ public class SharePlugin extends Plugin {
try {
size = new File(uri.getPath()).length();
} catch(Exception e) {
} catch (Exception e) {
Log.e("SendFileActivity", "Could not obtain file size");
e.printStackTrace();
}
}else{
} else {
// Probably a content:// uri, so we query the Media content provider
Cursor cursor = null;
try {
String[] proj = { MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.SIZE, MediaStore.MediaColumns.DISPLAY_NAME };
String[] proj = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.SIZE, MediaStore.MediaColumns.DISPLAY_NAME};
cursor = cr.query(uri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
cursor.moveToFirst();
String path = cursor.getString(column_index);
np.set("filename", Uri.parse(path).getLastPathSegment());
size = new File(path).length();
} catch(Exception unused) {
} catch (Exception unused) {
Log.w("SendFileActivity", "Could not resolve media to a file, trying to get info as media");
@@ -376,12 +374,15 @@ public class SharePlugin extends Plugin {
cursor.moveToFirst();
//For some reason this size can differ from the actual file size!
size = cursor.getInt(column_index);
} catch(Exception e) {
} catch (Exception e) {
Log.e("SendFileActivity", "Could not obtain file size");
e.printStackTrace();
}
} finally {
try { cursor.close(); } catch (Exception e) { }
try {
cursor.close();
} catch (Exception e) {
}
}
}
@@ -396,6 +397,59 @@ public class SharePlugin extends Plugin {
}
}
public static void share(Intent intent, Device device){
Bundle extras = intent.getExtras();
if (extras != null) {
if (extras.containsKey(Intent.EXTRA_STREAM)) {
try {
ArrayList<Uri> uriList;
if (!Intent.ACTION_SEND.equals(intent.getAction())) {
uriList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
} else {
Uri uri = extras.getParcelable(Intent.EXTRA_STREAM);
uriList = new ArrayList<>();
uriList.add(uri);
}
SharePlugin.queuedSendUriList(device.getContext(), device, uriList);
} catch (Exception e) {
Log.e("ShareActivity", "Exception");
e.printStackTrace();
}
} else if (extras.containsKey(Intent.EXTRA_TEXT)) {
String text = extras.getString(Intent.EXTRA_TEXT);
String subject = extras.getString(Intent.EXTRA_SUBJECT);
//Hack: Detect shared youtube videos, so we can open them in the browser instead of as text
if (subject != null && subject.endsWith("YouTube")) {
int index = text.indexOf(": http://youtu.be/");
if (index > 0) {
text = text.substring(index + 2); //Skip ": "
}
}
boolean isUrl;
try {
new URL(text);
isUrl = true;
} catch (Exception e) {
isUrl = false;
}
NetworkPackage np = new NetworkPackage(SharePlugin.PACKAGE_TYPE_SHARE_REQUEST);
if (isUrl) {
np.set("url", text);
} else {
np.set("text", text);
}
device.sendPackage(np);
}
}
}
@Override
public String[] getSupportedPackageTypes() {
@@ -407,5 +461,8 @@ public class SharePlugin extends Plugin {
return new String[]{PACKAGE_TYPE_SHARE_REQUEST};
}
@Override
public String[] getOptionalPermissions() {
return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
}
}

View File

@@ -93,6 +93,11 @@ public class ShareSettingsActivity extends PluginSettingsActivity {
}
}
}
try {
getDefaultDestinationDirectory().mkdirs();
} catch(Exception e) {
e.printStackTrace();
}
return DocumentFile.fromFile(getDefaultDestinationDirectory());
}

View File

@@ -20,9 +20,15 @@
package org.kde.kdeconnect.Plugins.TelepathyPlugin;
import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.telephony.SmsManager;
import android.util.Log;
import java.util.ArrayList;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin;
@@ -33,6 +39,14 @@ public class TelepathyPlugin extends Plugin {
public final static String PACKAGE_TYPE_SMS_REQUEST = "kdeconnect.sms.request";
private int telepathyPermissionExplanation = R.string.telepathy_permission_explanation;
@Override
public boolean onCreate() {
permissionExplanation = telepathyPermissionExplanation;
return true;
}
@Override
public String getDisplayName() {
return context.getResources().getString(R.string.pref_plugin_telepathy);
@@ -43,11 +57,6 @@ public class TelepathyPlugin extends Plugin {
return context.getResources().getString(R.string.pref_plugin_telepathy_desc);
}
@Override
public boolean onCreate() {
return true;
}
@Override
public void onDestroy() {
}
@@ -63,8 +72,20 @@ public class TelepathyPlugin extends Plugin {
String phoneNo = np.getString("phoneNumber");
String sms = np.getString("messageBody");
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo, null, sms, null, null);
int permissionCheck = ContextCompat.checkSelfPermission(context,
Manifest.permission.SEND_SMS);
if(permissionCheck == PackageManager.PERMISSION_GRANTED) {
SmsManager smsManager = SmsManager.getDefault();
ArrayList<String> parts = smsManager.divideMessage(sms);
// If this message turns out to fit in a single SMS, sendMultpartTextMessage
// properly handles that case
smsManager.sendMultipartTextMessage(phoneNo, null, parts, null, null);
} else if(permissionCheck == PackageManager.PERMISSION_DENIED){
// TODO Request Permission SEND_SMS
}
//TODO: Notify other end
} catch (Exception e) {
//TODO: Notify other end
@@ -176,4 +197,8 @@ public class TelepathyPlugin extends Plugin {
return new String[]{};
}
@Override
public String[] getRequiredPermissions() {
return new String[]{Manifest.permission.SEND_SMS/*, Manifest.permission.READ_CONTACTS*/};
}
}

View File

@@ -20,13 +20,16 @@
package org.kde.kdeconnect.Plugins.TelephonyPlugin;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -34,8 +37,10 @@ import android.util.Log;
import org.kde.kdeconnect.Helpers.ContactsHelper;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect_tp.BuildConfig;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@@ -49,6 +54,9 @@ public class TelephonyPlugin extends Plugin {
private NetworkPackage lastPackage = null;
private boolean isMuted = false;
private int telephonyPermissionExplanation = R.string.telephony_permission_explanation;
private int telephonyOptionalPermissionExplanation = R.string.telephony_optional_permission_explanation;
@Override
public String getDisplayName() {
return context.getResources().getString(R.string.pref_plugin_telephony);
@@ -72,11 +80,19 @@ public class TelephonyPlugin extends Plugin {
final Bundle bundle = intent.getExtras();
if (bundle == null) return;
final Object[] pdus = (Object[]) bundle.get("pdus");
ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
for (Object pdu : pdus) {
SmsMessage message = SmsMessage.createFromPdu((byte[])pdu);
smsBroadcastReceived(message);
// I hope, but am not sure, that the pdus array is in the order that the parts
// of the SMS message should be
// If it is not, I belive the pdu contains the information necessary to put it
// in order, but in my testing the order seems to be correct, so I won't worry
// about it now.
messages.add(SmsMessage.createFromPdu((byte[])pdu));
}
smsBroadcastReceived(messages);
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
@@ -102,32 +118,40 @@ public class TelephonyPlugin extends Plugin {
//Log.e("TelephonyPlugin", "callBroadcastReceived");
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_TELEPHONY);
if (phoneNumber != null) {
np.set("phoneNumber", phoneNumber);
}
int permissionCheck = ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CONTACTS);
if(permissionCheck==PackageManager.PERMISSION_GRANTED) {
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
if (contactInfo.containsKey("name")) {
np.set("contactName", contactInfo.get("name"));
}
if (contactInfo.containsKey("photoID")) {
String photoUri = contactInfo.get("photoID");
if (photoUri != null) {
try {
String base64photo = ContactsHelper.photoId64Encoded(context, photoUri);
if (base64photo != null && !base64photo.isEmpty()) {
np.set("phoneThumbnail", base64photo);
}
} catch (Exception e) {
Log.e("TelephonyPlugin", "Failed to get contact photo");
}
}
}
if (contactInfo.containsKey("name")) {
np.set("contactName", contactInfo.get("name"));
} else {
np.set("contactName", phoneNumber);
}
if (contactInfo.containsKey("photoID")) {
String photoUri = contactInfo.get("photoID");
if (photoUri != null) {
try {
String base64photo = ContactsHelper.photoId64Encoded(context, photoUri);
if (base64photo != null && !base64photo.isEmpty()) {
np.set("phoneThumbnail", base64photo);
}
} catch (Exception e) {
Log.e("TelephonyPlugin", "Failed to get contact photo");
}
}
if (phoneNumber != null) {
np.set("phoneNumber", phoneNumber);
}
switch (state) {
@@ -194,7 +218,14 @@ public class TelephonyPlugin extends Plugin {
lastState = state;
}
private void smsBroadcastReceived(SmsMessage message) {
private void smsBroadcastReceived(ArrayList<SmsMessage> messages) {
if (BuildConfig.DEBUG) {
if (!(messages.size() > 0))
{
throw new AssertionError("This method requires at least one message");
}
}
//Log.e("SmsBroadcastReceived", message.toString());
@@ -202,24 +233,33 @@ public class TelephonyPlugin extends Plugin {
np.set("event","sms");
String messageBody = message.getMessageBody();
if (messageBody != null) {
np.set("messageBody",messageBody);
StringBuilder messageBody = new StringBuilder();
for (int index = 0; index < messages.size(); index ++) {
messageBody.append(messages.get(index).getMessageBody());
}
np.set("messageBody", messageBody.toString());
String phoneNumber = message.getOriginatingAddress();
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
String phoneNumber = messages.get(0).getOriginatingAddress();
int permissionCheck = ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CONTACTS);
if(permissionCheck==PackageManager.PERMISSION_GRANTED) {
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
if (contactInfo.containsKey("name")) {
np.set("contactName", contactInfo.get("name"));
}
if (contactInfo.containsKey("photoID")) {
np.set("phoneThumbnail", ContactsHelper.photoId64Encoded(context, contactInfo.get("photoID")));
}
}
if (phoneNumber != null) {
np.set("phoneNumber", phoneNumber);
}
if (contactInfo.containsKey("name")) {
np.set("contactName", contactInfo.get("name"));
}
if (contactInfo.containsKey("photoID")) {
np.set("phoneThumbnail", ContactsHelper.photoId64Encoded(context, contactInfo.get("photoID")));
}
device.sendPackage(np);
}
@@ -231,6 +271,8 @@ public class TelephonyPlugin extends Plugin {
filter.setPriority(500);
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
context.registerReceiver(receiver, filter);
permissionExplanation = telephonyPermissionExplanation;
optionalPermissionExplanation = telephonyOptionalPermissionExplanation;
return true;
}
@@ -267,4 +309,13 @@ public class TelephonyPlugin extends Plugin {
return new String[]{PACKAGE_TYPE_TELEPHONY};
}
@Override
public String[] getRequiredPermissions() {
return new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_SMS};
}
@Override
public String[] getOptionalPermissions() {
return new String[]{Manifest.permission.READ_CONTACTS};
}
}

View File

@@ -26,7 +26,7 @@ import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
@@ -42,7 +42,7 @@ import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
public class CustomDevicesActivity extends ActionBarActivity {
public class CustomDevicesActivity extends AppCompatActivity {
private static final String LOG_ID = "CustomDevicesActivity";
public static final String KEY_CUSTOM_DEVLIST_PREFERENCE = "device_list_preference";

View File

@@ -62,31 +62,27 @@ import java.util.concurrent.ConcurrentHashMap;
public class DeviceFragment extends Fragment {
static final String ARG_DEVICE_ID = "deviceId";
static final String ARG_FROM_DEVICE_LIST = "fromDeviceList";
View rootView;
static String mDeviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
Device device;
TextView errorHeader;
MaterialActivity mActivity;
public DeviceFragment() { }
ArrayList<ListAdapter.Item> pluginListItems;
public DeviceFragment(String deviceId) {
Bundle args = new Bundle();
args.putString(ARG_DEVICE_ID, deviceId);
this.setArguments(args);
public DeviceFragment() {
}
public DeviceFragment(String deviceId, boolean fromDeviceList) {
Bundle args = new Bundle();
args.putString(ARG_DEVICE_ID, deviceId);
args.putBoolean("fromDeviceList", fromDeviceList);
args.putBoolean(ARG_FROM_DEVICE_LIST, fromDeviceList);
this.setArguments(args);
}
public DeviceFragment(String deviceId, MaterialActivity activity){
public DeviceFragment(String deviceId, MaterialActivity activity) {
this.mActivity = activity;
Bundle args = new Bundle();
args.putString(ARG_DEVICE_ID, deviceId);
@@ -134,7 +130,7 @@ public class DeviceFragment extends Fragment {
}
});
final Button pairButton = (Button)rootView.findViewById(R.id.pair_button);
final Button pairButton = (Button) rootView.findViewById(R.id.pair_button);
pairButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -299,7 +295,7 @@ public class DeviceFragment extends Fragment {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
boolean fromDeviceList = getArguments().getBoolean("fromDeviceList", false);
boolean fromDeviceList = getArguments().getBoolean(ARG_FROM_DEVICE_LIST, false);
// Handle back button so we go to the list of devices in case we came from there
if (fromDeviceList) {
mActivity.onDeviceSelected(null);
@@ -341,7 +337,7 @@ public class DeviceFragment extends Fragment {
rootView.findViewById(R.id.on_data_message).setVisibility((paired && !reachable && onData) ? View.VISIBLE : View.GONE);
try {
ArrayList<ListAdapter.Item> items = new ArrayList<>();
pluginListItems = new ArrayList<>();
//Plugins button list
final Collection<Plugin> plugins = device.getLoadedPlugins().values();
@@ -349,7 +345,7 @@ public class DeviceFragment extends Fragment {
if (!p.hasMainActivity()) continue;
if (p.displayInContextMenu()) continue;
items.add(new PluginItem(p, new View.OnClickListener() {
pluginListItems.add(new PluginItem(p, new View.OnClickListener() {
@Override
public void onClick(View v) {
p.startMainActivity(mActivity);
@@ -357,40 +353,27 @@ public class DeviceFragment extends Fragment {
}));
}
//Failed plugins List
final ConcurrentHashMap<String, Plugin> failed = device.getFailedPlugins();
if (!failed.isEmpty()) {
if (errorHeader == null) {
errorHeader = new TextView(mActivity);
errorHeader.setPadding(
0,
((int) (28 * getResources().getDisplayMetrics().density)),
0,
((int) (8 * getResources().getDisplayMetrics().density))
);
errorHeader.setOnClickListener(null);
errorHeader.setOnLongClickListener(null);
errorHeader.setText(getResources().getString(R.string.plugins_failed_to_load));
createPluginsList(device.getFailedPlugins(), R.string.plugins_failed_to_load, new PluginClickListener() {
@Override
void action() {
plugin.getErrorDialog(mActivity).show();
}
items.add(new CustomItem(errorHeader));
for (Map.Entry<String, Plugin> entry : failed.entrySet()) {
String pluginKey = entry.getKey();
final Plugin plugin = entry.getValue();
if (plugin == null) {
items.add(new SmallEntryItem(pluginKey));
} else {
items.add(new SmallEntryItem(plugin.getDisplayName(), new View.OnClickListener() {
@Override
public void onClick(View v) {
plugin.getErrorDialog(mActivity).show();
}
}));
}
});
createPluginsList(device.getPluginsWithoutPermissions(), R.string.plugins_need_permission, new PluginClickListener() {
@Override
void action() {
plugin.getPermissionExplanationDialog(mActivity).show();
}
}
});
createPluginsList(device.getPluginsWithoutOptionalPermissions(), R.string.plugins_need_optional_permission, new PluginClickListener() {
@Override
void action() {
plugin.getOptionalPermissionExplanationDialog(mActivity).show();
}
});
ListView buttonsList = (ListView) rootView.findViewById(R.id.buttons_list);
ListAdapter adapter = new ListAdapter(mActivity, items);
ListAdapter adapter = new ListAdapter(mActivity, pluginListItems);
buttonsList.setAdapter(adapter);
mActivity.invalidateOptionsMenu();
@@ -453,11 +436,15 @@ public class DeviceFragment extends Fragment {
};
public static void acceptPairing(final String devId, final MaterialActivity activity){
public static void acceptPairing(final String devId, final MaterialActivity activity) {
final DeviceFragment frag = new DeviceFragment(devId, activity);
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
public void onServiceStart(BackgroundService service) {
Device dev = service.getDevice(devId);
if (dev == null) {
Log.w("rejectPairing", "Device no longer exists: "+devId);
return;
}
activity.getSupportActionBar().setTitle(dev.getName());
dev.addPairingCallback(frag.pairingCallback);
@@ -472,11 +459,15 @@ public class DeviceFragment extends Fragment {
});
}
public static void rejectPairing(final String devId, final MaterialActivity activity){
public static void rejectPairing(final String devId, final MaterialActivity activity) {
final DeviceFragment frag = new DeviceFragment(devId, activity);
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
public void onServiceStart(BackgroundService service) {
Device dev = service.getDevice(devId);
if (dev == null) {
Log.w("rejectPairing", "Device no longer exists: "+devId);
return;
}
activity.getSupportActionBar().setTitle(dev.getName());
dev.addPairingCallback(frag.pairingCallback);
@@ -494,4 +485,58 @@ public class DeviceFragment extends Fragment {
}
});
}
void createPluginsList(ConcurrentHashMap<String, Plugin> plugins, int headerText, PluginClickListener onClickListener) {
if (!plugins.isEmpty()) {
TextView header = new TextView(mActivity);
header.setPadding(
0,
((int) (28 * getResources().getDisplayMetrics().density)),
0,
((int) (8 * getResources().getDisplayMetrics().density))
);
header.setOnClickListener(null);
header.setOnLongClickListener(null);
header.setText(headerText);
pluginListItems.add(new CustomItem(header));
for (Map.Entry<String, Plugin> entry : plugins.entrySet()) {
String pluginKey = entry.getKey();
final Plugin plugin = entry.getValue();
if (device.isPluginEnabled(pluginKey)) {
if (plugin == null) {
pluginListItems.add(new SmallEntryItem(pluginKey));
} else {
PluginClickListener listener = onClickListener.clone();
listener.plugin = plugin;
pluginListItems.add(new SmallEntryItem(plugin.getDisplayName(), listener));
}
}
}
}
}
private abstract class PluginClickListener implements View.OnClickListener, Cloneable {
Plugin plugin;
@Override
public void onClick(View v) {
action();
}
@Override
public PluginClickListener clone(){
try {
return (PluginClickListener) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
abstract void action();
}
}

View File

@@ -1,14 +1,17 @@
package org.kde.kdeconnect.UserInterface;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
@@ -236,7 +239,7 @@ public class MaterialActivity extends AppCompatActivity {
//TODO: Make it accept two parameters, a constant with the type of screen and the device id in
//case the screen is for a device, or even three parameters and the third one be the plugin id?
//This way we can keep adding more options with null device id (eg: about, help...)
public void onDeviceSelected(String deviceId, boolean stack) {
public void onDeviceSelected(String deviceId, boolean fromDeviceList) {
mCurrentDevice = deviceId;
@@ -251,7 +254,7 @@ public class MaterialActivity extends AppCompatActivity {
if (deviceId == null) {
fragment = new PairingFragment();
} else {
fragment = new DeviceFragment(deviceId, stack);
fragment = new DeviceFragment(deviceId, fromDeviceList);
}
getSupportFragmentManager()
@@ -294,6 +297,22 @@ public class MaterialActivity extends AppCompatActivity {
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
for (int result : grantResults) {
if (result == PackageManager.PERMISSION_GRANTED) {
//New permission granted, reload plugins
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(mCurrentDevice);
device.reloadPluginsFromSettings();
}
});
}
}
}
public void renameDevice() {
final TextView nameView = (TextView) mNavigationView.findViewById(R.id.device_name);
final EditText deviceNameEdit = new EditText(MaterialActivity.this);
@@ -313,6 +332,12 @@ public class MaterialActivity extends AppCompatActivity {
String deviceName = deviceNameEdit.getText().toString();
DeviceHelper.setDeviceName(MaterialActivity.this, deviceName);
nameView.setText(deviceName);
BackgroundService.RunCommand(MaterialActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(final BackgroundService service) {
service.onNetworkChange();
}
});
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {

View File

@@ -1,55 +0,0 @@
/*
* Copyright 2014 Albert Vaca Cintora <albertvaka@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.UserInterface;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageButton;
import org.kde.kdeconnect_tp.R;
public class MaxWidthImageButton extends ImageButton {
int mMaxWidth = Integer.MAX_VALUE;
public MaxWidthImageButton(Context context) {
super(context);
}
public MaxWidthImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthImageButton);
mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthImageButton_maxWidth, Integer.MAX_VALUE);
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(getMeasuredWidth() > mMaxWidth){
setMeasuredDimension(mMaxWidth, getMeasuredHeight());
}
}
}

View File

@@ -24,6 +24,7 @@ import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -55,10 +56,10 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
private static final int RESULT_PAIRING_SUCCESFUL = Activity.RESULT_FIRST_USER;
private View rootView;
private View listRootView;
private SwipeRefreshLayout mSwipeRefreshLayout;
private MaterialActivity mActivity;
private MenuItem menuProgress;
boolean listRefreshCalledThisFrame = false;
TextView headerText;
@@ -75,12 +76,21 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
setHasOptionsMenu(true);
rootView = inflater.inflate(R.layout.activity_list, container, false);
rootView = inflater.inflate(R.layout.activity_refresh_list, container, false);
listRootView = rootView.findViewById(R.id.listView1);
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_list_layout);
mSwipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
updateComputerListAction();
}
}
);
headerText = new TextView(inflater.getContext());
headerText.setText(getString(R.string.pairing_description));
headerText.setPadding(0, (int) (16 * getResources().getDisplayMetrics().density), 0, (int) (12 * getResources().getDisplayMetrics().density));
((ListView) rootView).addHeaderView(headerText);
((ListView) listRootView).addHeaderView(headerText);
return rootView;
}
@@ -91,7 +101,30 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
mActivity = ((MaterialActivity) getActivity());
}
void updateComputerList() {
private void updateComputerListAction() {
updateComputerList();
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
}
});
mSwipeRefreshLayout.setRefreshing(true);
new Thread(new Runnable() {
@Override
public void run() {
try { Thread.sleep(1500); } catch (InterruptedException ignored) { }
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
}
});
}
}).start();
}
private void updateComputerList() {
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(final BackgroundService service) {
@@ -99,6 +132,11 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
@Override
public void run() {
if (!isAdded()) {
//Fragment is not attached to an activity. We will crash if we try to do anything here.
return;
}
if (listRefreshCalledThisFrame) {
// This makes sure we don't try to call list.getFirstVisiblePosition()
// twice per frame, because the second time the list hasn't been drawn
@@ -108,6 +146,9 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
listRefreshCalledThisFrame = true;
headerText.setText(getString(NetworkHelper.isOnMobileNetwork(getContext()) ? R.string.on_data_message : R.string.pairing_description));
//Disable tap animation
headerText.setOnClickListener(null);
headerText.setOnLongClickListener(null);
try {
Collection<Device> devices = service.getDevices().values();
@@ -197,6 +238,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
@Override
public void onStop() {
super.onStop();
mSwipeRefreshLayout.setEnabled(false);
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
@@ -227,33 +269,13 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.pairing, menu);
menuProgress = menu.findItem(R.id.menu_progress);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_refresh:
updateComputerList();
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
}
});
menuProgress.setVisible(true);
new Thread(new Runnable() {
@Override
public void run() {
try { Thread.sleep(1500); } catch (InterruptedException e) { }
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
menuProgress.setVisible(false);
}
});
}
}).start();
updateComputerListAction();
break;
case R.id.menu_rename:
mActivity.renameDevice();