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

Compare commits

..

158 Commits
v1.3 ... v1.6

Author SHA1 Message Date
Albert Vaca
b6814c86c5 Bumped version to release 2017-02-14 22:23:33 +01:00
Dmitriy Bogdanov
3cc71a69a4 FindMyPhone: better activity lifecycle handling
Summary:
There are some minor problems with current implementation: if device configuration changes (screen orientation, etc.) while the "FindMyPhone" ringtone is playing, the activity gets recreated and starts to play a new ringtone again, but the first ringtone is not stopped.
Also if the user leaves the activity the ringtone continues to play, the user has no way to get back to the activity to stop it.

With these changes the ringtone starts playing when the activity becomes visible and stops when the activity is being hidden/destroyed. If the user leaves the activity (without destroying it) and then presses "Ring my phone" button again, the activity becomes visible again and starts to play the ringtone.

There are other ways to improve it that I did not touch: use a Service to play the ringtone (so not to depend on the activity's lifecycle) or handle configuration changes in activity (so it is not recreated on orientation changes).

Test Plan: Activate "Find My Phone" feature and try to turn phone or leave activity.

Reviewers: albertvaka

Reviewed By: albertvaka

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D4548
2017-02-14 22:12:38 +01:00
l10n daemon script
c0502803c4 GIT_SILENT made messages (after extraction) 2017-02-12 06:34:40 +01:00
l10n daemon script
ec6696b33b GIT_SILENT made messages (after extraction) 2017-02-11 06:59:47 +01:00
l10n daemon script
7e30e27f61 GIT_SILENT made messages (after extraction) 2017-02-10 06:30:56 +01:00
l10n daemon script
92a10bcd35 GIT_SILENT made messages (after extraction) 2017-02-08 06:21:40 +01:00
l10n daemon script
723f398ea8 GIT_SILENT made messages (after extraction) 2017-02-07 13:35:11 +01:00
l10n daemon script
060fa8200e GIT_SILENT made messages (after extraction) 2017-02-06 06:55:43 +01:00
Albert Vaca
7045c50c81 OPEN_DOCUMENT_TREE needs lollipop 2017-02-05 21:39:28 +01:00
Albert Vaca
fe0409e9e7 Bumped version to release in beta channel 2017-02-05 21:31:49 +01:00
Albert Vaca
4f39aa2b65 Disabled remote keyboard from stable branch
Se we can release from the stable branch without it until we release a
desktop version with this feature.
2017-02-05 21:31:34 +01:00
Albert Vaca
cba67c73a0 Fixed tests 2017-02-05 21:24:45 +01:00
Albert Vaca
2e5dc56366 Merge branch '1.x'
# Conflicts:
#	res/values-ast/strings.xml
#	res/values-gl/strings.xml
2017-02-05 21:23:13 +01:00
Albert Vaca
5ece4e21e7 Bumped android sdk version 2017-02-05 16:19:55 +01:00
Albert Vaca
be66fb23cf Stuff used from inner classes shouldn't be private. 2017-02-05 16:19:41 +01:00
Albert Vaca
a6bd803df8 Fixed NPE because frag.device was null
Why was this starting two RunCommand threads? Exec order is not guaranteed.
2017-02-05 15:42:03 +01:00
Albert Vaca
a5a4b360ae Fixed crash on unpairing 2017-02-05 15:34:16 +01:00
Albert Vaca
71e7218b4e Fixed java.lang.ClassCastException:
android.text.SpannableString cannot be cast to java.lang.String
2017-02-05 15:34:07 +01:00
Okoko Michaels
89ecdfc363 Accept or reject pair requests from the notification 2017-02-05 15:20:36 +01:00
l10n daemon script
1179807bcf GIT_SILENT made messages (after extraction) 2017-02-05 03:53:51 +01:00
l10n daemon script
4279ae824f GIT_SILENT made messages (after extraction) 2017-02-02 06:45:38 +01:00
l10n daemon script
753a6425ef GIT_SILENT made messages (after extraction) 2017-02-02 03:50:38 +01:00
l10n daemon script
08312e409d GIT_SILENT made messages (after extraction) 2017-01-31 08:49:33 +01:00
l10n daemon script
22526fdaa8 GIT_SILENT made messages (after extraction) 2017-01-30 03:47:18 +01:00
l10n daemon script
963b29ef6b GIT_SILENT made messages (after extraction) 2017-01-25 03:51:08 +01:00
Holger Kaelberer
ca9704eab2 Add remotekeyboard plugin
BUG: 370919
REVIEW: 129728
2017-01-23 09:07:18 +01:00
l10n daemon script
8d148aad92 GIT_SILENT made messages (after extraction) 2017-01-23 06:35:43 +01:00
l10n daemon script
1239944deb GIT_SILENT made messages (after extraction) 2017-01-23 03:43:48 +01:00
Albert Vaca
9e5e9b3047 Make package private 2017-01-22 06:08:07 +01:00
l10n daemon script
42f8289071 GIT_SILENT made messages (after extraction) 2017-01-15 04:03:15 +01:00
l10n daemon script
371ffefd20 GIT_SILENT made messages (after extraction) 2017-01-07 07:20:26 +01:00
l10n daemon script
614becd1a7 GIT_SILENT made messages (after extraction) 2017-01-07 03:41:41 +01:00
l10n daemon script
3c101210e2 GIT_SILENT made messages (after extraction) 2017-01-04 07:02:02 +01:00
l10n daemon script
52a4ac20ee GIT_SILENT made messages (after extraction) 2016-12-27 13:30:52 +01:00
l10n daemon script
42be344336 GIT_SILENT made messages (after extraction) 2016-12-26 06:42:43 +01:00
l10n daemon script
1811b93b0a GIT_SILENT made messages (after extraction) 2016-12-26 03:35:38 +01:00
Albert Vaca
6ed1bf6284 Fix crash when ringtone is null. 2016-12-25 16:57:32 +01:00
l10n daemon script
f1ca9a3c33 GIT_SILENT made messages (after extraction) 2016-12-22 06:40:55 +01:00
l10n daemon script
9d4bbbb629 GIT_SILENT made messages (after extraction) 2016-12-22 03:37:14 +01:00
l10n daemon script
60ff59bc34 GIT_SILENT made messages (after extraction) 2016-12-20 14:13:07 +01:00
l10n daemon script
059a3b2437 GIT_SILENT made messages (after extraction) 2016-12-20 08:31:20 +01:00
Albert Vaca
eeb19bd206 Allow sending more than one file from SendFileActivity 2016-12-19 09:19:40 +01:00
l10n daemon script
5e229085e9 GIT_SILENT made messages (after extraction) 2016-12-19 06:22:52 +01:00
l10n daemon script
a7c4bbd379 GIT_SILENT made messages (after extraction) 2016-12-18 06:17:35 +01:00
l10n daemon script
a38ffe34bd GIT_SILENT made messages (after extraction) 2016-12-18 03:44:15 +01:00
Albert Vaca
b5e6519efe Increased versio number to release 2016-12-17 15:33:09 +01:00
l10n daemon script
ad2b7678b9 GIT_SILENT made messages (after extraction) 2016-12-16 03:35:24 +01:00
l10n daemon script
9649efcdc4 GIT_SILENT made messages (after extraction) 2016-12-14 02:48:48 +01:00
l10n daemon script
99b7c4f312 GIT_SILENT made messages (after extraction) 2016-12-13 02:39:05 +01:00
l10n daemon script
c80820294c GIT_SILENT made messages (after extraction) 2016-12-12 02:34:13 +01:00
Albert Vaca
90856690fb Increased version number to release in the beta channel 2016-12-11 21:22:13 +01:00
Albert Vaca
1334dae342 Added a Share setting to add received files to the "Downloads" app
Only works for old-school (not-Storage Access Framework) paths, so we have
to keep track of the fact that we are using one or the other.

Also this requires the permission DOWNLOAD_WITHOUT_NOTIFICATION, but
hopefully the play store won't make users confirm this one.

This behaviour is enabled by default.
2016-12-11 21:03:39 +01:00
Albert Vaca
f8dd9bf923 Fixed crash if received file didn't have extension 2016-12-11 20:27:52 +01:00
Albert Vaca
72d8ba647a If transfer failed, don't create a pending intent nor index the file 2016-12-11 19:19:51 +01:00
Albert Vaca
b3449c87f7 Rewritten ShareSettingsActivity and de-duplicated SAF code in SharePlugin.
There was unused code and incorrect comments that were introduced in
commit e2e4086.
2016-12-11 18:57:21 +01:00
Albert Vaca
5c3b5a2737 Fixed comment as MayeulC suggested on IRC 2016-12-11 16:40:11 +01:00
Richard Wagler
e2e40863f8 Implement saving to SD card using SAF 2016-12-11 14:01:46 +01:00
Albert Vaca
036737deae Unused imports 2016-12-11 14:00:55 +01:00
Albert Vaca
8d7337b6b0 Refactored media scanner call into MediaStoreHelper 2016-12-11 13:59:52 +01:00
Albert Vaca
0a4459e8a0 Made Sftp server notify the Android MediaScanner of new/removed files
Plus refactored the code a bit to simplify logic
2016-12-11 13:59:00 +01:00
Albert Vaca
cef8cbd34a Android Studio update 2016-12-11 13:59:00 +01:00
l10n daemon script
3afb8ae8f3 GIT_SILENT made messages (after extraction) 2016-12-11 02:35:14 +01:00
l10n daemon script
85fce32bcb GIT_SILENT made messages (after extraction) 2016-12-10 02:32:33 +01:00
Albert Vaca
d52be109ee Revert "Add support to deal with album arts sent by mpris plugin."
This was very poorly implemented and can't stay as it is right now:
 - Every second or so the art image was being loaded from disk, scaled,
   base64 encoded and sent over the freakin network!
 - The Android interface didn't take into account small screens, and
   adding the image would cut stuff out of the screen.
 - Didn't manage "edge cases" like playing a song without cover after one
   with cover (previous image was still being shown) or changing players.

This reverts commit 24c404400f.

# Conflicts:
#	src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisActivity.java
#	src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisPlugin.java
2016-12-08 23:47:17 +01:00
Albert Vaca
66794002f7 Updated version number to release in the beta channel/ 2016-12-08 20:53:40 +01:00
Albert Vaca
d61536ef76 Improved sharing files.
- Refactored the code to separate reading the file, sending it and
  updating the notification. This last part it's now done in a standalone
  sendPackage callback class.
- Added a non-async sendPacakge function to device, so we can properly
  wait for a file to finish before sending the next one without using
  recursive callbacks as before.
- Fixed bug that made it impossible to share more than one file from
  certain apps. This was caused because we can't access content resolvers
  any longer after closing the activity that was launched to "share" to.
  Now we do the content resolutions first and once for all files.
- When sending more than one file, do not spam one notification for each.
- There is no need to update the notifications from the UI thread, now
  we do it from a background thread instead.
2016-12-08 20:50:49 +01:00
Albert Vaca
1dad3c145d Make onProgressChanged updates time-based.
If used to update a notification, calling it too often would lag the UI
2016-12-08 20:50:49 +01:00
Albert Vaca
33f7a4809d Don't call onProgressChanged unless it actually changes 2016-12-08 20:50:49 +01:00
Albert Vaca
d81448ad34 Fixed LanLink always calling onProgressChanged with a progress of 0 2016-12-08 20:50:49 +01:00
Albert Vaca
ed4c0d24df Introduced NotificationHelper 2016-12-08 20:50:49 +01:00
Albert Vaca
fed9bb1eec Not an error 2016-12-08 20:50:49 +01:00
Albert Vaca
b7418c1db6 Socket should be volatile to prevent data-race
CCBUG: 368438
2016-12-08 20:50:49 +01:00
Albert Vaca
e6bc78f013 Some refactoring on sendpackage to reduce allocations of empty callbacks 2016-12-08 20:50:49 +01:00
Albert Vaca
22de200cbf Typo 2016-12-08 20:50:49 +01:00
Albert Vaca
22dde07892 Typo 2016-12-08 20:50:49 +01:00
Albert Vaca
f9bdfb9fbd Not actually an error 2016-12-08 20:50:49 +01:00
Albert Vaca
9d6476a27e Moved the code around to split it in big blocks and add some comments 2016-12-08 20:50:49 +01:00
Albert Vaca
29a8db9c45 On error show an error message, not a success message :) 2016-12-08 20:50:49 +01:00
l10n daemon script
6e1f8e1496 SVN_SILENT made messages (after extraction) 2016-11-29 03:03:55 +01:00
Albert Vaca
82b15292fb Merge branch '1.x' 2016-11-28 14:48:39 +01:00
Albert Vaca
32f9f3b76a Update gradle plugin to make Android Studio happy 2016-11-28 14:48:22 +01:00
Albert Vaca
fc25e42196 Remove FindMyPhoneActivity from the application switcher,
because returning to it would make it to ring again.
2016-11-23 18:34:31 +01:00
l10n daemon script
db3422268f SVN_SILENT made messages (after extraction) 2016-11-05 07:16:39 +00:00
l10n daemon script
71bef30624 SVN_SILENT made messages (after extraction) 2016-10-28 10:31:23 +00:00
l10n daemon script
15e0188538 SVN_SILENT made messages (after extraction) 2016-10-28 06:56:05 +00:00
l10n daemon script
8bc8a47e9d SVN_SILENT made messages (after extraction) 2016-10-17 10:38:49 +00:00
l10n daemon script
ad7769edde SVN_SILENT made messages (after extraction) 2016-10-17 06:58:14 +00:00
l10n daemon script
a2c51a16ee SVN_SILENT made messages (after extraction) 2016-10-14 10:45:01 +00:00
l10n daemon script
788555b69c SVN_SILENT made messages (after extraction) 2016-10-14 07:05:25 +00:00
l10n daemon script
ccdeb3d806 SVN_SILENT made messages (after extraction) 2016-10-07 07:02:29 +00:00
l10n daemon script
00a5ad3c1f SVN_SILENT made messages (after extraction) 2016-09-30 10:42:37 +00:00
Albert Vaca
b35ce0f821 Do not clear values if the player didn't actually change 2016-09-29 14:15:31 +02:00
Albert Vaca
77e38da2d9 Fixed spotify hacks and moved them to a single function in the code 2016-09-29 14:14:55 +02:00
Albert Vaca
8fb942ccdf Nothing changes in this function, no need to update the list. 2016-09-29 13:21:31 +02:00
Albert Vaca
74dc1bcd63 Reduced logging. Renamed variables in camelcase. 2016-09-29 13:21:13 +02:00
Albert Vaca
0f655cf4eb Added a check to see if the dialog is already open.
If tapping fast, two dialogs could be opened. Opening it twice caused the
second dialog to segfault on tapping yes.
2016-09-29 13:20:43 +02:00
Albert Vaca
0de86785f8 Merge branch 'master' into 1.x
# Conflicts:
#	res/values-da/strings.xml
2016-09-29 13:01:25 +02:00
Thomas Posch
5320c3c226 Make commands sorted by name
BUG: 369239
2016-09-29 12:57:22 +02:00
l10n daemon script
7234b34db7 SVN_SILENT made messages (after extraction) 2016-09-28 10:26:51 +00:00
l10n daemon script
428fa947a4 SVN_SILENT made messages (after extraction) 2016-09-25 10:36:05 +00:00
Albert Vaca
b454dec0a0 Merge branch '1.x' 2016-09-24 20:34:03 +02:00
Albert Vaca
2e3fabb3e5 Bumped version to release 2016-09-24 20:28:05 +02:00
Albert Vaca
c7b754a36e Swapped branches in if statement caused settings to not be stored in db 2016-09-24 20:26:23 +02:00
l10n daemon script
347c34927d SVN_SILENT made messages (after extraction) 2016-09-23 10:40:27 +00:00
Albert Vaca
6c3811a0af Merge branch '1.x' 2016-09-20 12:47:50 +02:00
Albert Vaca
e9013e7995 Android Studio 2.2 complains if we use an old version of the gradle plugin 2016-09-20 12:46:59 +02:00
Albert Vaca
3b5a7deebe Rewritten the Notification Filter.
- Now we display every app in the phone.
- We show the app icon next to the name.
- Some apps can now be disabled by default.

Disabled notifications for the default Android messaging app, as SMS
notifications are already handled by the telephony plugin.

BUG: 367930
2016-09-20 12:46:28 +02:00
Albert Vaca
ac04f5a610 Oops 2016-09-20 11:08:59 +02:00
Albert Vaca
efce35366b Bumped version to release 2016-09-20 10:54:44 +02:00
Albert Vaca
1a32f8142d Do not unpair on every handshake error.
Sometimes we get stupid errors like "connection closed by peer".

BUG: 368812
2016-09-20 10:53:10 +02:00
Albert Vaca
103f24c140 Reduce logging 2016-09-20 10:51:37 +02:00
Albert Vaca
66cdb77bbd Fixed margins of notification filter activity 2016-09-20 10:48:06 +02:00
Albert Vaca
86245a697e Print a warning if device name is not in the list of human readable names. 2016-09-19 16:20:35 +02:00
Albert Vaca
041f172195 Merge remote-tracking branch 'origin/1.x' 2016-09-19 16:19:21 +02:00
Albert Vaca
91eefcc65a Fixed margins in the settings activity 2016-09-19 16:16:30 +02:00
Albert Vaca
b25ec2d133 Added cipher list for Android versions between 11 and 21.
BUG: 368172
2016-09-19 16:16:30 +02:00
l10n daemon script
e2e78cb562 SVN_SILENT made messages (after extraction) 2016-09-19 10:16:29 +00:00
l10n daemon script
8b0b65178b SVN_SILENT made messages (after extraction) 2016-09-18 10:38:50 +00:00
l10n daemon script
6c1dcda744 SVN_SILENT made messages (after extraction) 2016-09-18 07:04:53 +00:00
l10n daemon script
34d8a771d7 SVN_SILENT made messages (after extraction) 2016-09-14 10:29:43 +00:00
l10n daemon script
91913664be SVN_SILENT made messages (after extraction) 2016-09-14 06:53:53 +00:00
Albert Vaca
9e680d1494 Merge branch '1.x' 2016-09-13 16:58:41 +02:00
Albert Vaca
7f3afd194b Trying to debug a "no shared ciphers" issue some users are experiencing. 2016-09-13 16:56:23 +02:00
Albert Vaca
4158a14437 Merge branch '1.x' 2016-09-12 17:15:06 +02:00
Albert Vaca
ef79b04d1a Bumped version to release 2016-09-11 21:47:49 +02:00
Albert Vaca
62bf2ccab7 Fixed clipboard propagation loop bug
Now ClipboardListener is a singleton

BUG: 362596
2016-09-11 21:40:07 +02:00
l10n daemon script
28a33172ce SVN_SILENT made messages (after extraction) 2016-09-08 07:23:50 +00:00
Albert Vaca
901440f78a Don't return an empty list of supported plugins
If we don't know it yet return them all.
2016-09-06 10:53:24 +02:00
Albert Vaca
e9a64dc99a Don't show the Encryption Info menu if we are not connected with the device
We don't know the actual encryption used unless we have a device link.
2016-09-06 10:53:24 +02:00
l10n daemon script
086194c629 SVN_SILENT made messages (after extraction) 2016-09-01 07:22:43 +00:00
l10n daemon script
23f7eb90ba SVN_SILENT made messages (after extraction) 2016-08-31 10:22:15 +00:00
Albert Vaca
75eca915dd Merge branch 'master' of git.kde.org:kdeconnect-android 2016-08-29 11:54:08 +02:00
Albert Vaca
cfcf9d97e7 Merge branch '1.x' 2016-08-29 11:53:49 +02:00
Albert Vaca
a8838b57bb What XML file? 2016-08-29 11:49:25 +02:00
Albert Vaca
2989fe5ab3 Bump version to release 2016-08-29 11:49:04 +02:00
Albert Vaca
9c40374b00 Unpair only when there is no certificate
Unpairing on every error was a bit too aggressive.

BUG: 367937
2016-08-29 11:48:30 +02:00
l10n daemon script
4acf931f5a SVN_SILENT made messages (after extraction) 2016-08-27 07:23:55 +00:00
Albert Vaca
1b369d0bf8 Bumped version to release 2016-08-26 19:13:04 +02:00
Albert Vaca
f093326f93 Re-enabled SMS plugin 2016-08-26 19:13:04 +02:00
Saikrishna Arcot
e95265c263 MPRIS: Read and apply the allowed actions for the player.
Read list of allowed actions for the player sent from KDE, and hide
buttons that perform actions that aren't allowed based on MPRIS.

REVIEW: 128273
2016-08-26 11:12:58 +02:00
Albert Vaca
fa689bace6 Merge branch '1.x' 2016-08-26 11:06:43 +02:00
Albert Vaca
b43e0628c2 FindMyPhone: Calling ring twice now stop the ringing
BUG: 366253
2016-08-26 11:04:56 +02:00
Albert Vaca
fdd6de5cee Gradle 2.1.3 fixes a privilege escalation vulnerability in 2.1.2 2016-08-26 11:02:54 +02:00
Albert Vaca
816d47026e Bumped version to release 2016-08-25 18:08:16 +02:00
Albert Vaca
14e97545e4 Unpair on error 2016-08-25 18:06:56 +02:00
l10n daemon script
1d5efe36f0 SVN_SILENT made messages (after extraction) 2016-08-19 10:33:47 +00:00
l10n daemon script
625bdd36e3 SVN_SILENT made messages (after extraction) 2016-08-19 07:02:54 +00:00
l10n daemon script
9478f5bb39 SVN_SILENT made messages (after extraction) 2016-08-15 10:10:03 +00:00
l10n daemon script
1f0e7f9705 SVN_SILENT made messages (after extraction) 2016-08-13 10:45:06 +00:00
l10n daemon script
fe4f099663 SVN_SILENT made messages (after extraction) 2016-08-11 10:52:48 +00:00
l10n daemon script
7272c0abf1 SVN_SILENT made messages (after extraction) 2016-08-10 10:28:10 +00:00
l10n daemon script
cbb1f3d806 SVN_SILENT made messages (after extraction) 2016-08-08 10:28:30 +00:00
l10n daemon script
717bb081a7 SVN_SILENT made messages (after extraction) 2016-08-08 06:58:25 +00:00
l10n daemon script
37669e2be0 SVN_SILENT made messages (after extraction) 2016-08-06 11:10:46 +00:00
l10n daemon script
9d612192e3 SVN_SILENT made messages (after extraction) 2016-08-06 07:27:45 +00:00
l10n daemon script
25527af4ad SVN_SILENT made messages (after extraction) 2016-08-05 10:08:52 +00:00
l10n daemon script
6c7cb63af9 SVN_SILENT made messages (after extraction) 2016-08-04 11:04:58 +00:00
l10n daemon script
4b171e624f SVN_SILENT made messages (after extraction) 2016-07-17 07:34:28 +00:00
107 changed files with 2717 additions and 797 deletions

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kde.kdeconnect_tp"
android:versionCode="1320"
android:versionName="1.3.2">
android:versionCode="1600"
android:versionName="1.6">
<uses-sdk android:minSdkVersion="9"
android:targetSdkVersion="22" />
@@ -23,10 +23,11 @@
<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.SEND_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" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<application
android:allowBackup="true"
@@ -41,6 +42,17 @@
android:enabled="true" >
</service>
<!--Commented here and in PluginFactory until we release a desktop version with this feature, so we don't get bad "feature not working" reviews-->
<!--
<service android:name="org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin.RemoteKeyboardService"
android:label="KDE Connect Remote Keyboard"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/remotekeyboardplugin_method" />
</service>
-->
<activity
android:name="org.kde.kdeconnect.UserInterface.MaterialActivity"
android:label="KDE Connect"
@@ -83,6 +95,16 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="org.kde.kdeconnect.UserInterface.SettingsActivity" />
</activity>
<activity
android:name="org.kde.kdeconnect.Plugins.SharePlugin.ShareSettingsActivity"
android:label="@string/device_menu_plugins"
android:parentActivityName="org.kde.kdeconnect.UserInterface.SettingsActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.kde.kdeconnect.Plugins.SharePlugin.ShareSettingsActivity" />
</activity>
<receiver android:name="org.kde.kdeconnect.KdeConnectBroadcastReceiver" >
<intent-filter>
@@ -118,6 +140,8 @@
<activity
android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneActivity"
android:label="@string/findmyphone_title"
android:configChanges="orientation|screenSize"
android:excludeFromRecents="true"
android:launchMode="singleInstance">
</activity>
@@ -187,6 +211,7 @@
android:value="org.kde.kdeconnect.UserInterface.PluginSettingsActivity" />
</activity>
</application>
</manifest>

View File

@@ -3,18 +3,18 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.android.tools.build:gradle:2.2.3'
}
}
apply plugin: 'com.android.application'
android {
buildToolsVersion '23.0.3'
compileSdkVersion 23
buildToolsVersion '25.0.2'
compileSdkVersion 25
defaultConfig {
minSdkVersion 9
targetSdkVersion 22 //Bumping to 23 means we have to support the new permissions model
targetSdkVersion 22 //Bumping to >22 means we have to support the new permissions model
//multiDexEnabled true
//testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
}
@@ -71,9 +71,9 @@ dependencies {
mavenCentral()
}
compile 'com.android.support:support-v4:23.4.0'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
compile 'com.android.support:support-v4:25.1.1'
compile 'com.android.support:appcompat-v7:25.1.1'
compile 'com.android.support:design:25.1.1'
compile 'org.apache.sshd:sshd-core:0.8.0' //0.9 seems to fail on Android 6 and 1.+ requires java.nio.file, which doesn't exist in Android

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,22 +1,32 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity">
<TextView
android:text="@string/filter_apps_info"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:id="@+id/tFilter"/>
<ProgressBar
android:layout_marginTop="64dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/spinner" />
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/lvFilterApps"
android:layout_below="@id/tFilter"/>
android:visibility="gone"
/>
</RelativeLayout>
</LinearLayout>

View File

@@ -20,11 +20,6 @@
android:id="@+id/no_players"
android:layout_gravity="center_horizontal" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/artImageView" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -24,28 +24,23 @@
android:gravity="center_vertical"
android:paddingEnd="?android:attr/scrollbarSize"
android:paddingRight="?android:attr/scrollbarSize"
android:paddingStart="12dip"
android:paddingLeft="12dip"
android:background="?attr/selectableItemBackground">
<!-- Preference should place its actual preference widget here. -->
<!-- Preference will place its actual preference widget here. -->
<LinearLayout android:id="@+android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical" />
<ImageView
android:id="@+android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="15dip"
android:layout_marginLeft="15dip"
android:layout_marginEnd="15dip"
android:layout_marginStart="12dip"
android:layout_marginLeft="12dip"
android:layout_marginEnd="4dip"
android:layout_marginRight="4dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"

View File

@@ -4,17 +4,15 @@
<string name="pref_plugin_telephony_desc">Unvia avisos pa SMS y llamaes</string>
<string name="pref_plugin_battery">Informe de batería</string>
<string name="pref_plugin_battery_desc">Infoma davezu del estáu de la batería</string>
<string name="pref_plugin_sftp">Esposición del sistema de ficheros</string>
<string name="pref_plugin_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_runcommand">Executar comandu</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Unvia y recibe pings</string>
<string name="pref_plugin_ping_desc">Unvia y recibi 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">Compartir y recibir</string>
<string name="pref_plugin_sharereceiver">Unvia y recibi pings</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>
@@ -25,34 +23,23 @@
<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 botones de drecha y en mediu. Usa un primíu llargu p\'arrastrar y soltar.</string>
<string name="mousepad_double_tap_settings_title">Afitar aición de calcu con dos deos</string>
<string name="mousepad_triple_tap_settings_title">Afitar aición de calcu con tres deos</string>
<string name="mousepad_sensitivity_settings_title">Afitar sensibilidá del panel táutil</string>
<string name="mousepad_scroll_direction_title">Direición inversa de desplazamientu</string>
<string 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-array name="mousepad_tap_entries">
<item>Clic drechu</item>
<item>Clic d\'en mediu</item>
<item>Nada</item>
</string-array>
<string name="mousepad_double_default">drecha</string>
<string name="mousepad_triple_default">d\'en mediu</string>
<string name="mousepad_sensitivity_default">por defeutu</string>
<string-array name="mousepad_sensitivity_entries">
<item>La más lenta</item>
<item>Slowest</item>
<item>Above Slowest</item>
<item>Predeterminada</item>
<item>Penriba lo predeterminao</item>
<item>La más rápida</item>
<item>Default</item>
<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="plugins_failed_to_load">Los complementos fallaron al cargase (calca pa más información):</string>
<string name="device_menu_plugins">Axustes de complementos</string>
<string name="device_menu_unpair">Desempareyar</string>
<string name="device_not_reachable">El preséu empareyáu nun ye agamable</string>
<string name="pair_new_device">Empareyar preséu nuevu</string>
<string name="unknown_device">Preséu desconocíu</string>
<string name="error_not_reachable">Nun ye algamable\'l preséu</string>
<string name="error_already_requested">Empareyamientu yá solicitáu</string>
@@ -75,12 +62,9 @@
<string name="received_file_text">Tap to open \'%1s\'</string>
<string name="sent_file_title">Unvióse\'l ficheru a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Fallu al unviar el ficheru %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Calca pa responder</string>
<string name="reconnect">Reconeutar</string>
<string name="right_click">Unviar clic drechu</string>
<string name="middle_click">Unviar clic d\'en mediu</string>
<string name="show_keyboard">Amosar tecláu</string>
<string name="device_not_paired">Preséu non empareyáu</string>
<string name="request_pairing">Solicitar empareyamientu</string>
@@ -106,7 +90,6 @@
<item>1 minutu</item>
<item>2 minutos</item>
</string-array>
<string name="share_to">Compartir en...</string>
<string name="protocol_version_older">Esti preséu usa una versión vieya del protocolu</string>
<string name="protocol_version_newer">Esti preséu usa una versión anovada del protocolu</string>
<string name="general_settings">Axustes xenerales</string>
@@ -137,7 +120,7 @@
<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">Equí deberíen apaecer otros preseos executando 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>

View File

@@ -64,7 +64,6 @@
<string name="received_file_text">Kucni za otvaranje \'%1s\'</string>
<string name="sent_file_title">Poslana datoteka na %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Neuspjelo slanje datoteke %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Kucni za odgovor</string>
<string name="reconnect">Ponovo uspostavi vezu</string>

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Notificador de telefonia</string>
<string name="pref_plugin_telephony">Notificador de la telefonia</string>
<string name="pref_plugin_telephony_desc">Envia notificacions pels SMS i les trucades</string>
<string name="pref_plugin_battery">Informe de la bateria</string>
<string name="pref_plugin_battery_desc">Informa periòdicament sobre l\'estat de la bateria</string>
@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">Comparteix el contingut del porta-retalls</string>
<string name="pref_plugin_mousepad">Entrada remota</string>
<string name="pref_plugin_mousepad_desc">Usa el vostre telèfon o tauleta com un ratolí i un teclat</string>
<string name="pref_plugin_remotekeyboard">Rep les pulsacions de tecla remotes</string>
<string name="pref_plugin_remotekeyboard_desc">Rep els esdeveniments de pulsacions de tecla des de dispositius remots</string>
<string name="pref_plugin_mpris">Controls multimèdia</string>
<string name="pref_plugin_mpris_desc">Proporciona un comandament a distància pel reproductor multimèdia</string>
<string name="pref_plugin_runcommand">Executa una ordre</string>
@@ -30,6 +32,10 @@
<string name="no_permissions">Us caldrà concedir permís per accedir a les notificacions</string>
<string name="send_ping">Envia un ping</string>
<string name="open_mpris_controls">Control multimèdia</string>
<string name="remotekeyboard_editing_only_title">Fes servir les tecles remotes només en editar</string>
<string name="remotekeyboard_not_connected">No hi ha cap connexió activa amb el teclat remot, establiu-ne una al «kdeconnect»</string>
<string name="remotekeyboard_connected">La connexió amb el teclat remot està activa</string>
<string name="remotekeyboard_multiple_connections">Hi ha més d\'una connexió amb un teclat remot, seleccioneu el dispositiu per configurar-lo</string>
<string name="open_mousepad">Entrada remota</string>
<string name="mousepad_info">Moveu un dit per la pantalla per a moure el cursor del ratolí. Toqueu per un clic, i empreu dos/tres dits pels botons dret i mig. Empreu un toc llarg per arrossegar i deixar anar.</string>
<string name="mousepad_double_tap_settings_title">Estableix l\'acció de tocar amb dos dits</string>
@@ -68,7 +74,7 @@
<string name="error_canceled_by_user">Cancel·lat per l\'usuari</string>
<string name="error_canceled_by_other_peer">Cancel·lat per l\'altre parell</string>
<string name="error_invalid_key">S\'ha rebut una clau no vàlida</string>
<string name="encryption_info_title">Informació d\'encriptatge</string>
<string name="encryption_info_title">Informació de l\'encriptatge</string>
<string name="encryption_info_msg_no_ssl">L\'altre dispositiu no usa una versió recent del KDE Connect, s\'utilitzarà el mètode d\'encriptatge antic.</string>
<string name="my_device_fingerprint">L\'empremta digital SHA1 del certificat del vostre dispositiu és:</string>
<string name="remote_device_fingerprint">L\'empremta digital SHA1 del certificat del dispositiu remot és:</string>
@@ -79,13 +85,15 @@
<string name="incoming_file_title">Fitxer entrant des de %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">S\'està enviant el fitxer a %1s</string>
<string name="outgoing_files_title">S\'estan enviant fitxers a %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">S\'ha enviat %1$d de %2$d fitxers</string>
<string name="received_file_title">Fitxer rebut des de %1s</string>
<string name="received_file_fail_title">Ha fallat en rebre el fitxer des de %1s</string>
<string name="received_file_text">Puntegeu per obrir «%1s»</string>
<string name="sent_file_title">Envia el fitxer a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Ha fallat en enviar el fitxer %1s</string>
<string name="sent_file_failed_title">Ha fallat en enviar el fitxer a %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Puntegeu per a respondre</string>
<string name="reconnect">Reconnecta</string>
@@ -132,6 +140,10 @@
<string name="custom_device_list">Afegeix dispositius per la IP</string>
<string name="share_notification_preference">Rebombori de les notificacions</string>
<string name="share_notification_preference_summary">Vibra i reprodueix un so en rebre un fitxer</string>
<string name="share_destination_customize">Personalitza el directori de destinació</string>
<string name="share_destination_customize_summary_disabled">Els fitxers rebuts apareixeran a Baixades</string>
<string name="share_destination_customize_summary_enabled">Els fitxers seran emmagatzemats al directori de a sota</string>
<string name="share_destination_folder_preference">Directori de destinació</string>
<string name="title_activity_notification_filter">Filtre per a les notificacions</string>
<string name="filter_apps_info">Les notificacions se sincronitzaran per a les aplicacions seleccionades.</string>
<string name="sftp_internal_storage">Emmagatzematge intern</string>

View File

@@ -5,15 +5,23 @@
<string name="pref_plugin_battery">Hlášení baterie</string>
<string name="pref_plugin_battery_desc">Periodicky hlásit stav baterky</string>
<string name="pref_plugin_sftp">Přístup k souborovému systému</string>
<string name="pref_plugin_sftp_desc">Umožní vám vzdáleně prohlížet souborový systém tohoto zařízení</string>
<string name="pref_plugin_clipboard">Synchronizace schránky</string>
<string name="pref_plugin_clipboard_desc">Sdílet obsah schránky</string>
<string name="pref_plugin_mousepad">Vzdálený vstup</string>
<string name="pref_plugin_mousepad_desc">Používejte svůj telefon nebo tablet jako touchpad a klávesnici</string>
<string name="pref_plugin_remotekeyboard">Přijímat stisky kláves se vzdálených zařízení</string>
<string name="pref_plugin_remotekeyboard_desc">Přijímat události stisku kláves ze vzdálených zařízení</string>
<string name="pref_plugin_mpris">Ovládání multimédií</string>
<string name="pref_plugin_mpris_desc">Poskytuje dálkové ovládání přehrávačů médií</string>
<string name="pref_plugin_runcommand">Spustit příkaz</string>
<string name="pref_plugin_runcommand_desc">Spouštějte příkazy vzdáleně z vašeho telefonu</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Posílat a přijímat ping</string>
<string name="pref_plugin_notifications">Synchronizace upozornění</string>
<string name="pref_plugin_notifications_desc">Zpřístupněte si upozornění z jiných zařízení</string>
<string name="pref_plugin_receive_notifications">Přijímat ozná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_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>
@@ -24,6 +32,10 @@
<string name="no_permissions">Pro zpřístupnění upozornění potřebujete oprávnění</string>
<string name="send_ping">Poslat ping</string>
<string name="open_mpris_controls">Ovládání multimédií</string>
<string name="remotekeyboard_editing_only_title">Ovládat vzdálené klávesy při editaci</string>
<string name="remotekeyboard_not_connected">Není k dispozici žádné vzdálené připojení klávesnice. Nastavte nějaké pomocí kdeconnect</string>
<string name="remotekeyboard_connected">Vzdálené připojení klávesnice je aktivní</string>
<string name="remotekeyboard_multiple_connections">Je k dispozici více než jedno připojení klávesnice. Vyberte zařízení pro jeho nastavení.</string>
<string name="open_mousepad">Vzdálený vstup</string>
<string name="mousepad_info">Pohybujte prstem po obrazovce pro pohybování kurzorem myši. Ťukněte pro kliknutí a použijte dva/tři prsty jako pravé a prostřední tlačítko. Pro přetažení dlouze podržte.</string>
<string name="mousepad_double_tap_settings_title">Nastavit činnost pro ťuknutí dvěma prsty</string>
@@ -63,6 +75,9 @@
<string name="error_canceled_by_other_peer">Přerušeno druhým uživatelem</string>
<string name="error_invalid_key">Byl přijat neplatný klíč</string>
<string name="encryption_info_title">Informace o šifrování</string>
<string name="encryption_info_msg_no_ssl">Druhé zařízení nepoužívá poslední verzi KDE connect. Bude použita stará metoda šifrování.</string>
<string name="my_device_fingerprint">Otisk SHA1 certifikátu vašeho zařízení je:</string>
<string name="remote_device_fingerprint">Otisk SHA1 certifikátu vzdáleného zařízení je:</string>
<string name="pair_requested">Bylo vyžádáno párování</string>
<string name="pairing_request_from">Požadavek o párování z %1s</string>
<string name="received_url_title">Přijat odkaz od %1s</string>
@@ -70,13 +85,15 @@
<string name="incoming_file_title">Příchozí soubor od %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Odesílám soubor do %1s</string>
<string name="outgoing_files_title">Odesílám soubory do %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Odesláno %1$d ze %2$d souborů</string>
<string name="received_file_title">Přijat soubor od %1s</string>
<string name="received_file_fail_title">Selhalo přijímání souboru od %1s</string>
<string name="received_file_text">Ťukněte pro otevření \'%1s\'</string>
<string name="sent_file_title">Soubor byl odeslán do %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Nelze odeslat soubor %1s</string>
<string name="sent_file_failed_title">Odesílání souborů na %1s selhalo</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Ťukněte pro odpovězení</string>
<string name="reconnect">Znovu připojit</string>
@@ -123,6 +140,10 @@
<string name="custom_device_list">Přidat zařízení podle IP</string>
<string name="share_notification_preference">Hlasitá upozornění</string>
<string name="share_notification_preference_summary">Vibrovat a přehrát melodii při přijímání souboru</string>
<string name="share_destination_customize">Přizpůsobte si cílový adresář</string>
<string name="share_destination_customize_summary_disabled">Přijaté soubory se objeví v Downloads</string>
<string name="share_destination_customize_summary_enabled">Soubory budou ukládány v adresáři níže</string>
<string name="share_destination_folder_preference">Cílový adresář</string>
<string name="title_activity_notification_filter">Filtr upozornění</string>
<string name="filter_apps_info">Upozorňování mezi vybranými aplikacemi bude synchronizováno.</string>
<string name="sftp_internal_storage">Interní úložiště</string>
@@ -149,6 +170,8 @@
<string name="pref_plugin_telepathy_desc">Posílejte zprávy ze své pracovní plochy</string>
<string name="plugin_not_supported">Tento modul zařízení nepodporuje</string>
<string name="findmyphone_title">Najít můj telefon</string>
<string name="findmyphone_title_tablet">Najít můj tablet</string>
<string name="findmyphone_description">Prozvoní toto zařízení, takže jej můžete najít</string>
<string name="findmyphone_found">Nalezeno</string>
<string name="open">Otevřít</string>
<string name="close">Zavřít</string>

View File

@@ -5,15 +5,21 @@
<string name="pref_plugin_battery">Batterirapport</string>
<string name="pref_plugin_battery_desc">Rapportér batteristatus periodisk</string>
<string name="pref_plugin_sftp">Filsystem-expose</string>
<string name="pref_plugin_sftp_desc">Muliggør at gennemsøge denne enheds filsystem eksternt</string>
<string name="pref_plugin_clipboard">Synk. af udklipsholder</string>
<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_mpris">Multimediekontroller</string>
<string name="pref_plugin_mpris_desc">Giver en fjernbetjening til din medieafspiller</string>
<string name="pref_plugin_runcommand">Kør kommando</string>
<string name="pref_plugin_runcommand_desc">Kør eksterne kommandoer fra din telefon eller tablet</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Send og modtag ping</string>
<string name="pref_plugin_notifications">Synk. af bekendtgørelser</string>
<string name="pref_plugin_notifications_desc">Tilgå dine bekendtgørelser fra andre enheder</string>
<string name="pref_plugin_receive_notifications">Modtag bekendtgørelser</string>
<string name="pref_plugin_receive_notifications_desc">Modtag bekendtgørelser fra den anden enhed og vis dem på Android</string>
<string name="pref_plugin_sharereceiver">Del og modtag</string>
<string name="pref_plugin_sharereceiver_desc">Del filer og URL\'er mellem enheder</string>
<string name="plugin_not_available">Denne funktion er ikke tilgængelig i din Android-version</string>
@@ -43,7 +49,7 @@
<item>Over mest langsom</item>
<item>Standard</item>
<item>Over standard</item>
<item>Hurtigst</item>
<item>Hurtigste</item>
</string-array>
<string name="category_connected_devices">Forbundne enheder</string>
<string name="category_not_paired_devices">Tilgængelig enheder</string>
@@ -79,7 +85,6 @@
<string name="received_file_text">Tap for at åbne \"%1s\"</string>
<string name="sent_file_title">Fil sendt til %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Kunne ikke sende filen %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tap for at svare</string>
<string name="reconnect">Forbind igen</string>
@@ -152,6 +157,8 @@
<string name="pref_plugin_telepathy_desc">Send SMS-beskeder fra din desktop</string>
<string name="plugin_not_supported">Dette plugin er ikke understøttet af enheden</string>
<string name="findmyphone_title">Find min telefon</string>
<string name="findmyphone_title_tablet">Find min tablet</string>
<string name="findmyphone_description">Ringer til denne enhed, så du kan finde den.</string>
<string name="findmyphone_found">Fundet</string>
<string name="open">Åbn</string>
<string name="close">Luk</string>

View File

@@ -9,12 +9,15 @@
<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_mpris">Multimedia-Bedienung</string>
<string name="pref_plugin_runcommand">Befehl ausführen</string>
<string name="pref_plugin_runcommand_desc">Von Ihrem Telefon oder Tablett Befehle auf anderen Geräten ausführen</string>
<string name="pref_plugin_ping">Ping</string>
<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_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>
@@ -76,7 +79,6 @@
<string name="received_file_fail_title">Der Empfang der Datei %1s ist fehlgeschlagen</string>
<string name="sent_file_title">Datei an %1s gesendet</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Das Senden der Datei an %1s ist fehlgeschlagen</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tippen zum Antworten</string>
<string name="reconnect">Erneut verbinden</string>
@@ -146,6 +148,8 @@
<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_found">Gefunden</string>
<string name="open">Öffnen</string>
<string name="close">Schließen</string>

View File

@@ -5,15 +5,21 @@
<string name="pref_plugin_battery">Αναφορά μπαταρίας</string>
<string name="pref_plugin_battery_desc">Περιοδική αναφορά κατάστασης μπαταρίας</string>
<string name="pref_plugin_sftp">Αποκάλυψη συστήματος αρχείων</string>
<string name="pref_plugin_sftp_desc">Επιτρέπει την απομακρυσμένη περιήγηση του συστήματος αρχείων του κινητού</string>
<string name="pref_plugin_clipboard">Συγχρονισμός προχείρου</string>
<string name="pref_plugin_clipboard_desc">Διαμοιρασμός περιεχομένου προχείρου</string>
<string name="pref_plugin_mousepad">Απομακρυσμένη είσοδος στοιχείων</string>
<string name="pref_plugin_mousepad_desc">Χρήση του τηλεφώνου ή της ταμπλέτας σας ως επιφάνεια αφής και πληκτρολόγιο</string>
<string name="pref_plugin_mpris">Κονσόλα πολυμέσων</string>
<string name="pref_plugin_mpris_desc">Παρέχει ένα τηλεχειριστήριο για την αναπαραγωγή πολυμέσων</string>
<string name="pref_plugin_runcommand">Εκτέλεση εντολής</string>
<string name="pref_plugin_runcommand_desc">Εκτέλεση απομακρυσμένων εντολών από το τηλέφωνο ή την ταμπλέτα</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Αποστολή και λήψη pings</string>
<string name="pref_plugin_notifications">Συγχρονισμός ειδοποιήσεων</string>
<string name="pref_plugin_notifications_desc">Πρόσβαση σε ειδοποιήσεις από άλλες συσκευές</string>
<string name="pref_plugin_receive_notifications">Λήψη ειδοποιήσεων</string>
<string name="pref_plugin_receive_notifications_desc">Λήψη ειδοποιήσεων από την άλλη συσκευή και προβολή τους στο Android</string>
<string name="pref_plugin_sharereceiver">Διαμοιρασμός και λήψη</string>
<string name="pref_plugin_sharereceiver_desc">Διαμοιρασμός αρχείων και URL μεταξύ συσκευών</string>
<string name="plugin_not_available">Αυτή η λειτουργία δεν είναι διαθέσιμη στην τρέχουσα έκδοση του Android</string>
@@ -79,7 +85,6 @@
<string name="received_file_text">Χτυπήστε για άνοιγμα \'%1s\'</string>
<string name="sent_file_title">Εστάλη αρχείο στο %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Αποτυχία αποστολής αρχείου %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Χτυπήστε για να απαντήσετε</string>
<string name="reconnect">Επανασύνδεση</string>
@@ -152,6 +157,8 @@
<string name="pref_plugin_telepathy_desc">Αποστολή μηνυμάτων κειμένου από τον υπολογιστή σας</string>
<string name="plugin_not_supported">Αυτό το πρόσθετο δεν υποστηρίζεται από τη συσκευή</string>
<string name="findmyphone_title">Αναζήτηση του κινητού μου</string>
<string name="findmyphone_title_tablet">Εύρεση της ταμπλέτας μου</string>
<string name="findmyphone_description">Καλεί αυτή τη συσκευή ώστε να την εντοπίσετε</string>
<string name="findmyphone_found">Βρέθηκε</string>
<string name="open">Άνοιγμα</string>
<string name="close">Κλείσιμο</string>

View File

@@ -5,15 +5,23 @@
<string name="pref_plugin_battery">Battery report</string>
<string name="pref_plugin_battery_desc">Periodically report battery status</string>
<string name="pref_plugin_sftp">Filesystem expose</string>
<string name="pref_plugin_sftp_desc">Allows to browse this device\'s filesystem remotely</string>
<string name="pref_plugin_clipboard">Clipboard sync</string>
<string name="pref_plugin_clipboard_desc">Share the clipboard content</string>
<string name="pref_plugin_mousepad">Remote input</string>
<string name="pref_plugin_mousepad_desc">Use your phone or tablet as a touchpad and keyboard</string>
<string name="pref_plugin_remotekeyboard">Receive remote keypresses</string>
<string name="pref_plugin_remotekeyboard_desc">Receive keypress events from remote devices</string>
<string name="pref_plugin_mpris">Multimedia controls</string>
<string name="pref_plugin_mpris_desc">Provides a remote control for your media player</string>
<string name="pref_plugin_runcommand">Run Command</string>
<string name="pref_plugin_runcommand_desc">Trigger remote commands from your phone or tablet</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Send and receive pings</string>
<string name="pref_plugin_notifications">Notification sync</string>
<string name="pref_plugin_notifications_desc">Access your notifications from other devices</string>
<string name="pref_plugin_receive_notifications">Receive notifications</string>
<string name="pref_plugin_receive_notifications_desc">Receive notifications from the other device and display them on Android</string>
<string name="pref_plugin_sharereceiver">Share and receive</string>
<string name="pref_plugin_sharereceiver_desc">Share files and URLs between devices</string>
<string name="plugin_not_available">This feature is not available in your Android version</string>
@@ -24,6 +32,10 @@
<string name="no_permissions">You need to grant permission to access notifications</string>
<string name="send_ping">Send ping</string>
<string name="open_mpris_controls">Multimedia control</string>
<string name="remotekeyboard_editing_only_title">Handle remote keys only when editing</string>
<string name="remotekeyboard_not_connected">There is no active remote keyboard connection, establish one in kdeconnect</string>
<string name="remotekeyboard_connected">Remote keyboard connection is active</string>
<string name="remotekeyboard_multiple_connections">There is more than one remote keyboard connection, select the device to configure</string>
<string name="open_mousepad">Remote input</string>
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
@@ -62,6 +74,10 @@
<string name="error_canceled_by_user">Cancelled by user</string>
<string name="error_canceled_by_other_peer">Cancelled by other peer</string>
<string name="error_invalid_key">Invalid key received</string>
<string name="encryption_info_title">Encryption Info</string>
<string name="encryption_info_msg_no_ssl">The other device doesn\'t use a recent version of KDE Connect, using the legacy encryption method.</string>
<string name="my_device_fingerprint">SHA1 fingerprint of your device certificate is:</string>
<string name="remote_device_fingerprint">SHA1 fingerprint of remote device certificate is:</string>
<string name="pair_requested">Pair requested</string>
<string name="pairing_request_from">Pairing request from %1s</string>
<string name="received_url_title">Received link from %1s</string>
@@ -69,13 +85,15 @@
<string name="incoming_file_title">Incoming file from %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Sending file to %1s</string>
<string name="outgoing_files_title">Sending files to %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Sent %1$d out of %2$d files</string>
<string name="received_file_title">Received file from %1s</string>
<string name="received_file_fail_title">Failed receiving file from %1s</string>
<string name="received_file_text">Tap to open \'%1s\'</string>
<string name="sent_file_title">Sent file to %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Failed to send file %1s</string>
<string name="sent_file_failed_title">Failed to send file to %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tap to answer</string>
<string name="reconnect">Reconnect</string>
@@ -122,6 +140,10 @@
<string name="custom_device_list">Add devices by IP</string>
<string name="share_notification_preference">Noisy notifications</string>
<string name="share_notification_preference_summary">Vibrate and play a sound when receiving a file</string>
<string name="share_destination_customize">Customise destination directory</string>
<string name="share_destination_customize_summary_disabled">Received files will appear in Downloads</string>
<string name="share_destination_customize_summary_enabled">Files will be stored in the directory below</string>
<string name="share_destination_folder_preference">Destination directory</string>
<string name="title_activity_notification_filter">Notification filter</string>
<string name="filter_apps_info">Notifications will be synchronised for the selected apps.</string>
<string name="sftp_internal_storage">Internal storage</string>
@@ -147,6 +169,9 @@
<string name="pref_plugin_telepathy">Send SMS</string>
<string name="pref_plugin_telepathy_desc">Send text messages from your desktop</string>
<string name="plugin_not_supported">This plugin is not supported by the device</string>
<string name="findmyphone_title">Find my phone</string>
<string name="findmyphone_title_tablet">Find my tablet</string>
<string name="findmyphone_description">Rings this device so you can find it</string>
<string name="findmyphone_found">Found</string>
<string name="open">Open</string>
<string name="close">Close</string>

View File

@@ -79,13 +79,15 @@
<string name="incoming_file_title">Archivo entrante desde %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Enviando archivo a %1s</string>
<string name="outgoing_files_title">Enviando archivos a %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Enviados %1$d de %2$d archivos</string>
<string name="received_file_title">Archivo recibido desde %1s</string>
<string name="received_file_fail_title">Fallo recibiendo archivo desde %1s</string>
<string name="received_file_text">Pulse para abrir «%1s»</string>
<string name="sent_file_title">Archivo enviado a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Fallo al enviar el archivo %1s</string>
<string name="sent_file_failed_title">Fallo al enviar el archivo a %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Pulse para responder</string>
<string name="reconnect">Reconectar</string>
@@ -132,6 +134,10 @@
<string name="custom_device_list">Añadir dispositivos por IP</string>
<string name="share_notification_preference">Notificaciones ruidosas</string>
<string name="share_notification_preference_summary">Vibrar y reproducir un sonido cuando se reciba un archivo</string>
<string name="share_destination_customize">Personalizar directorio destino</string>
<string name="share_destination_customize_summary_disabled">Los archivos recibidos aparecerán en Descargas</string>
<string name="share_destination_customize_summary_enabled">Los archivos se almacenarán en el directorio indicado más abajo</string>
<string name="share_destination_folder_preference">Directorio destino</string>
<string name="title_activity_notification_filter">Filtro de notificaciones</string>
<string name="filter_apps_info">Las notificaciones se sincronizarán en las aplicaciones seleccionadas.</string>
<string name="sftp_internal_storage">Almacenamiento interno</string>

172
res/values-et/strings.xml Normal file
View File

@@ -0,0 +1,172 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Telefoni märguanded</string>
<string name="pref_plugin_telephony_desc">SMS-ide ja kõnede märguannete saatmine</string>
<string name="pref_plugin_battery">Aku aruanne</string>
<string name="pref_plugin_battery_desc">Perioodiline aku olekust teavitamine</string>
<string name="pref_plugin_sftp">Failisüsteemi sirvimine</string>
<string name="pref_plugin_sftp_desc">Seadme failisüsteemi eemalt sirvimise võimaldamine</string>
<string name="pref_plugin_clipboard">Lõikepuhvri sünkroonimine</string>
<string name="pref_plugin_clipboard_desc">Lõikepuhvri sisu jagamine</string>
<string name="pref_plugin_mousepad">Kaugsisestus</string>
<string name="pref_plugin_mousepad_desc">Telefoni või tahvli kasutamine puuteplaadi ja klaviatuurina</string>
<string name="pref_plugin_mpris">Multimeedia juhtimine</string>
<string name="pref_plugin_mpris_desc">Meediamängija kaugjuhtimise võimaldamine</string>
<string name="pref_plugin_runcommand">Käsu käivitamine</string>
<string name="pref_plugin_runcommand_desc">Telefonist või tahvlist kaugkäskude käivitamine</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Pingide saatmine ja vastuvõtmine</string>
<string name="pref_plugin_notifications">Märguannete sünkroonimine</string>
<string name="pref_plugin_notifications_desc">Märguannete nägemine teistes seadmetes</string>
<string name="pref_plugin_receive_notifications">Märguannete vastuvõtmine</string>
<string name="pref_plugin_receive_notifications_desc">Märguannete vastuvõtmine teisest seadmest ja nende näitamine Androidis</string>
<string name="pref_plugin_sharereceiver">Jagamine ja vastuvõtmine</string>
<string name="pref_plugin_sharereceiver_desc">Failide ja URL-ide jagamine seadmete vahel</string>
<string name="plugin_not_available">See omadus ei ole sinu Androidi versioonis veel saadaval</string>
<string name="device_list_empty">Seadmed puuduvad</string>
<string name="ok">OK</string>
<string name="cancel">Loobu</string>
<string name="open_settings">Ava seadistused</string>
<string name="no_permissions">Märguannete nägemiseks tuleb anda vastavad õigused</string>
<string name="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>
<string name="mousepad_scroll_direction_title">Vastupidi kerimise suund</string>
<string-array name="mousepad_tap_entries">
<item>Paremklõps</item>
<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>
<item>Vaikimisi</item>
<item>Keskmisest kiirem</item>
<item>Kõige kiirem</item>
</string-array>
<string name="category_connected_devices">Ühendatud seadmed</string>
<string name="category_not_paired_devices">Saadaolevad seadmed</string>
<string name="category_remembered_devices">Meeldejäetud seadmed</string>
<string name="plugins_failed_to_load">Pluginate laadimine nurjus (koputa rohkema teabe saamiseks)</string>
<string name="device_menu_plugins">Plugina seadistused</string>
<string name="device_menu_unpair">Eemalda paardumine</string>
<string name="device_not_reachable">Paardunud seade pole saadaval</string>
<string name="pair_new_device">Paarita uus seade</string>
<string name="unknown_device">Tundmatu seade</string>
<string name="error_not_reachable">Seade pole saadaval</string>
<string name="error_already_requested">Paardumist on juba soovitud</string>
<string name="error_already_paired">Seade on juba paaritatud</string>
<string name="error_could_not_send_package">Paketi saatmine nurjus</string>
<string name="error_timed_out">Ajaületus</string>
<string name="error_canceled_by_user">Kasutaja katkestas</string>
<string name="error_canceled_by_other_peer">Teine pool katkestas</string>
<string name="error_invalid_key">Saadi vigane võti</string>
<string name="encryption_info_title">Krüptimise teave</string>
<string name="encryption_info_msg_no_ssl">Teine seade ei kasuta KDE Connecti uusimat versiooni ja tarvitab krüptimisel pärandmeetodit.</string>
<string name="my_device_fingerprint">Sinu seadme sertifikaadi SHA1 sõrmejälg on:</string>
<string name="remote_device_fingerprint">Kaugseadme sertifikaadi SHA1 sõrmejälg on:</string>
<string name="pair_requested">Paardumise soov</string>
<string name="pairing_request_from">Paardumise soov seadmest %1s</string>
<string name="received_url_title">Lingi saamine seadmest %1s</string>
<string name="received_url_text">Koputa \"%1s\" avamiseks</string>
<string name="incoming_file_title">Saabuv fail seadmest %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Faili saatmine seadmesse %1s</string>
<string name="outgoing_files_title">Failide saatmine seadmesse %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Saadetud %1$d / %2$d faili</string>
<string name="received_file_title">Faili saamine seadmest %1s</string>
<string name="received_file_fail_title">Faili saamine seadmest %1s nurjus</string>
<string name="received_file_text">Koputa \"%1s\" avamiseks</string>
<string name="sent_file_title">Fail saadeti seadmesse %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Faili saatmine seadmesse %1s nurjus</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Koputa vastamiseks</string>
<string name="reconnect">Ühenda uuesti</string>
<string name="right_click">Saada paremklõps</string>
<string name="middle_click">Saada keskklõps</string>
<string name="show_keyboard">Näita klaviatuuri</string>
<string name="device_not_paired">Seadmed pole paaritatud</string>
<string name="request_pairing">Soovi paardumist</string>
<string name="pairing_accept">Nõustu</string>
<string name="pairing_reject">Keeldu</string>
<string name="device">Seade</string>
<string name="pair_device">Paarita seade</string>
<string name="remote_control">Kaugjuhtimine</string>
<string name="settings">KDE Connecti seadistused</string>
<string name="mpris_play">Esita</string>
<string name="mpris_previous">Eelmine</string>
<string name="mpris_rew">Keri tagasi</string>
<string name="mpris_ff">Kiiresti edasi</string>
<string name="mpris_next">Järgmine</string>
<string name="mpris_volume">Helitugevus</string>
<string name="mpris_settings">Multimeedia seadistused</string>
<string name="mpris_time_settings_title">Edasi-tagasikerimise nupud</string>
<string name="mpris_time_settings_summary">Kiire edasi-tagasikerimise aeg vajutamisel</string>
<string-array name="mpris_time_entries">
<item>10 sekundit</item>
<item>20 sekundit</item>
<item>30 sekundit</item>
<item>1 minut</item>
<item>2 minutit</item>
</string-array>
<string name="share_to">Jaga...</string>
<string name="protocol_version_older">See seade kasutab vana protokolli versiooni</string>
<string name="protocol_version_newer">See seade kasutab uuemat protokolli versiooni</string>
<string name="general_settings">Üldised seadistused</string>
<string name="plugin_settings">Seadistused</string>
<string name="plugin_settings_with_name">%s seadistused</string>
<string name="device_name">Seadme nimi</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">Vigane seadme nimi</string>
<string name="shareplugin_text_saved">Saadi tekst, salvestati lõikepuhvrisse</string>
<string name="custom_devices_settings">Kohandatud seadmete loend</string>
<string name="pair_device_action">Paarita uus seade</string>
<string name="unpair_device_action">Eemalda %s paardumine</string>
<string name="custom_device_list">Lisa seadmeid IP järgi</string>
<string name="share_notification_preference">Mürarikkad märguanded</string>
<string name="share_notification_preference_summary">Vibreerimine ja heli esitamine faili saamisel</string>
<string name="share_destination_customize">Sihtkataloogi kohandamine</string>
<string name="share_destination_customize_summary_disabled">Saadud failid salvestatakse kataloogi Allalaaditud</string>
<string name="share_destination_customize_summary_enabled">Failid salvestatakse allmääratud kataloogi</string>
<string name="share_destination_folder_preference">Sihtkataloog</string>
<string name="title_activity_notification_filter">Märguannete filter</string>
<string name="filter_apps_info">Valitud rakenduste märguanded sünkroonitakse</string>
<string name="sftp_internal_storage">Sisemine salvesti</string>
<string name="sftp_all_files">Kõik failid</string>
<string name="sftp_sdcard_num">SD-kaart %d</string>
<string name="sftp_sdcard">SD-kaart</string>
<string name="sftp_readonly">(kirjutuskaitstud)</string>
<string name="sftp_camera">Kaamera pildid</string>
<string name="add_host">Lisa masin/IP</string>
<string name="add_host_hint">Masinanimi või IP</string>
<string name="no_players_connected">Ühtegi mängijat ei leitud</string>
<string name="custom_dev_list_help">Seda tuleks kasutada ainult siis, kui sinu seadet ei tuvastatud automaatselt. Sisesta allpool IP-aadress või masinanimi ja puuduta nuppu selle lisamiseks loendisse. Puuduta olemasolevat kirjet selle eemaldamiseks loendist.</string>
<string name="mpris_player_on_device">%1$s seadmes %2$s</string>
<string name="send_files">Saada faile</string>
<string name="pairing_title">KDE Connecti seadmed</string>
<string name="pairing_description">Siin näeb teisi seadmeid samas võrgus, kus töötab KDE Connect</string>
<string name="device_paired">Seade on paaritatud</string>
<string name="device_rename_title">Muuda seadme nime</string>
<string name="device_rename_confirm">Muuda nime</string>
<string name="refresh">Värskenda</string>
<string name="unreachable_description">See paardunud seade pole saadaval. Kontrolli, kas see on ikka ühendatud sinuga samasse võrku.</string>
<string name="no_file_browser">Ühtegi failisirvijat pole paigaldatud</string>
<string name="pref_plugin_telepathy">Saada SMS</string>
<string name="pref_plugin_telepathy_desc">Tekstisõnumite saatmine oma töölaualt</string>
<string name="plugin_not_supported">Seade ei toeta seda pluginat</string>
<string name="findmyphone_title">Leia mu telefon</string>
<string name="findmyphone_title_tablet">Leia mu tahvel</string>
<string name="findmyphone_description">Seadmele helistamine, et see üles leida</string>
<string name="findmyphone_found">Leitud</string>
<string name="open">Ava</string>
<string name="close">Sulge</string>
</resources>

View File

@@ -5,15 +5,21 @@
<string name="pref_plugin_battery">Akkuraportti</string>
<string name="pref_plugin_battery_desc">Raportoi akun tila säännöllisesti</string>
<string name="pref_plugin_sftp">Tiedostojärjestelmän paljastaminen</string>
<string name="pref_plugin_sftp_desc">Mahdollistaa tämän laitteen tiedostojärjestelmän etäselaamisen</string>
<string name="pref_plugin_clipboard">Leikepöydän synkronointi</string>
<string name="pref_plugin_clipboard_desc">Jaa leikepöydän sisältö</string>
<string name="pref_plugin_mousepad">Kauko-ohjaus</string>
<string name="pref_plugin_mousepad_desc">Käytä puhelinta tai tablettia hiirenä ja näppäimistönä</string>
<string name="pref_plugin_mpris">Multimedian ohjaus</string>
<string name="pref_plugin_mpris_desc">Mahdollistaa mediasoittimen etäohjauksen</string>
<string name="pref_plugin_runcommand">Suorita komento</string>
<string name="pref_plugin_runcommand_desc">Suorita komentoja etänä puhelimelta tai tabletilta</string>
<string name="pref_plugin_ping">Tiedustelupaketti</string>
<string name="pref_plugin_ping_desc">Lähetä ja vastaanota tiedustelupaketteja</string>
<string name="pref_plugin_notifications">Ilmoitusten synkronointi</string>
<string name="pref_plugin_notifications_desc">Näe ilmoituksesi muissa laitteissa</string>
<string name="pref_plugin_receive_notifications">Vastaanota ilmoituksia</string>
<string name="pref_plugin_receive_notifications_desc">Vastaanota ilmoituksia toiselta laitteelta ja näytä ne Androidissa</string>
<string name="pref_plugin_sharereceiver">Jako ja vastaanottaminen</string>
<string name="pref_plugin_sharereceiver_desc">Jaa tiedostoja ja osoitteita laitteiden välillä</string>
<string name="plugin_not_available">Piirre ei ole käytettävissä Android-versiossasi</string>
@@ -62,6 +68,10 @@
<string name="error_canceled_by_user">Käyttäjä perui</string>
<string name="error_canceled_by_other_peer">Vertaiskäyttäjä perui</string>
<string name="error_invalid_key">Vastaanotettiin väärä avain</string>
<string name="encryption_info_title">Salaustiedot</string>
<string name="encryption_info_msg_no_ssl">Toinen laite ei käytä KDE Connectin uudehkoa versiota, joten käytetään vanhaa salausmenetelmää.</string>
<string name="my_device_fingerprint">Laitteen varmenteen SHA1-sormenjälki on:</string>
<string name="remote_device_fingerprint">Etälaitteen varmenteen SHA1-sormenjälki on:</string>
<string name="pair_requested">Paripyyntö</string>
<string name="pairing_request_from">Paripyyntö laitteesta %1s</string>
<string name="received_url_title">Vastaanotettiin linkki lähettäjältä %1s</string>
@@ -75,7 +85,6 @@
<string name="received_file_text">Avaa ”%1s” napauttamalla</string>
<string name="sent_file_title">Tiedosto lähetetty laitteeseen %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Tiedoston lähetys epäonnistui: %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Vastaa napauttamalla</string>
<string name="reconnect">Yhdistä uudelleen</string>
@@ -147,6 +156,9 @@
<string name="pref_plugin_telepathy">Lähetä tekstiviesti</string>
<string name="pref_plugin_telepathy_desc">Lähetä tekstiviestejä työpöydältäsi</string>
<string name="plugin_not_supported">Laite ei tue tätä liitännäistä</string>
<string name="findmyphone_title">Löydä puhelimeni</string>
<string name="findmyphone_title_tablet">Löydä tablettini</string>
<string name="findmyphone_description">Laittaa laitteen soimaan, jotta voit löytää sen.</string>
<string name="findmyphone_found">Löytyi</string>
<string name="open">Avaa</string>
<string name="close">Sulje</string>

View File

@@ -70,7 +70,6 @@
<string name="received_file_text">Appuyez pour ouvrir %1s</string>
<string name="sent_file_title">Fichier envoyé à %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Impossible d\'envoyer le fichier %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Cliquer pour répondre</string>
<string name="reconnect">Reconnecter</string>

View File

@@ -28,8 +28,6 @@
<string name="mousepad_info">Mova un dedo na pantalla para mover o cursor. Toque para facer clic, e use dous ou tres dedos para os botóns secundario e central. Prema durante un tempo para arrastrar e soltar.</string>
<string name="mousepad_double_tap_settings_title">Definir a acción de tocar con dous dedos</string>
<string name="mousepad_triple_tap_settings_title">Definir a acción de tocar con tres dedos</string>
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do punteiro táctil</string>
<string name="mousepad_scroll_direction_title">Inverter a dirección de desprazamento</string>
<string-array name="mousepad_tap_entries">
<item>Clic dereito</item>
<item>Clic central</item>
@@ -37,13 +35,12 @@
</string-array>
<string name="mousepad_double_default">dereita</string>
<string name="mousepad_triple_default">medio</string>
<string name="mousepad_sensitivity_default">predeterminado</string>
<string-array name="mousepad_sensitivity_entries">
<item>O máis lento</item>
<item>Lento</item>
<item>Predeterminado</item>
<item>Rápido</item>
<item>O mais rápido</item>
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
</string-array>
<string name="category_connected_devices">Dispositivos conectados</string>
<string name="category_not_paired_devices">Dispositivos dispoñíbeis</string>
@@ -75,7 +72,6 @@
<string name="received_file_text">Toque para abrir «%1s».</string>
<string name="sent_file_title">Enviouse o ficheiro a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Non foi posíbel enviar o ficheiro %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Toque para contestar</string>
<string name="reconnect">Conectar de novo</string>

View File

@@ -18,7 +18,7 @@
<string name="pref_plugin_sharereceiver_desc">שתף וקבל קבצים וכתובת אינטרנט בין התקנים</string>
<string name="plugin_not_available">אפשרות זו אינה זמינה בגרסת האנדרואיד שלך</string>
<string name="device_list_empty">אין התקנים</string>
<string name="ok">בסדר</string>
<string name="ok">אישור</string>
<string name="cancel">בטל</string>
<string name="open_settings">פתח הגדרות</string>
<string name="no_permissions">אתה צריך לתת הרשאות לגישה להתראות</string>
@@ -79,7 +79,6 @@
<string name="received_file_text">לחץ כדי לפתוח את %1s</string>
<string name="sent_file_title">הקובץ נשלח ל־%1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">נכשל בשליחת הקובץ ל־%1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">לחץ כדי לענות</string>
<string name="reconnect">התחבר מחדש</string>

View File

@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">Condividi il contenuto degli appunti</string>
<string name="pref_plugin_mousepad">Impulso remoto</string>
<string name="pref_plugin_mousepad_desc">Usa il tuo telefono o il tablet come touchpad e tastiera</string>
<string name="pref_plugin_remotekeyboard">Ricevi pressioni dei tasti da remoto</string>
<string name="pref_plugin_remotekeyboard_desc">Ricevi eventi di pressione dei tasti da dispositivi remoti</string>
<string name="pref_plugin_mpris">Controlli multimediali</string>
<string name="pref_plugin_mpris_desc">Fornisce un controllo remoto per il tuo lettore multimediale</string>
<string name="pref_plugin_runcommand">Esegui comando</string>
@@ -30,6 +32,10 @@
<string name="no_permissions">Devi concedere i permessi per l\'accesso alle notifiche</string>
<string name="send_ping">Invia ping</string>
<string name="open_mpris_controls">Controllo multimediale</string>
<string name="remotekeyboard_editing_only_title">Gestisci i tasti remoti solo durante la modifica</string>
<string name="remotekeyboard_not_connected">Non c\'è una connessione attiva della tastiera remota, stabiliscine una da kdeconnect</string>
<string name="remotekeyboard_connected">La connessione della tastiera remota è attiva</string>
<string name="remotekeyboard_multiple_connections">Ci sono più connessioni di tastiere remote, seleziona il dispositivo da configurare</string>
<string name="open_mousepad">Impulso remoto</string>
<string name="mousepad_info">Muovi un dito sullo schermo per spostare il puntatore del mouse. Tocca per un clic e usa due/tre dita per i pulsanti destro e centrale. Utilizza una pressione lunga per trascinare e rilasciare.</string>
<string name="mousepad_double_tap_settings_title">Imposta azione per il tocco a due dita</string>
@@ -79,13 +85,15 @@
<string name="incoming_file_title">File in ingresso da %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Invio file a %1s</string>
<string name="outgoing_files_title">Invio file a %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Inviati %1$d di %2$d file</string>
<string name="received_file_title">File ricevuto da %1s</string>
<string name="received_file_fail_title">Ricezione file da %1s non riuscita</string>
<string name="received_file_text">Tocca per aprire «%1s»</string>
<string name="sent_file_title">File inviato a %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Invio del file %1s non riuscito</string>
<string name="sent_file_failed_title">Invio del file a %1s non riuscito</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tocca per rispondere</string>
<string name="reconnect">Riconnetti</string>
@@ -132,6 +140,10 @@
<string name="custom_device_list">Aggiungi dispositivi per IP</string>
<string name="share_notification_preference">Notifiche rumorose</string>
<string name="share_notification_preference_summary">Vibra e riproduci un suono alla ricezione di un file</string>
<string name="share_destination_customize">Personalizza la cartella di destinazione</string>
<string name="share_destination_customize_summary_disabled">I file ricevuti saranno visualizzati in Downloads</string>
<string name="share_destination_customize_summary_enabled">I file saranno memorizzati nella cartella seguente</string>
<string name="share_destination_folder_preference">Cartella di destinazione</string>
<string name="title_activity_notification_filter">Filtro delle notifiche</string>
<string name="filter_apps_info">Le notifiche saranno sincronizzate per le applicazioni selezionate.</string>
<string name="sftp_internal_storage">Archiviazione interna</string>

View File

@@ -5,15 +5,21 @@
<string name="pref_plugin_battery">배터리 보고</string>
<string name="pref_plugin_battery_desc">주기적으로 배터리 상태 보고</string>
<string name="pref_plugin_sftp">파일 시스템 보기</string>
<string name="pref_plugin_sftp_desc">원격으로 이 장치의 파일 시스템 보기</string>
<string name="pref_plugin_clipboard">클립보드 동기화</string>
<string name="pref_plugin_clipboard_desc">클립보드 내용 동기화</string>
<string name="pref_plugin_mousepad">원격 입력</string>
<string name="pref_plugin_mousepad_desc">내 휴대폰이나 태블릿을 터치패드와 키보드로 사용하기</string>
<string name="pref_plugin_mpris">멀티미디어 제어</string>
<string name="pref_plugin_mpris_desc">내 미디어 재생기 원격 제어</string>
<string name="pref_plugin_runcommand">명령 실행</string>
<string name="pref_plugin_runcommand_desc">내 휴대폰이나 태블릿에서 원격 명령 실행</string>
<string name="pref_plugin_ping"></string>
<string name="pref_plugin_ping_desc">핑 보내고 받기</string>
<string name="pref_plugin_notifications">알림 동기화</string>
<string name="pref_plugin_notifications_desc">다른 장치에서 알림 보기</string>
<string name="pref_plugin_receive_notifications">알림 받기</string>
<string name="pref_plugin_receive_notifications_desc">다른 장치의 알림을 받아서 안드로이드 알림에 표시</string>
<string name="pref_plugin_sharereceiver">공유하고 받기</string>
<string name="pref_plugin_sharereceiver_desc">장치끼리 파일과 URL 공유</string>
<string name="plugin_not_available">현재 안드로이드 버전에서 사용할 수 없습니다</string>
@@ -28,6 +34,8 @@
<string name="mousepad_info">화면에서 손가락을 움직이면 마우스 커서를 움직입니다. 화면을 누르면 왼쪽 단추를 누르고, 두 손가락과 세 손가락으로 누르면 오른쪽/가운데 단추를 누릅니다. 드래그 앤 드롭을 사용하려면 길게 누르십시오.</string>
<string name="mousepad_double_tap_settings_title">두 손가락으로 눌렀을 때 동작 설정</string>
<string name="mousepad_triple_tap_settings_title">세 손가락으로 눌렀을 때 동작 설정</string>
<string name="mousepad_sensitivity_settings_title">터치패드 감도 설정</string>
<string name="mousepad_scroll_direction_title">스크롤 방향 뒤집기</string>
<string-array name="mousepad_tap_entries">
<item>오른쪽 단추 누름</item>
<item>가운데 단추 누름</item>
@@ -35,12 +43,13 @@
</string-array>
<string name="mousepad_double_default">오른쪽</string>
<string name="mousepad_triple_default">가운데</string>
<string name="mousepad_sensitivity_default">기본값</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
<item>느리게</item>
<item>느리게 이상</item>
<item>기본값</item>
<item>기본값 이상</item>
<item>빠르게</item>
</string-array>
<string name="category_connected_devices">연결된 장치</string>
<string name="category_not_paired_devices">사용 가능한 장치</string>
@@ -49,6 +58,7 @@
<string name="device_menu_plugins">플러그인 설정</string>
<string name="device_menu_unpair">연결 해제</string>
<string name="device_not_reachable">연결된 장치에 도달할 수 없음</string>
<string name="pair_new_device">새 장치 연결</string>
<string name="unknown_device">알 수 없는 장치</string>
<string name="error_not_reachable">장치에 접근할 수 없음</string>
<string name="error_already_requested">연결이 이미 요청됨</string>
@@ -58,6 +68,10 @@
<string name="error_canceled_by_user">사용자가 취소함</string>
<string name="error_canceled_by_other_peer">다른 쪽에서 취소함</string>
<string name="error_invalid_key">잘못된 키 받음</string>
<string name="encryption_info_title">암호화 정보</string>
<string name="encryption_info_msg_no_ssl">다른 장치에서 KDE Connect의 최근 버전을 실행하고 있지 않아서 레거시 암호화를 사용합니다.</string>
<string name="my_device_fingerprint">내 장치 인증서의 SHA1 지문:</string>
<string name="remote_device_fingerprint">원격 장치 인증서의 SHA1 지문:</string>
<string name="pair_requested">연결 요청됨</string>
<string name="pairing_request_from">%1s에서 연결 요청</string>
<string name="received_url_title">%1s에서 링크 받음</string>
@@ -65,13 +79,15 @@
<string name="incoming_file_title">%1s에서 파일 보냄</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">%1s(으)로 파일 보내는 중</string>
<string name="outgoing_files_title">%1s(으)로 파일 보내는 중</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">파일 %2$d개 중 %1$d개 보냄</string>
<string name="received_file_title">%1s에서 파일 받음</string>
<string name="received_file_fail_title">%1s에서 파일 받기 실패</string>
<string name="received_file_text">\'%1s\'을(를) 열려면 누르십시오</string>
<string name="sent_file_title">%1s(으)로 파일 보냄</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">파일 %1s을(를) 보낼 수 없음</string>
<string name="sent_file_failed_title">파일 %1s(으)로 보낼 수 없음</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">눌러서 응답하기</string>
<string name="reconnect">다시 연결</string>
@@ -118,6 +134,10 @@
<string name="custom_device_list">IP로 장치 추가</string>
<string name="share_notification_preference">시끄러운 알림</string>
<string name="share_notification_preference_summary">파일을 받았을 때 진동과 소리로 알림</string>
<string name="share_destination_customize">대상 디렉터리 사용자 정의</string>
<string name="share_destination_customize_summary_disabled">받은 파일을 다운로드 디렉터리에 저장함</string>
<string name="share_destination_customize_summary_enabled">받은 파일을 아래 디렉터리에 저장함</string>
<string name="share_destination_folder_preference">대상 디렉터리</string>
<string name="title_activity_notification_filter">알림 필터</string>
<string name="filter_apps_info">선택한 앱의 알림을 동기화합니다.</string>
<string name="sftp_internal_storage">내부 저장소</string>
@@ -143,6 +163,9 @@
<string name="pref_plugin_telepathy">SMS 보내기</string>
<string name="pref_plugin_telepathy_desc">데스크톱에서 문자 메시지 보내기</string>
<string name="plugin_not_supported">장치에서 이 플러그인을 지원하지 않습니다</string>
<string name="findmyphone_title">내 휴대폰 찾기</string>
<string name="findmyphone_title_tablet">내 태블릿 찾기</string>
<string name="findmyphone_description">이 장치에서 소리를 울려서 찾는 데 도움을 줍니다</string>
<string name="findmyphone_found">찾았음</string>
<string name="open">열기</string>
<string name="close">닫기</string>

View File

@@ -41,11 +41,14 @@
<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>
@@ -83,6 +86,7 @@
<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>
@@ -96,12 +100,9 @@
<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

@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">De inhoud van het klembord delen</string>
<string name="pref_plugin_mousepad">Invoer op afstand</string>
<string name="pref_plugin_mousepad_desc">Uw telefoon of tablet gebruiken als een touchpad en toetsenbord</string>
<string name="pref_plugin_remotekeyboard">Toetsaanslagen van afstand ontvangen</string>
<string name="pref_plugin_remotekeyboard_desc">Toetsaanslaggebeurtenissen ontvangen van externe apparaten</string>
<string name="pref_plugin_mpris">Bediening van multimedia</string>
<string name="pref_plugin_mpris_desc">Biedt een afstandsbediening voor uw mediaspeler</string>
<string name="pref_plugin_runcommand">Commando uitvoeren</string>
@@ -30,6 +32,10 @@
<string name="no_permissions">U moet toestemming geven voor toegang tot meldingen</string>
<string name="send_ping">Ping verzenden</string>
<string name="open_mpris_controls">Bediening van multimedia</string>
<string name="remotekeyboard_editing_only_title">Behandel toetsen op afstand alleen bij bewerken</string>
<string name="remotekeyboard_not_connected">Er is geen actieve verbinding met een toetsenbord op afstand, maak er een in kdeconnect</string>
<string name="remotekeyboard_connected">Verbinding met toetsenbord op afstand is actief</string>
<string name="remotekeyboard_multiple_connections">Er is meer dan een verbinding met een toetsenbord op afstand, selecteer het te configureren apparaat</string>
<string name="open_mousepad">Invoer op afstand</string>
<string name="mousepad_info">Veeg met een vinger op het scherm om de muiscursor te verplaatsen. Tik om te klikken en gebruik twee/drie vingers voor rechter en middelste knop. Druk lang voor slepen en loslaten.</string>
<string name="mousepad_double_tap_settings_title">Tikactie met twee vingers instellen</string>
@@ -79,13 +85,15 @@
<string name="incoming_file_title">Inkomend bestand van %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Bezig bestand te verzenden naar %1s</string>
<string name="outgoing_files_title">Bestanden verzenden naar %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Verzonden %1$d van %2$d bestanden</string>
<string name="received_file_title">Bestand ontvangen van %1s</string>
<string name="received_file_fail_title">Bestand ontvangen van %1s is mislukt</string>
<string name="received_file_text">Tap om \'%1s\' te openen</string>
<string name="sent_file_title">Bestand verzonden naar %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Verzenden van bestand %1s is mislukt</string>
<string name="sent_file_failed_title">Verzenden van bestanden naar %1s is mislukt</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tap om te antwoorden</string>
<string name="reconnect">Opnieuw verbinden</string>
@@ -132,6 +140,10 @@
<string name="custom_device_list">Voeg apparaten toe per IP-adres</string>
<string name="share_notification_preference">Luidruchtige meldingen</string>
<string name="share_notification_preference_summary">Vibreer en speel een geluidje bij ontvangen van een bestand</string>
<string name="share_destination_customize">Pas bestemmingsmap aan</string>
<string name="share_destination_customize_summary_disabled">Ontvangen bestanden zullen in Downloads verschijnen</string>
<string name="share_destination_customize_summary_enabled">Bestanden zullen opgeslagen worden in de onderstaande map</string>
<string name="share_destination_folder_preference">Bestemmingsmap</string>
<string name="title_activity_notification_filter">Filter voor meldingen</string>
<string name="filter_apps_info">Meldingen zullen gesynchroniseerd worden voor de geselecteerde apps.</string>
<string name="sftp_internal_storage">Interne opslag</string>

165
res/values-nn/strings.xml Normal file
View File

@@ -0,0 +1,165 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">Telefonvarsling</string>
<string name="pref_plugin_telephony_desc">Send varsling ved SMS og oppringing</string>
<string name="pref_plugin_battery">Batterirapport</string>
<string name="pref_plugin_battery_desc">Meld regelmessig frå om batteristatusen</string>
<string name="pref_plugin_sftp">Vis filsystem</string>
<string name="pref_plugin_sftp_desc">Tillat lesing av filsystemet frå datamaskina</string>
<string name="pref_plugin_clipboard">Synkroniser utklippstavle</string>
<string name="pref_plugin_clipboard_desc">Del innhaldet på utklippstavla</string>
<string name="pref_plugin_mousepad">Fjernstyring</string>
<string name="pref_plugin_mousepad_desc">Bruk telefonen eller nettbrettet som styrepute og tastatur</string>
<string name="pref_plugin_mpris">Mediekontrollar</string>
<string name="pref_plugin_mpris_desc">Gjev fjernkontroll til mediespelarar</string>
<string name="pref_plugin_runcommand">Køyr kommando</string>
<string name="pref_plugin_runcommand_desc">Utløys fjernkommandoar frå telefonen eller nettbrettet</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Send og ta imot ping-signal</string>
<string name="pref_plugin_notifications">Varslingssynkronisering</string>
<string name="pref_plugin_notifications_desc">Få tilgang til varslingar frå andre einingar</string>
<string name="pref_plugin_receive_notifications">Få varslingar</string>
<string name="pref_plugin_receive_notifications_desc">Få varslingar frå den andre eininga og vis dei i Android</string>
<string name="pref_plugin_sharereceiver">Del og ta imot</string>
<string name="pref_plugin_sharereceiver_desc">Del filer og nettadresser mellom einingar</string>
<string name="plugin_not_available">Denne funksjonen er ikkje tilgjengeleg i din Android-versjon</string>
<string name="device_list_empty">Ingen einingar</string>
<string name="ok">OK</string>
<string name="cancel">Avbryt</string>
<string name="open_settings">Opna innstillingar</string>
<string name="no_permissions">Du må gje tilgang til lesing av varslingar</string>
<string name="send_ping">Send pingsignal</string>
<string name="open_mpris_controls">Mediekontroll</string>
<string name="open_mousepad">Fjernstyring</string>
<string name="mousepad_info">Dra ein finger over skjermen for å flytta peikaren på datamaskina. Trykk for å klikka, og bruk to eller tre fingrar for høvesvis høgre- og midtknappen. Trykk og hald for å dra og sleppa.</string>
<string name="mousepad_double_tap_settings_title">Vel handling for tofingertrykk</string>
<string name="mousepad_triple_tap_settings_title">Vel handling for trefingertrykk</string>
<string name="mousepad_sensitivity_settings_title">Vel følsemd for styrepute</string>
<string name="mousepad_scroll_direction_title">Omvend rulleretning</string>
<string-array name="mousepad_tap_entries">
<item>Høgreklikk</item>
<item>Midtklikk</item>
<item>Ingenting</item>
</string-array>
<string name="mousepad_double_default">høgre</string>
<string name="mousepad_triple_default">midt</string>
<string name="mousepad_sensitivity_default">standard</string>
<string-array name="mousepad_sensitivity_entries">
<item>Saktast</item>
<item>Raskare enn saktast</item>
<item>Standard</item>
<item>Raskare enn standard</item>
<item>Raskast</item>
</string-array>
<string name="category_connected_devices">Tilkopla einingar</string>
<string name="category_not_paired_devices">Tilgjengelege einingar</string>
<string name="category_remembered_devices">Hugs einingar</string>
<string name="plugins_failed_to_load">Klarte ikkje lasta programtillegg (trykk for meir informasjon):</string>
<string name="device_menu_plugins">Innstillingar for programtillegg</string>
<string name="device_menu_unpair">Løys paring</string>
<string name="device_not_reachable">Får ikkje kontakt med para eining</string>
<string name="pair_new_device">Par ny eining</string>
<string name="unknown_device">Ukjend eining</string>
<string name="error_not_reachable">Får ikkje kontakt med eininga</string>
<string name="error_already_requested">Paringsførespurnad er alt send</string>
<string name="error_already_paired">Eininga er alt para</string>
<string name="error_could_not_send_package">Klarte ikkje senda pakke</string>
<string name="error_timed_out">Tidsavbrot</string>
<string name="error_canceled_by_user">Avbroten av brukar</string>
<string name="error_canceled_by_other_peer">Avbroten av den andre eininga</string>
<string name="error_invalid_key">Fekk ugyldig nøkkel</string>
<string name="encryption_info_title">Krypteringsinfo</string>
<string name="encryption_info_msg_no_ssl">Den andre eininga brukar ein gammal versjon av KDE Connect, med ein utdatert krypteringsmetode.</string>
<string name="my_device_fingerprint">SHA-fingeravtrykk av einingssertifikatet er:</string>
<string name="remote_device_fingerprint">SHA-fingeravtrykk av fjerneiningssertifikatet er:</string>
<string name="pair_requested">Paringsførespurnad</string>
<string name="pairing_request_from">Paringsførespurnad frå %1s</string>
<string name="received_url_title">Fekk lenkje frå %1s</string>
<string name="received_url_text">Trykk for å opna «%1s»</string>
<string name="incoming_file_title">Får fil frå %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Sender fil til %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="received_file_title">Fekk fil frå %1s</string>
<string name="received_file_fail_title">Klarte ikkje ta imot fil frå %1s</string>
<string name="received_file_text">Trykk for å opna «%1s»</string>
<string name="sent_file_title">Send fil til %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Trykk for å svara</string>
<string name="reconnect">Kopla til på nytt</string>
<string name="right_click">Send høgreklikk</string>
<string name="middle_click">Send midtklikk</string>
<string name="show_keyboard">Vis tastatur</string>
<string name="device_not_paired">Eininga er ikkje para</string>
<string name="request_pairing">Be om paring</string>
<string name="pairing_accept">Godta</string>
<string name="pairing_reject">Avvis</string>
<string name="device">Eining</string>
<string name="pair_device">Par ny eining</string>
<string name="remote_control">Fjernstyring</string>
<string name="settings">Innstillingar for KDE Connect</string>
<string name="mpris_play">Spel</string>
<string name="mpris_previous">Førre</string>
<string name="mpris_rew">Spol tilbake</string>
<string name="mpris_ff">Spol fram</string>
<string name="mpris_next">Neste</string>
<string name="mpris_volume">Lydstyrke</string>
<string name="mpris_settings">Medieinnstillingar</string>
<string name="mpris_time_settings_title">Spoleknappar</string>
<string name="mpris_time_settings_summary">Juster tida for spoling ved trykking.</string>
<string-array name="mpris_time_entries">
<item>10 sekund</item>
<item>20 sekund</item>
<item>30 sekund</item>
<item>1 minutt</item>
<item>2 minutt</item>
</string-array>
<string name="share_to">Del til </string>
<string name="protocol_version_older">Denne eininga brukar ein gammal protokollversjon</string>
<string name="protocol_version_newer">Denne eininga brukar ein nyare protokollversjon</string>
<string name="general_settings">Generelle innstillingar</string>
<string name="plugin_settings">Innstillingar</string>
<string name="plugin_settings_with_name">%s-innstillingar</string>
<string name="device_name">Einingsnamn</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">Ugyldig einingsnamn</string>
<string name="shareplugin_text_saved">Fekk tekst, som vart lagra på utklippstavla</string>
<string name="custom_devices_settings">Tilpassa einingsliste</string>
<string name="pair_device_action">Par ny eining</string>
<string name="unpair_device_action">Løys paring for %s</string>
<string name="custom_device_list">Legg til eining basert på IP</string>
<string name="share_notification_preference">Lydvarsling</string>
<string name="share_notification_preference_summary">Vibrer og spel ein lyd ved mottak av fil</string>
<string name="title_activity_notification_filter">Varslingsfilter</string>
<string name="filter_apps_info">Varslingar vert synkroniserte for dei valde appane.</string>
<string name="sftp_internal_storage">Intern lagring</string>
<string name="sftp_all_files">Alle filer</string>
<string name="sftp_sdcard_num">SD-kort %d</string>
<string name="sftp_sdcard">SD-kort</string>
<string name="sftp_readonly">(skriveverna)</string>
<string name="sftp_camera">Kamerabilete</string>
<string name="add_host">Legg til vert/IP</string>
<string name="add_host_hint">Vertsnamn/IP-adresse</string>
<string name="no_players_connected">Fann ingen spelarar</string>
<string name="custom_dev_list_help">Bruk berre dette valet viss eininga ikkje vert kjend att automatisk. Skriv inn IP-adressa eller vertsnamnet nedanfor, og trykk på knappen for å leggja eininga til oversikta. Trykk på element i oversikta for å fjerna dei.</string>
<string name="mpris_player_on_device">%1$s på %2$s</string>
<string name="send_files">Send filer</string>
<string name="pairing_title">KDE Connect-einingar</string>
<string name="pairing_description">Andre einingar i nettverket som køyrer KDE Connect vil dukka opp her.</string>
<string name="device_paired">Eininga er para</string>
<string name="device_rename_title">Endra namn på eining</string>
<string name="device_rename_confirm">Endra namn</string>
<string name="refresh">Oppdater</string>
<string name="unreachable_description">Får ikkje kontakt med den para eininga. Sjå til at ho er kopla til same nettverk.</string>
<string name="no_file_browser">Ingen filhandsamarar er installerte.</string>
<string name="pref_plugin_telepathy">Send SMS</string>
<string name="pref_plugin_telepathy_desc">Send tekstmeldingar frå datamaskina</string>
<string name="plugin_not_supported">Dette tillegget er ikkje støtta av eininga</string>
<string name="findmyphone_title">Finn telefonen min</string>
<string name="findmyphone_title_tablet">Finn nettbrettet mitt</string>
<string name="findmyphone_description">Ring til eininga, slik at du kan finna ho</string>
<string name="findmyphone_found">Fann</string>
<string name="open">Opna</string>
<string name="close">Lukk</string>
</resources>

View File

@@ -79,13 +79,15 @@
<string name="incoming_file_title">Plik przychodzący od %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Wysyłanie pliku do %1s</string>
<string name="outgoing_files_title">Wysyłanie pliku do %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Wysłano %1$d z %2$d plików</string>
<string name="received_file_title">Odebrano plik od %1s</string>
<string name="received_file_fail_title">Nieudane odbieranie pliku z %1s</string>
<string name="received_file_text">Znacznik do otwarcia \'%1s\'</string>
<string name="sent_file_title">Plik wysłano do %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Nieudane wysyłanie pliku %1s</string>
<string name="sent_file_failed_title">Nie udało się wyłanie pliku do %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Stuknij, aby odpowiedzieć</string>
<string name="reconnect">Połącz ponownie</string>
@@ -132,6 +134,10 @@
<string name="custom_device_list">Dodaj urządzenia po numerze IP</string>
<string name="share_notification_preference">Hałaśliwe powiadomienia</string>
<string name="share_notification_preference_summary">Zadrżyj i odegraj dźwięk przy odebraniu pliku</string>
<string name="share_destination_customize">Własny katalog docelowy</string>
<string name="share_destination_customize_summary_disabled">Pobrane pliki ukażą się w Pobranych</string>
<string name="share_destination_customize_summary_enabled">Pliki zostaną zapisane w poniższym katalogu</string>
<string name="share_destination_folder_preference">Katalog docelowy</string>
<string name="title_activity_notification_filter">Filtr powiadomień</string>
<string name="filter_apps_info">Powiadomienia zostaną zsynchronizowane z wybranymi aplikacjami.</string>
<string name="sftp_internal_storage">"Pamięć wewnętrzna "</string>

View File

@@ -5,15 +5,19 @@
<string name="pref_plugin_battery">Relatório da bateria</string>
<string name="pref_plugin_battery_desc">Informação periódica do status da bateria</string>
<string name="pref_plugin_sftp">Exposição do sistema de arquivos</string>
<string name="pref_plugin_sftp_desc">Permite navegar no sistema de arquivos deste telefone remotamente</string>
<string name="pref_plugin_clipboard">Sincronização da área de transferência</string>
<string name="pref_plugin_clipboard_desc">Compartilha o conteúdo da área de transferência</string>
<string name="pref_plugin_mousepad">Introdução de dados remota</string>
<string name="pref_plugin_mousepad_desc">Use seu telefone ou tablet como mouse e teclado</string>
<string name="pref_plugin_mpris">Controle multimídia</string>
<string name="pref_plugin_mpris_desc">Fornece um controle remoto de seu reprodutor de mídia</string>
<string name="pref_plugin_runcommand">Executar comando</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Envia e recebe pings</string>
<string name="pref_plugin_notifications">Sincronização de notificações</string>
<string name="pref_plugin_notifications_desc">Acesse suas notificações a partir de outros dispositivos</string>
<string name="pref_plugin_receive_notifications">Receber notificações</string>
<string name="pref_plugin_sharereceiver">Compartilhar e receber</string>
<string name="pref_plugin_sharereceiver_desc">Compartilha arquivos e URLs entre os dispositivos</string>
<string name="plugin_not_available">Esta funcionalidade não está disponível na sua versão do Android</string>
@@ -62,6 +66,7 @@
<string name="error_canceled_by_user">Cancelado pelo usuário</string>
<string name="error_canceled_by_other_peer">Cancelado pelo outro dispositivo</string>
<string name="error_invalid_key">Chave inválida recebida</string>
<string name="encryption_info_title">Informação da criptografia</string>
<string name="pair_requested">Solicitação de emparelhamento</string>
<string name="pairing_request_from">Emparelhamento solicitado por %1s</string>
<string name="received_url_title">Link recebido de %1s</string>
@@ -75,7 +80,6 @@
<string name="received_file_text">Toque para abrir o \'%1s\'</string>
<string name="sent_file_title">Enviar arquivo para %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Falha ao enviar o arquivo %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Toque para responder</string>
<string name="reconnect">Reconectar</string>
@@ -147,6 +151,8 @@
<string name="pref_plugin_telepathy">Enviar SMS</string>
<string name="pref_plugin_telepathy_desc">Enviar mensagens de texto do seu Desktop</string>
<string name="plugin_not_supported">Este plugin não é suportado pelo dispositivo</string>
<string name="findmyphone_title">Encontrar meu telefone</string>
<string name="findmyphone_title_tablet">Encontrar meu tablet</string>
<string name="findmyphone_found">Encontrado</string>
<string name="open">Abrir</string>
<string name="close">Fechar</string>

View File

@@ -10,6 +10,8 @@
<string name="pref_plugin_clipboard_desc">Partilhar o conteúdo da área de transferência</string>
<string name="pref_plugin_mousepad">Introdução remota de dados</string>
<string name="pref_plugin_mousepad_desc">Usar o seu telefone ou \'tablet\' como um rato ou teclado</string>
<string name="pref_plugin_remotekeyboard">Receber as teclas remotamente</string>
<string name="pref_plugin_remotekeyboard_desc">Receber eventos de teclas dos dispositivos remotos</string>
<string name="pref_plugin_mpris">Comandos multimédia</string>
<string name="pref_plugin_mpris_desc">Oferece um comando à distância para o seu leitor multimédia</string>
<string name="pref_plugin_runcommand">Executar um Comando</string>
@@ -30,6 +32,10 @@
<string name="no_permissions">Precisa de dar permissões de acesso às notificações</string>
<string name="send_ping">Enviar um pedido de contacto</string>
<string name="open_mpris_controls">Comando multimédia</string>
<string name="remotekeyboard_editing_only_title">Lidar com as teclas remotas apenas na edição</string>
<string name="remotekeyboard_not_connected">Não existe nenhuma ligação activa a teclados remotos - crie uma no \'kdeconnect\'</string>
<string name="remotekeyboard_connected">A ligação ao teclado remoto está activa</string>
<string name="remotekeyboard_multiple_connections">Existe mais que uma ligação a teclados remotos; seleccione o dispositivo a configurar</string>
<string name="open_mousepad">Introdução remota de dados</string>
<string name="mousepad_info">Mova um dedo pelo ecrã para mover o cursor do rato. Dê um toque para carregar no botão esquerdo e use dois/três dedos para os botões direito e do meio. Use uma pressão longa para arrastar e largar.</string>
<string name="mousepad_double_tap_settings_title">Definir a acção do toque com dois dedos</string>
@@ -79,13 +85,15 @@
<string name="incoming_file_title">Ficheiro recebido de %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">A enviar o ficheiro para o %1s</string>
<string name="outgoing_files_title">A enviar os ficheiros para o %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Foram enviados %1$d de %2$d ficheiros</string>
<string name="received_file_title">Ficheiro recebido de %1s</string>
<string name="received_file_fail_title">Falhou a recepção do ficheiro de %1s</string>
<string name="received_file_text">Toque para abrir o \'%1s\'</string>
<string name="sent_file_title">O ficheiro foi enviado para %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Não foi possível enviar o ficheiro %1s</string>
<string name="sent_file_failed_title">Não foi possível enviar o ficheiro para o %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Toque para responder</string>
<string name="reconnect">Ligar de Novo</string>
@@ -132,6 +140,10 @@
<string name="custom_device_list">Adicionar dispositivos pelo IP</string>
<string name="share_notification_preference">Notificações com ruído</string>
<string name="share_notification_preference_summary">Vibrar e tocar um som ao receber um ficheiro</string>
<string name="share_destination_customize">Personalizar a pasta de destino</string>
<string name="share_destination_customize_summary_disabled">Os ficheiros recebidos irão aparecer em \'Transferências\'</string>
<string name="share_destination_customize_summary_enabled">Os ficheiros serão guardados na pasta abaixo</string>
<string name="share_destination_folder_preference">Pasta de destino</string>
<string name="title_activity_notification_filter">Filtro de notificações</string>
<string name="filter_apps_info">As notificações serão sincronizadas para as aplicações seleccionadas.</string>
<string name="sftp_internal_storage">Armazenamento interno</string>

View File

@@ -71,7 +71,6 @@
<string name="received_file_text">Нажмите, чтобы открыть «%1s»</string>
<string name="sent_file_title">Файл отправлен на %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Не удалось отправить файл %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Нажмите, чтобы ответить</string>
<string name="reconnect">Подключить заново</string>

View File

@@ -5,15 +5,23 @@
<string name="pref_plugin_battery">Oznam o batérii</string>
<string name="pref_plugin_battery_desc">Periodicky oznamovať stav batérie</string>
<string name="pref_plugin_sftp">Odhaliť súborový systém</string>
<string name="pref_plugin_sftp_desc">Umožní prehliadač súborový systém zariadenia vzdialene</string>
<string name="pref_plugin_clipboard">Synchronizácia schránky</string>
<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>
<string name="pref_plugin_runcommand_desc">Vyvolať vzdialené príkazy z vášho mobilu alebo tabletu</string>
<string name="pref_plugin_ping">Ping</string>
<string name="pref_plugin_ping_desc">Poslať a prijať pingy</string>
<string name="pref_plugin_notifications">Synchronizácia pripomienok</string>
<string name="pref_plugin_notifications_desc">Prístup k vašim pripomienkam z iných zariadení</string>
<string name="pref_plugin_receive_notifications">Prijať upozornenia</string>
<string name="pref_plugin_receive_notifications_desc">Prístup k pripomienkam z iných zariadení a zobrazenie ich na Androide</string>
<string name="pref_plugin_sharereceiver">Zdieľať a prijať</string>
<string name="pref_plugin_sharereceiver_desc">Zdieľať súbory a medzi zariadeniami</string>
<string name="plugin_not_available">Táto funkcia nie je dostupná vo vašej verzii Androidu</string>
@@ -24,6 +32,10 @@
<string name="no_permissions">Musíte povoliť oprávnenia na prístup k pripomienkam</string>
<string name="send_ping">Poslať ping</string>
<string name="open_mpris_controls">Multimediálny ovládač</string>
<string name="remotekeyboard_editing_only_title">Spracúva vzdialené klávesy len pri editácii</string>
<string name="remotekeyboard_not_connected">Nie sú žiadne aktívne pripojenia vzdialenej klávesnice, vytvorte nejaké v Kdeconnect</string>
<string name="remotekeyboard_connected">Vzdialené pripojenie klávesnice je aktívne</string>
<string name="remotekeyboard_multiple_connections">Je viac ako jedno vzdialené pripojenie klávesnice, vyberte zariadenie na nastavenie</string>
<string name="open_mousepad">Vzdialený vstup</string>
<string name="mousepad_info">Posúvajte prst na obrazovke na posun kurzora. Ťuknutie vyvolá klik a použite dva/tri prsty pre pravé a stredné tlačidlo. Použite dlhé stlačenie pre drag and drop.</string>
<string name="mousepad_double_tap_settings_title">Nastaviť akciu dvoch prstov</string>
@@ -73,7 +85,9 @@
<string name="incoming_file_title">Prichádzajúci súbor od %s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Posielam súbor pre %1s</string>
<string name="outgoing_files_title">Posielam súbor pre %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Poslať %1$d z %2$d súborov</string>
<string name="received_file_title">Prijatý súbor od %1s</string>
<string name="received_file_fail_title">Zlyhalo prijatie súboru od %1s</string>
<string name="received_file_text">Ťuknite na otvorenie \'%1s\'</string>
@@ -126,6 +140,10 @@
<string name="custom_device_list">Pridať zariadenia podľa IP</string>
<string name="share_notification_preference">Hlučné pripomienky</string>
<string name="share_notification_preference_summary">Vibrovať a prehrať zvuk pri prijatí súboru</string>
<string name="share_destination_customize">Prispôsobiť cieľový adresár</string>
<string name="share_destination_customize_summary_disabled">Prijaté súbory sa objavia v Preberaniach</string>
<string name="share_destination_customize_summary_enabled">Súbory sa uložia v adresári dolu</string>
<string name="share_destination_folder_preference">Cieľový adresár</string>
<string name="title_activity_notification_filter">Filter upozornení</string>
<string name="filter_apps_info">Upozornenia budú synchronizované pre vybrané aplikácie.</string>
<string name="sftp_internal_storage">Interné úložisko</string>
@@ -152,6 +170,8 @@
<string name="pref_plugin_telepathy_desc">Posielať textové správy z vášho počítača</string>
<string name="plugin_not_supported">Tento plugin nie je podporovaný zariadením</string>
<string name="findmyphone_title">Nájsť môj telefón</string>
<string name="findmyphone_title_tablet">Nájsť môj tablet</string>
<string name="findmyphone_description">Prezvoní vaše zariadenie, aby ste ho našli</string>
<string name="findmyphone_found">Nájdené</string>
<string name="open">Otvoriť</string>
<string name="close">Zavrieť</string>

View File

@@ -79,13 +79,15 @@
<string name="incoming_file_title">Inkommande fil från %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Skickar fil till %1s</string>
<string name="outgoing_files_title">Skickar filer till %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Skickade %1$d av %2$d filer</string>
<string name="received_file_title">Tog emot fil från %1s</string>
<string name="received_file_fail_title">Misslyckades ta emot fil från %1s</string>
<string name="received_file_text">Rör för att öppna \'%1s\'</string>
<string name="sent_file_title">Skickade fil till %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Misslyckades skicka fil %1s</string>
<string name="sent_file_failed_title">Misslyckades skicka fil till %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Rör för att svara</string>
<string name="reconnect">Anslut igen</string>
@@ -132,6 +134,10 @@
<string name="custom_device_list">Lägg till apparater enligt IP-adress</string>
<string name="share_notification_preference">Ljudliga underrättelser</string>
<string name="share_notification_preference_summary">Vibrera och spela ett ljud när en fil tas emot</string>
<string name="share_destination_customize">Anpassa målkatalog</string>
<string name="share_destination_customize_summary_disabled">Mottagna filer hamnar i Nerladdningar</string>
<string name="share_destination_customize_summary_enabled">Filer lagras i katalogen nedan</string>
<string name="share_destination_folder_preference">Målkatalog</string>
<string name="title_activity_notification_filter">Underrättelsefilter</string>
<string name="filter_apps_info">Underrättelser synkroniseras för markerade applikationer.</string>
<string name="sftp_internal_storage">Intern lagring</string>

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,6 +32,10 @@
<string name="no_permissions">Вам слід надати доступ до сповіщень</string>
<string name="send_ping">Надіслати сигнал підтримання зв’язку</string>
<string name="open_mpris_controls">Керування відтворенням</string>
<string name="remotekeyboard_editing_only_title">Обробляти віддалені клавіші лише під час редагування</string>
<string name="remotekeyboard_not_connected">Немає активних з’єднань із віддаленою клавіатурою. Встановіть таке з’єднання у kdeconnect.</string>
<string name="remotekeyboard_connected">З’єднання з віддаленою клавіатурою є активним</string>
<string name="remotekeyboard_multiple_connections">Існує декілька з’єднань із віддаленою клавіатурою. Виберіть пристрій для налаштовування.</string>
<string name="open_mousepad">Дистанційне введення</string>
<string name="mousepad_info">Проведіть по екрану пальцем, щоб пересунути вказівник миші. Дотик одним пальцем означатиме клацання, дотиком двома або трьома пальцями можна імітувати праву і середню кнопки. Для перетягування зі скиданням скористайтеся тривалим натисканням.</string>
<string name="mousepad_double_tap_settings_title">Встановлення дії для торкання двома пальцями</string>
@@ -79,13 +85,15 @@
<string name="incoming_file_title">Вхідний файл з %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Надсилаємо файл до %1s</string>
<string name="outgoing_files_title">Надсилаємо файли на %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Надіслано %1$d з %2$d файлів</string>
<string name="received_file_title">Отримано файл з %1s</string>
<string name="received_file_fail_title">Не вдалося отримати файл з %1s</string>
<string name="received_file_text">Натисніть, щоб відкрити «%1s»</string>
<string name="sent_file_title">Файл надіслано до %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Не вдалося надіслати файл %1s</string>
<string name="sent_file_failed_title">Не вдалося надіслати файл на %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Натисніть, щоб відповісти</string>
<string name="reconnect">З\'єднати знову</string>
@@ -132,6 +140,10 @@
<string name="custom_device_list">Додати пристрої за IP</string>
<string name="share_notification_preference">Звукові сповіщення</string>
<string name="share_notification_preference_summary">Вібрація і відтворення звуку у відповідь на отримання файла</string>
<string name="share_destination_customize">Налаштування каталогу призначення</string>
<string name="share_destination_customize_summary_disabled">Отримані файли зберігатимуться до каталогу «Завантаження»</string>
<string name="share_destination_customize_summary_enabled">Файли зберігатимуться у вказаному нижче каталозі</string>
<string name="share_destination_folder_preference">Каталог призначення</string>
<string name="title_activity_notification_filter">Фільтр сповіщень</string>
<string name="filter_apps_info">Сповіщення буде синхронізовано для позначених програм.</string>
<string name="sftp_internal_storage">Вбудоване сховище даних</string>

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">Ping</string>
<string name="pref_plugin_ping_desc">发送和接受ping</string>
<string name="pref_plugin_notifications">通知同步</string>
<string name="pref_plugin_notifications_desc">从其他设备访问你的通知</string>
<string name="pref_plugin_receive_notifications">接收通知</string>
<string name="pref_plugin_receive_notifications_desc">从其他设备接收通知并显示在 Android 上</string>
<string name="pref_plugin_sharereceiver">分享和接收</string>
<string name="pref_plugin_sharereceiver_desc">在设备间共享文件和 URL</string>
<string name="plugin_not_available">该特性不适用于您的Android版本</string>
@@ -24,10 +32,16 @@
<string name="no_permissions">你需要授予权限以便访问通知</string>
<string name="send_ping">发送ping</string>
<string name="open_mpris_controls">多媒体控制</string>
<string name="remotekeyboard_editing_only_title">只有在编辑时才接受远程按键</string>
<string name="remotekeyboard_not_connected">没有活动的远程键盘链接,请在 KDE Connect 中连接</string>
<string name="remotekeyboard_connected">远程键盘连接已启用</string>
<string name="remotekeyboard_multiple_connections">发现多个远程键盘连接,请选择设备进行配置</string>
<string name="open_mousepad">远程输入</string>
<string name="mousepad_info">在屏幕上移动手指来移动光标。轻击代表左键,双指或三指点击代表右键或中键。用长按来拖放。</string>
<string name="mousepad_double_tap_settings_title">设置双指点击动作</string>
<string name="mousepad_triple_tap_settings_title">设置三指点击动作</string>
<string name="mousepad_sensitivity_settings_title">设置触摸板灵敏度</string>
<string name="mousepad_scroll_direction_title">滚动方向反向</string>
<string-array name="mousepad_tap_entries">
<item>右键点击</item>
<item>中键点击</item>
@@ -35,12 +49,13 @@
</string-array>
<string name="mousepad_double_default"></string>
<string name="mousepad_triple_default"></string>
<string name="mousepad_sensitivity_default">默认</string>
<string-array name="mousepad_sensitivity_entries">
<item>Slowest</item>
<item>Above Slowest</item>
<item>Default</item>
<item>Above Default</item>
<item>Fastest</item>
<item>最慢</item>
<item>高于最慢</item>
<item>默认</item>
<item>高于默认</item>
<item>最快</item>
</string-array>
<string name="category_connected_devices">已连接设备</string>
<string name="category_not_paired_devices">可用设备</string>
@@ -59,6 +74,10 @@
<string name="error_canceled_by_user">已被用户取消</string>
<string name="error_canceled_by_other_peer">已被另一方取消</string>
<string name="error_invalid_key">收到无效密钥</string>
<string name="encryption_info_title">加密信息</string>
<string name="encryption_info_msg_no_ssl">另一设备没有使用最新的 KDE Connect使用旧版加密方法。</string>
<string name="my_device_fingerprint">您的设备证书的 SHA1 指纹是:</string>
<string name="remote_device_fingerprint">远程设备证书的 SHA1 指纹是:</string>
<string name="pair_requested">已请求配对</string>
<string name="pairing_request_from">来自%1s的配对请求</string>
<string name="received_url_title">已从%1s接收链接</string>
@@ -66,13 +85,15 @@
<string name="incoming_file_title">来自%1s的文件</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">正在向%1s发送文件</string>
<string name="outgoing_files_title">正在向 %1s 发送文件</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">已发送 %2$d 个文件中的 %1$d 个</string>
<string name="received_file_title">已从%1s接收文件</string>
<string name="received_file_fail_title">未能从%1s接收文件</string>
<string name="received_file_text">点击以打开“%1s”</string>
<string name="sent_file_title">发送文件到%1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">未能发送文件%1s</string>
<string name="sent_file_failed_title">向 %1s 发送文件失败</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">点击以应答</string>
<string name="reconnect">重新连接</string>
@@ -119,6 +140,10 @@
<string name="custom_device_list">通过IP增加设备</string>
<string name="share_notification_preference">出声通知</string>
<string name="share_notification_preference_summary">当收到文件时震动并播放声音</string>
<string name="share_destination_customize">配置目标目录</string>
<string name="share_destination_customize_summary_disabled">接收的文件会出现在“Downloads”中</string>
<string name="share_destination_customize_summary_enabled">文件将会被存储在以下目录中</string>
<string name="share_destination_folder_preference">目标目录</string>
<string name="title_activity_notification_filter">通知过滤器</string>
<string name="filter_apps_info">所选软件的通知将会被同步。</string>
<string name="sftp_internal_storage">内部存储</string>
@@ -144,7 +169,7 @@
<string name="pref_plugin_telepathy">发送短消息</string>
<string name="pref_plugin_telepathy_desc">从桌面发送短消息</string>
<string name="plugin_not_supported">设备不支持此插件</string>
<string name="findmyphone_title">找到我的手机</string>
<string name="findmyphone_description">让设备响铃从而找到它</string>
<string name="findmyphone_found">找到</string>
<string name="open">打开</string>
<string name="close">关闭</string>
</resources>

View File

@@ -0,0 +1,165 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="pref_plugin_telephony">電話通知器</string>
<string name="pref_plugin_telephony_desc">發送短訊與電話的通知</string>
<string name="pref_plugin_battery">電池報告</string>
<string name="pref_plugin_battery_desc">定期回報電池狀態</string>
<string name="pref_plugin_sftp">顯示檔案系統</string>
<string name="pref_plugin_sftp_desc">同意讓遠端可以瀏覽檔案系統</string>
<string name="pref_plugin_clipboard">同步剪貼板</string>
<string name="pref_plugin_clipboard_desc">分享剪貼板的內容</string>
<string name="pref_plugin_mousepad">遠端輸入</string>
<string name="pref_plugin_mousepad_desc">使用您的智慧型手機或者平板來模擬觸碰板與鍵盤</string>
<string name="pref_plugin_mpris">多媒體控制</string>
<string name="pref_plugin_mpris_desc">成為您多媒體播放器的遙控器</string>
<string name="pref_plugin_runcommand">執行指令</string>
<string name="pref_plugin_runcommand_desc">從您的智慧型手機或者平板當中觸發遠端設備上的命令</string>
<string name="pref_plugin_ping">Ping回應封包</string>
<string name="pref_plugin_ping_desc">傳送與接收Ping回應封包</string>
<string name="pref_plugin_notifications">同步通知</string>
<string name="pref_plugin_notifications_desc">存取其他設備上的通知</string>
<string name="pref_plugin_receive_notifications">接收通知</string>
<string name="pref_plugin_receive_notifications_desc">在Android上顯示從其他裝置收到的通知</string>
<string name="pref_plugin_sharereceiver">分享與接收</string>
<string name="pref_plugin_sharereceiver_desc">在兩個設備當中互相分享URL網址與檔案</string>
<string name="plugin_not_available">這個功能無法在您的Android版本上執行。</string>
<string name="device_list_empty">沒有裝置</string>
<string name="ok">OK</string>
<string name="cancel">取消</string>
<string name="open_settings">開啟設定</string>
<string name="no_permissions">您需要授予存取通知的權限</string>
<string name="send_ping">傳送Ping回應封包</string>
<string name="open_mpris_controls">多媒體控制</string>
<string name="open_mousepad">遠端輸入</string>
<string name="mousepad_info">在您的智慧型手機的螢幕上移動手指頭,用來控制電腦螢幕的鼠標。點擊表示滑鼠的左鍵,使用兩隻/三隻手指頭點擊來表示滑鼠的右鍵/中鍵。長按則表示要拖拉。</string>
<string name="mousepad_double_tap_settings_title">設定兩隻手指頭點擊的動作</string>
<string name="mousepad_triple_tap_settings_title">設定三隻手指頭點擊的動作</string>
<string name="mousepad_sensitivity_settings_title">設定觸碰板的靈敏度</string>
<string name="mousepad_scroll_direction_title">滾動方向相反</string>
<string-array name="mousepad_tap_entries">
<item>右鍵點擊</item>
<item>中鍵點擊</item>
<item></item>
</string-array>
<string name="mousepad_double_default"></string>
<string name="mousepad_triple_default"></string>
<string name="mousepad_sensitivity_default">預設</string>
<string-array name="mousepad_sensitivity_entries">
<item></item>
<item>最慢</item>
<item>預設</item>
<item>高於預設值</item>
<item>最快</item>
</string-array>
<string name="category_connected_devices">已連接的設備</string>
<string name="category_not_paired_devices">可連接的設備</string>
<string name="category_remembered_devices">已記住的設備</string>
<string name="plugins_failed_to_load">擴展插件讀取錯誤(點擊查看更多資訊)</string>
<string name="device_menu_plugins">擴展插件設定</string>
<string name="device_menu_unpair">取消配對</string>
<string name="device_not_reachable">配對的設備無法連接</string>
<string name="pair_new_device">配對新設備</string>
<string name="unknown_device">不明的設備</string>
<string name="error_not_reachable">設備無法連接</string>
<string name="error_already_requested">已請求配對</string>
<string name="error_already_paired">裝置已經配對</string>
<string name="error_could_not_send_package">無法傳送封包</string>
<string name="error_timed_out">逾時</string>
<string name="error_canceled_by_user">使用者中斷</string>
<string name="error_canceled_by_other_peer">被其他同等功能應用中斷</string>
<string name="error_invalid_key">接收的密鑰無效</string>
<string name="encryption_info_title">加密資訊</string>
<string name="encryption_info_msg_no_ssl">其他的設備沒有使用新版本的KDE連線使用傳統的加密模式。</string>
<string name="my_device_fingerprint">您設備上的SHA1指紋辨識認證是</string>
<string name="remote_device_fingerprint">您遠端設備上的SHA1指紋辨識認證是</string>
<string name="pair_requested">已請求配對</string>
<string name="pairing_request_from">從 %1s 來的配對請求</string>
<string name="received_url_title">已從 %1s 連線接收</string>
<string name="received_url_text">點擊開啟 \'%1s\'</string>
<string name="incoming_file_title">從 %1s 傳來的檔案</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">正在將檔案發送到 %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="received_file_title">已從 %1s 接收檔案</string>
<string name="received_file_fail_title">從 %1s 接收檔案失敗</string>
<string name="received_file_text">點擊開啟 \'%1s\'</string>
<string name="sent_file_title">將檔案傳送到 %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">點擊即可應答</string>
<string name="reconnect">重新連線</string>
<string name="right_click">傳送右鍵點擊</string>
<string name="middle_click">傳送中鍵點擊</string>
<string name="show_keyboard">顯示鍵盤</string>
<string name="device_not_paired">裝置未配對</string>
<string name="request_pairing">請求配對</string>
<string name="pairing_accept">同意</string>
<string name="pairing_reject">回絕</string>
<string name="device">裝置</string>
<string name="pair_device">配對裝置</string>
<string name="remote_control">遠端控制</string>
<string name="settings">KDE連線設定</string>
<string name="mpris_play">播放</string>
<string name="mpris_previous">往前</string>
<string name="mpris_rew">往後</string>
<string name="mpris_ff">快轉</string>
<string name="mpris_next">下一首</string>
<string name="mpris_volume">音量</string>
<string name="mpris_settings">多媒體設定</string>
<string name="mpris_time_settings_title">往前/往後按鍵</string>
<string name="mpris_time_settings_summary">調整按下時往前/往後的時間。</string>
<string-array name="mpris_time_entries">
<item>10秒鐘</item>
<item>20秒鐘</item>
<item>30秒鐘</item>
<item>1分鐘</item>
<item>2分鐘</item>
</string-array>
<string name="share_to">分享給</string>
<string name="protocol_version_older">這個裝置使用舊版本的通訊協定</string>
<string name="protocol_version_newer">此設備使用較新的通訊協定</string>
<string name="general_settings">通用設定</string>
<string name="plugin_settings">設定</string>
<string name="plugin_settings_with_name">%s 設定</string>
<string name="device_name">設備名稱</string>
<string name="device_name_preference_summary">%s</string>
<string name="invalid_device_name">無效的設備名稱</string>
<string name="shareplugin_text_saved">已接收文字,並且儲存到剪貼簿</string>
<string name="custom_devices_settings">自定義設備列表</string>
<string name="pair_device_action">配對新設備</string>
<string name="unpair_device_action">未配對 %s</string>
<string name="custom_device_list">以IP來新增設備</string>
<string name="share_notification_preference">通知方式</string>
<string name="share_notification_preference_summary">當接收檔案時發出振動以及播放聲音</string>
<string name="title_activity_notification_filter">通知過濾器</string>
<string name="filter_apps_info">將會以您選擇的App應用程式啟用同步通知</string>
<string name="sftp_internal_storage">內部儲存空間</string>
<string name="sftp_all_files">全部檔案</string>
<string name="sftp_sdcard_num">SD卡 %d</string>
<string name="sftp_sdcard">SD卡</string>
<string name="sftp_readonly">(唯讀)</string>
<string name="sftp_camera">相機圖片</string>
<string name="add_host">增加 host/IP</string>
<string name="add_host_hint">Hostname或者IP</string>
<string name="no_players_connected">沒有發現播放器</string>
<string name="custom_dev_list_help">能夠在您的裝置沒有自動偵測到裝置時使用這個選項。輸入IP位址或者是Hostname在下面並且按下按鈕來增加進入列表當中。觸碰以從列表中刪除現有項目。</string>
<string name="mpris_player_on_device">%1$s on %2$s</string>
<string name="send_files">傳送檔案</string>
<string name="pairing_title">KDE連線裝置</string>
<string name="pairing_description">在您相同網域當中有其他有執行KDE連線的裝置會出現在這裡。</string>
<string name="device_paired">裝置已配對</string>
<string name="device_rename_title">更改裝置名稱</string>
<string name="device_rename_confirm">更改名稱</string>
<string name="refresh">刷新</string>
<string name="unreachable_description">此配對的裝置無法連接。 請確保它連接到與您相同的網域。</string>
<string name="no_file_browser">沒有安裝此檔案的瀏覽程式</string>
<string name="pref_plugin_telepathy">傳送簡訊</string>
<string name="pref_plugin_telepathy_desc">傳送文字簡訊到您的電腦桌面</string>
<string name="plugin_not_supported">這個擴充插件並不支援您的手機</string>
<string name="findmyphone_title">找尋我的手機</string>
<string name="findmyphone_title_tablet">找尋我的平板</string>
<string name="findmyphone_description">讓這個裝置發出聲響讓您能找到它</string>
<string name="findmyphone_found">找到</string>
<string name="open">開啟</string>
<string name="close">關閉</string>
</resources>

View File

@@ -2,4 +2,5 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="key_height">48dip</dimen>
</resources>

View File

@@ -11,6 +11,8 @@
<string name="pref_plugin_clipboard_desc">Share the clipboard content</string>
<string name="pref_plugin_mousepad">Remote input</string>
<string name="pref_plugin_mousepad_desc">Use your phone or tablet as a touchpad and keyboard</string>
<string name="pref_plugin_remotekeyboard">Receive remote keypresses</string>
<string name="pref_plugin_remotekeyboard_desc">Receive keypress events from remote devices</string>
<string name="pref_plugin_mpris">Multimedia controls</string>
<string name="pref_plugin_mpris_desc">Provides a remote control for your media player</string>
<string name="pref_plugin_runcommand">Run Command</string>
@@ -31,6 +33,11 @@
<string name="no_permissions">You need to grant permission to access notifications</string>
<string name="send_ping">Send ping</string>
<string name="open_mpris_controls">Multimedia control</string>
<string name="remotekeyboard_editing_only" translatable="false">remotekeyboard_editing_only</string>
<string name="remotekeyboard_editing_only_title" translatable="true">Handle remote keys only when editing</string>
<string name="remotekeyboard_not_connected" translatable="true">There is no active remote keyboard connection, establish one in kdeconnect</string>
<string name="remotekeyboard_connected" translatable="true">Remote keyboard connection is active</string>
<string name="remotekeyboard_multiple_connections" translatable="true">There is more than one remote keyboard connection, select the device to configure</string>
<string name="open_mousepad">Remote input</string>
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
@@ -96,13 +103,15 @@
<string name="incoming_file_title">Incoming file from %1s</string>
<string name="incoming_file_text">%1s</string>
<string name="outgoing_file_title">Sending file to %1s</string>
<string name="outgoing_files_title">Sending files to %1s</string>
<string name="outgoing_file_text">%1s</string>
<string name="outgoing_files_text">Sent %1$d out of %2$d files</string>
<string name="received_file_title">Received file from %1s</string>
<string name="received_file_fail_title">Failed receiving file from %1s</string>
<string name="received_file_text">Tap to open \'%1s\'</string>
<string name="sent_file_title">Sent file to %1s</string>
<string name="sent_file_text">%1s</string>
<string name="sent_file_failed_title">Failed to send file %1s</string>
<string name="sent_file_failed_title">Failed to send file to %1s</string>
<string name="sent_file_failed_text">%1s</string>
<string name="tap_to_answer">Tap to answer</string>
<string name="reconnect">Reconnect</string>
@@ -158,6 +167,10 @@
<string name="custom_device_list">Add devices by IP</string>
<string name="share_notification_preference">Noisy notifications</string>
<string name="share_notification_preference_summary">Vibrate and play a sound when receiving a file</string>
<string name="share_destination_customize">Customize destination directory</string>
<string name="share_destination_customize_summary_disabled">Received files will appear in Downloads</string>
<string name="share_destination_customize_summary_enabled">Files will be stored in the directory below</string>
<string name="share_destination_folder_preference">Destination directory</string>
<string name="title_activity_notification_filter">Notification filter</string>
<string name="filter_apps_info">Notifications will be synchronized for the selected apps.</string>
<string name="sftp_internal_storage">Internal storage</string>
@@ -191,4 +204,5 @@
<string name="open">Open</string>
<string name="close">Close</string>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Keyboard
xmlns:android="http://schemas.android.com/apk/res/android"
android:keyHeight="@dimen/key_height"
android:horizontalGap="0px"
android:verticalGap="0px" >
<Row android:rowEdgeFlags="bottom">
<Key android:keyIcon="@drawable/ic_keyboard_hide_white_36dp" android:codes="0" android:keyWidth="20%" />
<Key android:keyIcon="@drawable/ic_action_settings" android:codes="1" android:keyWidth="40%"/>
<Key android:keyIcon="@drawable/ic_action_keyboard" android:codes="2" android:keyWidth="40%"/>
<Key android:keyIcon="@drawable/ic_phonelink_white_36dp" android:codes="3" android:keyWidth="20%" />-->
</Row>
</Keyboard>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:supportsSwitchingToNextInputMethod="true">
</input-method>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBoxPreference
android:id="@+id/remotekeyboard_editing_only"
android:key="@string/remotekeyboard_editing_only"
android:title="@string/remotekeyboard_editing_only_title"
android:defaultValue="true" />
</PreferenceScreen>

View File

@@ -3,6 +3,19 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBoxPreference
android:id="@+id/share_destination_customize"
android:key="share_destination_custom"
android:title="@string/share_destination_customize"
android:summaryOff="@string/share_destination_customize_summary_disabled"
android:summaryOn="@string/share_destination_customize_summary_enabled"
android:defaultValue="false" />
<Preference
android:id="@+id/share_destination_folder_preference"
android:key="share_destination_folder_preference"
android:title="@string/share_destination_folder_preference" />
<CheckBoxPreference
android:id="@+id/share_notification_preference"
android:key="share_notification_preference"

View File

@@ -89,7 +89,7 @@ public abstract class BaseLink {
}
//TO OVERRIDE, should be sync
public abstract void sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback);
public abstract boolean sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback);
@Deprecated
public abstract void sendPackageEncrypted(NetworkPackage np,Device.SendPackageStatusCallback callback, PublicKey key);
public abstract boolean sendPackageEncrypted(NetworkPackage np,Device.SendPackageStatusCallback callback, PublicKey key);
}

View File

@@ -23,8 +23,6 @@ package org.kde.kdeconnect.Backends;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.NetworkPackage;
import java.util.Timer;
/**
* This class separates the pairing interface for each type of link.
* Since different links can pair via different methods, like for LanLink certificate and public key should be shared,

View File

@@ -61,7 +61,7 @@ public class LanLink extends BaseLink {
// because it's probably trying to find me and
// potentially ask for pairing.
private Socket socket = null;
private volatile Socket socket = null;
private LinkDisconnectedCallback callback;
@@ -142,11 +142,11 @@ public class LanLink extends BaseLink {
}
//Blocking, do not call from main thread
private void sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) {
private boolean sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) {
if (socket == null) {
Log.e("KDE/sendPackage", "Not yet connected");
callback.sendFailure(new NotYetConnectedException());
return;
callback.onFailure(new NotYetConnectedException());
return false;
}
try {
@@ -171,14 +171,12 @@ public class LanLink extends BaseLink {
//Send body of the network package
try {
OutputStream writter = socket.getOutputStream();
writter.write(np.serialize().getBytes(StringsHelper.UTF8));
writter.flush();
OutputStream writer = socket.getOutputStream();
writer.write(np.serialize().getBytes(StringsHelper.UTF8));
writer.flush();
} catch (Exception e) {
callback.sendFailure(e);
e.printStackTrace();
disconnect();
return;
disconnect(); //main socket is broken, disconnect
throw e;
}
//Send payload
@@ -203,23 +201,24 @@ public class LanLink extends BaseLink {
Log.i("KDE/LanLink", "Beginning to send payload");
byte[] buffer = new byte[4096];
int bytesRead;
long size = np.getPayloadSize();
long progress = 0;
long timeSinceLastUpdate = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
//Log.e("ok",""+bytesRead);
progress += bytesRead;
outputStream.write(buffer, 0, bytesRead);
if (np.getPayloadSize() > 0) {
callback.sendProgress((int)(progress / np.getPayloadSize()));
if (size > 0) {
if (timeSinceLastUpdate + 500 < System.currentTimeMillis()) { //Report progress every half a second
long percent = ((100 * progress) / size);
callback.onProgressChanged((int) percent);
timeSinceLastUpdate = System.currentTimeMillis();
}
}
}
outputStream.flush();
outputStream.close();
Log.i("KDE/LanLink", "Finished sending payload ("+progress+" bytes written)");
} catch (Exception e) {
e.printStackTrace();
Log.e("KDE/sendPackage", "Exception: "+e);
callback.sendFailure(e);
return;
} finally {
try { server.close(); } catch (Exception e) { }
try { payloadSocket.close(); } catch (Exception e) { }
@@ -228,12 +227,13 @@ public class LanLink extends BaseLink {
}
}
callback.sendSuccess();
callback.onSuccess();
return true;
} catch (Exception e) {
if (callback != null) {
callback.sendFailure(e);
callback.onFailure(e);
}
return false;
} finally {
//Make sure we close the payload stream, if any
InputStream stream = np.getPayload();
@@ -244,14 +244,14 @@ public class LanLink extends BaseLink {
//Blocking, do not call from main thread
@Override
public void sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback) {
sendPackageInternal(np, callback, null);
public boolean sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback) {
return sendPackageInternal(np, callback, null);
}
//Blocking, do not call from main thread
@Override
public void sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
sendPackageInternal(np, callback, key);
public boolean sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
return sendPackageInternal(np, callback, key);
}
private void receivedNetworkPackage(NetworkPackage np) {

View File

@@ -198,6 +198,20 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
boolean isDeviceTrusted = preferences.getBoolean(deviceId, false);
if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
//Device paired with and old version, we can't use it as we lack the certificate
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
if (device == null) return;
device.unpair();
//Retry as unpaired
identityPackageReceived(identityPackage, socket, connectionStarted);
}
});
}
Log.i("KDE/LanLinkProvider","Starting SSL handshake with " + identityPackage.getString("deviceName") + " trusted:"+isDeviceTrusted);
final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
@@ -233,14 +247,11 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
} catch (Exception e) {
Log.e("KDE/LanLinkProvider","Handshake failed with " + identityPackage.getString("deviceName"));
e.printStackTrace();
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(deviceId);
if (device == null) return;
device.unpair();
}
});
//String[] ciphers = sslsocket.getSupportedCipherSuites();
//for (String cipher : ciphers) {
// Log.i("SupportedCiphers","cipher: " + cipher);
//}
}
}
}).start();

View File

@@ -39,7 +39,7 @@ import java.util.TimerTask;
public class LanPairingHandler extends BasePairingHandler {
private Timer mPairingTimer;
Timer mPairingTimer;
public LanPairingHandler(Device device, final PairingHandlerCallback callback) {
super(device, callback);
@@ -142,7 +142,7 @@ public class LanPairingHandler extends BasePairingHandler {
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
@Override
protected void onSuccess() {
public void onSuccess() {
hidePairingNotification(); //Will stop the pairingTimer if it was running
mPairingTimer = new Timer();
mPairingTimer.schedule(new TimerTask() {
@@ -157,14 +157,19 @@ public class LanPairingHandler extends BasePairingHandler {
}
@Override
protected void onFailure(Throwable e) {
public void onFailure(Throwable e) {
if (e != null) {
e.printStackTrace();
} else {
Log.e("LanPairing/onFailure", "Unknown (null) exception");
}
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_could_not_send_package));
}
};
mDevice.sendPackage(createPairPackage(), statusCallback);
}
public void hidePairingNotification() {
void hidePairingNotification() {
mDevice.hidePairingNotification();
if (mPairingTimer != null) {
mPairingTimer .cancel();
@@ -176,12 +181,17 @@ public class LanPairingHandler extends BasePairingHandler {
hidePairingNotification();
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
@Override
protected void onSuccess() {
public void onSuccess() {
pairingDone();
}
@Override
protected void onFailure(Throwable e) {
public void onFailure(Throwable e) {
if (e != null) {
e.printStackTrace();
} else {
Log.e("LanPairing/onFailure", "Unknown (null) exception");
}
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_not_reachable));
}
};
@@ -197,7 +207,7 @@ public class LanPairingHandler extends BasePairingHandler {
mDevice.sendPackage(np);
}
public void pairingDone() {
void pairingDone() {
// Store device information needed to create a Device object in a future
//Log.e("KDE/PairingDone", "Pairing Done");
SharedPreferences.Editor editor = mDevice.getContext().getSharedPreferences(mDevice.getDeviceId(), Context.MODE_PRIVATE).edit();

View File

@@ -47,18 +47,19 @@ public class LoopbackLink extends BaseLink {
}
@Override
public void sendPackage(NetworkPackage in, Device.SendPackageStatusCallback callback) {
public boolean sendPackage(NetworkPackage in, Device.SendPackageStatusCallback callback) {
packageReceived(in);
if (in.hasPayload()) {
callback.sendProgress(0);
callback.onProgressChanged(0);
in.setPayload(in.getPayload(), in.getPayloadSize());
callback.sendProgress(100);
callback.onProgressChanged(100);
}
callback.sendSuccess();
callback.onSuccess();
return true;
}
@Override
public void sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
sendPackage(np, callback);
public boolean sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
return sendPackage(np, callback);
}
}

View File

@@ -27,7 +27,6 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import org.kde.kdeconnect.Backends.BaseLink;

View File

@@ -37,6 +37,7 @@ import android.util.Log;
import org.kde.kdeconnect.Backends.BaseLink;
import org.kde.kdeconnect.Backends.BasePairingHandler;
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.Plugins.PluginFactory;
@@ -146,6 +147,9 @@ public class Device implements BaseLink.PackageReceiver {
Log.e("KDE/Device","Exception deserializing stored public key for device");
}
//Assume every plugin is supported until addLink is called and we can get the actual list
m_supportedPlugins = new Vector<>(PluginFactory.getAvailablePlugins());
//Do not load plugins yet, the device is not present
//reloadPluginsFromSettings();
}
@@ -284,7 +288,6 @@ public class Device implements BaseLink.PackageReceiver {
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
preferences.edit().remove(deviceId).apply();
// FIXME : We delete all device info here, but the xml file still persists
SharedPreferences devicePreferences = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
devicePreferences.edit().clear().apply();
@@ -365,7 +368,23 @@ public class Device implements BaseLink.PackageReceiver {
Intent intent = new Intent(getContext(), MaterialActivity.class);
intent.putExtra("deviceId", getDeviceId());
intent.putExtra("notificationId", notificationId);
PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Intent acceptIntent = new Intent(getContext(), MaterialActivity.class);
Intent rejectIntent = new Intent(getContext(), MaterialActivity.class);
acceptIntent.putExtra("deviceId", getDeviceId());
acceptIntent.putExtra("notificationId", notificationId);
acceptIntent.setAction("action "+System.currentTimeMillis());
acceptIntent.putExtra(MaterialActivity.PAIR_REQUEST_STATUS, MaterialActivity.PAIRING_ACCEPTED);
rejectIntent.putExtra("deviceId", getDeviceId());
rejectIntent.putExtra("notificationId", notificationId);
rejectIntent.setAction("action "+System.currentTimeMillis());
rejectIntent.putExtra(MaterialActivity.PAIR_REQUEST_STATUS, MaterialActivity.PAIRING_REJECTED);
PendingIntent acceptedPendingIntent = PendingIntent.getActivity(getContext(), 2, acceptIntent, PendingIntent.FLAG_ONE_SHOT);
PendingIntent rejectedPendingIntent = PendingIntent.getActivity(getContext(), 4, rejectIntent, PendingIntent.FLAG_ONE_SHOT);
Resources res = getContext().getResources();
@@ -375,19 +394,16 @@ public class Device implements BaseLink.PackageReceiver {
.setContentIntent(pendingIntent)
.setTicker(res.getString(R.string.pair_requested))
.setSmallIcon(R.drawable.ic_notification)
.addAction(R.drawable.ic_accept_pairing, res.getString(R.string.pairing_accept), acceptedPendingIntent)
.addAction(R.drawable.ic_reject_pairing, res.getString(R.string.pairing_reject), rejectedPendingIntent)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.build();
final NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationHelper.notifyCompat(notificationManager, notificationId, noti);
try {
BackgroundService.addGuiInUseCounter(context);
notificationManager.notify(notificationId, noti);
} catch(Exception e) {
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
}
BackgroundService.addGuiInUseCounter(context);
}
public void hidePairingNotification() {
@@ -580,42 +596,43 @@ public class Device implements BaseLink.PackageReceiver {
}
public static abstract class SendPackageStatusCallback {
protected abstract void onSuccess();
protected abstract void onFailure(Throwable e);
protected void onProgressChanged(int percent) { }
public abstract void onSuccess();
public abstract void onFailure(Throwable e);
public void onProgressChanged(int percent) { }
}
private boolean success = false;
public void sendSuccess() {
success = true;
onSuccess();
}
public void sendFailure(Throwable e) {
private SendPackageStatusCallback defaultCallback = new SendPackageStatusCallback() {
@Override
public void onSuccess() { }
@Override
public void onFailure(Throwable e) {
if (e != null) {
e.printStackTrace();
Log.e("KDE/sendPackage", "Exception: " + e.getMessage());
} else {
Log.e("KDE/sendPackage", "Unknown (null) exception");
}
onFailure(e);
}
public void sendProgress(int percent) { onProgressChanged(percent); }
}
};
public void sendPackage(NetworkPackage np) {
sendPackage(np,new SendPackageStatusCallback() {
@Override
protected void onSuccess() { }
@Override
protected void onFailure(Throwable e) { }
});
sendPackage(np, defaultCallback);
}
public boolean sendPackageBlocking(NetworkPackage np) {
return sendPackageBlocking(np, defaultCallback);
}
//Async
public void sendPackage(final NetworkPackage np, final SendPackageStatusCallback callback) {
new Thread(new Runnable() {
@Override
public void run() {
sendPackageBlocking(np, callback);
}
}).start();
}
hackToMakeRetrocompatiblePacketTypes(np);
public boolean sendPackageBlocking(final NetworkPackage np, final SendPackageStatusCallback callback) {
/*
if (!m_outgoingCapabilities.contains(np.getType()) && !NetworkPackage.protocolPackageTypes.contains(np.getType())) {
@@ -624,37 +641,29 @@ public class Device implements BaseLink.PackageReceiver {
}
*/
//Log.e("sendPackage", "Sending package...");
//Log.e("sendPackage", np.serialize());
hackToMakeRetrocompatiblePacketTypes(np);
final Throwable backtrace = new Throwable();
new Thread(new Runnable() {
@Override
public void run() {
boolean useEncryption = (protocolVersion < LanLinkProvider.MIN_VERSION_WITH_SSL_SUPPORT && (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired()));
//Make a copy to avoid concurrent modification exception if the original list changes
for (final BaseLink link : links) {
if (link == null) continue; //Since we made a copy, maybe somebody destroyed the link in the meanwhile
if (useEncryption) {
link.sendPackageEncrypted(np, callback, publicKey);
} else {
link.sendPackage(np, callback);
}
if (callback.success) break; //If the link didn't call sendSuccess(), try the next one
}
if (!callback.success) {
Log.e("KDE/sendPackage", "No device link (of "+links.size()+" available) could send the package. Package "+np.getType()+" to " + name + " lost!");
backtrace.printStackTrace();
}
boolean useEncryption = (protocolVersion < LanLinkProvider.MIN_VERSION_WITH_SSL_SUPPORT && (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired()));
boolean success = false;
//Make a copy to avoid concurrent modification exception if the original list changes
for (final BaseLink link : links) {
if (link == null) continue; //Since we made a copy, maybe somebody destroyed the link in the meanwhile
if (useEncryption) {
success = link.sendPackageEncrypted(np, callback, publicKey);
} else {
success = link.sendPackage(np, callback);
}
}).start();
if (success) break; //If the link didn't call sendSuccess(), try the next one
}
if (!success) {
Log.e("KDE/sendPackage", "No device link (of "+links.size()+" available) could send the package. Package "+np.getType()+" to " + name + " lost!");
}
return success;
}
//
// Plugin-related functions
//

View File

@@ -450,13 +450,17 @@ public class DeviceHelper {
public static String getAndroidDeviceName() {
String deviceName = null;
try {
String dictName = humanReadableNames.get(Build.MODEL.replace(' ', '_'));
String internalName = Build.MODEL.replace(' ', '_');
String dictName = humanReadableNames.get(internalName);
if (dictName != null) {
deviceName = dictName;
} else if (Build.BRAND.equalsIgnoreCase("samsung")) {
deviceName = "Samsung " + Build.MODEL;
} else {
deviceName = Build.BRAND;
Log.w("getAndroidDeviceName", "Not found human readable name for device '" + internalName + "'");
if (Build.BRAND.equalsIgnoreCase("samsung")) {
deviceName = "Samsung " + Build.MODEL;
} else {
deviceName = Build.BRAND;
}
}
} catch (Exception e) {
//Some phones might not define BRAND or MODEL, ignore exceptions

View File

@@ -27,17 +27,35 @@ import java.io.File;
public class FilesHelper {
public static String getFileExt(String fileName) {
//return MimeTypeMap.getFileExtensionFromUrl(fileName);
return fileName.substring((fileName.lastIndexOf(".") + 1), fileName.length());
public static String getFileExt(String filename) {
//return MimeTypeMap.getFileExtensionFromUrl(filename);
return filename.substring((filename.lastIndexOf(".") + 1));
}
public static String getFileNameWithoutExt(String filename) {
int dot = filename.lastIndexOf(".");
return (dot < 0)? filename : filename.substring(0, dot);
}
public static String getMimeTypeFromFile(String file) {
String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileExt(file));
if (mime == null) mime = "*/*";
return mime;
}
public static String findNonExistingNameForNewFile(String path, String filename) {
int dot = filename.lastIndexOf(".");
String name = (dot < 0)? filename : filename.substring(0, dot);
String ext = (dot < 0)? "" : filename.substring(filename.lastIndexOf("."));
int num = 1;
while (new File(path+"/"+filename).exists()) {
filename = name+" ("+num+")"+ext;
num++;
}
return filename;
}
//Following code from http://activemq.apache.org/maven/5.7.0/kahadb/apidocs/src-html/org/apache/kahadb/util/IOHelper.html
/**
* Converts any string into a string that is safe to use as a file name.

View File

@@ -0,0 +1,17 @@
package org.kde.kdeconnect.Helpers;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
public class MediaStoreHelper {
//Maybe this class could batch successive calls together
public static void indexFile(Context context, Uri path) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(path);
context.sendBroadcast(mediaScanIntent);
}
}

View File

@@ -0,0 +1,25 @@
package org.kde.kdeconnect.Helpers;
import android.app.Notification;
import android.app.NotificationManager;
public class NotificationHelper {
public static void notifyCompat(NotificationManager notificationManager, int notificationId, Notification notification) {
try {
notificationManager.notify(notificationId, notification);
} catch(Exception e) {
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
}
}
public static void notifyCompat(NotificationManager notificationManager, String tag, int notificationId, Notification notification) {
try {
notificationManager.notify(tag, notificationId, notification);
} catch(Exception e) {
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
}
}
}

View File

@@ -131,6 +131,12 @@ public class SslHelper {
}
}
public static boolean isCertificateStored(Context context, String deviceId) {
SharedPreferences devicePreferences = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
String cert = devicePreferences.getString("certificate", "");
return !cert.isEmpty();
}
public static SSLContext getSslContext(Context context, String deviceId, boolean isDeviceTrusted) {
//TODO: Cache
try {
@@ -203,13 +209,17 @@ public class SslHelper {
// These cipher suites are most common of them that are accepted by kde and android during handshake
ArrayList<String> supportedCiphers = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
supportedCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"); // API 20+
supportedCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); // API 20+
supportedCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); // API 11+
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
supportedCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); // API 11+
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA"); // API 9+
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5"); // API 9+
} else {
// Following ciphers are for and due to old devices
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA");
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5");
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA"); // API 9+
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5"); // API 9+
}
socket.setEnabledCipherSuites(supportedCiphers.toArray(new String[supportedCiphers.size()]));

View File

@@ -6,4 +6,11 @@ public class StringsHelper {
public static final Charset UTF8 = Charset.forName("UTF-8");
public static int compare(String a, String b) {
if (a == b) return 0;
if (a == null) return -1;
if (b == null) return 1;
return a.compareToIgnoreCase(b);
}
}

View File

@@ -28,12 +28,15 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.NetworkPackage;
import java.util.HashSet;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class ClipboardListener {
public interface ClipboardObserver {
void clipboardChanged(String content);
}
private HashSet<ClipboardObserver> observers = new HashSet<>();
private final Context context;
private String currentContent;
@@ -41,9 +44,26 @@ public class ClipboardListener {
private ClipboardManager cm = null;
private ClipboardManager.OnPrimaryClipChangedListener listener;
ClipboardListener(final Context ctx, final Device device) {
private static ClipboardListener _instance = null;
public static ClipboardListener instance(Context context) {
if (_instance == null) {
_instance = new ClipboardListener(context);
}
return _instance;
}
public void registerObserver(ClipboardObserver observer) {
observers.add(observer);
}
public void removeObserver(ClipboardObserver observer) {
observers.remove(observer);
}
ClipboardListener(final Context ctx) {
context = ctx;
if(android.os.Build.VERSION.SDK_INT < 11) {
if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return;
}
@@ -59,11 +79,14 @@ public class ClipboardListener {
ClipData.Item item = cm.getPrimaryClip().getItemAt(0);
String content = item.coerceToText(context).toString();
if (!content.equals(currentContent)) {
NetworkPackage np = new NetworkPackage(ClipboardPlugin.PACKAGE_TYPE_CLIPBOARD);
np.set("content", content);
device.sendPackage(np);
currentContent = content;
if (content.equals(currentContent)) {
return;
}
currentContent = content;
for (ClipboardObserver observer : observers) {
observer.clipboardChanged(content);
}
} catch (Exception e) {
@@ -76,18 +99,10 @@ public class ClipboardListener {
});
}
public void stop() {
if(android.os.Build.VERSION.SDK_INT < 11) {
return;
}
cm.removePrimaryClipChangedListener(listener);
}
@SuppressWarnings("deprecation")
public void setText(String text) {
currentContent = text;
if(android.os.Build.VERSION.SDK_INT < 11) {
if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(text);
}

View File

@@ -20,6 +20,8 @@
package org.kde.kdeconnect.Plugins.ClibpoardPlugin;
import android.os.Build;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect_tp.R;
@@ -41,28 +43,34 @@ public class ClipboardPlugin extends Plugin {
@Override
public boolean isEnabledByDefault() {
//Disabled by default due to just one direction sync(incoming clipboard change) in early version of android.
return (android.os.Build.VERSION.SDK_INT >= 11);
return (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB);
}
private ClipboardListener listener;
@Override
public boolean onPackageReceived(NetworkPackage np) {
String content = np.getString("content");
ClipboardListener.instance(context).setText(content);
return true;
}
private ClipboardListener.ClipboardObserver observer = new ClipboardListener.ClipboardObserver() {
@Override
public void clipboardChanged(String content) {
NetworkPackage np = new NetworkPackage(ClipboardPlugin.PACKAGE_TYPE_CLIPBOARD);
np.set("content", content);
device.sendPackage(np);
}
};
@Override
public boolean onCreate() {
listener = new ClipboardListener(context, device);
ClipboardListener.instance(context).registerObserver(observer);
return true;
}
@Override
public void onDestroy() {
listener.stop();
}
@Override
public boolean onPackageReceived(NetworkPackage np) {
String content = np.getString("content");
listener.setText(content);
return true;
ClipboardListener.instance(context).removeObserver(observer);
}
@Override

View File

@@ -1,12 +1,14 @@
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
import android.app.Activity;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@@ -16,6 +18,17 @@ import org.kde.kdeconnect_tp.R;
public class FindMyPhoneActivity extends Activity {
Ringtone ringtone;
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(ringtone != null) {
// If this activity was already open and we received the ring packet again, just finish it
finish();
}
// otherwise the activity will become active again
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -26,8 +39,28 @@ public class FindMyPhoneActivity extends Activity {
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
@Override
protected void onStart() {
super.onStart();
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
if (ringtone == null) {
ringtoneUri = RingtoneManager.getValidRingtoneUri(getApplicationContext());
if (ringtoneUri == null) {
Log.e("FindMyPhone", "Could not find a ringtone to play!");
return;
}
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
}
if (android.os.Build.VERSION.SDK_INT >= 21) {
AudioAttributes.Builder b = new AudioAttributes.Builder();
@@ -38,18 +71,16 @@ public class FindMyPhoneActivity extends Activity {
}
ringtone.play();
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
@Override
public void finish() {
ringtone.stop();
super.finish();
protected void onStop() {
super.onStop();
if(ringtone != null) {
ringtone.stop();
ringtone = null;
}
}
}

View File

@@ -21,7 +21,6 @@
package org.kde.kdeconnect.Plugins.MprisPlugin;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -34,7 +33,6 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
@@ -95,22 +93,16 @@ public class MprisActivity extends ActionBarActivity {
TextView nowPlaying = (TextView) findViewById(R.id.now_playing_textview);
if (!nowPlaying.getText().toString().equals(song)) {
nowPlaying.setText(song);
Bitmap currentArt = mpris.getCurrentArt();
ImageView artView = (ImageView) findViewById(R.id.artImageView);
if (currentArt != null) {
artView.setImageBitmap(currentArt);
}
}
if (mpris.getLength() > -1 && mpris.getPosition() > -1 && !"spotify".equals(mpris.getPlayer().toLowerCase())) {
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(mpris.getLength()));
//Hacks for Spotify because it reports incorrect info about what it supports
boolean isSpotify = "spotify".equals(mpris.getPlayer().toLowerCase());
if (mpris.getLength() > -1 && mpris.getPosition() > -1 && !isSpotify) {
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(mpris.getLength()));
SeekBar positionSeek = (SeekBar)findViewById(R.id.positionSeek);
positionSeek.setMax((int)(mpris.getLength()));
positionSeek.setProgress((int)(mpris.getPosition()));
findViewById(R.id.progress_slider).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.progress_slider).setVisibility(View.GONE);
@@ -122,9 +114,23 @@ public class MprisActivity extends ActionBarActivity {
boolean isPlaying = mpris.isPlaying();
if (isPlaying) {
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_pause);
findViewById(R.id.play_button).setVisibility(mpris.isPauseAllowed() ? View.VISIBLE : View.GONE);
} else {
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_play);
findViewById(R.id.play_button).setVisibility(mpris.isPlayAllowed() ? View.VISIBLE : View.GONE);
}
if (isSpotify) {
findViewById(R.id.volume_layout).setVisibility(View.INVISIBLE);
findViewById(R.id.rew_button).setVisibility(View.GONE);
findViewById(R.id.ff_button).setVisibility(View.GONE);
} else {
findViewById(R.id.volume_layout).setVisibility(View.VISIBLE);
findViewById(R.id.rew_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
findViewById(R.id.ff_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
}
findViewById(R.id.next_button).setVisibility(mpris.isGoNextAllowed() ? View.VISIBLE : View.GONE);
findViewById(R.id.prev_button).setVisibility(mpris.isGoPreviousAllowed() ? View.VISIBLE : View.GONE);
}
});
}
@@ -162,23 +168,16 @@ public class MprisActivity extends ActionBarActivity {
if (pos >= playerList.size()) return;
((TextView) findViewById(R.id.now_playing_textview)).setText("");
String player = playerList.get(pos);
mpris.setPlayer(player);
//Spotify doesn't support changing the volume yet...
//Also doesn't support seeking and telling actual position...
if (player.toLowerCase().equals("spotify")) {
findViewById(R.id.volume_layout).setVisibility(View.INVISIBLE);
findViewById(R.id.rew_button).setVisibility(View.GONE);
findViewById(R.id.ff_button).setVisibility(View.GONE);
findViewById(R.id.positionSeek).setVisibility(View.INVISIBLE);
findViewById(R.id.progress_slider).setVisibility(View.GONE);
} else {
findViewById(R.id.volume_layout).setVisibility(View.VISIBLE);
findViewById(R.id.rew_button).setVisibility(View.VISIBLE);
findViewById(R.id.ff_button).setVisibility(View.VISIBLE);
findViewById(R.id.positionSeek).setVisibility(View.VISIBLE);
if (player.equals(mpris.getPlayer())) {
return; //Player hasn't actually changed
}
mpris.setPlayer(player);
//Clear values from previous player
((TextView) findViewById(R.id.now_playing_textview)).setText("");
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(0));
((SeekBar)findViewById(R.id.positionSeek)).setMax(0);
}
@Override

View File

@@ -22,13 +22,10 @@ package org.kde.kdeconnect.Plugins.MprisPlugin;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.support.v4.content.ContextCompat;
import android.util.Base64;
import android.util.Log;
import org.kde.kdeconnect.NetworkPackage;
@@ -47,11 +44,15 @@ public class MprisPlugin extends Plugin {
private String player = "";
private boolean playing = false;
private String currentSong = "";
private Bitmap currentArt;
private int volume = 50;
private long length = -1;
private long lastPosition;
private long lastPositionTime;
private boolean playAllowed = true;
private boolean pauseAllowed = true;
private boolean goNextAllowed = true;
private boolean goPreviousAllowed = true;
private boolean seekAllowed = true;
private HashMap<String,Handler> playerStatusUpdated = new HashMap<>();
private List<String> playerList = new ArrayList<>();
@@ -125,8 +126,7 @@ public class MprisPlugin extends Plugin {
@Override
public boolean onPackageReceived(NetworkPackage np) {
if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") ||
np.has("pos") || np.has("artImage")) {
if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") || np.has("pos")) {
if (np.getString("player").equals(player)) {
currentSong = np.getString("nowPlaying", currentSong);
volume = np.getInt("volume", volume);
@@ -135,12 +135,12 @@ public class MprisPlugin extends Plugin {
lastPosition = np.getLong("pos", lastPosition);
lastPositionTime = System.currentTimeMillis();
}
if (np.has("artImage")) {
String base64Image = np.getString("artImage");
byte[] decodedBytes = Base64.decode(base64Image, 0);
currentArt = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
}
playing = np.getBoolean("isPlaying", playing);
playAllowed = np.getBoolean("canPlay", playAllowed);
pauseAllowed = np.getBoolean("canPause", pauseAllowed);
goNextAllowed = np.getBoolean("canGoNext", goNextAllowed);
goPreviousAllowed = np.getBoolean("canGoPrevious", goPreviousAllowed);
seekAllowed = np.getBoolean("canSeek", seekAllowed);
for (String key : playerStatusUpdated.keySet()) {
try {
playerStatusUpdated.get(key).dispatchMessage(new Message());
@@ -218,9 +218,13 @@ public class MprisPlugin extends Plugin {
if (player == null || player.equals(this.player)) return;
this.player = player;
currentSong = "";
currentArt = null;
volume = 50;
playing = false;
playAllowed = true;
pauseAllowed = true;
goNextAllowed = true;
goPreviousAllowed = true;
seekAllowed = true;
for (String key : playerStatusUpdated.keySet()) {
try {
playerStatusUpdated.get(key).dispatchMessage(new Message());
@@ -241,8 +245,6 @@ public class MprisPlugin extends Plugin {
return currentSong;
}
public Bitmap getCurrentArt() { return currentArt; }
public String getPlayer() {
return player;
}
@@ -257,6 +259,26 @@ public class MprisPlugin extends Plugin {
return playing;
}
public boolean isPlayAllowed() {
return playAllowed;
}
public boolean isPauseAllowed() {
return pauseAllowed;
}
public boolean isGoNextAllowed() {
return goNextAllowed;
}
public boolean isGoPreviousAllowed() {
return goPreviousAllowed;
}
public boolean isSeekAllowed() {
return seekAllowed;
}
public long getPosition(){
if(playing) {
return lastPosition + (System.currentTimeMillis() - lastPositionTime);

View File

@@ -26,26 +26,32 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.HashSet;
public class AppDatabase {
public static final String KEY_ROW_ID = "id";
public static final String KEY_NAME = "app";
public static final String KEY_PACKAGE_NAME = "packageName";
public static final String KEY_IS_ENABLED = "isEnabled";
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
}
private static final String DATABASE_NAME = "Applications";
private static final String DATABASE_TABLE = "Applications";
private static final int DATABASE_VERSION = 1;
static final String KEY_PACKAGE_NAME = "packageName";
static final String KEY_IS_ENABLED = "isEnabled";
private final Context ourContext;
private SQLiteDatabase ourDatabase;
private DbHelper ourHelper;
static final String DATABASE_NAME = "Applications";
static final String DATABASE_TABLE = "Applications";
static final int DATABASE_VERSION = 2;
final Context ourContext;
SQLiteDatabase ourDatabase;
DbHelper ourHelper;
public AppDatabase(Context c) {
ourContext = c;
}
private static class DbHelper extends SQLiteOpenHelper{
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -53,73 +59,57 @@ public class AppDatabase {
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DATABASE_TABLE + "(" + KEY_ROW_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ KEY_NAME + " TEXT NOT NULL, " + KEY_PACKAGE_NAME + " TEXT NOT NULL, " + KEY_IS_ENABLED + " TEXT NOT NULL); ");
db.execSQL("CREATE TABLE " + DATABASE_TABLE + "(" + KEY_PACKAGE_NAME + " TEXT PRIMARY KEY NOT NULL, " + KEY_IS_ENABLED + " TEXT NOT NULL); ");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i2) {
db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE);
onCreate(db);
}
}
public void open(){
public void open() {
ourHelper = new DbHelper(ourContext);
ourDatabase = ourHelper.getWritableDatabase();
}
public void close(){
public void close() {
ourHelper.close();
}
public Cursor getAllApplications()
{
String[] columns = new String []{KEY_ROW_ID,KEY_NAME,KEY_PACKAGE_NAME,KEY_IS_ENABLED};
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,null,null,null,null,KEY_NAME);
return res;
}
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);
public long create(String appName, String packageName, boolean isEnabled) {
ContentValues cv = new ContentValues();
cv.put(KEY_NAME, appName);
cv.put(KEY_PACKAGE_NAME, packageName);
cv.put(KEY_IS_ENABLED, isEnabled?"true":"false");
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}
public long update(String packageName, boolean isEnabled) {
ContentValues cvUpdate = new ContentValues();
cvUpdate.put(KEY_IS_ENABLED, isEnabled?"true":"false");
return ourDatabase.update(DATABASE_TABLE,cvUpdate,KEY_PACKAGE_NAME + "=?",new String[]{packageName});
}
public boolean exists(String packageName) {
String[] columns = new String []{KEY_ROW_ID};
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
int count = res.getCount();
if (res.getCount() > 0) {
ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?",new String[]{packageName});
} else {
cv.put(KEY_PACKAGE_NAME, packageName);
ourDatabase.insert(DATABASE_TABLE, null, cv);
}
res.close();
return (count != 0);
}
public boolean isEnabled(String packageName){
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 result = true; //Apps are enabled by default
boolean result;
if (res.getCount() > 0) {
res.moveToFirst();
result = (res.getString(res.getColumnIndex(KEY_IS_ENABLED))).equals("true");
} else {
result = getDefaultStatus(packageName);
}
res.close();
return result;
}
public void delete(String packageName){
ourDatabase.delete(DATABASE_TABLE,KEY_PACKAGE_NAME + " =? ",new String[]{packageName} );
private boolean getDefaultStatus(String packageName) {
return !disabledByDefault.contains(packageName);
}
}

View File

@@ -22,142 +22,144 @@ package org.kde.kdeconnect.Plugins.NotificationsPlugin;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.content.res.Resources;
import android.graphics.Bitmap;
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.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.CheckedTextView;
import android.widget.ListView;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Helpers.StringsHelper;
import org.kde.kdeconnect_tp.R;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class NotificationFilterActivity extends ActionBarActivity {
private AppDatabase appDatabase;
AppDatabase appDatabase;
static class AppListInfo {
String pkg;
String name;
Drawable icon;
boolean isEnabled;
}
AppListInfo[] apps;
class AppListAdapter extends BaseAdapter {
@Override
public int getCount() {
return apps.length;
}
@Override
public AppListInfo getItem(int position) {
return apps[position];
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = getLayoutInflater();
view = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null, true);
}
CheckedTextView checkedTextView = (CheckedTextView)view;
checkedTextView.setText(apps[position].name);
checkedTextView.setCompoundDrawablesWithIntrinsicBounds(apps[position].icon, null, null, null);
checkedTextView.setCompoundDrawablePadding((int)(8*getResources().getDisplayMetrics().density));
return view;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification_filter);
final ListView listView = (ListView)findViewById(R.id.lvFilterApps);
appDatabase = new AppDatabase(this);
appDatabase = new AppDatabase(NotificationFilterActivity.this);
deleteUninstalledApps();
addNewlyInstalledApps();
new Thread(new Runnable() {
@Override
public void run() {
appDatabase.open();
Cursor res = appDatabase.getAllApplications();
res.moveToFirst();
PackageManager packageManager = getPackageManager();
List<ApplicationInfo> appList = packageManager.getInstalledApplications(0);
int count = appList.size();
String[] appName = new String[res.getCount()];
final String[] pkgName = new String[res.getCount()];
Boolean[] isFiltered = new Boolean[res.getCount()];
apps = new AppListInfo[count];
appDatabase.open();
for (int i = 0; i < count; i++) {
ApplicationInfo appInfo = appList.get(i);
apps[i] = new AppListInfo();
apps[i].pkg = appInfo.packageName;
apps[i].name = appInfo.loadLabel(packageManager).toString();
apps[i].icon = resizeIcon(appInfo.loadIcon(packageManager), 48);
apps[i].isEnabled = appDatabase.isEnabled(appInfo.packageName);
}
appDatabase.close();
int i = 0;
while(!res.isAfterLast()){
appName[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_NAME));
pkgName[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME));
isFiltered[i] = res.getString(res.getColumnIndex(AppDatabase.KEY_IS_ENABLED)).equals("true");
res.moveToNext();
i++;
}
res.close();
appDatabase.close();
Arrays.sort(apps, new Comparator<AppListInfo>() {
@Override
public int compare(AppListInfo lhs, AppListInfo rhs) {
return StringsHelper.compare(lhs.name, rhs.name);
}
});
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_multiple_choice, android.R.id.text1, appName);
runOnUiThread(new Runnable() {
@Override
public void run() {
displayAppList();
}
});
}
}).start();
}
void displayAppList() {
final ListView listView = (ListView) findViewById(R.id.lvFilterApps);
AppListAdapter adapter = new AppListAdapter();
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
for (i = 0 ; i < isFiltered.length; i++){
if (isFiltered[i]) {
listView.setItemChecked(i, true);
}
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
boolean checked = listView.isItemChecked(i);
//Log.e("NotificationFilterActivity", pkgName[i] + ":" + checked);
appDatabase.open();
appDatabase.update(pkgName[i], checked);
appDatabase.setEnabled(apps[i].pkg, checked);
appDatabase.close();
apps[i].isEnabled = checked;
}
});
}
// Delete apps from database which are uninstalled
private void deleteUninstalledApps(){
Cursor res;
appDatabase.open();
res = appDatabase.getAllApplications();
if (res != null) {
res.moveToFirst();
while (!res.isAfterLast()) {
String packageName = res.getString(res.getColumnIndex(AppDatabase.KEY_PACKAGE_NAME));
if (!isPackageInstalled(packageName)) {
appDatabase.delete(packageName);
}
res.moveToNext();
}
res.close();
}
appDatabase.close();
}
// Adding newly installed apps in database
private void addNewlyInstalledApps() {
List<ApplicationInfo> PackList = getPackageManager().getInstalledApplications(0);
appDatabase.open();
for (int i=0; i < PackList.size(); i++)
{
ApplicationInfo PackInfo = PackList.get(i);
String appName = PackInfo.loadLabel(getPackageManager()).toString();
String packageName = PackInfo.packageName;
if ( (PackInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ) {
if (!appDatabase.exists(packageName)) {
appDatabase.create(appName, packageName, true);
}
//Log.e("App FLAG_UPDATED_SYSTEM_APP: " + Integer.toString(i), appName);
} else if ( (PackInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
//ignore these apps
} else {
if (!appDatabase.exists(packageName)) {
appDatabase.create(appName, packageName, true);
}
//Log.e("App : " + Integer.toString(i), appName);
}
for (int i = 0 ; i < apps.length; i++) {
listView.setItemChecked(i, apps[i].isEnabled);
}
appDatabase.close();
listView.setVisibility(View.VISIBLE);
findViewById(R.id.spinner).setVisibility(View.GONE);
}
private boolean isPackageInstalled(String packageName){
PackageManager pm = getPackageManager();
try {
pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
} catch (Exception e) {
return false;
}
return true;
}
@Override
protected void onStart() {
super.onStart();
@@ -170,4 +172,19 @@ public class NotificationFilterActivity extends ActionBarActivity {
BackgroundService.removeGuiInUseCounter(this);
}
Drawable resizeIcon(Drawable icon, int maxSize) {
Resources res = getResources();
//Convert to display pixels
maxSize = (int)(maxSize*res.getDisplayMetrics().density);
Bitmap bitmap = Bitmap.createBitmap(maxSize, maxSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
icon.draw(canvas);
return new BitmapDrawable(res, bitmap);
}
}

View File

@@ -170,11 +170,6 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
return;
}
if (packageName.equals("com.google.android.googlequicksearchbox")) {
//HACK: Hide Google Now notifications that keep constantly popping up (and without text because we don't know how to read them properly)
return;
}
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
if (packageName.equals("org.kde.kdeconnect_tp"))
@@ -229,7 +224,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Bundle extras = notification.extras;
String extraTitle = extras.getString(TITLE_KEY);
String extraTitle = extras.getCharSequence(TITLE_KEY).toString();
String extraText = null;
Object extraTextExtra = extras.get(TEXT_KEY);
if (extraTextExtra != null) extraText = extraTextExtra.toString();

View File

@@ -30,6 +30,7 @@ import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.UserInterface.MaterialActivity;
@@ -89,12 +90,7 @@ public class PingPlugin extends Plugin {
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
try {
notificationManager.notify(id, noti);
} catch(Exception e) {
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
}
NotificationHelper.notifyCompat(notificationManager, id, noti);
return true;

View File

@@ -161,8 +161,9 @@ public abstract class Plugin {
public void onDestroy() { }
/**
* If onCreate returns false, should create a dialog explaining
* the problem (and how to fix it, if possible) to the user.
* Called when a plugin receives a package. By convention we return true
* when we have done something in response to the package or false
* otherwise, even though that value is unused as of now.
*/
public boolean onPackageReceived(NetworkPackage np) { return false; }

View File

@@ -33,9 +33,11 @@ import org.kde.kdeconnect.Plugins.MprisPlugin.MprisPlugin;
import org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationsPlugin;
import org.kde.kdeconnect.Plugins.PingPlugin.PingPlugin;
import org.kde.kdeconnect.Plugins.ReceiveNotificationsPlugin.ReceiveNotificationsPlugin;
import org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin.RemoteKeyboardPlugin;
import org.kde.kdeconnect.Plugins.RunCommandPlugin.RunCommandPlugin;
import org.kde.kdeconnect.Plugins.SftpPlugin.SftpPlugin;
import org.kde.kdeconnect.Plugins.SharePlugin.SharePlugin;
import org.kde.kdeconnect.Plugins.TelepathyPlugin.TelepathyPlugin;
import org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin;
import java.util.Collections;
@@ -110,7 +112,6 @@ public class PluginFactory {
private static final Map<String, PluginInfo> pluginInfoCache = new TreeMap<>();
static {
//TODO: Use reflection to find all subclasses of Plugin, instead of adding them manually
PluginFactory.registerPlugin(TelephonyPlugin.class);
PluginFactory.registerPlugin(PingPlugin.class);
PluginFactory.registerPlugin(MprisPlugin.class);
@@ -121,9 +122,11 @@ public class PluginFactory {
PluginFactory.registerPlugin(ReceiveNotificationsPlugin.class);
PluginFactory.registerPlugin(MousePadPlugin.class);
PluginFactory.registerPlugin(SharePlugin.class);
//PluginFactory.registerPlugin(TelepathyPlugin.class);
PluginFactory.registerPlugin(TelepathyPlugin.class);
PluginFactory.registerPlugin(FindMyPhonePlugin.class);
PluginFactory.registerPlugin(RunCommandPlugin.class);
//Commented here and in AndroidManifest until we release a desktop version with this feature, so we don't get bad "feature not working" reviews
//PluginFactory.registerPlugin(RemoteKeyboardPlugin.class);
}
public static PluginInfo getPluginInfo(Context context, String pluginKey) {

View File

@@ -32,6 +32,7 @@ import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.UserInterface.MaterialActivity;
@@ -114,13 +115,8 @@ public class ReceiveNotificationsPlugin extends Plugin {
.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
try {
// tag all incoming notifications
notificationManager.notify("kdeconnectId:" + np.getString("id", "0"), np.getInt("id", 0), noti);
} catch (Exception e) {
//4.1 will throw an exception about not having the VIBRATE permission, ignore it.
//https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/
}
NotificationHelper.notifyCompat(notificationManager, "kdeconnectId:" + np.getString("id", "0"), np.getInt("id", 0), noti);
}
return true;

View File

@@ -0,0 +1,398 @@
/*
* Copyright 2017 Holger Kaelberer <holger.k@elberer.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.util.Pair;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
public class RemoteKeyboardPlugin extends Plugin {
public final static String PACKAGE_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
public final static String PACKAGE_TYPE_MOUSEPAD_ECHO = "kdeconnect.mousepad.echo";
public final static String PACKAGE_TYPE_MOUSEPAD_KEYBOARDSTATE = "kdeconnect.mousepad.keyboardstate";
/**
* Track and expose plugin instances to allow for a 'connected'-indicator in the IME:
*/
private static ArrayList<RemoteKeyboardPlugin> instances = new ArrayList<RemoteKeyboardPlugin>();
private static ReentrantLock instancesLock = new ReentrantLock(true);
public static ArrayList<RemoteKeyboardPlugin> getInstances() {
return instances;
}
public static ArrayList<RemoteKeyboardPlugin> acquireInstances() {
instancesLock.lock();
return getInstances();
}
public static ArrayList<RemoteKeyboardPlugin> releaseInstances() {
instancesLock.unlock();
return getInstances();
}
public static boolean isConnected() {
return instances.size() > 0;
}
private static SparseIntArray specialKeyMap = new SparseIntArray();
static {
int i = 0;
specialKeyMap.put(++i, KeyEvent.KEYCODE_DEL); // 1
specialKeyMap.put(++i, KeyEvent.KEYCODE_TAB); // 2
++i; //specialKeyMap.put(++i, KeyEvent.KEYCODE_ENTER, 12); // 3 is not used
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_LEFT); // 4
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_UP); // 5
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_RIGHT); // 6
specialKeyMap.put(++i, KeyEvent.KEYCODE_DPAD_DOWN); // 7
specialKeyMap.put(++i, KeyEvent.KEYCODE_PAGE_UP); // 8
specialKeyMap.put(++i, KeyEvent.KEYCODE_PAGE_DOWN); // 9
if (Build.VERSION.SDK_INT >= 11) {
specialKeyMap.put(++i, KeyEvent.KEYCODE_MOVE_HOME); // 10
specialKeyMap.put(++i, KeyEvent.KEYCODE_MOVE_END); // 11
specialKeyMap.put(++i, KeyEvent.KEYCODE_ENTER); // 12
specialKeyMap.put(++i, KeyEvent.KEYCODE_FORWARD_DEL); // 13
specialKeyMap.put(++i, KeyEvent.KEYCODE_ESCAPE); // 14
specialKeyMap.put(++i, KeyEvent.KEYCODE_SYSRQ); // 15
specialKeyMap.put(++i, KeyEvent.KEYCODE_SCROLL_LOCK); // 16
++i; // 17
++i; // 18
++i; // 19
++i; // 20
specialKeyMap.put(++i, KeyEvent.KEYCODE_F1); // 21
specialKeyMap.put(++i, KeyEvent.KEYCODE_F2); // 22
specialKeyMap.put(++i, KeyEvent.KEYCODE_F3); // 23
specialKeyMap.put(++i, KeyEvent.KEYCODE_F4); // 24
specialKeyMap.put(++i, KeyEvent.KEYCODE_F5); // 25
specialKeyMap.put(++i, KeyEvent.KEYCODE_F6); // 26
specialKeyMap.put(++i, KeyEvent.KEYCODE_F7); // 27
specialKeyMap.put(++i, KeyEvent.KEYCODE_F8); // 28
specialKeyMap.put(++i, KeyEvent.KEYCODE_F9); // 29
specialKeyMap.put(++i, KeyEvent.KEYCODE_F10); // 30
specialKeyMap.put(++i, KeyEvent.KEYCODE_F11); // 31
specialKeyMap.put(++i, KeyEvent.KEYCODE_F12); // 21
}
}
@Override
public boolean onCreate() {
Log.d("RemoteKeyboardPlugin", "Creating for device " + device.getName());
acquireInstances();
try {
instances.add(this);
} finally {
releaseInstances();
}
if (RemoteKeyboardService.instance != null)
RemoteKeyboardService.instance.handler.post(new Runnable() {
@Override
public void run() {
RemoteKeyboardService.instance.updateInputView();
}
});
return true;
}
@Override
public void onDestroy() {
acquireInstances();
try {
if (instances.contains(this)) {
instances.remove(this);
if (instances.size() < 1 && RemoteKeyboardService.instance != null)
RemoteKeyboardService.instance.handler.post(new Runnable() {
@Override
public void run() {
RemoteKeyboardService.instance.updateInputView();
}
});
}
} finally {
releaseInstances();
}
Log.d("RemoteKeyboardPlugin", "Destroying for device " + device.getName());
}
@Override
public String getDisplayName() {
return context.getString(R.string.pref_plugin_remotekeyboard);
}
@Override
public String getDescription() {
return context.getString(R.string.pref_plugin_remotekeyboard_desc);
}
@Override
public Drawable getIcon() {
return ContextCompat.getDrawable(context, R.drawable.ic_action_keyboard);
}
@Override
public boolean hasSettings() {
return true;
}
@Override
public boolean hasMainActivity() {
return false;
}
@Override
public String[] getSupportedPackageTypes() {
return new String[]{PACKAGE_TYPE_MOUSEPAD_REQUEST};
}
@Override
public String[] getOutgoingPackageTypes() {
return new String[]{PACKAGE_TYPE_MOUSEPAD_ECHO, PACKAGE_TYPE_MOUSEPAD_KEYBOARDSTATE};
}
private boolean isValidSpecialKey(int key) {
return (specialKeyMap.get(key, 0) > 0);
}
private int getCharPos(ExtractedText extractedText, char ch, boolean forward) {
int pos = -1;
if (extractedText != null) {
if (!forward) // backward
pos = extractedText.text.toString().lastIndexOf(" ", extractedText.selectionEnd - 2);
else
pos = extractedText.text.toString().indexOf(" ", extractedText.selectionEnd + 1);
return pos;
}
return pos;
}
private int currentTextLength(ExtractedText extractedText) {
if (extractedText != null)
return extractedText.text.length();
return -1;
}
private int currentCursorPos(ExtractedText extractedText) {
if (extractedText != null)
return extractedText.selectionEnd;
return -1;
}
private Pair<Integer,Integer> currentSelection(ExtractedText extractedText) {
if (extractedText != null)
return new Pair<>(extractedText.selectionStart, extractedText.selectionEnd);
return new Pair<>(-1, -1);
}
private boolean handleSpecialKey(int key, boolean shift, boolean ctrl, boolean alt) {
int keyEvent = specialKeyMap.get(key, 0);
if (keyEvent == 0)
return false;
InputConnection inputConn = RemoteKeyboardService.instance.getCurrentInputConnection();
// Log.d("RemoteKeyboardPlugin", "Handling special key " + key + " translated to " + keyEvent + " shift=" + shift + " ctrl=" + ctrl + " alt=" + alt);
// special sequences:
if (ctrl && (keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT)) {
// Ctrl + right -> next word
ExtractedText extractedText = inputConn.getExtractedText(new ExtractedTextRequest(), 0);
int pos = getCharPos(extractedText, ' ', keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT);
if (pos == -1)
pos = currentTextLength(extractedText);
else
pos++;
int startPos = pos;
int endPos = pos;
if (shift) { // Shift -> select word (otherwise jump)
Pair<Integer,Integer> sel = currentSelection(extractedText);
int cursor = currentCursorPos(extractedText);
// Log.d("RemoteKeyboardPlugin", "Selection (to right): " + sel.first + " / " + sel.second + " cursor: " + cursor);
startPos = cursor;
if (sel.first < cursor || // active selection from left to right -> grow
sel.first > sel.second) // active selection from right to left -> shrink
startPos = sel.first;
}
inputConn.setSelection(startPos, endPos);
} else if (ctrl && keyEvent == KeyEvent.KEYCODE_DPAD_LEFT) {
// Ctrl + left -> previous word
ExtractedText extractedText = inputConn.getExtractedText(new ExtractedTextRequest(), 0);
int pos = getCharPos(extractedText, ' ', keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT);
if (pos == -1)
pos = 0;
else
pos++;
int startPos = pos;
int endPos = pos;
if (shift) {
Pair<Integer,Integer> sel = currentSelection(extractedText);
int cursor = currentCursorPos(extractedText);
// Log.d("RemoteKeyboardPlugin", "Selection (to left): " + sel.first + " / " + sel.second + " cursor: " + cursor);
startPos = cursor;
if (cursor < sel.first || // active selection from right to left -> grow
sel.first < sel.second) // active selection from right to left -> shrink
startPos = sel.first;
}
inputConn.setSelection(startPos, endPos);
} else if (shift
&& (keyEvent == KeyEvent.KEYCODE_DPAD_LEFT
|| keyEvent == KeyEvent.KEYCODE_DPAD_RIGHT
|| keyEvent == KeyEvent.KEYCODE_DPAD_UP
|| keyEvent == KeyEvent.KEYCODE_DPAD_DOWN
|| keyEvent == KeyEvent.KEYCODE_MOVE_HOME
|| keyEvent == KeyEvent.KEYCODE_MOVE_END)) {
// Shift + up/down/left/right/home/end
long now = SystemClock.uptimeMillis();
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0));
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyEvent, 0, KeyEvent.META_SHIFT_LEFT_ON));
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyEvent, 0, KeyEvent.META_SHIFT_LEFT_ON));
inputConn.sendKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0));
} else if (keyEvent == KeyEvent.KEYCODE_NUMPAD_ENTER
|| keyEvent == KeyEvent.KEYCODE_ENTER) {
// Enter key
EditorInfo editorInfo = RemoteKeyboardService.instance.getCurrentInputEditorInfo();
// Log.d("RemoteKeyboardPlugin", "Enter: " + editorInfo.imeOptions);
if (editorInfo != null
&& (((editorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0)
|| ctrl)) { // Ctrl+Return overrides IME_FLAG_NO_ENTER_ACTION (FIXME: make configurable?)
// check for special DONE/GO/etc actions first:
int[] actions = { EditorInfo.IME_ACTION_GO, EditorInfo.IME_ACTION_NEXT,
EditorInfo.IME_ACTION_SEND, EditorInfo.IME_ACTION_SEARCH,
EditorInfo.IME_ACTION_DONE}; // note: DONE should be last or we might hide the ime instead of "go"
for (int i = 0; i < actions.length; i++) {
if ((editorInfo.imeOptions & actions[i]) == actions[i]) {
// Log.d("RemoteKeyboardPlugin", "Enter-action: " + actions[i]);
inputConn.performEditorAction(actions[i]);
return true;
}
}
} else {
// else: fall back to regular Enter-event:
// Log.d("RemoteKeyboardPlugin", "Enter: normal keypress");
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyEvent));
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyEvent));
}
} else {
// default handling:
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyEvent));
inputConn.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyEvent));
}
return true;
}
private boolean handleVisibleKey(String key, boolean shift, boolean ctrl, boolean alt) {
// Log.d("RemoteKeyboardPlugin", "Handling visible key " + key + " shift=" + shift + " ctrl=" + ctrl + " alt=" + alt + " " + key.equalsIgnoreCase("c") + " " + key.length());
if (key.isEmpty())
return false;
InputConnection inputConn = RemoteKeyboardService.instance.getCurrentInputConnection();
if (inputConn == null)
return false;
// ctrl+c/v/x
if (key.equalsIgnoreCase("c") && ctrl) {
return inputConn.performContextMenuAction(android.R.id.copy);
} else if (key.equalsIgnoreCase("v") && ctrl)
return inputConn.performContextMenuAction(android.R.id.paste);
else if (key.equalsIgnoreCase("x") && ctrl)
return inputConn.performContextMenuAction(android.R.id.cut);
else if (key.equalsIgnoreCase("a") && ctrl)
return inputConn.performContextMenuAction(android.R.id.selectAll);
// Log.d("RemoteKeyboardPlugin", "Committing visible key '" + key + "'");
inputConn.commitText(key, key.length());
return true;
}
private boolean handleEvent(NetworkPackage np) {
if (np.has("specialKey") && isValidSpecialKey(np.getInt("specialKey")))
return handleSpecialKey(np.getInt("specialKey"), np.getBoolean("shift"),
np.getBoolean("ctrl"), np.getBoolean("alt"));
// try visible key
return handleVisibleKey(np.getString("key"), np.getBoolean("shift"),
np.getBoolean("ctrl"), np.getBoolean("alt"));
}
@Override
public boolean onPackageReceived(NetworkPackage np) {
if (!np.getType().equals(PACKAGE_TYPE_MOUSEPAD_REQUEST)
|| (!np.has("key") && !np.has("specialKey"))) { // expect at least key OR specialKey
Log.e("RemoteKeyboardPlugin", "Invalid package for remotekeyboard plugin!");
return false;
}
if (RemoteKeyboardService.instance == null) {
Log.i("RemoteKeyboardPlugin", "Remote keyboard is not the currently selected input method, dropping key");
return false;
}
if (!RemoteKeyboardService.instance.visible &&
PreferenceManager.getDefaultSharedPreferences(context).getBoolean(context.getString(R.string.remotekeyboard_editing_only), true)) {
Log.i("RemoteKeyboardPlugin", "Remote keyboard is currently not visible, dropping key");
return false;
}
if (!handleEvent(np)) {
Log.i("RemoteKeyboardPlugin", "Could not handle event!");
return false;
}
if (np.getBoolean("sendAck")) {
NetworkPackage reply = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_ECHO);
reply.set("key", np.getString("key"));
if (np.has("specialKey"))
reply.set("specialKey", np.getInt("specialKey"));
if (np.has("shift"))
reply.set("shift", np.getBoolean("shift"));
if (np.has("ctrl"))
reply.set("ctrl", np.getBoolean("ctrl"));
if (np.has("alt"))
reply.set("alt", np.getBoolean("alt"));
reply.set("isAck", true);
device.sendPackage(reply);
}
return true;
}
public void notifyKeyboardState(boolean state) {
Log.d("RemoteKeyboardPlugin", "Keyboardstate changed to " + state);
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_KEYBOARDSTATE);
np.set("state", state);
device.sendPackage(np);
}
}

View File

@@ -0,0 +1,233 @@
/*
* Copyright 2017 Holger Kaelberer <holger.k@elberer.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin;
import android.content.Context;
import android.content.Intent;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import org.kde.kdeconnect.UserInterface.MaterialActivity;
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
import java.util.List;
public class RemoteKeyboardService
extends InputMethodService
implements OnKeyboardActionListener {
/**
* Reference to our instance
* null if this InputMethod is not currently selected.
*/
public static RemoteKeyboardService instance = null;
/**
* Whether input is currently accepted
* Implies visible == true
*/
public boolean active = false;
/**
* Whether this InputMethod is currently visible.
*/
public boolean visible = false;
KeyboardView inputView = null;
private final int StatusKeyIdx = 3;
private final int connectedIcon = R.drawable.ic_phonelink_white_36dp;
private final int disconnectedIcon = R.drawable.ic_phonelink_off_white_36dp;
Handler handler;
void updateInputView() {
if (inputView == null)
return;
Keyboard currentKeyboard = inputView.getKeyboard();
List<Keyboard.Key> keys = currentKeyboard.getKeys();
boolean connected = RemoteKeyboardPlugin.isConnected();
// Log.d("RemoteKeyboardService", "Updating keyboard connection icon, connected=" + connected);
keys.get(StatusKeyIdx).icon = getResources().getDrawable(connected ? connectedIcon : disconnectedIcon);
inputView.invalidateKey(StatusKeyIdx);
}
@Override
public void onCreate() {
super.onCreate();
active = false;
visible = false;
instance = this;
handler = new Handler();
Log.d("RemoteKeyboardService", "Remote keyboard initialized");
}
@Override
public void onDestroy() {
super.onDestroy();
instance = null;
Log.d("RemoteKeyboardService", "Destroyed");
}
@Override
public void onInitializeInterface() {
super.onInitializeInterface();
}
@Override
public View onCreateInputView() {
// Log.d("RemoteKeyboardService", "onCreateInputView connected=" + RemoteKeyboardPlugin.isConnected());
inputView = new KeyboardView(this, null);
inputView.setKeyboard(new Keyboard(this, R.xml.remotekeyboardplugin_keyboard));
inputView.setPreviewEnabled(false);
inputView.setOnKeyboardActionListener(this);
updateInputView();
return inputView;
}
@Override
public void onStartInputView(EditorInfo attribute, boolean restarting) {
// Log.d("RemoteKeyboardService", "onStartInputView");
super.onStartInputView(attribute, restarting);
visible = true;
ArrayList<RemoteKeyboardPlugin> instances = RemoteKeyboardPlugin.acquireInstances();
try {
for (RemoteKeyboardPlugin i: instances)
i.notifyKeyboardState(true);
} finally {
RemoteKeyboardPlugin.releaseInstances();
}
}
@Override
public void onFinishInputView(boolean finishingInput) {
// Log.d("RemoteKeyboardService", "onFinishInputView");
super.onFinishInputView(finishingInput);
visible = false;
ArrayList<RemoteKeyboardPlugin> instances = RemoteKeyboardPlugin.acquireInstances();
try {
for (RemoteKeyboardPlugin i: instances)
i.notifyKeyboardState(false);
} finally {
RemoteKeyboardPlugin.releaseInstances();
}
}
@Override
public void onStartInput(EditorInfo attribute, boolean restarting) {
// Log.d("RemoteKeyboardService", "onStartInput");
super.onStartInput(attribute, restarting);
active = true;
}
@Override
public void onFinishInput() {
// Log.d("RemoteKeyboardService", "onFinishInput");
super.onFinishInput();
active = false;
}
@Override
public void onPress(int primaryCode) {
switch (primaryCode) {
case 0: { // "hide keyboard"
requestHideSelf(0);
break;
}
case 1: { // "settings"
ArrayList<RemoteKeyboardPlugin> instances = RemoteKeyboardPlugin.acquireInstances();
try {
if (instances.size() == 1) { // single instance of RemoteKeyboardPlugin -> access its settings
RemoteKeyboardPlugin plugin = instances.get(0);
if (plugin != null) {
Intent intent = new Intent(this, PluginSettingsActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("plugin_display_name", plugin.getDisplayName());
intent.putExtra("plugin_key", plugin.getPluginKey());
startActivity(intent);
}
} else { // != 1 instance of plugin -> show main activity view
Intent intent = new Intent(this, MaterialActivity.class);
intent.putExtra("forceOverview", true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
if (instances.size() < 1)
Toast.makeText(this, R.string.remotekeyboard_not_connected, Toast.LENGTH_SHORT).show();
else // instances.size() > 1
Toast.makeText(this, R.string.remotekeyboard_multiple_connections, Toast.LENGTH_SHORT).show();
}
} finally {
RemoteKeyboardPlugin.releaseInstances();
}
break;
}
case 2: { // "keyboard"
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showInputMethodPicker();
break;
}
case 3: { // "connected"?
if (RemoteKeyboardPlugin.isConnected())
Toast.makeText(this, R.string.remotekeyboard_connected, Toast.LENGTH_SHORT).show();
else
Toast.makeText(this, R.string.remotekeyboard_not_connected, Toast.LENGTH_SHORT).show();
break;
}
}
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
}
@Override
public void onText(CharSequence text) {
}
@Override
public void swipeRight() {
}
@Override
public void swipeLeft() {
}
@Override
public void swipeDown() {
}
@Override
public void swipeUp() {
}
@Override
public void onRelease(int primaryCode) {
}
}

View File

@@ -0,0 +1,3 @@
Besides the official Android examples about implementing IMEs I learned a lot about using
the Android APIs around InputConnection from the excellent "Remote Keyboard" app from onyxbits
(http://www.onyxbits.de/remotekeyboard). Thanks!

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2016 Thomas Posch <kdeconnect@online.posch.name>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kde.kdeconnect.Plugins.RunCommandPlugin;
import org.kde.kdeconnect.UserInterface.List.EntryItem;
public class CommandEntry extends EntryItem {
private final String key;
public CommandEntry(String name, String cmd, String key) {
super(name, cmd);
this.key = key;
}
public String getKey() {
return key;
}
public String getName() {
return title;
}
}

View File

@@ -32,11 +32,12 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.UserInterface.List.EntryItem;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class RunCommandActivity extends ActionBarActivity {
@@ -59,28 +60,33 @@ public class RunCommandActivity extends ActionBarActivity {
public void run() {
ListView view = (ListView) findViewById(R.id.listView1);
final ArrayList<JSONObject> commands = plugin.getCommandList();
ArrayList<ListAdapter.Item> commandItems = new ArrayList<>();
for (JSONObject obj : commands) {
final ArrayList<ListAdapter.Item> commandItems = new ArrayList<>();
for (JSONObject obj : plugin.getCommandList()) {
try {
commandItems.add(new EntryItem(obj.getString("name"), obj.getString("command")));
commandItems.add(new CommandEntry(obj.getString("name"),
obj.getString("command"), obj.getString("key")));
} catch (JSONException e) {
e.printStackTrace();
}
}
Collections.sort(commandItems, new Comparator<ListAdapter.Item>() {
@Override
public int compare(ListAdapter.Item lhs, ListAdapter.Item rhs) {
String lName = ((CommandEntry) lhs).getName();
String rName = ((CommandEntry) rhs).getName();
return lName.compareTo(rName);
}
});
ListAdapter adapter = new ListAdapter(RunCommandActivity.this, commandItems);
view.setAdapter(adapter);
view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
try {
plugin.runCommand(commands.get(i).getString("key"));
} catch (JSONException e) {
e.printStackTrace();
}
CommandEntry entry = (CommandEntry) commandItems.get(i);
plugin.runCommand(entry.getKey());
}
});
}

View File

@@ -68,9 +68,9 @@ public class SftpPlugin extends Plugin {
NetworkPackage np2 = new NetworkPackage(PACKAGE_TYPE_SFTP);
np2.set("ip", server.getLocalIpAddress());
np2.set("port", server.port);
np2.set("user", server.passwordAuth.getUser());
np2.set("password", server.passwordAuth.getPassword());
np2.set("port", server.getPort());
np2.set("user", SimpleSftpServer.USER);
np2.set("password", server.getPassword());
//Kept for compatibility, in case "multiPaths" is not possible or the other end does not support it
np2.set("path", Environment.getExternalStorageDirectory().getAbsolutePath());

View File

@@ -21,6 +21,7 @@
package org.kde.kdeconnect.Plugins.SftpPlugin;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import org.apache.sshd.SshServer;
@@ -42,33 +43,33 @@ import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.MediaStoreHelper;
import org.kde.kdeconnect.Helpers.RandomHelper;
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
import java.io.File;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.PublicKey;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
class SimpleSftpServer {
private static final int STARTPORT = 1739;
private static final int ENDPORT = 1764;
private static final String USER = "kdeconnect";
static final String USER = "kdeconnect";
public static int port = -1;
private static boolean started = false;
private int port = -1;
private boolean started = false;
public final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
public final SimplePublicKeyAuthenticator keyAuth = new SimplePublicKeyAuthenticator();
private final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
private final SimplePublicKeyAuthenticator keyAuth = new SimplePublicKeyAuthenticator();
static {
Security.insertProviderAt(SslHelper.BC, 1);
@@ -76,20 +77,20 @@ class SimpleSftpServer {
}
private final SshServer sshd = SshServer.setUpDefaultServer();
public void init(Context ctx, Device device) {
public void init(Context context, Device device) {
sshd.setKeyExchangeFactories(Arrays.asList(
new DHG14.Factory(),
new DHG1.Factory()));
passwordAuth.setUser(USER);
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(ctx.getFilesDir() + "/sftpd.ser"));
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(context.getFilesDir() + "/sftpd.ser"));
sshd.setFileSystemFactory(new SecureFileSystemFactory());
sshd.setFileSystemFactory(new AndroidFileSystemFactory(context));
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setSubsystemFactories(Collections.singletonList((NamedFactory<Command>)new SftpSubsystem.Factory()));
if (device.publicKey != null) {
keyAuth.addKey(device.publicKey);
keyAuth.deviceKey = device.publicKey;
sshd.setPublickeyAuthenticator(keyAuth);
}
sshd.setPasswordAuthenticator(passwordAuth);
@@ -98,8 +99,7 @@ class SimpleSftpServer {
public boolean start() {
if (!started) {
String password = RandomHelper.randomString(28);
passwordAuth.setPassword(password);
passwordAuth.password = RandomHelper.randomString(28);
port = STARTPORT;
while(!started) {
@@ -131,6 +131,14 @@ class SimpleSftpServer {
}
}
public String getPassword() {
return passwordAuth.password;
}
public int getPort() {
return port;
}
public String getLocalIpAddress() {
String ip6 = null;
try {
@@ -153,92 +161,89 @@ class SimpleSftpServer {
return ip6;
}
static class SecureFileSystemFactory implements FileSystemFactory {
static class AndroidFileSystemFactory implements FileSystemFactory {
public SecureFileSystemFactory() {}
final private Context context;
public AndroidFileSystemFactory(Context context) {
this.context = context;
}
@Override
public FileSystemView createFileSystemView(final Session username) {
final String base = "/";
return new SecureFileSystemView(base, username.getUsername());
return new AndroidFileSystemView(username.getUsername(), context);
}
}
static class SecureFileSystemView extends NativeFileSystemView {
// the first and the last character will always be '/'
// It is always with respect to the root directory.
private String currDir = "/";
private String rootDir = "/";
private String userName;
//
public SecureFileSystemView(final String rootDir, final String userName) {
super(userName);
this.rootDir = NativeSshFile.normalizeSeparateChar(rootDir);
static class AndroidFileSystemView extends NativeFileSystemView {
final private String userName;
final private Context context;
public AndroidFileSystemView(final String userName, Context context) {
super(userName, true);
this.userName = userName;
}
//
@Override
public SshFile getFile(final String file) {
return getFile(currDir, file);
this.context = context;
}
@Override
public SshFile getFile(final SshFile baseDir, final String file) {
return getFile(baseDir.getAbsolutePath(), file);
}
//
protected SshFile getFile(final String dir, final String file) {
// get actual file object
final boolean caseInsensitive = false;
String physicalName = NativeSshFile.getPhysicalName("/", dir, file, caseInsensitive);
File fileObj = new File(rootDir, physicalName); // chroot
// strip the root directory and return
String userFileName = physicalName.substring("/".length() - 1);
return new SecureSshFile(userFileName, fileObj, userName);
File fileObj = new File(dir, file);
return new AndroidSshFile(fileObj, userName, context);
}
}
static class SecureSshFile extends NativeSshFile {
public SecureSshFile(final String fileName, final File file, final String userName) {
super(fileName, file, userName);
static class AndroidSshFile extends NativeSshFile {
final private Context context;
final private File file;
public AndroidSshFile(final File file, final String userName, Context context) {
super(file.getAbsolutePath(), file, userName);
this.context = context;
this.file = file;
}
@Override
public boolean delete() {
//Log.e("Sshd", "deleting file");
boolean ret = super.delete();
if (ret) {
MediaStoreHelper.indexFile(context, Uri.fromFile(file));
}
return ret;
}
@Override
public boolean create() throws IOException {
//Log.e("Sshd", "creating file");
boolean ret = super.create();
if (ret) {
MediaStoreHelper.indexFile(context, Uri.fromFile(file));
}
return ret;
}
}
static class SimplePasswordAuthenticator implements PasswordAuthenticator {
public void setUser(String user) {this.user = user;}
public String getUser() {return this.user;}
public void setPassword(String password) {this.password = password;}
public String getPassword() {return this.password;}
public String password;
@Override
public boolean authenticate(String user, String password, ServerSession session) {
return user.equals(this.user) && password.equals(this.password);
return user.equals(SimpleSftpServer.USER) && password.equals(this.password);
}
private String user;
private String password;
}
static class SimplePublicKeyAuthenticator implements PublickeyAuthenticator {
private final List<PublicKey> keys = new ArrayList<>();
public void addKey(PublicKey key) {
keys.add(key);
}
public PublicKey deviceKey;
@Override
public boolean authenticate(String user, PublicKey key, ServerSession session) {
for (PublicKey k : keys) {
if (key.equals(k)) {
return true;
}
}
return false;
return deviceKey.equals(key);
}
}

View File

@@ -0,0 +1,122 @@
package org.kde.kdeconnect.Plugins.SharePlugin;
import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
import android.support.v4.app.NotificationCompat;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect.NetworkPackage;
import org.kde.kdeconnect_tp.R;
import java.util.ArrayList;
class NotificationUpdateCallback extends Device.SendPackageStatusCallback {
final Context context;
final Resources res;
final Device device;
final NotificationManager notificationManager;
final NotificationCompat.Builder builder;
final ArrayList<NetworkPackage> toSend;
final int notificationId;
int sentFiles = 0;
final int numFiles;
NotificationUpdateCallback(Context context, Device device, ArrayList<NetworkPackage> toSend) {
this.context = context;
this.toSend = toSend;
this.device = device;
this.res = context.getResources();
String title;
if (toSend.size() > 1) {
title = res.getString(R.string.outgoing_files_title, device.getName());
} else {
title = res.getString(R.string.outgoing_file_title, device.getName());
}
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
builder = new NotificationCompat.Builder(context)
.setSmallIcon(android.R.drawable.stat_sys_upload)
.setAutoCancel(true)
.setProgress(100, 0, false)
.setContentTitle(title)
.setTicker(title);
notificationId = (int)System.currentTimeMillis();
numFiles = toSend.size();
}
@Override
public void onProgressChanged(int progress) {
builder.setProgress(100 * numFiles, (100 * sentFiles) + progress, false);
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
}
@Override
public void onSuccess() {
sentFiles++;
if (sentFiles == numFiles) {
updateDone(true);
} else {
updateText();
}
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
}
@Override
public void onFailure(Throwable e) {
updateDone(false);
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
}
private void updateText() {
String text;
if (numFiles > 1) {
text = res.getString(R.string.outgoing_files_text, sentFiles, numFiles);
} else {
text = res.getString(R.string.outgoing_file_text, device.getName());
}
builder.setContentText(text);
}
private void updateDone(boolean successful) {
int icon;
String title;
String text;
int progress;
if (successful) {
progress = 1;
if (numFiles > 1) {
text = res.getString(R.string.outgoing_files_text, sentFiles, numFiles);
} else {
final String filename = toSend.get(0).getString("filename");
text = res.getString(R.string.sent_file_text, filename);
}
title = res.getString(R.string.sent_file_title, device.getName());
icon = android.R.drawable.stat_sys_upload_done;
} else {
progress = 0;
final String filename = toSend.get(sentFiles).getString("filename");
title = res.getString(R.string.sent_file_failed_title, device.getName());
text = res.getString(R.string.sent_file_failed_text, filename);
icon = android.R.drawable.stat_notify_error;
}
builder.setOngoing(false)
.setTicker(title)
.setContentTitle(title)
.setContentText(text)
.setSmallIcon(icon)
.setProgress(progress, progress, false); //setting progress to 0 out of 0 remove the progress bar
}
}

View File

@@ -21,8 +21,10 @@
package org.kde.kdeconnect.Plugins.SharePlugin;
import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
@@ -47,6 +49,9 @@ public class SendFileActivity extends ActionBarActivity {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(
@@ -62,23 +67,39 @@ public class SendFileActivity extends ActionBarActivity {
switch (requestCode) {
case Activity.RESULT_FIRST_USER:
if (resultCode == RESULT_OK) {
final Uri uri = data.getData();
Log.e("SendFileActivity", "File Uri: " + uri.toString());
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(mDeviceId);
if (device == null) {
Log.e("SendFileActivity", "Device is null");
finish();
return;
}
ArrayList<Uri> uris = new ArrayList<>();
uris.add(uri);
SharePlugin.queuedSendUriList(getApplicationContext(), device, uris);
final ArrayList<Uri> uris = new ArrayList<>();
Uri uri = data.getData();
if (uri != null) {
uris.add(uri);
}
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)) {
ClipData clipdata = data.getClipData();
if (clipdata != null) {
for (int i = 0; i < clipdata.getItemCount(); i++) {
uris.add(clipdata.getItemAt(i).getUri());
}
}
});
}
if (uris.isEmpty()) {
Log.w("SendFileActivity", "No files to send?");
} else {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(BackgroundService service) {
Device device = service.getDevice(mDeviceId);
if (device == null) {
Log.e("SendFileActivity", "Device is null");
finish();
return;
}
SharePlugin.queuedSendUriList(getApplicationContext(), device, uris);
}
});
}
}
finish();
break;

View File

@@ -198,6 +198,7 @@ public class ShareActivity extends ActionBarActivity {
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
setContentView(R.layout.activity_list);
}

Some files were not shown because too many files have changed in this diff Show More