Compare commits
382 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e49ab67e26 | ||
|
edc3075763 | ||
|
fd2102b432 | ||
|
adee9014fd | ||
|
2c0d9af64d | ||
|
53117c9a4b | ||
|
47ba298128 | ||
|
c5456fd84e | ||
|
d29868ac04 | ||
|
4b7c5fb85a | ||
|
de81a20f82 | ||
|
ed9b804693 | ||
|
d9cc1c0ba4 | ||
|
92b8238977 | ||
|
8567abdfa6 | ||
|
d490d53be7 | ||
|
7981d952ec | ||
|
4e86eb0dd3 | ||
|
6f8947377a | ||
|
106e651c6c | ||
|
5669e3c22c | ||
|
2d1dbd124c | ||
|
1edcbd2b39 | ||
|
c76a32ff05 | ||
|
c078e45a98 | ||
|
163e3c31f4 | ||
|
5a5e236710 | ||
|
603c87d42d | ||
|
1a04bfbbea | ||
|
fec0b34330 | ||
|
f6c4084746 | ||
|
968d018f41 | ||
|
4fc6ca8d4f | ||
|
d3ab18b721 | ||
|
b2d0e57641 | ||
|
66238406d6 | ||
|
010c960680 | ||
|
49d4383828 | ||
|
226869e200 | ||
|
bbc1113710 | ||
|
b3bacf241c | ||
|
ff47313409 | ||
|
ac4f072322 | ||
|
5ed1b80716 | ||
|
8a413bb42e | ||
|
71dc713578 | ||
|
ca3d677db6 | ||
|
79ed37345b | ||
|
24c404400f | ||
|
082de423c0 | ||
|
b5fb7f73ee | ||
|
097d1f5fa5 | ||
|
5fa43f8979 | ||
|
e5c7adba3a | ||
|
ced5c71369 | ||
|
9bf2adefc4 | ||
|
24685348cf | ||
|
7556e1d7fa | ||
|
c9b852f88c | ||
|
d8169f3787 | ||
|
b71e8562bc | ||
|
4d19a7cdc8 | ||
|
ae7a80e262 | ||
|
4a269a607c | ||
|
a6c23b252c | ||
|
fa5f584fe4 | ||
|
634f71d724 | ||
|
055e0f6454 | ||
|
8df2b7b0ee | ||
|
5f64e94878 | ||
|
abbbc9414d | ||
|
cfa13cb16b | ||
|
d726fe23bf | ||
|
d920b2659d | ||
|
0836453c35 | ||
|
09e1811bd8 | ||
|
1ab07d201e | ||
|
1c2dfdb795 | ||
|
dd3df9d19f | ||
|
5bfbd90414 | ||
|
5eb17f7a9a | ||
|
44be314899 | ||
|
728fa0b508 | ||
|
e9e93423f1 | ||
|
a1dd4fe2cc | ||
|
2294f30505 | ||
|
8c86edcf33 | ||
|
113739e1d9 | ||
|
48cd5aa29b | ||
|
5487c5556b | ||
|
e34de854bf | ||
|
d8aab59d4b | ||
|
835a4f0bc7 | ||
|
a588c8f787 | ||
|
36d1145df7 | ||
|
5d3ccbe0b0 | ||
|
2497ec2b1c | ||
|
bb8f015e87 | ||
|
f3e5bf917a | ||
|
45ba30e0ba | ||
|
f967c2888d | ||
|
6f0b581c02 | ||
|
b0b67f2059 | ||
|
53ad86fe9a | ||
|
39107400d4 | ||
|
3f20af445a | ||
|
e433ad8bce | ||
|
53ca2a392c | ||
|
b7d9cb5d81 | ||
|
05e031d41f | ||
|
d7956650da | ||
|
43467aedd8 | ||
|
541cd97c71 | ||
|
7759152eeb | ||
|
305d496bf5 | ||
|
01b5c3e2a1 | ||
|
a26d6a94f9 | ||
|
9dc8db00b5 | ||
|
5ef5161378 | ||
|
0897f25a6f | ||
|
394e530545 | ||
|
ebbf5d165c | ||
|
a0d2a61ce9 | ||
|
2350e86023 | ||
|
2552663742 | ||
|
d729eed1cd | ||
|
284ef5e571 | ||
|
0c98964f16 | ||
|
6783ce2f1b | ||
|
6f6caa0e8d | ||
|
614505518b | ||
|
240fa34833 | ||
|
6ecfc5071e | ||
|
d539cd704b | ||
|
d253fcfd0b | ||
|
01b1e6ee4a | ||
|
969249e6d7 | ||
|
4f70c42ce5 | ||
|
4a612fd073 | ||
|
108f9e911d | ||
|
ddef90b985 | ||
|
e96f520829 | ||
|
f9aeca8ef9 | ||
|
65c3dc4570 | ||
|
aee22b5d15 | ||
|
2759da8d64 | ||
|
f615e95eeb | ||
|
e14da0d544 | ||
|
c01892f113 | ||
|
e39d5cc8ca | ||
|
45aa9d151f | ||
|
00715f3b6e | ||
|
6e95e20521 | ||
|
2c513b598a | ||
|
fd7d39e6ac | ||
|
98914ce182 | ||
|
36e8d14973 | ||
|
17d5eeade0 | ||
|
76eb88b51f | ||
|
07a9319c30 | ||
|
c87b09c5f0 | ||
|
708bcf9928 | ||
|
b45a15c822 | ||
|
0eba461654 | ||
|
7813b7309d | ||
|
87e214761f | ||
|
6ed3a18f53 | ||
|
db7e40fb35 | ||
|
501ac90379 | ||
|
4d553518f6 | ||
|
9a2167774b | ||
|
22edb24230 | ||
|
f13a7148fc | ||
|
c0d21e986c | ||
|
baee1771f5 | ||
|
910af86c31 | ||
|
9f2999de23 | ||
|
acb2888bde | ||
|
06c872fddc | ||
|
158931f766 | ||
|
deac88031b | ||
|
f4c221cf66 | ||
|
521a27c09d | ||
|
89a65ab3e2 | ||
|
abd91b7d6c | ||
|
79f096c09e | ||
|
9d0ef3ddf9 | ||
|
8c0fe406ec | ||
|
7047622a62 | ||
|
98ef6aec8c | ||
|
c927af4bf3 | ||
|
88b7c9898f | ||
|
62742ff8ae | ||
|
7f0ee677bd | ||
|
9b1f866cb0 | ||
|
353dc12165 | ||
|
5588c83909 | ||
|
b39433f237 | ||
|
612b019856 | ||
|
721856ebb6 | ||
|
2bd4d16361 | ||
|
e3c5ac9228 | ||
|
a75db516ec | ||
|
cf82127144 | ||
|
8a0e4caaff | ||
|
c647cbd93c | ||
|
55871b6523 | ||
|
8134c39a6d | ||
|
87c0a9f98e | ||
|
226e934d0f | ||
|
cfed03881b | ||
|
f618e8e670 | ||
|
fe7b03830e | ||
|
caa491d1e7 | ||
|
fba3e75cec | ||
|
71810c82d3 | ||
|
7755772f5b | ||
|
53096e39eb | ||
|
c7640967fe | ||
|
15c2126387 | ||
|
4f9945205c | ||
|
f0bcf84f6c | ||
|
49d499d9a9 | ||
|
a0f102b26a | ||
|
d07ff5a802 | ||
|
2421abea22 | ||
|
1ca09d7f58 | ||
|
3e9509123e | ||
|
8e990765da | ||
|
3071323f84 | ||
|
2b89c0ed15 | ||
|
3861e393e0 | ||
|
1c65f55d00 | ||
|
742332df1e | ||
|
d992e6c4eb | ||
|
4312648e29 | ||
|
d9a144b723 | ||
|
513f46aee1 | ||
|
f8da00b9b5 | ||
|
da66446200 | ||
|
b2804a4378 | ||
|
5687ced2a4 | ||
|
115420d2ce | ||
|
de8835e9d1 | ||
|
7cf2c7d916 | ||
|
4e9a036627 | ||
|
fe37a29c53 | ||
|
78929ad31e | ||
|
f60920d556 | ||
|
0f2f036c45 | ||
|
1a16335f05 | ||
|
475f85d0d3 | ||
|
6c50d0f05d | ||
|
aad298ae31 | ||
|
1e8aedf582 | ||
|
4fab4d4a6c | ||
|
47db10e055 | ||
|
c0ae2c9c08 | ||
|
f4db8e6160 | ||
|
d67985d484 | ||
|
857d754f8c | ||
|
d20cf1696b | ||
|
ca0ca6f7b7 | ||
|
b7f21e05a8 | ||
|
3ee9ee27cd | ||
|
29ff203f24 | ||
|
fb8e4a7cc2 | ||
|
6258497989 | ||
|
9612dabb0a | ||
|
1e152581e6 | ||
|
d59750441f | ||
|
61ded9469c | ||
|
f82c01eb66 | ||
|
54881a65fa | ||
|
1630ca9a25 | ||
|
39db14b2ab | ||
|
1c13fe90a5 | ||
|
d283ed6ecc | ||
|
0ff6893b39 | ||
|
977fc8a7b6 | ||
|
7abace799a | ||
|
3207066928 | ||
|
12b84811ab | ||
|
b66fe45b4f | ||
|
9322970d58 | ||
|
47c9729e04 | ||
|
a9676be722 | ||
|
f3f80893d2 | ||
|
b2819557bc | ||
|
6035b91848 | ||
|
3648ee32b4 | ||
|
b8daca41b0 | ||
|
e464c993c2 | ||
|
b342199ed6 | ||
|
6ef91dbb54 | ||
|
278a358b71 | ||
|
a3f331f600 | ||
|
e985e3648c | ||
|
45ca9aae89 | ||
|
dff28d7ee7 | ||
|
13dd8a36bd | ||
|
2dbb1fcb11 | ||
|
13369b078b | ||
|
80026f6d62 | ||
|
0732f94a78 | ||
|
33c233c780 | ||
|
9c29cbf594 | ||
|
6940bac3e6 | ||
|
629b38dec9 | ||
|
effa740db4 | ||
|
3de229f1e5 | ||
|
9b03bdf2c0 | ||
|
56d6cffb71 | ||
|
a54c0ac4bd | ||
|
83415c699c | ||
|
a6b590e477 | ||
|
8f53142a16 | ||
|
8aebaaea2f | ||
|
f5725b7c8d | ||
|
291abddeba | ||
|
2c829af4e5 | ||
|
4456210953 | ||
|
8307850805 | ||
|
424763e3b6 | ||
|
7fc7a37be4 | ||
|
132a223b8c | ||
|
35dd42f560 | ||
|
5777dfe238 | ||
|
d7123e3435 | ||
|
37f6c48d56 | ||
|
1fe01db26e | ||
|
f56fc9ceb8 | ||
|
1caa44b0ab | ||
|
13ec8d7a3f | ||
|
0eda30b135 | ||
|
4fa0a89691 | ||
|
476f7a7840 | ||
|
27723c697b | ||
|
6d28726c3b | ||
|
4c0bafa60f | ||
|
ab131863fd | ||
|
506bc8d2c2 | ||
|
b4f8d037e6 | ||
|
0b50bd8747 | ||
|
da0d5af9d1 | ||
|
b87aead06b | ||
|
f908f5d8a1 | ||
|
c4a27255a7 | ||
|
8cd59e701a | ||
|
8556e9399e | ||
|
6a4f0e79a9 | ||
|
cf4b840509 | ||
|
50fcea2cd9 | ||
|
7c9d6630d0 | ||
|
7fec58d6b2 | ||
|
cc7a1f5a2b | ||
|
5b0876f424 | ||
|
ce5d2c8394 | ||
|
f715c0797b | ||
|
6314e4217e | ||
|
f7f00057c9 | ||
|
b084c8653e | ||
|
d1dc0ba2b2 | ||
|
fd5063e7a7 | ||
|
442c01a8e5 | ||
|
72ad2e010c | ||
|
67227f4aa0 | ||
|
d93eb5d71e | ||
|
aeb9a717d4 | ||
|
1b726018d3 | ||
|
ed6aef42a6 | ||
|
02826ccfe4 | ||
|
00557052ff | ||
|
7be045e7c4 | ||
|
8128c42824 | ||
|
41100ad371 | ||
|
00a4d39bf6 | ||
|
8084b92990 | ||
|
e14f5a0df1 | ||
|
af548ae949 | ||
|
2f16656aa0 | ||
|
b6b4850355 |
@@ -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="906"
|
||||
android:versionName="0.9.1">
|
||||
android:versionCode="1320"
|
||||
android:versionName="1.3.2">
|
||||
|
||||
<uses-sdk android:minSdkVersion="9"
|
||||
android:targetSdkVersion="22" />
|
||||
@@ -14,21 +14,16 @@
|
||||
android:smallScreens="true"
|
||||
android:xlargeScreens="true" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.telephony"
|
||||
android:required="false" />
|
||||
<uses-feature android:name="android.hardware.telephony" android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_PHONE_STATE"
|
||||
android:required="false" />
|
||||
<uses-permission android:name="android.permission.BATTERY_STATS" />
|
||||
<uses-permission
|
||||
android:name="android.permission.RECEIVE_SMS"
|
||||
android:required="false" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:required="false" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" android:required="false" />
|
||||
<!-- <uses-permission android:name="android.permission.SEND_SMS" android:required="false" /> -->
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
@@ -36,6 +31,7 @@
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/icon"
|
||||
android:supportsRtl="true"
|
||||
android:label="KDE Connect"
|
||||
android:theme="@style/KdeConnectTheme"
|
||||
>
|
||||
@@ -119,6 +115,12 @@
|
||||
-->
|
||||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneActivity"
|
||||
android:label="@string/findmyphone_title"
|
||||
android:launchMode="singleInstance">
|
||||
</activity>
|
||||
|
||||
<!-- Plugin-related activities and services -->
|
||||
|
||||
<activity
|
||||
@@ -130,12 +132,20 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.UserInterface.MaterialActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.RunCommandPlugin.RunCommandActivity"
|
||||
android:label="@string/remote_control"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.MaterialActivity"
|
||||
>
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.UserInterface.MaterialActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.MousePadPlugin.MousePadActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:label="@string/remote_control"
|
||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.MaterialActivity"
|
||||
android:screenOrientation="fullSensor"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize" >
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
|
@@ -22,4 +22,4 @@ You can install this app from the [Play Store](https://play.google.com/store/app
|
||||
## License
|
||||
[GNU GPL v2](https://www.gnu.org/licenses/gpl-2.0.html) and [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
If you are reading this from Github, you should know that this is just a mirror of the [KDE Project repo](https://projects.kde.org/projects/playground/base/kdeconnect-android/repository/).
|
||||
If you are reading this from Github, you should know that this is just a mirror of the [KDE Project repo](https://projects.kde.org/projects/extragear/network/kdeconnect-android/repository/).
|
||||
|
@@ -7,7 +7,7 @@ function export_pot_file # First parameter will be the path of the pot file we h
|
||||
{
|
||||
potfile=$1
|
||||
mkdir outdir
|
||||
a2po export --android res/ --gettext outdir
|
||||
ANSI_COLORS_DISABLED=1 a2po export --android res/ --gettext outdir
|
||||
mv outdir/template.pot $potfile
|
||||
rm -rf outdir
|
||||
}
|
||||
@@ -15,7 +15,9 @@ function export_pot_file # First parameter will be the path of the pot file we h
|
||||
function import_po_files # First parameter will be a path that will contain several .po files with the format LANG.po
|
||||
{
|
||||
podir=$1
|
||||
a2po import --ignore-fuzzy --android res/ --gettext $podir
|
||||
ANSI_COLORS_DISABLED=1 a2po import --ignore-fuzzy --android res/ --gettext $podir
|
||||
#Android doesn't support languages with an @
|
||||
rm -r res/values-*@*
|
||||
}
|
||||
|
||||
|
||||
|
52
build.gradle
@@ -3,18 +3,29 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.3.0'
|
||||
classpath 'com.android.tools.build:gradle:2.1.2'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion '22.0.1'
|
||||
buildToolsVersion '23.0.3'
|
||||
compileSdkVersion 23
|
||||
defaultConfig {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 22
|
||||
targetSdkVersion 22 //Bumping to 23 means we have to support the new permissions model
|
||||
//multiDexEnabled true
|
||||
//testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
|
||||
}
|
||||
dexOptions {
|
||||
javaMaxHeapSize "2g"
|
||||
}
|
||||
compileOptions {
|
||||
// Use Java 1.7, requires minSdk 8
|
||||
//SSHD requires mina when running on JDK < 7
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
@@ -32,36 +43,45 @@ android {
|
||||
pickFirst "META-INF/DEPENDENCIES"
|
||||
pickFirst "META-INF/LICENSE"
|
||||
pickFirst "META-INF/NOTICE"
|
||||
pickFirst "META-INF/BCKEY.SF"
|
||||
pickFirst "META-INF/BCKEY.DSA"
|
||||
pickFirst "META-INF/INDEX.LIST"
|
||||
pickFirst "META-INF/io.netty.versions.properties"
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
checkReleaseBuilds false
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
debug {
|
||||
minifyEnabled false
|
||||
useProguard false
|
||||
}
|
||||
release { //keep on 'releae', set to 'all' when testing to make sure proguard is not deleting important stuff
|
||||
minifyEnabled true
|
||||
useProguard true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
compile 'com.android.support:support-v4:22.2.1'
|
||||
compile 'com.android.support:appcompat-v7:22.2.1'
|
||||
compile 'com.android.support:design:22.2.1'
|
||||
|
||||
compile 'org.apache.mina:mina-core:2.0.9'
|
||||
compile 'org.apache.sshd:sshd-core:0.8.0'
|
||||
compile 'org.bouncycastle:bcprov-jdk16:1.46'
|
||||
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 'org.apache.sshd:sshd-core:0.8.0' //0.9 seems to fail on Android 6 and 1.+ requires java.nio.file, which doesn't exist in Android
|
||||
|
||||
compile 'com.madgag.spongycastle:pkix:1.54.0.0' //For SSL certificate generation
|
||||
|
||||
// Testing
|
||||
androidTestCompile 'org.mockito:mockito-core:1.10.19'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'// Because mockito has some problems with dex environment
|
||||
androidTestCompile 'org.skyscreamer:jsonassert:1.3.0'
|
||||
|
||||
// Because mockito has some problems with dex environment
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker:1.1'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'
|
||||
|
||||
//compile fileTree(dir: 'libs', include: '*.jar')
|
||||
}
|
||||
|
31
icon.svg
@@ -14,7 +14,7 @@
|
||||
height="274.43201"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
inkscape:version="0.91 r"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:export-filename="/home/vaka/kdeconnect/kdeconnect-android/res/drawable-mdpi/icon.png"
|
||||
inkscape:export-xdpi="15.741604"
|
||||
@@ -736,23 +736,24 @@
|
||||
borderopacity="1"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="-397.02564"
|
||||
inkscape:cy="247.25211"
|
||||
inkscape:zoom="2"
|
||||
inkscape:cx="118.88075"
|
||||
inkscape:cy="143.06055"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1025"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
fit-margin-bottom="0"
|
||||
showborder="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2985"
|
||||
@@ -814,7 +815,7 @@
|
||||
id="layer1"
|
||||
transform="translate(8.7869998,-787.86042)">
|
||||
<path
|
||||
style="fill:#f2f2f2;fill-opacity:1;stroke:none"
|
||||
style="fill:#f5f5f5;fill-opacity:1;stroke:none"
|
||||
d="m 64.090487,801.86214 128.677053,0 c 5.09194,0 9.19121,3.92526 9.19121,8.80103 l 0,44.00509 -11.02945,0 0,-40.48469 -125.000587,0 0,214.74493 125.000587,0 0,-174.26024 11.02945,0 0,184.82144 c 0,4.8757 -4.09927,8.801 -9.19121,8.801 l -128.677053,0 c -5.091955,0 -9.191239,-3.9253 -9.191239,-8.801 l 0,-228.82653 c 0,-4.87577 4.099284,-8.80103 9.191239,-8.80103 z"
|
||||
id="rect3099-1"
|
||||
inkscape:connector-curvature="0"
|
||||
@@ -861,5 +862,19 @@
|
||||
id="rect3907-9-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
style="opacity:0.4;fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 72.876953,14.001953 c -5.091955,0 -9.191406,3.925011 -9.191406,8.800781 l 0,2 c 0,-4.87577 4.099451,-8.800781 9.191406,-8.800781 l 128.677737,0 c 5.09194,0 9.1914,3.925011 9.1914,8.800781 l 0,-2 c 0,-4.87577 -4.09946,-8.800781 -9.1914,-8.800781 z"
|
||||
transform="translate(-8.7869998,787.86042)"
|
||||
id="path4295"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sscsscsss" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;opacity:0.1"
|
||||
d="m 63.685547,249.62891 0,2 c 0,4.8757 4.099451,8.80078 9.191406,8.80078 l 128.677737,0 c 5.09194,0 9.1914,-3.92508 9.1914,-8.80078 l 0,-2 c 0,4.8757 -4.09946,8.80078 -9.1914,8.80078 l -128.677737,0 c -5.091955,0 -9.191406,-3.92508 -9.191406,-8.80078 z"
|
||||
id="path4300"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csssscssc"
|
||||
transform="translate(-8.7869998,787.86042)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
15
proguard-rules.pro
vendored
@@ -16,15 +16,24 @@
|
||||
# public *;
|
||||
#}
|
||||
|
||||
-dontobfuscate
|
||||
|
||||
# Allow obfuscation of android.support.v7.internal.view.menu.**
|
||||
# to avoid problem on Samsung 4.2.2 devices with appcompat v21
|
||||
# see https://code.google.com/p/android/issues/detail?id=78377
|
||||
-keep class !android.support.v7.internal.view.menu.**,** {*;}
|
||||
-keepnames class !android.support.v7.internal.view.menu.**,android.support.v7.** {*;}
|
||||
|
||||
-dontwarn org.spongycastle.**
|
||||
-dontwarn org.apache.sshd.**
|
||||
-dontwarn org.apache.mina.**
|
||||
-dontwarn org.bouncycastle.**
|
||||
-dontwarn org.slf4j.**
|
||||
-dontwarn io.netty.**
|
||||
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
-keepattributes SourceFile,LineNumberTable,Signature,*Annotation*
|
||||
|
||||
-keep class org.spongycastle.** {*;}
|
||||
|
||||
# SSHd requires mina, and mina uses reflection so some classes would get deleted
|
||||
-keep class org.apache.mina.** {*;}
|
||||
|
||||
-keep class org.kde.kdeconnect.** {*;}
|
||||
|
BIN
res/drawable-hdpi/ic_error_outline_black_48dp.png
Normal file
After Width: | Height: | Size: 959 B |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 449 B |
BIN
res/drawable-hdpi/runcommand_plugin_icon.png
Normal file
After Width: | Height: | Size: 553 B |
BIN
res/drawable-mdpi/ic_error_outline_black_48dp.png
Normal file
After Width: | Height: | Size: 650 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 290 B |
BIN
res/drawable-mdpi/runcommand_plugin_icon.png
Normal file
After Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 373 B After Width: | Height: | Size: 308 B |
BIN
res/drawable-xhdpi/ic_error_outline_black_48dp.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 529 B |
BIN
res/drawable-xhdpi/runcommand_plugin_icon.png
Normal file
After Width: | Height: | Size: 591 B |
Before Width: | Height: | Size: 684 B After Width: | Height: | Size: 608 B |
BIN
res/drawable-xxhdpi/ic_error_outline_black_48dp.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 686 B After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable-xxhdpi/runcommand_plugin_icon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable-xxxhdpi/ic_error_outline_black_48dp.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
res/drawable-xxxhdpi/mpris_plugin_action.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
res/drawable-xxxhdpi/runcommand_plugin_icon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-xxxhdpi/share_plugin_action.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
@@ -26,7 +26,6 @@
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/device_not_paired"
|
||||
android:id="@+id/pair_message"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
/>
|
||||
|
||||
<Button
|
||||
@@ -74,10 +73,14 @@
|
||||
android:id="@+id/unpair_message"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:drawableStart="@drawable/ic_error_outline_black_48dp"
|
||||
android:drawableLeft="@drawable/ic_error_outline_black_48dp"
|
||||
android:drawablePadding="8dip"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/unreachable_description"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:gravity="center" />
|
||||
/>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/buttons_list"
|
||||
|
26
res/layout/activity_find_my_phone.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<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"
|
||||
tools:context="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneActivity">
|
||||
|
||||
|
||||
|
||||
<Button
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/findmyphone_found"
|
||||
android:textSize="50dp"
|
||||
android:id="@+id/bFindMyPhone"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true" />
|
||||
|
||||
|
||||
|
||||
|
||||
</RelativeLayout>
|
@@ -12,22 +12,27 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
android:elevation="8dp"
|
||||
android:background="?attr/colorPrimary" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.design.widget.NavigationView
|
||||
android:id="@+id/navigation_drawer"
|
||||
android:background="@drawable/state_list_drawer_background"
|
||||
app:itemBackground="@drawable/state_list_drawer_background"
|
||||
app:itemTextColor="@color/state_list_drawer_text"
|
||||
app:itemIconTint="@color/state_list_drawer_text"
|
||||
|
@@ -29,8 +29,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:singleLine="true"
|
||||
android:textColor="#CC2222"
|
||||
android:visibility="gone"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:text="" />
|
||||
|
||||
|
||||
|
@@ -7,9 +7,9 @@
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/mpris_control_view"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="60dip"
|
||||
android:paddingLeft="30dip"
|
||||
android:paddingTop="5dip"
|
||||
android:paddingRight="60dip"
|
||||
android:paddingRight="30dip"
|
||||
android:paddingBottom="5dip">
|
||||
|
||||
<TextView
|
||||
@@ -20,6 +20,11 @@
|
||||
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"
|
||||
@@ -32,6 +37,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:id="@+id/now_playing_textview"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true"
|
||||
android:gravity="center"
|
||||
android:padding="8dip"
|
||||
@@ -148,7 +156,6 @@
|
||||
android:layout_marginEnd="10dip"
|
||||
android:id="@+id/imageView"
|
||||
android:layout_weight="0"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
android:contentDescription="@string/mpris_volume"
|
||||
android:src="@drawable/ic_volume"
|
||||
/>
|
||||
|
@@ -1,21 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:padding="16dp"
|
||||
android:background="@drawable/drawer_header"
|
||||
android:orientation="vertical"
|
||||
android:gravity="bottom">
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="KDE Connect"
|
||||
android:textColor="#FFF"
|
||||
android:textStyle="bold"
|
||||
android:paddingBottom="4dp"
|
||||
android:layout_above="@+id/device_name"
|
||||
android:id="@+id/kdeconnect_label"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="48dp"
|
||||
android:paddingEnd="48dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
@@ -23,12 +25,14 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="My device"
|
||||
android:id="@+id/device_name"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:textColor="#fff"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
/>
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingRight="48dp"
|
||||
android:paddingEnd="48dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingLeft="16dp" />
|
||||
|
||||
<!--
|
||||
<ImageView
|
||||
@@ -46,4 +50,4 @@
|
||||
/>
|
||||
-->
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
@@ -18,14 +18,13 @@
|
||||
Preference is able to place a specific widget for its particular
|
||||
type in the "widget_frame" layout. -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:res="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingEnd="?android:attr/scrollbarSize"
|
||||
android:paddingRight="?android:attr/scrollbarSize"
|
||||
android:background="?attr/selectableItemBackground" >
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<!-- Preference should place its actual preference widget here. -->
|
||||
<LinearLayout android:id="@+android:id/widget_frame"
|
||||
|
@@ -5,12 +5,9 @@
|
||||
<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_desc">تحكّم بالصّوت والصّورة من هاتفك</string>
|
||||
<string name="pref_plugin_ping">وخزة</string>
|
||||
<string name="pref_plugin_ping_desc">أرسل واستقبل وخزات</string>
|
||||
<string name="pref_plugin_notifications">مزامنة الإخطارات</string>
|
||||
@@ -27,6 +24,13 @@
|
||||
<item/>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">الأجهزة المقترن بها</string>
|
||||
<string name="category_not_paired_devices">الأجهزة المتوفّرة</string>
|
||||
<string name="category_remembered_devices">الأجهزة المتذكَّرة</string>
|
||||
|
153
res/values-ast/strings.xml
Normal file
@@ -0,0 +1,153 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Notificador telefónicu</string>
|
||||
<string name="pref_plugin_telephony_desc">Unvia avisos pa SMS y llamaes</string>
|
||||
<string name="pref_plugin_battery">Informe de batería</string>
|
||||
<string name="pref_plugin_battery_desc">Infoma davezu del estáu de la batería</string>
|
||||
<string name="pref_plugin_sftp">Esposición del sistema de ficheros</string>
|
||||
<string name="pref_plugin_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_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_desc">Comparte ficheros y URLs ente preseos</string>
|
||||
<string name="plugin_not_available">Esta carauterística nun ta disponible na to versión d\'Android</string>
|
||||
<string name="device_list_empty">Ensin preseos</string>
|
||||
<string name="ok">Aceutar</string>
|
||||
<string name="cancel">Encaboxar</string>
|
||||
<string name="open_settings">Abrir axustes</string>
|
||||
<string name="no_permissions">Necesites garantizar l\'accesu a los avisos</string>
|
||||
<string name="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-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>Above Slowest</item>
|
||||
<item>Predeterminada</item>
|
||||
<item>Penriba lo predeterminao</item>
|
||||
<item>La más rápida</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Preseos coneutaos</string>
|
||||
<string name="category_not_paired_devices">Preseos disponibles</string>
|
||||
<string name="category_remembered_devices">Preseos recordaos</string>
|
||||
<string name="plugins_failed_to_load">Los complementos fallaron al cargase (calca pa más información):</string>
|
||||
<string name="device_menu_plugins">Axustes de complementos</string>
|
||||
<string name="device_menu_unpair">Desempareyar</string>
|
||||
<string name="device_not_reachable">El preséu empareyáu nun ye agamable</string>
|
||||
<string name="pair_new_device">Empareyar preséu nuevu</string>
|
||||
<string name="unknown_device">Preséu desconocíu</string>
|
||||
<string name="error_not_reachable">Nun ye algamable\'l preséu</string>
|
||||
<string name="error_already_requested">Empareyamientu yá solicitáu</string>
|
||||
<string name="error_already_paired">El preséu yá ta empareyáu</string>
|
||||
<string name="error_could_not_send_package">Nun pudo unviase\'l paquete</string>
|
||||
<string name="error_timed_out">Tiempu escosao</string>
|
||||
<string name="error_canceled_by_user">Encaboxáu pol usuariu</string>
|
||||
<string name="error_canceled_by_other_peer">Encaboxáu pola otra parte</string>
|
||||
<string name="error_invalid_key">Recibióse una clave non válida</string>
|
||||
<string name="pair_requested">Solicitóse l\'empareyamientu</string>
|
||||
<string name="pairing_request_from">Solicitú d\'empareyamientu de %1s</string>
|
||||
<string name="received_url_title">Recibióse l\'enllaz de %1s</string>
|
||||
<string name="received_url_text">Calca p\'abrir «%1s»</string>
|
||||
<string name="incoming_file_title">Ficheru entrante de %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Unviando ficheru a %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="received_file_title">Recibióse\'l ficheru de %1s</string>
|
||||
<string name="received_file_fail_title">Fallu al recibir el ficheru de %1s</string>
|
||||
<string name="received_file_text">Tap to open \'%1s\'</string>
|
||||
<string name="sent_file_title">Unvióse\'l ficheru a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_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>
|
||||
<string name="pairing_accept">Aceutar</string>
|
||||
<string name="pairing_reject">Refugar</string>
|
||||
<string name="device">Preséu</string>
|
||||
<string name="pair_device">Empareyar preséu</string>
|
||||
<string name="remote_control">Control remotu</string>
|
||||
<string name="settings">Axustes KDE Connect</string>
|
||||
<string name="mpris_play">Reproducir</string>
|
||||
<string name="mpris_previous">Anterior</string>
|
||||
<string name="mpris_rew">Rebobinar</string>
|
||||
<string name="mpris_ff">Avance rápidu</string>
|
||||
<string name="mpris_next">Siguiente</string>
|
||||
<string name="mpris_volume">Volume</string>
|
||||
<string name="mpris_settings">Axustes multimedia</string>
|
||||
<string name="mpris_time_settings_title">Botones d\'avanzar/rebobinar</string>
|
||||
<string name="mpris_time_settings_summary">Axusta\'l tiempu p\'avanzar/rebobinar al primise</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 segundos</item>
|
||||
<item>20 segundos</item>
|
||||
<item>30 segundos</item>
|
||||
<item>1 minutu</item>
|
||||
<item>2 minutos</item>
|
||||
</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>
|
||||
<string name="plugin_settings">Axustes</string>
|
||||
<string name="plugin_settings_with_name">Axustes de %s</string>
|
||||
<string name="device_name">Nome de preséu</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Nome de preséu non válidu</string>
|
||||
<string name="shareplugin_text_saved">Recibióse\'l testu y guardóse nel cartafueyu</string>
|
||||
<string name="custom_devices_settings">Llista de preseos personalizada</string>
|
||||
<string name="pair_device_action">Empareyar con un preséu nuevu</string>
|
||||
<string name="unpair_device_action">Desempareyar %s</string>
|
||||
<string name="custom_device_list">Amestar preseos pola IP</string>
|
||||
<string name="share_notification_preference">Avisos sonoros</string>
|
||||
<string name="share_notification_preference_summary">Fai vibrar y reproduz un soníu al recibir un ficheru</string>
|
||||
<string name="title_activity_notification_filter">Peñera d\'avisos</string>
|
||||
<string name="filter_apps_info">Los avisos sincronizaránse coles aplicaciones esbillaes.</string>
|
||||
<string name="sftp_internal_storage">Almacenamientu internu</string>
|
||||
<string name="sftp_all_files">Tolos ficheros</string>
|
||||
<string name="sftp_sdcard_num">Tarxeta SD %d</string>
|
||||
<string name="sftp_sdcard">Tarxeta SD</string>
|
||||
<string name="sftp_readonly">(namai llectura)</string>
|
||||
<string name="sftp_camera">Semeyes de cámara</string>
|
||||
<string name="add_host">Amestar agospiu/IP</string>
|
||||
<string name="add_host_hint">Nome d\'agospiu o IP</string>
|
||||
<string name="no_players_connected">Nun s\'alcontraron reproductores</string>
|
||||
<string name="custom_dev_list_help">Usa esta opción namái si\'l to preséu nun se deteuta automáticamente. Introduz la direición o\'l nome d\'agospiu y toca\'l botón p\'amestalu a la llista. Toca un elementu esistente pa desanicialu de la llista.</string>
|
||||
<string name="mpris_player_on_device">%1$s en %2$s</string>
|
||||
<string name="send_files">Unviar ficheros</string>
|
||||
<string name="pairing_title">Preseos KDE Connect</string>
|
||||
<string name="pairing_description">Equí deberíen apaecer otros preseos executando KDE Connect.</string>
|
||||
<string name="device_paired">Preséu empareyáu</string>
|
||||
<string name="device_rename_title">Renomar preséu</string>
|
||||
<string name="device_rename_confirm">Renomar</string>
|
||||
<string name="refresh">Refrescar</string>
|
||||
<string name="unreachable_description">Esti preséu empareyáu nun ye algamable. Asegúrate que ta coneutáu a la to mesma rede.</string>
|
||||
<string name="no_file_browser">Nun hai restoladores de ficheros instalaos.</string>
|
||||
<string name="pref_plugin_telepathy">Unviar SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Unvia mensaxes de testu dende\'l to escritoriu</string>
|
||||
<string name="plugin_not_supported">Esti complementu nun ta sofitáu pol preséu</string>
|
||||
<string name="findmyphone_found">Alcontrar</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Zarrar</string>
|
||||
</resources>
|
@@ -5,10 +5,8 @@
|
||||
<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_mpris_desc">Управление на звук/видео от телефона</string>
|
||||
<string name="pref_plugin_ping">Пинг</string>
|
||||
<string name="pref_plugin_ping_desc">Изпращане и получаване на пинг</string>
|
||||
<string name="pref_plugin_notifications">Синхронизиране на уведомленията</string>
|
||||
@@ -25,6 +23,13 @@
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Свързани устройства</string>
|
||||
<string name="category_remembered_devices">Запомнени устройства</string>
|
||||
<string name="plugins_failed_to_load">Неуспешно зареждане на приставки (докоснете за подробности)</string>
|
||||
|
@@ -5,12 +5,9 @@
|
||||
<string name="pref_plugin_battery">Baterijski izvještaj</string>
|
||||
<string name="pref_plugin_battery_desc">Periodično javi baterijski status</string>
|
||||
<string name="pref_plugin_sftp">Otkrivanje datotečnog sistema</string>
|
||||
<string name="pref_plugin_sftp_desc">Dopušta daljinsko pretraživanje datotečnog sistema telefona</string>
|
||||
<string name="pref_plugin_clipboard">Sinhronizovanje sandučića</string>
|
||||
<string name="pref_plugin_clipboard_desc">Podijeli sadržaj sandučića</string>
|
||||
<string name="pref_plugin_mousepad">Daljinska kontrola ulaza</string>
|
||||
<string name="pref_plugin_mousepad_desc">Koristi telofon kao miš i tastaturu</string>
|
||||
<string name="pref_plugin_mpris_desc">Upravljajte zvukom/slikom sa vašeg telefona</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Šalji i primaj ping-ove</string>
|
||||
<string name="pref_plugin_notifications">Sinhronizovano obavještenje</string>
|
||||
@@ -32,6 +29,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">desno</string>
|
||||
<string name="mousepad_triple_default">Srednje</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Spojeni uređaji</string>
|
||||
<string name="category_not_paired_devices">Dostupni uređaji</string>
|
||||
<string name="category_remembered_devices">Zapamćeni uređaji</string>
|
||||
|
@@ -5,17 +5,21 @@
|
||||
<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>
|
||||
<string name="pref_plugin_sftp">Exposa el sistema de fitxers</string>
|
||||
<string name="pref_plugin_sftp_desc">Permet navegar de forma remota pel sistema de fitxers del telèfon</string>
|
||||
<string name="pref_plugin_sftp_desc">Permet navegar de forma remota pel sistema de fitxers del dispositiu</string>
|
||||
<string name="pref_plugin_clipboard">Sincronitza el porta-retalls</string>
|
||||
<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 com un ratolí i un teclat</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_mpris">Controls multimèdia</string>
|
||||
<string name="pref_plugin_mpris_desc">Controla l\'àudio i el vídeo del vostre telèfon</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>
|
||||
<string name="pref_plugin_runcommand_desc">Activa les ordres remotes des del telèfon o tauleta</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Envia i rep els pings</string>
|
||||
<string name="pref_plugin_notifications">Sincronitza les notificacions</string>
|
||||
<string name="pref_plugin_notifications_desc">Accedeix a les vostres notificacions des d\'altres dispositius</string>
|
||||
<string name="pref_plugin_receive_notifications">Recepció de les notificacions</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Rep notificacions des d\'altres dispositius i mostrar-los a l\'Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Comparteix i rep</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Comparteix els fitxers i els URL entre els dispositius</string>
|
||||
<string name="plugin_not_available">Aquesta característica no està disponible en la vostra versió d\'Android</string>
|
||||
@@ -30,6 +34,8 @@
|
||||
<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>
|
||||
<string name="mousepad_triple_tap_settings_title">Estableix l\'acció de tocar amb tres dits</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Estableix la sensibilitat del ratolí tàctil</string>
|
||||
<string name="mousepad_scroll_direction_title">Inverteix la direcció del desplaçament</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic dret</item>
|
||||
<item>Clic del mig</item>
|
||||
@@ -37,6 +43,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">dret</string>
|
||||
<string name="mousepad_triple_default">mig</string>
|
||||
<string name="mousepad_sensitivity_default">Predeterminada</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>La més lenta</item>
|
||||
<item>Lenta</item>
|
||||
<item>Predeterminada</item>
|
||||
<item>Ràpida</item>
|
||||
<item>La més ràpida</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositius connectats</string>
|
||||
<string name="category_not_paired_devices">Dispositius disponibles</string>
|
||||
<string name="category_remembered_devices">Dispositius recordats</string>
|
||||
@@ -44,6 +58,7 @@
|
||||
<string name="device_menu_plugins">Arranjament del connector</string>
|
||||
<string name="device_menu_unpair">Desparella</string>
|
||||
<string name="device_not_reachable">No s\'ha pogut accedir al dispositiu parell</string>
|
||||
<string name="pair_new_device">Aparella amb un dispositiu nou</string>
|
||||
<string name="unknown_device">Dispositiu desconegut</string>
|
||||
<string name="error_not_reachable">No es pot accedir al dispositiu</string>
|
||||
<string name="error_already_requested">Ja s\'ha demanat aparellar</string>
|
||||
@@ -53,6 +68,10 @@
|
||||
<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_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>
|
||||
<string name="pair_requested">S\'ha demanat aparellar</string>
|
||||
<string name="pairing_request_from">S\'ha demanat aparellar des de %1s</string>
|
||||
<string name="received_url_title">S\'ha rebut un vincle des de %1s</string>
|
||||
@@ -138,4 +157,10 @@
|
||||
<string name="pref_plugin_telepathy">Envia un SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Envia missatges de text des de l\'escriptori</string>
|
||||
<string name="plugin_not_supported">Aquest connector no és admès pel dispositiu</string>
|
||||
<string name="findmyphone_title">Cerca el meu telèfon</string>
|
||||
<string name="findmyphone_title_tablet">Cerca la meva tauleta</string>
|
||||
<string name="findmyphone_description">Fa sonar aquest dispositiu perquè el pugueu trobar.</string>
|
||||
<string name="findmyphone_found">L\'he trobat</string>
|
||||
<string name="open">Obre</string>
|
||||
<string name="close">Tanca</string>
|
||||
</resources>
|
||||
|
@@ -5,13 +5,11 @@
|
||||
<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 telefonu</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 jako myš a klávesnici</string>
|
||||
<string name="pref_plugin_mpris">Ovládání multimédií</string>
|
||||
<string name="pref_plugin_mpris_desc">Ovládejte audio/video z vašeho telefonu</string>
|
||||
<string name="pref_plugin_runcommand">Spustit příkaz</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>
|
||||
@@ -30,6 +28,8 @@
|
||||
<string name="mousepad_info">Pohybujte prstem po obrazovce pro pohybování kurzorem myši. Ťukněte pro kliknutí a použijte dva/tři prsty jako pravé a prostřední tlačítko. Pro přetažení dlouze podržte.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Nastavit činnost pro ťuknutí dvěma prsty</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Nastavit činnost pro ťuknutí třemi prsty</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Nastavit citlivost touchpadu</string>
|
||||
<string name="mousepad_scroll_direction_title">Obrácený směr posunu</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Kliknutí pravým tlačítkem myši</item>
|
||||
<item>Kliknutí prostředním tlačítkem myši</item>
|
||||
@@ -37,6 +37,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">pravé</string>
|
||||
<string name="mousepad_triple_default">prostřední</string>
|
||||
<string name="mousepad_sensitivity_default">výchozí</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Nejpomalejší</item>
|
||||
<item>Méně pomalý</item>
|
||||
<item>Výchozí</item>
|
||||
<item>Rychlejší</item>
|
||||
<item>Nejrychlejší</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Připojená zařízení</string>
|
||||
<string name="category_not_paired_devices">Dostupná zařízení</string>
|
||||
<string name="category_remembered_devices">Zapamatovaná zařízení</string>
|
||||
@@ -44,6 +52,7 @@
|
||||
<string name="device_menu_plugins">Nastavení modulů</string>
|
||||
<string name="device_menu_unpair">Zrušit párování</string>
|
||||
<string name="device_not_reachable">Spárované zařízení je nedostupné</string>
|
||||
<string name="pair_new_device">Spárovat nové zařízení</string>
|
||||
<string name="unknown_device">Neznámé zařízení</string>
|
||||
<string name="error_not_reachable">Zařízení je nedostupné</string>
|
||||
<string name="error_already_requested">Párování již bylo vyžádáno</string>
|
||||
@@ -53,6 +62,7 @@
|
||||
<string name="error_canceled_by_user">Přerušeno uživatelem</string>
|
||||
<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="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>
|
||||
@@ -138,4 +148,8 @@
|
||||
<string name="pref_plugin_telepathy">Poslat SMS</string>
|
||||
<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_found">Nalezeno</string>
|
||||
<string name="open">Otevřít</string>
|
||||
<string name="close">Zavřít</string>
|
||||
</resources>
|
||||
|
@@ -5,16 +5,17 @@
|
||||
<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 telefonens 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 som mus og tastatur</string>
|
||||
<string name="pref_plugin_mpris_desc">Styr lyd og video fra din telefon</string>
|
||||
<string name="pref_plugin_mpris">Multimediekontroller</string>
|
||||
<string name="pref_plugin_runcommand">Kør kommando</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_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>
|
||||
<string name="device_list_empty">Ingen enheder</string>
|
||||
<string name="ok">O.k.</string>
|
||||
@@ -22,9 +23,13 @@
|
||||
<string name="open_settings">Åbn indstillinger</string>
|
||||
<string name="no_permissions">Du skal give tilladelse for at tilgå bekendtgørelser</string>
|
||||
<string name="send_ping">Send ping</string>
|
||||
<string name="open_mpris_controls">Multimediekontrol</string>
|
||||
<string name="open_mousepad">Eksternt input</string>
|
||||
<string name="mousepad_info">Bevæg en finger på skærmen for at flytte musemarkøren. Tap for at klikke og brug to/tre-fingre for højre og midterste museknap. Brug et langt tryk til at trække og slippe.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Angiv handling for tap med to fingre</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Angiv handling for tap med tre fingre</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Angiv følsomhed for touchpad</string>
|
||||
<string name="mousepad_scroll_direction_title">Omvendt rulleretning</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Højreklik</item>
|
||||
<item>Midterklik</item>
|
||||
@@ -32,6 +37,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">højre</string>
|
||||
<string name="mousepad_triple_default">midter</string>
|
||||
<string name="mousepad_sensitivity_default">standard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Mest langsom</item>
|
||||
<item>Over mest langsom</item>
|
||||
<item>Standard</item>
|
||||
<item>Over standard</item>
|
||||
<item>Hurtigst</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Forbundne enheder</string>
|
||||
<string name="category_not_paired_devices">Tilgængelig enheder</string>
|
||||
<string name="category_remembered_devices">Huskede enheder</string>
|
||||
@@ -39,6 +52,7 @@
|
||||
<string name="device_menu_plugins">Plugin-indstillinger</string>
|
||||
<string name="device_menu_unpair">Fjern parring</string>
|
||||
<string name="device_not_reachable">Den parrede enhed kan ikke tilgås</string>
|
||||
<string name="pair_new_device">Par med ny enhed</string>
|
||||
<string name="unknown_device">Ukendt enhed</string>
|
||||
<string name="error_not_reachable">Enheden kan ikke nås</string>
|
||||
<string name="error_already_requested">Allerede anmodet om parring</string>
|
||||
@@ -48,6 +62,10 @@
|
||||
<string name="error_canceled_by_user">Annulleret af brugeren</string>
|
||||
<string name="error_canceled_by_other_peer">Annulleret af modpart</string>
|
||||
<string name="error_invalid_key">Ugyldige nøgle modtaget</string>
|
||||
<string name="encryption_info_title">Krypteringsinfo</string>
|
||||
<string name="encryption_info_msg_no_ssl">Den anden enhed bruger ikke en nylig version af KDE Connect, og bruger dermed den forældede krypteringsmetode.</string>
|
||||
<string name="my_device_fingerprint">SHA1-fingeraftrykket for dit enhedscertifikat er:</string>
|
||||
<string name="remote_device_fingerprint">SHA1-fingeraftrykket for det eksterne enhedscertifikat er:</string>
|
||||
<string name="pair_requested">Anmodet om parring</string>
|
||||
<string name="pairing_request_from">Parringsanmodning fra %1s</string>
|
||||
<string name="received_url_title">Modtog link fra %1s</string>
|
||||
@@ -103,6 +121,8 @@
|
||||
<string name="invalid_device_name">Ugyldigt enhedsnavn</string>
|
||||
<string name="shareplugin_text_saved">Modtog tekst, gemt til udklipsholder</string>
|
||||
<string name="custom_devices_settings">Brugertilpasset liste over enheder</string>
|
||||
<string name="pair_device_action">Par med en ny enhed</string>
|
||||
<string name="unpair_device_action">Fjern parring med %s</string>
|
||||
<string name="custom_device_list">Tilføj enheder via IP</string>
|
||||
<string name="share_notification_preference">Støjende bekendtgørelser</string>
|
||||
<string name="share_notification_preference_summary">Vibrér og afspil en lyd når en fil modtages</string>
|
||||
@@ -119,4 +139,20 @@
|
||||
<string name="no_players_connected">Ingen afspillere fundet</string>
|
||||
<string name="custom_dev_list_help">Brug kun denne indstilling hvis din enhed ikke opdages automatisk. Angiv IP-adresse eller værtsnavn nedenfor og tryk på knappen for at føje den til listen. Tryk på et eksisterende element for at fjerne det fra listen.</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-enheder</string>
|
||||
<string name="pairing_description">Andre enheder som kører KDE Connect i samme netværk som dig, bør dukke op her.</string>
|
||||
<string name="device_paired">Enhed parret</string>
|
||||
<string name="device_rename_title">Omdøb enhed</string>
|
||||
<string name="device_rename_confirm">Omdøb</string>
|
||||
<string name="refresh">Genopfrisk</string>
|
||||
<string name="unreachable_description">Denne parrede enhed kan ikke nås. Sørg for at den er forbundet til samme netværk som dig.</string>
|
||||
<string name="no_file_browser">Der er ingen filhåndtering installeret.</string>
|
||||
<string name="pref_plugin_telepathy">Send SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Send SMS-beskeder fra din desktop</string>
|
||||
<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_found">Fundet</string>
|
||||
<string name="open">Åbn</string>
|
||||
<string name="close">Luk</string>
|
||||
</resources>
|
||||
|
@@ -5,12 +5,12 @@
|
||||
<string name="pref_plugin_battery">Akkubericht</string>
|
||||
<string name="pref_plugin_battery_desc">Akkustatus periodisch berichten</string>
|
||||
<string name="pref_plugin_sftp">Dateisystem zeigen</string>
|
||||
<string name="pref_plugin_sftp_desc">Erlaubt das Browsen des Dateisystems auf dem entfernten Handy</string>
|
||||
<string name="pref_plugin_sftp_desc">Erlaubt das Browsen des Dateisystems auf diesem Gerät aus der Ferne</string>
|
||||
<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_desc">Verwendet Ihr Handy als Maus und Tastatur</string>
|
||||
<string name="pref_plugin_mousepad">Ferneingabe</string>
|
||||
<string name="pref_plugin_mpris">Multimedia-Bedienung</string>
|
||||
<string name="pref_plugin_mpris_desc">Audio und Video mit Ihrem Telefon steuern</string>
|
||||
<string name="pref_plugin_runcommand">Befehl 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>
|
||||
@@ -25,6 +25,11 @@
|
||||
<string name="no_permissions">Sie müssen die Erlaubnis zum Zugriff auf Benachrichtigungen erteilen</string>
|
||||
<string name="send_ping">Ping senden</string>
|
||||
<string name="open_mpris_controls">Multimedia-Bedienung</string>
|
||||
<string name="open_mousepad">Ferneingabe</string>
|
||||
<string name="mousepad_double_tap_settings_title">Aktionsausführung bei Berührung mit zwei Fingern einstellen</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Aktionsausführung bei Berührung mit drei Fingern einstellen</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Empfindlichkeit des Touchpads einstellen</string>
|
||||
<string name="mousepad_scroll_direction_title">Bildlaufrichtung umkehren</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Rechtsklick</item>
|
||||
<item>Mittelklick</item>
|
||||
@@ -32,6 +37,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Rechts</string>
|
||||
<string name="mousepad_triple_default">Mitte</string>
|
||||
<string name="mousepad_sensitivity_default">Standard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Langsamste</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Standard</item>
|
||||
<item>Above Default</item>
|
||||
<item>Schnellste</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Verbundene Geräte</string>
|
||||
<string name="category_not_paired_devices">Verfügbare Gerät</string>
|
||||
<string name="category_remembered_devices">Gemerkte Geräte</string>
|
||||
@@ -39,6 +52,7 @@
|
||||
<string name="device_menu_plugins">Modul-Einstellungen</string>
|
||||
<string name="device_menu_unpair">Verbindung trennen</string>
|
||||
<string name="device_not_reachable">Das angegeben Gerät ist nicht erreichbar</string>
|
||||
<string name="pair_new_device">Ein neues Gerät verbinden</string>
|
||||
<string name="unknown_device">Unbekanntes Gerät</string>
|
||||
<string name="error_not_reachable">Das Gerät ist nicht erreichbar</string>
|
||||
<string name="error_already_requested">Die Verbindung wurde bereits angefragt</string>
|
||||
@@ -48,6 +62,9 @@
|
||||
<string name="error_canceled_by_user">Abbruch durch Benutzer</string>
|
||||
<string name="error_canceled_by_other_peer">Abbruch durch Gegenstelle</string>
|
||||
<string name="error_invalid_key">Ungültiger Schlüssel empfangen</string>
|
||||
<string name="encryption_info_title">Verschlüsselungsinformationen</string>
|
||||
<string name="my_device_fingerprint">Der SHA1-Fingerabdruck Ihres Gerätezertifikats lautet:</string>
|
||||
<string name="remote_device_fingerprint">Der SHA1-Fingerabdruck des Gerätezertifikats der Gegenstelle lautet:</string>
|
||||
<string name="pair_requested">Verbindung angefordert</string>
|
||||
<string name="pairing_request_from">Verbindungsanfrage von %1s</string>
|
||||
<string name="received_url_title">Verknüpfung von %1s erhalten</string>
|
||||
@@ -81,6 +98,7 @@
|
||||
<string name="mpris_next">Weiter</string>
|
||||
<string name="mpris_volume">Lautstärke</string>
|
||||
<string name="mpris_settings">Multimedia-Einstellungen</string>
|
||||
<string name="mpris_time_settings_title">Knöpfe Vorwärts/Rückwärts</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 Sekunden</item>
|
||||
<item>20 Sekunden</item>
|
||||
@@ -99,7 +117,10 @@
|
||||
<string name="invalid_device_name">Ungültiger Gerätename</string>
|
||||
<string name="shareplugin_text_saved">Text empfangen und in der Zwischenablage gespeichert</string>
|
||||
<string name="custom_devices_settings">Benutzerdefinierte Geräteliste</string>
|
||||
<string name="pair_device_action">Ein neues Gerät verbinden</string>
|
||||
<string name="unpair_device_action">Verbindung %s trennen</string>
|
||||
<string name="custom_device_list">Geräte nach IP hinzufügen</string>
|
||||
<string name="share_notification_preference">Ausführliche Benachrichtigungen</string>
|
||||
<string name="share_notification_preference_summary">Beim Empfang einer Datei vibrieren und einen Sound abspielen</string>
|
||||
<string name="title_activity_notification_filter">Benachrichtigungs-Filter</string>
|
||||
<string name="filter_apps_info">Benachrichtigungen werden zwischen den ausgewählten Anwendungen abgeglichen.</string>
|
||||
@@ -113,4 +134,19 @@
|
||||
<string name="add_host_hint">Rechnername oder IP</string>
|
||||
<string name="no_players_connected">Keine Medienspieler gefunden</string>
|
||||
<string name="mpris_player_on_device">%1$s auf %2$s</string>
|
||||
<string name="send_files">Dateien senden</string>
|
||||
<string name="pairing_title">KDE-Connect-Geräte</string>
|
||||
<string name="pairing_description">Andere Geräte, auf denen KDE-Connect läuft im gleichen Netzwerk,sollte hier angezeigt werden.</string>
|
||||
<string name="device_paired">Gerät verbunden</string>
|
||||
<string name="device_rename_title">Geräte umbenennen</string>
|
||||
<string name="device_rename_confirm">Umbenennen</string>
|
||||
<string name="refresh">Aktualisieren</string>
|
||||
<string name="no_file_browser">Es sind keine Dateiverwaltungsprogramme installiert.</string>
|
||||
<string name="pref_plugin_telepathy">SMS senden</string>
|
||||
<string name="pref_plugin_telepathy_desc">Text-Nachrichten von Ihrer Arbeitsfläche senden</string>
|
||||
<string name="plugin_not_supported">Dieses Modul wird durch das Gerät nicht unterstützt</string>
|
||||
<string name="findmyphone_title">Mein Telefon suchen</string>
|
||||
<string name="findmyphone_found">Gefunden</string>
|
||||
<string name="open">Öffnen</string>
|
||||
<string name="close">Schließen</string>
|
||||
</resources>
|
||||
|
158
res/values-el/strings.xml
Normal file
@@ -0,0 +1,158 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Ειδοποιήσεις τηλεφωνίας</string>
|
||||
<string name="pref_plugin_telephony_desc">Αποστολή ειδοποιήσεων για SMS και κλήσεις</string>
|
||||
<string name="pref_plugin_battery">Αναφορά μπαταρίας</string>
|
||||
<string name="pref_plugin_battery_desc">Περιοδική αναφορά κατάστασης μπαταρίας</string>
|
||||
<string name="pref_plugin_sftp">Αποκάλυψη συστήματος αρχείων</string>
|
||||
<string name="pref_plugin_clipboard">Συγχρονισμός προχείρου</string>
|
||||
<string name="pref_plugin_clipboard_desc">Διαμοιρασμός περιεχομένου προχείρου</string>
|
||||
<string name="pref_plugin_mousepad">Απομακρυσμένη είσοδος στοιχείων</string>
|
||||
<string name="pref_plugin_mpris">Κονσόλα πολυμέσων</string>
|
||||
<string name="pref_plugin_runcommand">Εκτέλεση εντολής</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_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">Εντάξει</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 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>
|
||||
<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_title">Αποτυχία αποστολής αρχείου %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Χτυπήστε για να απαντήσετε</string>
|
||||
<string name="reconnect">Επανασύνδεση</string>
|
||||
<string name="right_click">Αποστολή δεξιού κλικ</string>
|
||||
<string name="middle_click">Αποστολή μεσαίου κλικ</string>
|
||||
<string name="show_keyboard">Εμφάνιση πληκτρολογίου</string>
|
||||
<string name="device_not_paired">Η συσκευή δεν συζεύχθηκε</string>
|
||||
<string name="request_pairing">Αίτημα σύζευξης</string>
|
||||
<string name="pairing_accept">Αποδοχή</string>
|
||||
<string name="pairing_reject">Απόρριψη</string>
|
||||
<string name="device">Συσκευή</string>
|
||||
<string name="pair_device">Σύζευξη συσκευής</string>
|
||||
<string name="remote_control">Απομακρυσμένος έλεγχος</string>
|
||||
<string name="settings">Ρυθμίσεις KDE Connect</string>
|
||||
<string name="mpris_play">Αναπαραγωγή</string>
|
||||
<string name="mpris_previous">Προηγούμενο</string>
|
||||
<string name="mpris_rew">Ταχεία ώθηση όπισθεν</string>
|
||||
<string name="mpris_ff">Ταχεία προώθηση</string>
|
||||
<string name="mpris_next">Επόμενο</string>
|
||||
<string name="mpris_volume">Τόμος</string>
|
||||
<string name="mpris_settings">Ρυθμίσεις πολυμέσων</string>
|
||||
<string name="mpris_time_settings_title">Κουμπιά ταχείας ώθησης</string>
|
||||
<string name="mpris_time_settings_summary">Χρονική προσαρμογή ταχείας ώθησης ανάλογα με την πίεση.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 seconds</item>
|
||||
<item>20 seconds</item>
|
||||
<item>30 seconds</item>
|
||||
<item>1 λεπτό</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">Οι ειδοποιήσεις θα συγχρονίζονται για επιλεγμένες εφαρμογές.</string>
|
||||
<string name="sftp_internal_storage">Εσωτερικός αποθηκευτικός χώρος</string>
|
||||
<string name="sftp_all_files">Όλα τα αρχεία</string>
|
||||
<string name="sftp_sdcard_num">SD card %d</string>
|
||||
<string name="sftp_sdcard">SD card</string>
|
||||
<string name="sftp_readonly">(ανάγνωση μόνο)</string>
|
||||
<string name="sftp_camera">Φωτογραφίες</string>
|
||||
<string name="add_host">Προσθήκη υπολογιστή/IP</string>
|
||||
<string name="add_host_hint">Όνομα υπολογιστή ή IP</string>
|
||||
<string name="no_players_connected">Δεν βρέθηκαν συσκευές αναπαραγωγής</string>
|
||||
<string name="custom_dev_list_help">Χρησιμοποιήστε την επιλογή αυτή μόνο αν η συσκευή σας δεν έχει εντοπιστεί αυτόματα. Δώστε την IP διεύθυνση ή το όνομα του υπολογιστή και αγγίξτε το κουμπί για να προστεθεί στη λίστα. Αγγίξτε ένα αντικείμενο της λίστας για να το αφαιρέσετε.</string>
|
||||
<string name="mpris_player_on_device">%1$s σε %2$s</string>
|
||||
<string name="send_files">Αποστολή αρχείων</string>
|
||||
<string name="pairing_title">Συσκευές KDE Connect</string>
|
||||
<string name="pairing_description">Άλλες συσκευές με KDE Connect στο ίδιο δίκτυο θα εμφανίζονται εδώ.</string>
|
||||
<string name="device_paired">Η συσκευή συζεύχθηκε</string>
|
||||
<string name="device_rename_title">Μετονομασία συσκευής</string>
|
||||
<string name="device_rename_confirm">Μετονομασία</string>
|
||||
<string name="refresh">Ανανέωση</string>
|
||||
<string name="unreachable_description">Αυτή η συζευγμένη συσκευή δεν είναι προσβάσιμη. Βεβαιωθείτε ότι είναι συνδεδεμένη στο δίκτυό σας.</string>
|
||||
<string name="no_file_browser">Δεν υπάρχουν εγκατεστημένοι περιηγητές αρχείων.</string>
|
||||
<string name="pref_plugin_telepathy">Αποστολή SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Αποστολή μηνυμάτων κειμένου από τον υπολογιστή σας</string>
|
||||
<string name="plugin_not_supported">Αυτό το πρόσθετο δεν υποστηρίζεται από τη συσκευή</string>
|
||||
<string name="findmyphone_title">Αναζήτηση του κινητού μου</string>
|
||||
<string name="findmyphone_found">Βρέθηκε</string>
|
||||
<string name="open">Άνοιγμα</string>
|
||||
<string name="close">Κλείσιμο</string>
|
||||
</resources>
|
153
res/values-en-rGB/strings.xml
Normal file
@@ -0,0 +1,153 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Telephony notifier</string>
|
||||
<string name="pref_plugin_telephony_desc">Send notifications for SMS and calls</string>
|
||||
<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_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_mpris">Multimedia controls</string>
|
||||
<string name="pref_plugin_runcommand">Run Command</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_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>
|
||||
<string name="device_list_empty">No devices</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="open_settings">Open settings</string>
|
||||
<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="open_mousepad">Remote input</string>
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Set touchpad sensitivity</string>
|
||||
<string name="mousepad_scroll_direction_title">Reverse Scrolling Direction</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">right</string>
|
||||
<string name="mousepad_triple_default">middle</string>
|
||||
<string name="mousepad_sensitivity_default">default</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Connected devices</string>
|
||||
<string name="category_not_paired_devices">Available devices</string>
|
||||
<string name="category_remembered_devices">Remembered devices</string>
|
||||
<string name="plugins_failed_to_load">Plugins failed to load (tap for more info):</string>
|
||||
<string name="device_menu_plugins">Plugin settings</string>
|
||||
<string name="device_menu_unpair">Unpair</string>
|
||||
<string name="device_not_reachable">Paired device not reachable</string>
|
||||
<string name="pair_new_device">Pair new device</string>
|
||||
<string name="unknown_device">Unknown device</string>
|
||||
<string name="error_not_reachable">Device not reachable</string>
|
||||
<string name="error_already_requested">Pairing already requested</string>
|
||||
<string name="error_already_paired">Device already paired</string>
|
||||
<string name="error_could_not_send_package">Could not send package</string>
|
||||
<string name="error_timed_out">Timed out</string>
|
||||
<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="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>
|
||||
<string name="received_url_text">Tap to open \'%1s\'</string>
|
||||
<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_file_text">%1s</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_text">%1s</string>
|
||||
<string name="tap_to_answer">Tap to answer</string>
|
||||
<string name="reconnect">Reconnect</string>
|
||||
<string name="right_click">Send Right Click</string>
|
||||
<string name="middle_click">Send Middle Click</string>
|
||||
<string name="show_keyboard">Show Keyboard</string>
|
||||
<string name="device_not_paired">Device not paired</string>
|
||||
<string name="request_pairing">Request pairing</string>
|
||||
<string name="pairing_accept">Accept</string>
|
||||
<string name="pairing_reject">Reject</string>
|
||||
<string name="device">Device</string>
|
||||
<string name="pair_device">Pair device</string>
|
||||
<string name="remote_control">Remote control</string>
|
||||
<string name="settings">KDE Connect Settings</string>
|
||||
<string name="mpris_play">Play</string>
|
||||
<string name="mpris_previous">Previous</string>
|
||||
<string name="mpris_rew">Rewind</string>
|
||||
<string name="mpris_ff">Fast-forward</string>
|
||||
<string name="mpris_next">Next</string>
|
||||
<string name="mpris_volume">Volume</string>
|
||||
<string name="mpris_settings">Multimedia Settings</string>
|
||||
<string name="mpris_time_settings_title">Forward/rewind buttons</string>
|
||||
<string name="mpris_time_settings_summary">Adjust the time to fast forward/rewind when pressed.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 seconds</item>
|
||||
<item>20 seconds</item>
|
||||
<item>30 seconds</item>
|
||||
<item>1 minute</item>
|
||||
<item>2 minutes</item>
|
||||
</string-array>
|
||||
<string name="share_to">Share To...</string>
|
||||
<string name="protocol_version_older">This device uses an old protocol version</string>
|
||||
<string name="protocol_version_newer">This device uses a newer protocol version</string>
|
||||
<string name="general_settings">General Settings</string>
|
||||
<string name="plugin_settings">Settings</string>
|
||||
<string name="plugin_settings_with_name">%s settings</string>
|
||||
<string name="device_name">Device name</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Invalid device name</string>
|
||||
<string name="shareplugin_text_saved">Received text, saved to clipboard</string>
|
||||
<string name="custom_devices_settings">Custom device list</string>
|
||||
<string name="pair_device_action">Pair a new device</string>
|
||||
<string name="unpair_device_action">Unpair %s</string>
|
||||
<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="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>
|
||||
<string name="sftp_all_files">All files</string>
|
||||
<string name="sftp_sdcard_num">SD card %d</string>
|
||||
<string name="sftp_sdcard">SD card</string>
|
||||
<string name="sftp_readonly">(read only)</string>
|
||||
<string name="sftp_camera">Camera pictures</string>
|
||||
<string name="add_host">Add host/IP</string>
|
||||
<string name="add_host_hint">Hostname or IP</string>
|
||||
<string name="no_players_connected">No players found</string>
|
||||
<string name="custom_dev_list_help">Use this option only if your device is not automatically detected. Enter IP address or hostname below and touch the button to add it to the list. Touch an existing item to remove it from the list.</string>
|
||||
<string name="mpris_player_on_device">%1$s on %2$s</string>
|
||||
<string name="send_files">Send files</string>
|
||||
<string name="pairing_title">KDE Connect Devices</string>
|
||||
<string name="pairing_description">Other devices running KDE Connect in your same network should appear here.</string>
|
||||
<string name="device_paired">Device paired</string>
|
||||
<string name="device_rename_title">Rename device</string>
|
||||
<string name="device_rename_confirm">Rename</string>
|
||||
<string name="refresh">Refresh</string>
|
||||
<string name="unreachable_description">This paired device is not reachable. Make sure it is connected to your same network.</string>
|
||||
<string name="no_file_browser">There are no file browsers installed.</string>
|
||||
<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_found">Found</string>
|
||||
<string name="open">Open</string>
|
||||
<string name="close">Close</string>
|
||||
</resources>
|
@@ -5,17 +5,21 @@
|
||||
<string name="pref_plugin_battery">Informe de la batería</string>
|
||||
<string name="pref_plugin_battery_desc">Informar periódicamente del estado de la batería</string>
|
||||
<string name="pref_plugin_sftp">Mostrar el sistema de archivos</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite examinar de forma remota el sistema de archivos del teléfono</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite examinar de forma remota el sistema de archivos de este dispositivo</string>
|
||||
<string name="pref_plugin_clipboard">Sincronización del portapapeles</string>
|
||||
<string name="pref_plugin_clipboard_desc">Compartir el contenido del portapapeles</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usar su teléfono como ratón y teclado</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usar su teléfono o tableta como teclado y teclado táctil</string>
|
||||
<string name="pref_plugin_mpris">Controles multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Controlar audio y vídeo desde el teléfono</string>
|
||||
<string name="pref_plugin_mpris_desc">Proporciona un control remoto para su reproductor de medios</string>
|
||||
<string name="pref_plugin_runcommand">Ejecutar orden</string>
|
||||
<string name="pref_plugin_runcommand_desc">Desencadenar órdenes remotas desde su teléfono o tableta</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Enviar y recibir pings</string>
|
||||
<string name="pref_plugin_notifications">Sincronizar notificaciones</string>
|
||||
<string name="pref_plugin_notifications_desc">Acceder a las notificaciones desde otros dispositivos</string>
|
||||
<string name="pref_plugin_receive_notifications">Recibir notificaciones</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Recibir notificaciones desde el otro dispositivo y mostrarlas en Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Compartir y recibir</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Compartir archivos y URL entre dispositivos</string>
|
||||
<string name="plugin_not_available">Esta funcionalidad no está disponible en su versión de Android</string>
|
||||
@@ -30,6 +34,8 @@
|
||||
<string name="mousepad_info">Mueva un dedo sobre la pantalla para mover el cursor del ratón. Pulse para ejecutar un clic y use dos/tres dedos para emular los botones derecho y central. Use una pulsación larga para arrastrar y soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Establecer la acción al pulsar con dos dedos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Establecer la acción al pulsar con tres dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Establecer sensibilidad del panel táctil</string>
|
||||
<string name="mousepad_scroll_direction_title">Invertir dirección de desplazamiento</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic derecho</item>
|
||||
<item>Clic del botón central</item>
|
||||
@@ -37,6 +43,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">derecho</string>
|
||||
<string name="mousepad_triple_default">medio</string>
|
||||
<string name="mousepad_sensitivity_default">por defecto</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Muy poco sensible</item>
|
||||
<item>Poco sensible</item>
|
||||
<item>Predeterminada</item>
|
||||
<item>Sensible</item>
|
||||
<item>Muy sensible</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivos conectados</string>
|
||||
<string name="category_not_paired_devices">Dispositivos disponibles</string>
|
||||
<string name="category_remembered_devices">Dispositivos recordados</string>
|
||||
@@ -44,6 +58,7 @@
|
||||
<string name="device_menu_plugins">Preferencias del complemento</string>
|
||||
<string name="device_menu_unpair">Desvincular</string>
|
||||
<string name="device_not_reachable">No se encuentra el dispositivo aparejado</string>
|
||||
<string name="pair_new_device">Vincular nuevo dispositivo</string>
|
||||
<string name="unknown_device">Dispositivo desconocido</string>
|
||||
<string name="error_not_reachable">No se encuentra el dispositivo</string>
|
||||
<string name="error_already_requested">Ya ha solicitado vincularse</string>
|
||||
@@ -53,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Cancelado por el usuario</string>
|
||||
<string name="error_canceled_by_other_peer">Cancelado por la otra parte</string>
|
||||
<string name="error_invalid_key">Se ha recibido una clave no valida</string>
|
||||
<string name="encryption_info_title">Información de cifrado</string>
|
||||
<string name="encryption_info_msg_no_ssl">El otro dispositivo no dispone de una versión reciente de KDE Connect, se usará un método de cifrado antiguo.</string>
|
||||
<string name="my_device_fingerprint">La huella digital SHA1 del certificado de su dispositivo es:</string>
|
||||
<string name="remote_device_fingerprint">La huella digital SHA1 del certificado del dispositivo remoto es:</string>
|
||||
<string name="pair_requested">Vinculación solicitada</string>
|
||||
<string name="pairing_request_from">Solicitud de vinculación de %1s</string>
|
||||
<string name="received_url_title">Enlace recibido desde %1s</string>
|
||||
@@ -138,4 +157,10 @@
|
||||
<string name="pref_plugin_telepathy">Enviar SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensajes de texto desde el escritorio</string>
|
||||
<string name="plugin_not_supported">Este complemento no está permitido por el dispositivo</string>
|
||||
<string name="findmyphone_title">Encontrar mi teléfono</string>
|
||||
<string name="findmyphone_title_tablet">Encontrar mi tableta</string>
|
||||
<string name="findmyphone_description">Hace sonar este dispositivo para que pueda encontrarlo</string>
|
||||
<string name="findmyphone_found">Encontrado</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Cerrar</string>
|
||||
</resources>
|
||||
|
@@ -5,13 +5,11 @@
|
||||
<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 puhelimen 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ä puhelintasi hiirenä ja näppäimistönä</string>
|
||||
<string name="pref_plugin_mpris">Multimedian ohjaus</string>
|
||||
<string name="pref_plugin_mpris_desc">Ohjaa ääntä ja videota puhelimestasi</string>
|
||||
<string name="pref_plugin_runcommand">Suorita komento</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>
|
||||
@@ -30,6 +28,8 @@
|
||||
<string name="mousepad_info">Liikuta hiiren osoitinta liikuttamalla sormeasi näytöllä. Napsauta napauttamalla yhdellä sormella, käytä oikeaa painiketta kahdella sormella ja keskipainiketta kolmella. Vedä ja pudota painamalla pitkään.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Aseta kahden sormen napautuksen toiminto</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Aseta kolmen sormen napautuksen toiminto</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Aseta kosketuslevyn herkkyys</string>
|
||||
<string name="mousepad_scroll_direction_title">Käänteinen vierityssuunta</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Oikea napsautus</item>
|
||||
<item>Keskinapsautus</item>
|
||||
@@ -37,6 +37,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Oikea painike</string>
|
||||
<string name="mousepad_triple_default">Keskipainike</string>
|
||||
<string name="mousepad_sensitivity_default">oletus</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Hitain</item>
|
||||
<item>Hitainta suurempi</item>
|
||||
<item>Oletus</item>
|
||||
<item>Oletusta suurempi</item>
|
||||
<item>Nopein</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Yhdistetyt laitteet</string>
|
||||
<string name="category_not_paired_devices">Saatavilla olevat laitteet</string>
|
||||
<string name="category_remembered_devices">Muistetut laitteet</string>
|
||||
@@ -44,6 +52,7 @@
|
||||
<string name="device_menu_plugins">Liitännäisten asetukset</string>
|
||||
<string name="device_menu_unpair">Poista laitepari</string>
|
||||
<string name="device_not_reachable">Laitepari tavoittamattomissa</string>
|
||||
<string name="pair_new_device">Kytke uusi laite pariksi</string>
|
||||
<string name="unknown_device">Tuntematon laite</string>
|
||||
<string name="error_not_reachable">Laite tavoittamattomissa</string>
|
||||
<string name="error_already_requested">Pariksi kytkemistä on jo pyydetty</string>
|
||||
@@ -124,18 +133,21 @@
|
||||
<string name="add_host">Lisää kone/IP</string>
|
||||
<string name="add_host_hint">Konenimi tai IP-osoite</string>
|
||||
<string name="no_players_connected">Soittimia ei löytynyt</string>
|
||||
<string name="custom_dev_list_help">Käytä tätä vain, jos laitettasi ei tunnisteta automaattisesti. Kirjoita IP-osoite tai konenimi alle ja kosketa painiketta lisätäksesi sen luetteloon. Kosketa olemassa olevaa kohtaa poistaaksesi sen luettelosta.</string>
|
||||
<string name="custom_dev_list_help">Käytä tätä vain, jos laitettasi ei tunnisteta automaattisesti. Kirjoita IP-osoite tai konenimi alle ja lisää se luetteloon koskettamalla painiketta. Voit poistaa olemassa olevan kohdan luettelosta koskettamalla sitä.</string>
|
||||
<string name="mpris_player_on_device">%1$s laitteella %2$s</string>
|
||||
<string name="send_files">Lähetä tiedostoja</string>
|
||||
<string name="pairing_title">KDE Connect -laitteet</string>
|
||||
<string name="pairing_description">Muiden samassa verkossa olevien KDE Connectia käyttävien laitteiden pitäisi ilmestyä tähän.</string>
|
||||
<string name="device_paired">Laite kytketty pariksi</string>
|
||||
<string name="device_rename_title">Laitteen nimen muuttaminen</string>
|
||||
<string name="device_rename_title">Muuta laitteen nimeä</string>
|
||||
<string name="device_rename_confirm">Muuta nimi</string>
|
||||
<string name="refresh">Päivitä</string>
|
||||
<string name="unreachable_description">Tämä pariksi kytketty laite ei ole tavoitttavissa. Tarkista, että se on yhteydessä samaan verkkoon.</string>
|
||||
<string name="unreachable_description">Tämä pariksi kytketty laite ei ole tavoitettavissa. Tarkista, että se on yhteydessä samaan verkkoon.</string>
|
||||
<string name="no_file_browser">Tiedostoselaimia ei asennettu.</string>
|
||||
<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_found">Löytyi</string>
|
||||
<string name="open">Avaa</string>
|
||||
<string name="close">Sulje</string>
|
||||
</resources>
|
||||
|
@@ -5,16 +5,16 @@
|
||||
<string name="pref_plugin_battery">Rapport sur la batterie</string>
|
||||
<string name="pref_plugin_battery_desc">Rapport périodique sur l\'état de la batterie</string>
|
||||
<string name="pref_plugin_sftp">Exposer le système de fichiers</string>
|
||||
<string name="pref_plugin_sftp_desc">Permettre de parcourir le système de fichiers du téléphone à distance</string>
|
||||
<string name="pref_plugin_clipboard">Synchronisation avec le presse-papiers</string>
|
||||
<string name="pref_plugin_clipboard_desc">Partage le contenu du presse-papiers</string>
|
||||
<string name="pref_plugin_mousepad">Contrôle distant</string>
|
||||
<string name="pref_plugin_mousepad_desc">Utilisez votre téléphone comme une souris et un clavier</string>
|
||||
<string name="pref_plugin_mpris_desc">Contrôle l\'audio / la vidéo depuis votre téléphone</string>
|
||||
<string name="pref_plugin_mpris">Contrôles multimédia</string>
|
||||
<string name="pref_plugin_ping">Commande « Ping »</string>
|
||||
<string name="pref_plugin_ping_desc">Envoie et reçoit des commandes « Ping »</string>
|
||||
<string name="pref_plugin_notifications">Synchronisation des notifications</string>
|
||||
<string name="pref_plugin_notifications_desc">Accédez à vos notifications depuis d\'autres périphériques</string>
|
||||
<string name="pref_plugin_sharereceiver">Partager et recevoir</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Partagez des URLs et des fichiers entre périphériques</string>
|
||||
<string name="plugin_not_available">Cette fonctionnalité n\'est pas disponible dans votre version de Android</string>
|
||||
<string name="device_list_empty">Pas de périphériques</string>
|
||||
<string name="ok">Ok</string>
|
||||
@@ -22,6 +22,8 @@
|
||||
<string name="open_settings">Accéder aux paramètres</string>
|
||||
<string name="no_permissions">Vous devez accorder la permission d\'accéder aux notifications</string>
|
||||
<string name="send_ping">Envoyer un « Ping »</string>
|
||||
<string name="open_mpris_controls">Contrôles multimédia</string>
|
||||
<string name="open_mousepad">Contrôle distant</string>
|
||||
<string name="mousepad_info">Déplacer le doigt sur l\'écran pour bouger le pointeur de la souris. Appuyez pour cliquer et utiliser deux/trois doigts pour les clic droit et centre. Appuyez longtemps pour faire un glisser déplacer.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Action pour l\'appui à deux doigts</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Action pour l\'appui à trois doigts</string>
|
||||
@@ -32,6 +34,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Droite</string>
|
||||
<string name="mousepad_triple_default">Milieu</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Périphériques connectés</string>
|
||||
<string name="category_not_paired_devices">Périphériques disponibles</string>
|
||||
<string name="category_remembered_devices">Périphériques mémorisés</string>
|
||||
@@ -57,6 +66,7 @@
|
||||
<string name="outgoing_file_title">Envoi d\'un fichier à %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="received_file_title">Fichier reçu de %1s</string>
|
||||
<string name="received_file_fail_title">Impossible de recevoir le fichier depuis : %1s</string>
|
||||
<string name="received_file_text">Appuyez pour ouvrir %1s</string>
|
||||
<string name="sent_file_title">Fichier envoyé à %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
|
@@ -5,13 +5,11 @@
|
||||
<string name="pref_plugin_battery">Informe da batería</string>
|
||||
<string name="pref_plugin_battery_desc">Envíe periodicamente un informe sobre o estado da batería.</string>
|
||||
<string name="pref_plugin_sftp">Revelador do sistema de ficheiros</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite examinar o sistema de ficheiros do teléfono remotamente.</string>
|
||||
<string name="pref_plugin_clipboard">Sincronización do portapapeis</string>
|
||||
<string name="pref_plugin_clipboard_desc">Comparta o contido do portapapeis.</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Use o teléfono como rato e teclado.</string>
|
||||
<string name="pref_plugin_mpris">Controis multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Controle o son e o vídeo desde o teléfono.</string>
|
||||
<string name="pref_plugin_runcommand">Executar unha orde</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Envíe e reciba pings.</string>
|
||||
<string name="pref_plugin_notifications">Sincronización de notificacións</string>
|
||||
@@ -30,6 +28,8 @@
|
||||
<string name="mousepad_info">Mova un dedo na pantalla para mover o cursor. Toque para facer clic, e use dous ou tres dedos para os botóns secundario e central. Prema durante un tempo para arrastrar e soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Definir a acción de tocar con dous dedos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Definir a acción de tocar con tres dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do punteiro táctil</string>
|
||||
<string name="mousepad_scroll_direction_title">Inverter a dirección de desprazamento</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic dereito</item>
|
||||
<item>Clic central</item>
|
||||
@@ -37,6 +37,14 @@
|
||||
</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>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivos conectados</string>
|
||||
<string name="category_not_paired_devices">Dispositivos dispoñíbeis</string>
|
||||
<string name="category_remembered_devices">Dispositivos coñecidos</string>
|
||||
@@ -44,6 +52,7 @@
|
||||
<string name="device_menu_plugins">Configuración do engadido</string>
|
||||
<string name="device_menu_unpair">Desemparellarse</string>
|
||||
<string name="device_not_reachable">O dispositivo emparellado está fóra do alcance.</string>
|
||||
<string name="pair_new_device">Emparellar cun novo dispositivo</string>
|
||||
<string name="unknown_device">Dispositivo descoñecido</string>
|
||||
<string name="error_not_reachable">Dispositivo fóra do alcance</string>
|
||||
<string name="error_already_requested">Xa solicitou emparellarse.</string>
|
||||
@@ -108,6 +117,8 @@
|
||||
<string name="invalid_device_name">Nome de dispositivo incorrecto</string>
|
||||
<string name="shareplugin_text_saved">Recibiuse un texto e gardouse no portapapeis</string>
|
||||
<string name="custom_devices_settings">Lista de dispositivos personalizada</string>
|
||||
<string name="pair_device_action">Emparellar cun novo dispositivo</string>
|
||||
<string name="unpair_device_action">Desemparellarse de %s</string>
|
||||
<string name="custom_device_list">Engadir dispositivos por IP</string>
|
||||
<string name="share_notification_preference">Notificacións sonoras</string>
|
||||
<string name="share_notification_preference_summary">Vibrar e reproducir un son ao recibir un ficheiro.</string>
|
||||
@@ -124,4 +135,19 @@
|
||||
<string name="no_players_connected">Non se atoparon reprodutores.</string>
|
||||
<string name="custom_dev_list_help">Marque esta opción unicamente se o seu dispositivo non se detecta automaticamente. Escriba o enderezo IP ou o nome de servidor do dispositivo e toque o botón para engadilo á lista. Toque un elemento existente para retiralo da lista.</string>
|
||||
<string name="mpris_player_on_device">%1$s en %2$s</string>
|
||||
<string name="send_files">Enviar ficheiros</string>
|
||||
<string name="pairing_title">Dispositivos con KDE Connect</string>
|
||||
<string name="pairing_description">Outros dispositivos que estean a executar KDE Connect na mesma rede deberían aparecer aquí.</string>
|
||||
<string name="device_paired">Emparellouse co dispositivo</string>
|
||||
<string name="device_rename_title">Cambiar o nome do dispositivo</string>
|
||||
<string name="device_rename_confirm">Mudar o nome</string>
|
||||
<string name="refresh">Actualizar</string>
|
||||
<string name="unreachable_description">Este dispositivo emparellado está fóra do alcance. Asegúrese de que está conectado á mesma rede.</string>
|
||||
<string name="no_file_browser">Non hai navegadores de ficheiros instalados.</string>
|
||||
<string name="pref_plugin_telepathy">Enviar unha mensaxe de texto</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensaxes de texto desde un computador de escritorio.</string>
|
||||
<string name="plugin_not_supported">O dispositivo non é compatíbel con este complemento.</string>
|
||||
<string name="findmyphone_found">Atopado</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Pechar</string>
|
||||
</resources>
|
||||
|
158
res/values-he/strings.xml
Normal file
@@ -0,0 +1,158 @@
|
||||
<?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_clipboard">סנכנרון לוח העתקה</string>
|
||||
<string name="pref_plugin_clipboard_desc">שתף בין המחשבים את מה שמועתק</string>
|
||||
<string name="pref_plugin_mousepad">שליטה מרחוק</string>
|
||||
<string name="pref_plugin_mpris">שליטה במדיה</string>
|
||||
<string name="pref_plugin_runcommand">הרץ פקודה</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_sharereceiver">שתף וקבל קבצים וכתובות</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">שתף וקבל קבצים וכתובת אינטרנט בין התקנים</string>
|
||||
<string name="plugin_not_available">אפשרות זו אינה זמינה בגרסת האנדרואיד שלך</string>
|
||||
<string name="device_list_empty">אין התקנים</string>
|
||||
<string name="ok">בסדר</string>
|
||||
<string name="cancel">בטל</string>
|
||||
<string name="open_settings">פתח הגדרות</string>
|
||||
<string name="no_permissions">אתה צריך לתת הרשאות לגישה להתראות</string>
|
||||
<string name="send_ping">שלח פינג</string>
|
||||
<string name="open_mpris_controls">שליטה על המדיה</string>
|
||||
<string name="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 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>
|
||||
<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_title">נכשל בשליחת הקובץ ל־%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">לחץ כדי לענות</string>
|
||||
<string name="reconnect">התחבר מחדש</string>
|
||||
<string name="right_click">שלח לחיצה ימנית</string>
|
||||
<string name="middle_click">שלח לחיצה אמצעית (גלגלת)</string>
|
||||
<string name="show_keyboard">הראה מקלדת</string>
|
||||
<string name="device_not_paired">ההתקן לא מותאם</string>
|
||||
<string name="request_pairing">בקש התאמה</string>
|
||||
<string name="pairing_accept">אשר</string>
|
||||
<string name="pairing_reject">דחה</string>
|
||||
<string name="device">התקן</string>
|
||||
<string name="pair_device">התאם התקן</string>
|
||||
<string name="remote_control">שלוט מרחוק</string>
|
||||
<string name="settings">הגדרות KDE Connect</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>חצי דקה</item>
|
||||
<item>דקה</item>
|
||||
<item>שתי דקות</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">התראות יסונכרנו רק לאפליקציות נבחרות</string>
|
||||
<string name="sftp_internal_storage">זיכרון פנימי</string>
|
||||
<string name="sftp_all_files">כל הקבצים</string>
|
||||
<string name="sftp_sdcard_num">כרטיס זיכרון %d</string>
|
||||
<string name="sftp_sdcard">כרטיס זיכרון</string>
|
||||
<string name="sftp_readonly">(לקריאה בלבד)</string>
|
||||
<string name="sftp_camera">תמונות מצלמה</string>
|
||||
<string name="add_host">הוסף כתובת שרת או IP</string>
|
||||
<string name="add_host_hint">כתבות שרת או IP</string>
|
||||
<string name="no_players_connected">לא נמצא נגן</string>
|
||||
<string name="custom_dev_list_help">השתמש באפשרות זו רק אם המכשיר שלך לא מזוהה באופן אוטומטי. הקלד את כתובת הIP או את כינוי ההתקן למטה ולחץ על הכפתור כדי להוסיף לרשימה. לחץ על פריט קיים כדי להסיר אותו מהרשימה.</string>
|
||||
<string name="mpris_player_on_device">%1$s ב־%2$s</string>
|
||||
<string name="send_files">שלח קובץ</string>
|
||||
<string name="pairing_title">מכשירי KDE Connect</string>
|
||||
<string name="pairing_description">התקנים אחרים המריצים KDE Connect ברשת הנוכחית צריכים להופיע פה.</string>
|
||||
<string name="device_paired">התקן מתואם</string>
|
||||
<string name="device_rename_title">שנה שם התקן</string>
|
||||
<string name="device_rename_confirm">שנה שם</string>
|
||||
<string name="refresh">רענן</string>
|
||||
<string name="unreachable_description">ההתקן המתואם לא זמין, וודא שהוא מחובר לאותה רשת אליה התקן זה מחובר.</string>
|
||||
<string name="no_file_browser">לא נמצאו מנהלי קבצים מותקנים במכשיר זה.</string>
|
||||
<string name="pref_plugin_telepathy">שלח SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">שלח הודעות מהמחשב שלך</string>
|
||||
<string name="plugin_not_supported">התוסף הזה לא נתמך ע\"י המכשיר שלך</string>
|
||||
<string name="findmyphone_title">מצא את המכשיר שלי</string>
|
||||
<string name="findmyphone_found">נמצא</string>
|
||||
<string name="open">פתח</string>
|
||||
<string name="close">סגור</string>
|
||||
</resources>
|
@@ -5,10 +5,8 @@
|
||||
<string name="pref_plugin_battery">Akkumulátor jelentés</string>
|
||||
<string name="pref_plugin_battery_desc">Akkumulátorállapot időszakos jelentése</string>
|
||||
<string name="pref_plugin_sftp">Fájlrendszer kifejtés</string>
|
||||
<string name="pref_plugin_sftp_desc">Lehetővé teszi a telefon fájlrendszerének távolról történő tallózását</string>
|
||||
<string name="pref_plugin_clipboard">Vágólap szinkronizáció</string>
|
||||
<string name="pref_plugin_clipboard_desc">A vágólap tartalmának megosztása</string>
|
||||
<string name="pref_plugin_mpris_desc">Hang vagy videó vezérlése a telefonról</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Pingek küldése és fogadása</string>
|
||||
<string name="pref_plugin_notifications">Értesítés szinkronizáció</string>
|
||||
@@ -25,6 +23,13 @@
|
||||
<item/>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Csatlakoztatott eszközök</string>
|
||||
<string name="category_remembered_devices">Megjegyzett eszközök</string>
|
||||
<string name="plugins_failed_to_load">A bővítményeket nem sikerült betölteni (érintse meg a további információkért):</string>
|
||||
|
@@ -5,17 +5,21 @@
|
||||
<string name="pref_plugin_battery">Livello batteria</string>
|
||||
<string name="pref_plugin_battery_desc">Comunica periodicamente lo stato della batteria</string>
|
||||
<string name="pref_plugin_sftp">Esposizione filesystem</string>
|
||||
<string name="pref_plugin_sftp_desc">Consente di navigare da remoto il filesystem del telefono</string>
|
||||
<string name="pref_plugin_sftp_desc">Consente di navigare da remoto il filesystem del dispositivo</string>
|
||||
<string name="pref_plugin_clipboard">Sincronizzazione appunti</string>
|
||||
<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 come mouse e tastiera</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usa il tuo telefono o il tablet come touchpad e tastiera</string>
|
||||
<string name="pref_plugin_mpris">Controlli multimediali</string>
|
||||
<string name="pref_plugin_mpris_desc">Controlla la riproduzione audio/video dal telefono</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>
|
||||
<string name="pref_plugin_runcommand_desc">Esegui comandi remoti dal tuo telefono o tablet</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Invia e ricevi ping</string>
|
||||
<string name="pref_plugin_notifications">Sincronizzazione notifiche</string>
|
||||
<string name="pref_plugin_notifications_desc">Consenti l\'accesso alle notifiche dagli altri dispositivi</string>
|
||||
<string name="pref_plugin_receive_notifications">Ricevi notifiche</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Ricevi notifiche da altri dispositivi e le visualizza su Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Condividi e ricevi</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Condividi file e URL tra i dispositivi</string>
|
||||
<string name="plugin_not_available">Questa funzionalità non è disponibile sulla tua versione di Android</string>
|
||||
@@ -30,6 +34,8 @@
|
||||
<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>
|
||||
<string name="mousepad_triple_tap_settings_title">Imposta azione per il tocco a tre dita</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Imposta la sensibilità del touchpad</string>
|
||||
<string name="mousepad_scroll_direction_title">Inverti direzione di scorrimento</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic destro</item>
|
||||
<item>Clic centrale</item>
|
||||
@@ -37,6 +43,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">destra</string>
|
||||
<string name="mousepad_triple_default">centro</string>
|
||||
<string name="mousepad_sensitivity_default">predefinita</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Minima</item>
|
||||
<item>Più veloce</item>
|
||||
<item>Predefinita</item>
|
||||
<item>Superiore a predefinita</item>
|
||||
<item>Massima</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivi connessi</string>
|
||||
<string name="category_not_paired_devices">Dispositivi disponibili</string>
|
||||
<string name="category_remembered_devices">Dispositivi memorizzati</string>
|
||||
@@ -44,6 +58,7 @@
|
||||
<string name="device_menu_plugins">Impostazioni estensioni</string>
|
||||
<string name="device_menu_unpair">Disassocia</string>
|
||||
<string name="device_not_reachable">Dispositivo associato non raggiungibile</string>
|
||||
<string name="pair_new_device">Associa nuovo dispositivo</string>
|
||||
<string name="unknown_device">Dispositivo sconosciuto</string>
|
||||
<string name="error_not_reachable">Dispositivo fuori portata</string>
|
||||
<string name="error_already_requested">Richiesta già inviata</string>
|
||||
@@ -53,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Annullata dall\'utente</string>
|
||||
<string name="error_canceled_by_other_peer">Annullata dal dispositivo remoto</string>
|
||||
<string name="error_invalid_key">Ricevuta chiave non valida</string>
|
||||
<string name="encryption_info_title">Informazioni di cifratura</string>
|
||||
<string name="encryption_info_msg_no_ssl">L\'altro dispositivo non utilizza una versione recente di KDE Connect, utilizzando il metodo di cifratura precedente.</string>
|
||||
<string name="my_device_fingerprint">L\'impronta digitale SHA1 del certificato di dispositivo è:</string>
|
||||
<string name="remote_device_fingerprint">L\'impronta digitale SHA1 del certificato di dispositivo remoto è:</string>
|
||||
<string name="pair_requested">Richiesta di associazione</string>
|
||||
<string name="pairing_request_from">Richiesta associazione da %1s</string>
|
||||
<string name="received_url_title">Collegamento ricevuto da %1s</string>
|
||||
@@ -108,6 +127,8 @@
|
||||
<string name="invalid_device_name">Nome dispositivo non valido</string>
|
||||
<string name="shareplugin_text_saved">Testo ricevuto, salvato negli appunti</string>
|
||||
<string name="custom_devices_settings">Elenco dispositivi personalizzato</string>
|
||||
<string name="pair_device_action">Associa un nuovo dispositivo</string>
|
||||
<string name="unpair_device_action">Disassocia %s</string>
|
||||
<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>
|
||||
@@ -124,4 +145,22 @@
|
||||
<string name="no_players_connected">Nessun lettore trovato</string>
|
||||
<string name="custom_dev_list_help">Usa questa opzione solo se il tuo dispositivo non è rilevato automaticamente. Digita l\'indirizzo IP o il nome host in basso e tocca il pulsante per aggiungerlo all\'elenco. Tocca un elemento esistente per rimuoverlo dall\'elenco.</string>
|
||||
<string name="mpris_player_on_device">%1$s su %2$s</string>
|
||||
<string name="send_files">Invia file</string>
|
||||
<string name="pairing_title">Dispositivi KDE Connect</string>
|
||||
<string name="pairing_description">Altri dispositivi che eseguono KDE Connect nella tua stessa rete dovrebbero apparire qui.</string>
|
||||
<string name="device_paired">Dispositivo associato</string>
|
||||
<string name="device_rename_title">Rinomina dispositivo</string>
|
||||
<string name="device_rename_confirm">Rinomina</string>
|
||||
<string name="refresh">Aggiorna</string>
|
||||
<string name="unreachable_description">Questo dispositivo associato non è raggiungibile. Assicurati che sia connesso alla tua stessa rete.</string>
|
||||
<string name="no_file_browser">Non ci sono navigatori di file installati.</string>
|
||||
<string name="pref_plugin_telepathy">Invia SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Invia messaggi di testo dal tuo desktop</string>
|
||||
<string name="plugin_not_supported">Questa estensione non è supportata dal dispositivo</string>
|
||||
<string name="findmyphone_title">Trova il mio telefono</string>
|
||||
<string name="findmyphone_title_tablet">Trova il mio tablet</string>
|
||||
<string name="findmyphone_description">Fa squillare questo dispositivo per trovarlo</string>
|
||||
<string name="findmyphone_found">Trovato</string>
|
||||
<string name="open">Apri</string>
|
||||
<string name="close">Chiudi</string>
|
||||
</resources>
|
||||
|
@@ -5,6 +5,13 @@
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 seconds</item>
|
||||
<item>20 seconds</item>
|
||||
|
@@ -5,16 +5,17 @@
|
||||
<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_desc">휴대폰에서 오디오/비디오 제어</string>
|
||||
<string name="pref_plugin_mpris">멀티미디어 제어</string>
|
||||
<string name="pref_plugin_runcommand">명령 실행</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_sharereceiver">공유하고 받기</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">장치끼리 파일과 URL 공유</string>
|
||||
<string name="plugin_not_available">현재 안드로이드 버전에서 사용할 수 없습니다</string>
|
||||
<string name="device_list_empty">장치 없음</string>
|
||||
<string name="ok">확인</string>
|
||||
@@ -22,45 +23,67 @@
|
||||
<string name="open_settings">설정 열기</string>
|
||||
<string name="no_permissions">알림 접근 권한을 허가해야 합니다</string>
|
||||
<string name="send_ping">핑 보내기</string>
|
||||
<string name="open_mpris_controls">멀티미디어 제어</string>
|
||||
<string name="open_mousepad">원격 입력</string>
|
||||
<string name="mousepad_info">화면에서 손가락을 움직이면 마우스 커서를 움직입니다. 화면을 누르면 왼쪽 단추를 누르고, 두 손가락과 세 손가락으로 누르면 오른쪽/가운데 단추를 누릅니다. 드래그 앤 드롭을 사용하려면 길게 누르십시오.</string>
|
||||
<string name="mousepad_double_tap_settings_title">두 손가락으로 눌렀을 때 동작 설정</string>
|
||||
<string name="mousepad_triple_tap_settings_title">세 손가락으로 눌렀을 때 동작 설정</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item/>
|
||||
<item/>
|
||||
<item>Nothing</item>
|
||||
<item>오른쪽 단추 누름</item>
|
||||
<item>가운데 단추 누름</item>
|
||||
<item>아무것도 안 함</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">오른쪽</string>
|
||||
<string name="mousepad_triple_default">가운데</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">연결된 장치</string>
|
||||
<string name="category_not_paired_devices">사용 가능한 장치</string>
|
||||
<string name="category_remembered_devices">기억하는 장치</string>
|
||||
<string name="plugins_failed_to_load">불러올 수 없는 플러그인(정보를 보려면 누르기)</string>
|
||||
<string name="device_menu_unpair">페어링 해제</string>
|
||||
<string name="device_not_reachable">페어링된 장치에 도달할 수 없음</string>
|
||||
<string name="device_menu_plugins">플러그인 설정</string>
|
||||
<string name="device_menu_unpair">연결 해제</string>
|
||||
<string name="device_not_reachable">연결된 장치에 도달할 수 없음</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_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="pair_requested">페어링 요청됨</string>
|
||||
<string name="pairing_request_from">%1s에서 페어링 요청</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_title">파일 %1s을(를) 보낼 수 없음</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">눌러서 응답하기</string>
|
||||
<string name="reconnect">다시 연결</string>
|
||||
<string name="right_click">오른쪽 단추 누름 신호 보내기</string>
|
||||
<string name="middle_click">가운데 단추 누름 신호 보내기</string>
|
||||
<string name="show_keyboard">키보드 보이기</string>
|
||||
<string name="device_not_paired">장치가 페어링되지 않음</string>
|
||||
<string name="request_pairing">페어링 요청</string>
|
||||
<string name="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="pair_device">장치 연결</string>
|
||||
<string name="remote_control">원격 제어</string>
|
||||
<string name="settings">KDE Connect 설정</string>
|
||||
<string name="mpris_play">재생</string>
|
||||
@@ -70,6 +93,8 @@
|
||||
<string name="mpris_next">다음</string>
|
||||
<string name="mpris_volume">음량</string>
|
||||
<string name="mpris_settings">멀티미디어 설정</string>
|
||||
<string name="mpris_time_settings_title">되감기/빨리감기 단추</string>
|
||||
<string name="mpris_time_settings_summary">눌렀을 때 되감거나 빨리 감을 시간을 조정합니다.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10초</item>
|
||||
<item>20초</item>
|
||||
@@ -88,9 +113,13 @@
|
||||
<string name="invalid_device_name">잘못된 장치 이름</string>
|
||||
<string name="shareplugin_text_saved">텍스트 수신, 클립보드에 복사됨</string>
|
||||
<string name="custom_devices_settings">사용자 정의 장치 목록</string>
|
||||
<string name="pair_device_action">새 장치 연결</string>
|
||||
<string name="unpair_device_action">%s 연결 해제</string>
|
||||
<string name="custom_device_list">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">선택한 앱의 알림을 동기화합니다.</string>
|
||||
<string name="sftp_internal_storage">내부 저장소</string>
|
||||
<string name="sftp_all_files">모든 파일</string>
|
||||
<string name="sftp_sdcard_num">SD 카드 %d</string>
|
||||
@@ -98,7 +127,23 @@
|
||||
<string name="sftp_readonly">(읽기 전용)</string>
|
||||
<string name="sftp_camera">카메라 사진</string>
|
||||
<string name="add_host">호스트/IP 주소 추가</string>
|
||||
<string name="add_host_hint">호스트 이름이나 IP</string>
|
||||
<string name="no_players_connected">재생기를 찾을 수 없음</string>
|
||||
<string name="custom_dev_list_help">장치를 자동으로 인식할 수 없을 때 이 옵션을 사용하십시오. IP 주소나 호스트 이름을 입력하고 단추를 누르면 목록에 추가합니다. 목록에 있는 항목을 누르면 삭제합니다.</string>
|
||||
<string name="mpris_player_on_device">%2$s의 %1$s</string>
|
||||
<string name="send_files">파일 보내기</string>
|
||||
<string name="pairing_title">KDE Connect 장치</string>
|
||||
<string name="pairing_description">같은 네트워크에서 KDE Connect를 실행하는 다른 장치가 여기에 표시됩니다.</string>
|
||||
<string name="device_paired">장치 연결됨</string>
|
||||
<string name="device_rename_title">장치 이름 바꾸기</string>
|
||||
<string name="device_rename_confirm">이름 바꾸기</string>
|
||||
<string name="refresh">새로 고침</string>
|
||||
<string name="unreachable_description">이 연결된 장치에 접근할 수 없습니다. 같은 네트워크에 있는 지 확인하십시오.</string>
|
||||
<string name="no_file_browser">설치된 파일 탐색기가 없습니다.</string>
|
||||
<string name="pref_plugin_telepathy">SMS 보내기</string>
|
||||
<string name="pref_plugin_telepathy_desc">데스크톱에서 문자 메시지 보내기</string>
|
||||
<string name="plugin_not_supported">장치에서 이 플러그인을 지원하지 않습니다</string>
|
||||
<string name="findmyphone_found">찾았음</string>
|
||||
<string name="open">열기</string>
|
||||
<string name="close">닫기</string>
|
||||
</resources>
|
||||
|
@@ -1,15 +1,107 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Telefono žinutės ir skambučiai</string>
|
||||
<string name="pref_plugin_telephony_desc">Siųsti pranešimus apie SMS ir skambučius</string>
|
||||
<string name="pref_plugin_battery">Akumuliatoriaus ataskaita</string>
|
||||
<string name="pref_plugin_sftp">Failų sistemos naršymas</string>
|
||||
<string name="pref_plugin_clipboard">Iškarpinės sinchronizavimas</string>
|
||||
<string name="pref_plugin_mousepad">Nuotolinis įvedimas</string>
|
||||
<string name="pref_plugin_mpris">Įvairialypės terpės valdikliai</string>
|
||||
<string name="pref_plugin_runcommand">Vykdyti komandą</string>
|
||||
<string name="pref_plugin_ping">Ryšio patikrinimas</string>
|
||||
<string name="pref_plugin_notifications">Pranešimų sinchronizavimas</string>
|
||||
<string name="pref_plugin_sharereceiver">Dalintis ir gauti</string>
|
||||
<string name="device_list_empty">Įrenginių nerasta</string>
|
||||
<string name="ok">Gerai</string>
|
||||
<string name="cancel">Atšaukti</string>
|
||||
<string name="open_settings">Atverti nuostatas</string>
|
||||
<string name="send_ping">Tikrinti ryšį</string>
|
||||
<string name="open_mpris_controls">Garso ir vaizdo kūrinių grojimo valdymas</string>
|
||||
<string name="open_mousepad">Nuotolinis įvedimas</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
<item>Nieko</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Prijungti įrenginiai</string>
|
||||
<string name="category_not_paired_devices">Pasiekiami įrenginiai</string>
|
||||
<string name="category_remembered_devices">Įsimintieji įrenginiai</string>
|
||||
<string name="device_menu_plugins">Papildinio nuostatos</string>
|
||||
<string name="device_menu_unpair">Atrišti</string>
|
||||
<string name="device_not_reachable">Nepavyksta pasiekti suporuoto įrenginio</string>
|
||||
<string name="unknown_device">Nežinomas įrenginys</string>
|
||||
<string name="error_not_reachable">Įrenginys nepasiekiamas</string>
|
||||
<string name="error_already_requested">Jau paprašyta suporuoti</string>
|
||||
<string name="error_already_paired">Įrenginys jau suporuotas</string>
|
||||
<string name="error_could_not_send_package">Nepavyksta išsiųsti paketo</string>
|
||||
<string name="error_timed_out">Skirtasis laikas baigėsi</string>
|
||||
<string name="error_canceled_by_user">Naudotojas atšaukė užduotį</string>
|
||||
<string name="error_canceled_by_other_peer">Porininkas atšaukė užduotį</string>
|
||||
<string name="error_invalid_key">Gautas netinkamas raktas</string>
|
||||
<string name="pair_requested">Paprašyta suporuoti</string>
|
||||
<string name="tap_to_answer">Norėdami atsakyti, palieskite</string>
|
||||
<string name="reconnect">Prisijungti iš naujo</string>
|
||||
<string name="show_keyboard">Rodyti klaviatūrą</string>
|
||||
<string name="device_not_paired">Įrenginys nesuporuotas</string>
|
||||
<string name="request_pairing">Bandyti suporuoti</string>
|
||||
<string name="pairing_accept">Priimti</string>
|
||||
<string name="pairing_reject">Atmesti</string>
|
||||
<string name="device">Įrenginys</string>
|
||||
<string name="pair_device">Suporuoti įrenginį</string>
|
||||
<string name="remote_control">Nuotolinis valdymas</string>
|
||||
<string name="settings">„KDE Connect“ nuostatos</string>
|
||||
<string name="mpris_play">Groti</string>
|
||||
<string name="mpris_previous">Ankstesnis</string>
|
||||
<string name="mpris_rew">Atsukti</string>
|
||||
<string name="mpris_ff">Prasukti</string>
|
||||
<string name="mpris_next">Tolesnis</string>
|
||||
<string name="mpris_volume">Garsumas</string>
|
||||
<string name="mpris_settings">Įvairialypės terpės nuostatos</string>
|
||||
<string name="mpris_time_settings_title">Prasukimo ir atsukimo mygtukai</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 seconds</item>
|
||||
<item>20 seconds</item>
|
||||
<item>30 seconds</item>
|
||||
<item>1 minute</item>
|
||||
<item>2 minutes</item>
|
||||
<item>10 sekundžių</item>
|
||||
<item>20 sekundžių</item>
|
||||
<item>30 sekundžių</item>
|
||||
<item>1 minutė</item>
|
||||
<item>2 minutės</item>
|
||||
</string-array>
|
||||
<string name="share_to">Dalintis...</string>
|
||||
<string name="general_settings">Bendrosios nuostatos</string>
|
||||
<string name="plugin_settings">Nuostatos</string>
|
||||
<string name="plugin_settings_with_name">%s nuostatos</string>
|
||||
<string name="device_name">Įrenginio pavadinimas</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Netinkamas įrenginio pavadinimas</string>
|
||||
<string name="custom_devices_settings">Savitas įrenginių sąrašas</string>
|
||||
<string name="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_all_files">Visi failai</string>
|
||||
<string name="sftp_sdcard_num">SD kortelė %d</string>
|
||||
<string name="sftp_sdcard">SD kortelė</string>
|
||||
<string name="sftp_readonly">(tik skaitymui)</string>
|
||||
<string name="sftp_camera">Nuotraukos</string>
|
||||
<string name="add_host">Pridėti kompiuterį / IP</string>
|
||||
<string name="add_host_hint">Adresas arba IP</string>
|
||||
<string name="mpris_player_on_device">%1$s - %2$s</string>
|
||||
<string name="send_files">Siųsti failus</string>
|
||||
<string name="pairing_title">„KDE Connect“ įrenginiai</string>
|
||||
<string name="pairing_description">Čia turėtų pasirodyti to kiti paties tinklo įrenginiai, kuriuose veikia „KDE Connect“</string>
|
||||
<string name="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>
|
||||
|
@@ -5,17 +5,21 @@
|
||||
<string name="pref_plugin_battery">Batterijrapportage</string>
|
||||
<string name="pref_plugin_battery_desc">Rapporteer periodiek de status van de batterij</string>
|
||||
<string name="pref_plugin_sftp">Bestandssysteem blootstellen</string>
|
||||
<string name="pref_plugin_sftp_desc">Het bladeren in het bestandssysteem op afstand in de telefoon toestaan</string>
|
||||
<string name="pref_plugin_sftp_desc">Het bladeren in het bestandssysteem van het apparaat op afstand toestaan</string>
|
||||
<string name="pref_plugin_clipboard">Klembordsynchronisatie</string>
|
||||
<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 gebruiken als een muis en toetsenbord</string>
|
||||
<string name="pref_plugin_mousepad_desc">Uw telefoon of tablet gebruiken als een touchpad en toetsenbord</string>
|
||||
<string name="pref_plugin_mpris">Bediening van multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Bedien de audio/video vanaf uw telefoon</string>
|
||||
<string name="pref_plugin_mpris_desc">Biedt een afstandsbediening voor uw mediaspeler</string>
|
||||
<string name="pref_plugin_runcommand">Commando uitvoeren</string>
|
||||
<string name="pref_plugin_runcommand_desc">Commando\'s afvuren op afstand vanaf uw telefoon of tablet</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Pings verzenden en ontvangen</string>
|
||||
<string name="pref_plugin_notifications">Synchronisatie van meldingen</string>
|
||||
<string name="pref_plugin_notifications_desc">Bekijk uw meldingen van andere apparaten</string>
|
||||
<string name="pref_plugin_receive_notifications">Meldingen ontvangen</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Meldingen van het andere apparaat ontvangen en tonen op Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Delen en Ontvangen</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Bestanden en URL\'s delen tussen apparaten</string>
|
||||
<string name="plugin_not_available">Deze functie is niet beschikbaar in uw versie van Android</string>
|
||||
@@ -30,6 +34,8 @@
|
||||
<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>
|
||||
<string name="mousepad_triple_tap_settings_title">Tikactie met drie vingers instellen</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Gevoeligheid van touchpad instellen</string>
|
||||
<string name="mousepad_scroll_direction_title">Schuifrichting omdraaien</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Rechter muisklik</item>
|
||||
<item>Middelste muisklik</item>
|
||||
@@ -37,6 +43,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">rechts</string>
|
||||
<string name="mousepad_triple_default">midden</string>
|
||||
<string name="mousepad_sensitivity_default">standaard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Langzaamst</item>
|
||||
<item>Langzaam</item>
|
||||
<item>Standaard</item>
|
||||
<item>Boven standaard</item>
|
||||
<item>Snelste</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Verbonden apparaten</string>
|
||||
<string name="category_not_paired_devices">Beschikbare apparaten</string>
|
||||
<string name="category_remembered_devices">Onthouden apparaten</string>
|
||||
@@ -44,6 +58,7 @@
|
||||
<string name="device_menu_plugins">Plugin-instellingen</string>
|
||||
<string name="device_menu_unpair">Paar uit elkaar halen</string>
|
||||
<string name="device_not_reachable">Gepaard apparaat niet bereikbaar</string>
|
||||
<string name="pair_new_device">Nieuw apparaat paren</string>
|
||||
<string name="unknown_device">Onbekend apparaat</string>
|
||||
<string name="error_not_reachable">Apparaat niet bereikbaar</string>
|
||||
<string name="error_already_requested">Paar maken is al gevraagd</string>
|
||||
@@ -53,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Geannuleerd door gebruiker</string>
|
||||
<string name="error_canceled_by_other_peer">Geannuleerd door andere kant</string>
|
||||
<string name="error_invalid_key">Ongeldige sleutel ontvangen</string>
|
||||
<string name="encryption_info_title">Versleutelde informatie</string>
|
||||
<string name="encryption_info_msg_no_ssl">Het andere apparaat gebruikt geen recente versie van KDE Connect, de verouderde versleutelingsmethode zal worden gebruikt.</string>
|
||||
<string name="my_device_fingerprint">De SHA1 vingerafdruk van het certificaat van uw apparaat is:</string>
|
||||
<string name="remote_device_fingerprint">De SHA1 vingerafdruk van het certificaat van het apparaat op afstand is:</string>
|
||||
<string name="pair_requested">Paar gevraagd</string>
|
||||
<string name="pairing_request_from">Verzoek om een paar te maken van %1s</string>
|
||||
<string name="received_url_title">Ontvangen koppeling van %1s</string>
|
||||
@@ -138,4 +157,10 @@
|
||||
<string name="pref_plugin_telepathy">SMS verzenden</string>
|
||||
<string name="pref_plugin_telepathy_desc">Stuur tekstberichten van uw bureaublad</string>
|
||||
<string name="plugin_not_supported">Deze plug-in wordt niet ondersteund door het apparaat</string>
|
||||
<string name="findmyphone_title">Zoek mijn telefoon</string>
|
||||
<string name="findmyphone_title_tablet">Zoek mijn tablet</string>
|
||||
<string name="findmyphone_description">Laat dit apparaat bellen zodat u het kunt vinden</string>
|
||||
<string name="findmyphone_found">Gevonden</string>
|
||||
<string name="open">Openen</string>
|
||||
<string name="close">Sluiten</string>
|
||||
</resources>
|
||||
|
@@ -5,17 +5,21 @@
|
||||
<string name="pref_plugin_battery">Zgłaszanie baterii</string>
|
||||
<string name="pref_plugin_battery_desc">Okresowo zgłaszaj stan baterii</string>
|
||||
<string name="pref_plugin_sftp">Eksponowanie systemu plików</string>
|
||||
<string name="pref_plugin_sftp_desc">Zezwala na zdalne przeglądanie systemu plików telefonu</string>
|
||||
<string name="pref_plugin_sftp_desc">Zezwala na zdalne przeglądanie systemu plików tego urządzenia</string>
|
||||
<string name="pref_plugin_clipboard">Synchronizacja schowka</string>
|
||||
<string name="pref_plugin_clipboard_desc">Udostępnij zawartość schowka</string>
|
||||
<string name="pref_plugin_mousepad">Zdalne sterowanie</string>
|
||||
<string name="pref_plugin_mousepad_desc">Użyj swojego telefonu jako myszy i klawiatury</string>
|
||||
<string name="pref_plugin_mousepad_desc">Użyj swojego telefonu lub tabletu jako myszy i klawiatury</string>
|
||||
<string name="pref_plugin_mpris">Sterowanie multimediami</string>
|
||||
<string name="pref_plugin_mpris_desc">Steruj dźwiękiem/obrazem ze swojego telefonu</string>
|
||||
<string name="pref_plugin_mpris_desc">Zapewnia zdalne sterowanie twoim odtwarzaczem multimedialnym</string>
|
||||
<string name="pref_plugin_runcommand">Wykonaj polecenie</string>
|
||||
<string name="pref_plugin_runcommand_desc">Wyzwalaj zdalne polecenia z twojego telefonu lub tabletu</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Wysyłaj i otrzymuj pingi</string>
|
||||
<string name="pref_plugin_notifications">Powiadomienia synchronizacji</string>
|
||||
<string name="pref_plugin_notifications_desc">Uzyskaj dostęp do swoich powiadomień z innego urządzenia</string>
|
||||
<string name="pref_plugin_receive_notifications">Otrzymuj powiadomienia</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Otrzymuj powiadomienia z urządzeń i wyświetlaj je na Androidzie</string>
|
||||
<string name="pref_plugin_sharereceiver">Udostępniaj i otrzymuj</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Współdziel pliki i adresy URL pomiędzy urządzeniami</string>
|
||||
<string name="plugin_not_available">Funkcja ta nie jest dostępna w twojej wersji Androida</string>
|
||||
@@ -30,13 +34,23 @@
|
||||
<string name="mousepad_info">Przesuń palcem po ekranie, aby przesunąć wskaźnik myszy. Stuknij, aby wywołać naciśniecie lewym przyciskiem myszy i użyj dwóch/trzech palców, aby wywołać naciśniecie prawym i środkowym przyciskiem myszy. Przyciśnij na dłużej, aby przeciągnąć i upuścić.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ustaw działanie po dwukrotnym stuknięciu palcem</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ustaw działanie po trzykrotnym stuknięciu palcem</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Ustaw czułość gładzika</string>
|
||||
<string name="mousepad_scroll_direction_title">Odwróć stronę przewijania</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Naciśnięcie prawym</item>
|
||||
<item>Naciśnięcie środkowym</item>
|
||||
<item>Kliknięcie prawym</item>
|
||||
<item>Kliknięcie środkowym</item>
|
||||
<item>Nic</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">prawo</string>
|
||||
<string name="mousepad_triple_default">środek</string>
|
||||
<string name="mousepad_sensitivity_default">domyślne</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Najmniejsza</item>
|
||||
<item>Ponad najmniejszą</item>
|
||||
<item>Domyślna</item>
|
||||
<item>Powyżej domyślnej</item>
|
||||
<item>Największa</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Podłączone urządzenia</string>
|
||||
<string name="category_not_paired_devices">Dostępne urządzenia</string>
|
||||
<string name="category_remembered_devices">Zapamiętane urządzenia</string>
|
||||
@@ -44,6 +58,7 @@
|
||||
<string name="device_menu_plugins">Ustawienia wtyczki</string>
|
||||
<string name="device_menu_unpair">Odparuj</string>
|
||||
<string name="device_not_reachable">Sparowane urządzenie nieosiągalne</string>
|
||||
<string name="pair_new_device">Sparuj nowe urządzenie</string>
|
||||
<string name="unknown_device">Nieznane urządzenie</string>
|
||||
<string name="error_not_reachable">Urządzenie nieosiągalne</string>
|
||||
<string name="error_already_requested">Już zażądano parowania</string>
|
||||
@@ -53,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Anulowane przez użytkownika</string>
|
||||
<string name="error_canceled_by_other_peer">Anulowane przez innego partnera</string>
|
||||
<string name="error_invalid_key">Otrzymano nieprawidłowy klucz</string>
|
||||
<string name="encryption_info_title">Zaszyfrowane informacje</string>
|
||||
<string name="encryption_info_msg_no_ssl">Drugie urządzenie nie używa ostatniej wersji KDE Connect, użyto przestarzałego szyfrowania.</string>
|
||||
<string name="my_device_fingerprint">Odcisk palca SHA1 certyfikatu twojego urządzenia to:</string>
|
||||
<string name="remote_device_fingerprint">Odcisk palca SHA1 certyfikatu twojego zdalnego urządzenia to:</string>
|
||||
<string name="pair_requested">Zażądano parowania</string>
|
||||
<string name="pairing_request_from">Żądanie parowania z %1s</string>
|
||||
<string name="received_url_title">Odebrano odsyłacz od %1s</string>
|
||||
@@ -138,4 +157,10 @@
|
||||
<string name="pref_plugin_telepathy">Wyślij SMS-a</string>
|
||||
<string name="pref_plugin_telepathy_desc">Wyślij wiadomość tekstową z komputera</string>
|
||||
<string name="plugin_not_supported">Ta wtyczka nie jest obsługiwana przez to urządzenie</string>
|
||||
<string name="findmyphone_title">Znajdź mój telefon</string>
|
||||
<string name="findmyphone_title_tablet">Znajdź mój tablet</string>
|
||||
<string name="findmyphone_description">Dzwoni na dane urządzenie, tak abyś mógł je znaleźć.</string>
|
||||
<string name="findmyphone_found">Znaleziony</string>
|
||||
<string name="open">Otwórz</string>
|
||||
<string name="close">Zamknij</string>
|
||||
</resources>
|
||||
|
@@ -1,23 +1,21 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Notificação telefônica</string>
|
||||
<string name="pref_plugin_telephony">Notificação de telefonia</string>
|
||||
<string name="pref_plugin_telephony_desc">Envia notificações de SMS e chamadas</string>
|
||||
<string name="pref_plugin_battery">Relatório da bateria</string>
|
||||
<string name="pref_plugin_battery_desc">Informa o status da bateria periodicamente</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 remotamente pelo sistema de arquivos telefone</string>
|
||||
<string name="pref_plugin_clipboard">Sincronizar área de transferência</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">Usar seu telefone como mouse ou teclado</string>
|
||||
<string name="pref_plugin_mpris">Controle multimídia</string>
|
||||
<string name="pref_plugin_mpris_desc">Controla áudio e vídeo a partir do seu telefone</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_sharereceiver">Compartilhar e receber</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Compartilhar arquivos e URLs entre os dispositivos</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>
|
||||
<string name="device_list_empty">Sem dispositivos</string>
|
||||
<string name="ok">OK</string>
|
||||
@@ -27,9 +25,11 @@
|
||||
<string name="send_ping">Enviar ping</string>
|
||||
<string name="open_mpris_controls">Controle multimídia</string>
|
||||
<string name="open_mousepad">Introdução de dados remota</string>
|
||||
<string name="mousepad_info">Mova um dedo pelo tela para mover o ponteiro do mouse. Dê um toque para clicar e use dois/três dedos para os botões da direita e do meio. Use uma pressão longa para arrastar e soltar.</string>
|
||||
<string name="mousepad_info">Mova um dedo pela tela para mover o ponteiro do mouse. Dê um toque para clicar e use dois/três dedos para os botões da direita e do meio. Use uma pressão longa para arrastar e soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Definir a ação do toque com dois dedos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Definir a ação do toque com três dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do touchpad</string>
|
||||
<string name="mousepad_scroll_direction_title">Direção de rolagem inversa</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Botão direito</item>
|
||||
<item>Botão do meio</item>
|
||||
@@ -37,13 +37,22 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">direita</string>
|
||||
<string name="mousepad_triple_default">meio</string>
|
||||
<string name="mousepad_sensitivity_default">padrão</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Mais lento</item>
|
||||
<item>Ainda mais lento</item>
|
||||
<item>Padrão</item>
|
||||
<item>Acima do padrão</item>
|
||||
<item>Mais rápido</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivos conectados</string>
|
||||
<string name="category_not_paired_devices">Dispositivos disponíveis</string>
|
||||
<string name="category_remembered_devices">Dispositivos lembrados</string>
|
||||
<string name="plugins_failed_to_load">Plugins não carregados (toque para mais informações):</string>
|
||||
<string name="device_menu_plugins">Configurações do plugin</string>
|
||||
<string name="device_menu_plugins">Configuração dos plugins</string>
|
||||
<string name="device_menu_unpair">Cancelar emparelhamento</string>
|
||||
<string name="device_not_reachable">O dispositivo pareado está inacessível</string>
|
||||
<string name="pair_new_device">Emparelhar novo dispositivo</string>
|
||||
<string name="unknown_device">Dispositivo desconhecido</string>
|
||||
<string name="error_not_reachable">Dispositivo inacessível</string>
|
||||
<string name="error_already_requested">O emparelhamento já foi solicitado</string>
|
||||
@@ -53,8 +62,8 @@
|
||||
<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="pair_requested">Emparelhamento solicitado</string>
|
||||
<string name="pairing_request_from">Emparelhando solicitação de %1s</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>
|
||||
<string name="received_url_text">Toque para abrir o \'%1s\'</string>
|
||||
<string name="incoming_file_title">Arquivo recebido de %1s</string>
|
||||
@@ -109,12 +118,12 @@
|
||||
<string name="shareplugin_text_saved">Texto recebido e salvo na área de transferência</string>
|
||||
<string name="custom_devices_settings">Lista de dispositivos personalizada</string>
|
||||
<string name="pair_device_action">Emparelhar um novo dispositivo</string>
|
||||
<string name="unpair_device_action">Desemparelhar o %s</string>
|
||||
<string name="unpair_device_action">Desemparelhar %s</string>
|
||||
<string name="custom_device_list">Adicionar dispositivos pelo IP</string>
|
||||
<string name="share_notification_preference">Notificações barulhentas</string>
|
||||
<string name="share_notification_preference_summary">Vibrar e tocar um som ao receber um arquivo</string>
|
||||
<string name="share_notification_preference">Notificações sonoras</string>
|
||||
<string name="share_notification_preference_summary">Vibra e reproduz um som ao receber um arquivo</string>
|
||||
<string name="title_activity_notification_filter">Filtro de notificações</string>
|
||||
<string name="filter_apps_info">As notificações serão sincronizadas para os aplicativos selecionados.</string>
|
||||
<string name="filter_apps_info">As notificações dos aplicativos selecionados serão sincronizadas.</string>
|
||||
<string name="sftp_internal_storage">Armazenamento interno</string>
|
||||
<string name="sftp_all_files">Todos os arquivos</string>
|
||||
<string name="sftp_sdcard_num">Cartão SD %d</string>
|
||||
@@ -128,7 +137,7 @@
|
||||
<string name="mpris_player_on_device">%1$s em %2$s</string>
|
||||
<string name="send_files">Enviar arquivos</string>
|
||||
<string name="pairing_title">Dispositivos do KDE Connect</string>
|
||||
<string name="pairing_description">Os outros dispositivos executando o KDE Connect na mesma rede devem aparecer aqui.</string>
|
||||
<string name="pairing_description">Outros dispositivos executando o KDE Connect na mesma rede devem aparecer aqui.</string>
|
||||
<string name="device_paired">Dispositivo emparelhado</string>
|
||||
<string name="device_rename_title">Renomear dispositivo</string>
|
||||
<string name="device_rename_confirm">Renomear</string>
|
||||
@@ -138,4 +147,7 @@
|
||||
<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_found">Encontrado</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Fechar</string>
|
||||
</resources>
|
||||
|
@@ -5,17 +5,21 @@
|
||||
<string name="pref_plugin_battery">Relatório da bateria</string>
|
||||
<string name="pref_plugin_battery_desc">Comunicar periodicamente o estado da bateria</string>
|
||||
<string name="pref_plugin_sftp">Exposição do sistema de ficheiros</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite navegar pelo sistema de ficheiros remoto do telefone</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite navegar pelo sistema de ficheiros remoto deste dispositivo</string>
|
||||
<string name="pref_plugin_clipboard">Sincronização da área de transferência</string>
|
||||
<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 como um rato ou teclado</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usar o seu telefone ou \'tablet\' como um rato ou teclado</string>
|
||||
<string name="pref_plugin_mpris">Comandos multimédia</string>
|
||||
<string name="pref_plugin_mpris_desc">Controlar o áudio/vídeo a partir do seu telefone</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>
|
||||
<string name="pref_plugin_runcommand_desc">Despoletar comandos remotos a partir do seu telefone ou \'tablet\'</string>
|
||||
<string name="pref_plugin_ping">Contacto</string>
|
||||
<string name="pref_plugin_ping_desc">Enviar e receber pedidos de contacto (\'ping\')</string>
|
||||
<string name="pref_plugin_notifications">Sincronização da notificação</string>
|
||||
<string name="pref_plugin_notifications_desc">Aceder às suas notificações a partir de outros dispositivos</string>
|
||||
<string name="pref_plugin_receive_notifications">Receber as notificações</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Receber as notificações de outros dispositivos e mostrá-las no Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Partilhar e receber</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Partilhar ficheiros e URL\'s entre dispositivos</string>
|
||||
<string name="plugin_not_available">Esta funcionalidade não está disponível na sua versão do Android</string>
|
||||
@@ -30,6 +34,8 @@
|
||||
<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>
|
||||
<string name="mousepad_triple_tap_settings_title">Definir a acção do toque com três dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do rato por toque</string>
|
||||
<string name="mousepad_scroll_direction_title">Direcção de Deslocamento Inversa</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Botão direito</item>
|
||||
<item>Botão do meio</item>
|
||||
@@ -37,6 +43,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">direita</string>
|
||||
<string name="mousepad_triple_default">meio</string>
|
||||
<string name="mousepad_sensitivity_default">predefinição</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Mais Lento</item>
|
||||
<item>Ainda Mais Lento</item>
|
||||
<item>Predefinição</item>
|
||||
<item>Acima da Predefinição</item>
|
||||
<item>Mais Rápido</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivos ligados</string>
|
||||
<string name="category_not_paired_devices">Dispositivos disponíveis</string>
|
||||
<string name="category_remembered_devices">Dispositivos recordados</string>
|
||||
@@ -44,6 +58,7 @@
|
||||
<string name="device_menu_plugins">Configuração do \'plugin\'</string>
|
||||
<string name="device_menu_unpair">Desemparelhar</string>
|
||||
<string name="device_not_reachable">O dispositivo emparelhado está inacessível</string>
|
||||
<string name="pair_new_device">Emparelhar um novo dispositivo</string>
|
||||
<string name="unknown_device">Dispositivo desconhecido</string>
|
||||
<string name="error_not_reachable">Dispositivo inacessível</string>
|
||||
<string name="error_already_requested">O emparelhamento já foi pedido</string>
|
||||
@@ -53,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Cancelado pelo utilizador</string>
|
||||
<string name="error_canceled_by_other_peer">Cancelado pela outra máquina</string>
|
||||
<string name="error_invalid_key">Chave inválida recebida</string>
|
||||
<string name="encryption_info_title">Dados de Encriptação</string>
|
||||
<string name="encryption_info_msg_no_ssl">O outro dispositivo não usa uma versão recente do KDE Connect; será usado o método antigo de encriptação.</string>
|
||||
<string name="my_device_fingerprint">A impressão digital SHA1 do certificado do seu dispositivo é:</string>
|
||||
<string name="remote_device_fingerprint">A impressão digital SHA1 do certificado do dispositivo remoto é:</string>
|
||||
<string name="pair_requested">Emparelhamento pedido</string>
|
||||
<string name="pairing_request_from">Pedido de emparelhamento de %1s</string>
|
||||
<string name="received_url_title">Ligação recebida de %1s</string>
|
||||
@@ -138,4 +157,10 @@
|
||||
<string name="pref_plugin_telepathy">Enviar um SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensagens de texto a partir do seu ambiente de trabalho</string>
|
||||
<string name="plugin_not_supported">Este \'plugin\' não é suportado pelo dispositivo</string>
|
||||
<string name="findmyphone_title">Descobrir o meu telefone</string>
|
||||
<string name="findmyphone_title_tablet">Descobrir o meu \'tablet\'</string>
|
||||
<string name="findmyphone_description">Toca este dispositivo para que o possa encontrar</string>
|
||||
<string name="findmyphone_found">Encontrado</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Fechar</string>
|
||||
</resources>
|
||||
|
@@ -5,10 +5,8 @@
|
||||
<string name="pref_plugin_battery">Raport acumulator</string>
|
||||
<string name="pref_plugin_battery_desc">Raportează periodic starea acumulatorului</string>
|
||||
<string name="pref_plugin_sftp">Expunere sistem de fișiere</string>
|
||||
<string name="pref_plugin_sftp_desc">Vă permite să răsfoiți de la distanță sistemul de fișiere al dispozitivului</string>
|
||||
<string name="pref_plugin_clipboard">Sincronizare clipboard</string>
|
||||
<string name="pref_plugin_clipboard_desc">Partajează conținutul clipboardului</string>
|
||||
<string name="pref_plugin_mpris_desc">Controlați audio/video de pe telefon</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Trimite și primește ping-uri</string>
|
||||
<string name="pref_plugin_notifications">Sincronizare notificări</string>
|
||||
@@ -25,6 +23,13 @@
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispozitive conectate</string>
|
||||
<string name="category_remembered_devices">Dispozitive memorizate</string>
|
||||
<string name="plugins_failed_to_load">Încărcarea extensiilor a eșuat (atingeți pentru mai multe informații):</string>
|
||||
|
@@ -1,65 +1,149 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Уведомления телефонии</string>
|
||||
<string name="pref_plugin_telephony_desc">Отправлять уведомления о SMS и звонках</string>
|
||||
<string name="pref_plugin_telephony">События телефонии</string>
|
||||
<string name="pref_plugin_telephony_desc">Отправка уведомлений об SMS и звонках</string>
|
||||
<string name="pref_plugin_battery">Состояние батареи</string>
|
||||
<string name="pref_plugin_battery_desc">Периодически сообщать о состоянии батареи</string>
|
||||
<string name="pref_plugin_battery_desc">Периодическое информирование о состоянии батареи</string>
|
||||
<string name="pref_plugin_sftp">Просмотр файловой системы</string>
|
||||
<string name="pref_plugin_clipboard">Синхронизация буфера обмена</string>
|
||||
<string name="pref_plugin_clipboard_desc">Сделать содержимое буфера обмена общим</string>
|
||||
<string name="pref_plugin_mpris_desc">Управление аудио/видео с устройства</string>
|
||||
<string name="pref_plugin_clipboard_desc">Использование общего буфера обмена</string>
|
||||
<string name="pref_plugin_mousepad">Удалённый ввод</string>
|
||||
<string name="pref_plugin_mpris">Управление воспроизведением</string>
|
||||
<string name="pref_plugin_runcommand">Запуск команд</string>
|
||||
<string name="pref_plugin_ping">Пинг</string>
|
||||
<string name="pref_plugin_ping_desc">Посылать и получать пинги</string>
|
||||
<string name="pref_plugin_ping_desc">Отправка и получение тестовых сигналов</string>
|
||||
<string name="pref_plugin_notifications">Синхронизация уведомлений</string>
|
||||
<string name="pref_plugin_notifications_desc">Доступ к уведомлениям с других устройств</string>
|
||||
<string name="plugin_not_available">Этот функционал недоступен в вашей версии 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="ok">ОК</string>
|
||||
<string name="cancel">Отмена</string>
|
||||
<string name="open_settings">Открыть настройки</string>
|
||||
<string name="no_permissions">Вы должны разрешить доступ к уведомлениям</string>
|
||||
<string name="send_ping">Послать пинг</string>
|
||||
<string name="open_settings">Настроить</string>
|
||||
<string name="no_permissions">Нужно разрешить доступ к уведомлениям</string>
|
||||
<string name="send_ping">Отправить тестовый сигнал</string>
|
||||
<string name="open_mpris_controls">Управление воспроизведением</string>
|
||||
<string name="open_mousepad">Удалённый ввод</string>
|
||||
<string name="mousepad_info">Перемещайте палец по экрану для перемещения курсора мыши. Коснитесь для нажатия, используйте два/три пальца для правой и средней кнопок. Используйте долгое нажатие для перетаскивания.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Действие при нажатии двумя пальцами</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Действие при нажатии тремя пальцами</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
<item>Нажатие правой кнопки</item>
|
||||
<item>Нажатие средней кнопки</item>
|
||||
<item>Ничего не делать</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Нажатие правой кнопки</string>
|
||||
<string name="mousepad_triple_default">Нажатие средней кнопки</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Подключённые устройства</string>
|
||||
<string name="category_remembered_devices">Запомненные устройства</string>
|
||||
<string name="plugins_failed_to_load">Сбой загрузки следующих модулей (прикоснитесь чтобы получить подробности):</string>
|
||||
<string name="device_menu_unpair">Разделить спаренные устройства</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="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_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="pair_requested">Запрошено спаривание</string>
|
||||
<string name="pairing_request_from">Запрос на спаривание от %1s</string>
|
||||
<string name="tap_to_answer">Коснитесь чтобы ответить</string>
|
||||
<string name="reconnect">Переподключить</string>
|
||||
<string name="device_not_paired">Устройство не спарено</string>
|
||||
<string name="request_pairing">Запросить спаривание</string>
|
||||
<string name="error_invalid_key">Получен недопустимый ключ</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_title">Не удалось отправить файл %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Нажмите, чтобы ответить</string>
|
||||
<string name="reconnect">Подключить заново</string>
|
||||
<string name="right_click">Нажатие правой кнопки</string>
|
||||
<string name="middle_click">Нажатие средней кнопки</string>
|
||||
<string name="show_keyboard">Показать клавиатуру</string>
|
||||
<string name="device_not_paired">Устройство не сопряжено</string>
|
||||
<string name="request_pairing">Запросить сопряжение</string>
|
||||
<string name="pairing_accept">Принять</string>
|
||||
<string name="pairing_reject">Отклонить</string>
|
||||
<string name="device">Устройство</string>
|
||||
<string name="pair_device">Спарить устройство</string>
|
||||
<string name="pair_device">Сопрячь устройство</string>
|
||||
<string name="remote_control">Дистанционное управление</string>
|
||||
<string name="settings">Настройки KDE Connect</string>
|
||||
<string name="mpris_play">Воспроизвести</string>
|
||||
<string name="mpris_previous">Предыдущий</string>
|
||||
<string name="mpris_next">Следующее</string>
|
||||
<string name="settings">Настройка KDE Connect</string>
|
||||
<string name="mpris_play">Воспроизведение</string>
|
||||
<string name="mpris_previous">Предыдущая</string>
|
||||
<string name="mpris_rew">Назад</string>
|
||||
<string name="mpris_ff">Вперёд</string>
|
||||
<string name="mpris_next">Следующая</string>
|
||||
<string name="mpris_volume">Громкость</string>
|
||||
<string name="mpris_settings">Настройка мультимедиа</string>
|
||||
<string name="mpris_time_settings_title">Кнопки вперёд/назад</string>
|
||||
<string name="mpris_time_settings_summary">Дальность перемотки вперёд/назад при нажатии.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 seconds</item>
|
||||
<item>20 seconds</item>
|
||||
<item>30 seconds</item>
|
||||
<item>1 minute</item>
|
||||
<item>2 minutes</item>
|
||||
<item>10 секунд</item>
|
||||
<item>20 секунд</item>
|
||||
<item>30 секунд</item>
|
||||
<item>1 минута</item>
|
||||
<item>2 минуты</item>
|
||||
</string-array>
|
||||
<string name="share_to">Сделать общим с...</string>
|
||||
<string name="protocol_version_older">Это устройство использует старую версию протокола</string>
|
||||
<string name="protocol_version_newer">Это устройство использует более свежую версию протокола</string>
|
||||
<string name="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">Уведомления будут синхронизированы для выбранных приложений.</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">Добавить хост/IP-адрес</string>
|
||||
<string name="add_host_hint">Имя хоста или IP-адрес</string>
|
||||
<string name="no_players_connected">Медиапроигрывателей не найдено</string>
|
||||
<string name="custom_dev_list_help">Используйте эту форму только если ваше устройство не определяется автоматически. Введите IP-адрес или имя хоста ниже и нажмите кнопку для добавления в список. Нажмите на существующий элемент для удаления из списка.</string>
|
||||
<string name="mpris_player_on_device">%1$s на %2$s</string>
|
||||
<string name="send_files">Отправить файлы</string>
|
||||
<string name="pairing_title">Устройства с KDE Connect</string>
|
||||
<string name="pairing_description">Здесь появятся другие устройства в этой же сети, на которых запущен KDE Connect.</string>
|
||||
<string name="device_paired">Устройство сопряжено</string>
|
||||
<string name="device_rename_title">Переименование устройства</string>
|
||||
<string name="device_rename_confirm">Переименовать</string>
|
||||
<string name="refresh">Обновить</string>
|
||||
<string name="unreachable_description">Это сопряжённое устройство недоступно. Проверьте, что оно подключено к той же локальной сети.</string>
|
||||
<string name="no_file_browser">Не удалось открыть диалог выбора файла.</string>
|
||||
<string name="pref_plugin_telepathy">Отправка SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Отправка SMS-сообщений с вашего компьютера</string>
|
||||
<string name="plugin_not_supported">Этот модуль не поддерживается устройством</string>
|
||||
<string name="findmyphone_found">Найден</string>
|
||||
<string name="open">Открыть</string>
|
||||
<string name="close">Закрыть</string>
|
||||
</resources>
|
||||
|
@@ -5,13 +5,11 @@
|
||||
<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í prístup na súborový systém telefónu 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 ako myš a klávesnicu</string>
|
||||
<string name="pref_plugin_mpris">Multimediálne ovládače</string>
|
||||
<string name="pref_plugin_mpris_desc">Ovládať audio/video z vášho telefónu</string>
|
||||
<string name="pref_plugin_runcommand">Spustiť príkaz</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>
|
||||
@@ -30,6 +28,8 @@
|
||||
<string name="mousepad_info">Posúvajte prst na obrazovke na posun kurzora. Ťuknutie vyvolá klik a použite dva/tri prsty pre pravé a stredné tlačidlo. Použite dlhé stlačenie pre drag and drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Nastaviť akciu dvoch prstov</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Nastaviť akciu troch prstov</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Nastaviť citlivosť touchpadu</string>
|
||||
<string name="mousepad_scroll_direction_title">Obrátený smer rolovania</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Kliknutie pravým tlačidlom</item>
|
||||
<item>Stredný klik</item>
|
||||
@@ -37,6 +37,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">vpravo</string>
|
||||
<string name="mousepad_triple_default">stred</string>
|
||||
<string name="mousepad_sensitivity_default">predvolené</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Najpomalšie</item>
|
||||
<item>Nad najpomalším</item>
|
||||
<item>Predvolené</item>
|
||||
<item>Nad priemerným</item>
|
||||
<item>Najrýchlejšie</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Pripojené zariadenia</string>
|
||||
<string name="category_not_paired_devices">Dostupné zariadenia</string>
|
||||
<string name="category_remembered_devices">Zapamätané zariadenia</string>
|
||||
@@ -44,6 +52,7 @@
|
||||
<string name="device_menu_plugins">Nastavenia pluginu</string>
|
||||
<string name="device_menu_unpair">Odpárovať</string>
|
||||
<string name="device_not_reachable">Spárované zariadenie nedostupné</string>
|
||||
<string name="pair_new_device">Spárovať nové zariadenie</string>
|
||||
<string name="unknown_device">Neznáme zariadenie</string>
|
||||
<string name="error_not_reachable">Zariadenie nedostupné</string>
|
||||
<string name="error_already_requested">Spárovanie už vyžiadané</string>
|
||||
@@ -53,6 +62,10 @@
|
||||
<string name="error_canceled_by_user">Zrušené používateľom</string>
|
||||
<string name="error_canceled_by_other_peer">Zrušené iným klientom</string>
|
||||
<string name="error_invalid_key">Získaný nesprávny kľúč</string>
|
||||
<string name="encryption_info_title">Informácia o šifrovaní</string>
|
||||
<string name="encryption_info_msg_no_ssl">Ďalšie zariadenie nepoužíva aktuálnu verziu KDE Connect, používam klasickú metódu šifrovania.</string>
|
||||
<string name="my_device_fingerprint">Odtlačok SHA1 vášho certifikátu zariadenia je:</string>
|
||||
<string name="remote_device_fingerprint">Odtlačok SHA1 vzdialeného certifikátu zariadenia je:</string>
|
||||
<string name="pair_requested">Spárovanie vyžiadané</string>
|
||||
<string name="pairing_request_from">Požiadavka na spárovanie od %1s</string>
|
||||
<string name="received_url_title">Prijatý odkaz od %1s</string>
|
||||
@@ -108,6 +121,8 @@
|
||||
<string name="invalid_device_name">Neplatný názov zariadenia</string>
|
||||
<string name="shareplugin_text_saved">Prijatý text, uložený do schránky</string>
|
||||
<string name="custom_devices_settings">Zoznam vlastných zariadení</string>
|
||||
<string name="pair_device_action">Spárovať nové zariadenie</string>
|
||||
<string name="unpair_device_action">Odpárovať %s</string>
|
||||
<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>
|
||||
@@ -124,4 +139,20 @@
|
||||
<string name="no_players_connected">Nenašli sa žiadne prehrávače</string>
|
||||
<string name="custom_dev_list_help">Túto voľbu použite iba vtedy, ak vaše zariadenie nie je automaticky detekované. Zadajte IP adresu alebo názov hostiteľa nižšie a kliknite na tlačidlo na pridanie do zoznamu. Kliknite na existujúcu položku na odstránenie jej zo zoznamu.</string>
|
||||
<string name="mpris_player_on_device">%1$s na %2$s</string>
|
||||
<string name="send_files">Odoslať súbory</string>
|
||||
<string name="pairing_title">KDE Connect zariadenia</string>
|
||||
<string name="pairing_description">Iné zariadenie so spusteným KDE Connect v rovnakej sieti by sa tu mali objaviť.</string>
|
||||
<string name="device_paired">Zariadenie spárované</string>
|
||||
<string name="device_rename_title">Premenovať zariadenie</string>
|
||||
<string name="device_rename_confirm">Premenovať</string>
|
||||
<string name="refresh">Obnoviť</string>
|
||||
<string name="unreachable_description">Toto spárované zariadenie nie je dosiahnuteľné. Prosím, uistite sa, že je pripojené do rovnakej siete.</string>
|
||||
<string name="no_file_browser">Nie sú nainštalované žiadne prehliadače.</string>
|
||||
<string name="pref_plugin_telepathy">Poslať SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Posielať textové správy z vášho počítača</string>
|
||||
<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_found">Nájdené</string>
|
||||
<string name="open">Otvoriť</string>
|
||||
<string name="close">Zavrieť</string>
|
||||
</resources>
|
||||
|
@@ -5,17 +5,21 @@
|
||||
<string name="pref_plugin_battery">Batterirapport</string>
|
||||
<string name="pref_plugin_battery_desc">Rapportera periodiskt batteriets status</string>
|
||||
<string name="pref_plugin_sftp">Exponera filsystem</string>
|
||||
<string name="pref_plugin_sftp_desc">Gör det möjligt att bläddra i telefonens filsystem från annan apparat</string>
|
||||
<string name="pref_plugin_sftp_desc">Gör det möjligt att bläddra i apparatens filsystem från annan apparat</string>
|
||||
<string name="pref_plugin_clipboard">Synkronisera klippbord</string>
|
||||
<string name="pref_plugin_clipboard_desc">Dela klippbordets innehåll</string>
|
||||
<string name="pref_plugin_mousepad">Fjärrinmatning</string>
|
||||
<string name="pref_plugin_mousepad_desc">Använd telefonen som mus och tangentbord</string>
|
||||
<string name="pref_plugin_mousepad_desc">Använd telefonen eller surfplattan som mus och tangentbord</string>
|
||||
<string name="pref_plugin_mpris">Multimediakontroller</string>
|
||||
<string name="pref_plugin_mpris_desc">Styr ljud och video från telefonen</string>
|
||||
<string name="pref_plugin_mpris_desc">Tillhandahåller en fjärrkontroll för mediaspelaren</string>
|
||||
<string name="pref_plugin_runcommand">Kör kommando</string>
|
||||
<string name="pref_plugin_runcommand_desc">Utlös fjärrkommandon från din telefon eller surfplatta</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Skicka och ta emot ping</string>
|
||||
<string name="pref_plugin_notifications">Synkronisering av underrättelser</string>
|
||||
<string name="pref_plugin_notifications_desc">Kom åt underrättelser från andra apparater</string>
|
||||
<string name="pref_plugin_receive_notifications">Ta emot underrättelser</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Ta emot underrättelser från andra apparater och visa dem på Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Dela och ta emot</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Dela filer och webbadresser mellan apparater</string>
|
||||
<string name="plugin_not_available">Funktionen är inte tillgänglig i Android-versionen</string>
|
||||
@@ -30,6 +34,8 @@
|
||||
<string name="mousepad_info">Flytta fingret på skärmen för att röra muspekaren. Rör för att klicka, och använd två eller tre fingrar för höger- och mittenknapparna. Använd en längre beröring för drag och släpp.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ställ in åtgärd vid två fingerberöringar</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ställ in åtgärd vid tre fingerberöringar</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Ställ in tryckplattans känslighet</string>
|
||||
<string name="mousepad_scroll_direction_title">Omvänd rullningsriktning</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Högerklick</item>
|
||||
<item>Mittenklick</item>
|
||||
@@ -37,6 +43,14 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">höger</string>
|
||||
<string name="mousepad_triple_default">mitten</string>
|
||||
<string name="mousepad_sensitivity_default">normal</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Långsammaste</item>
|
||||
<item>Ovanför långsammaste</item>
|
||||
<item>Normal</item>
|
||||
<item>Ovanför normal</item>
|
||||
<item>Snabbaste</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Anslutna apparater</string>
|
||||
<string name="category_not_paired_devices">Tillgängliga apparater</string>
|
||||
<string name="category_remembered_devices">Ihågkomna apparater</string>
|
||||
@@ -44,6 +58,7 @@
|
||||
<string name="device_menu_plugins">Inställningar av insticksprogram</string>
|
||||
<string name="device_menu_unpair">Ta bort ihopparning</string>
|
||||
<string name="device_not_reachable">Ihopparad apparat kan inte nås</string>
|
||||
<string name="pair_new_device">Para ihop ny apparat</string>
|
||||
<string name="unknown_device">Okänd apparat</string>
|
||||
<string name="error_not_reachable">Apparaten kan inte nås</string>
|
||||
<string name="error_already_requested">Ihopparning redan begärd</string>
|
||||
@@ -53,6 +68,10 @@
|
||||
<string name="error_canceled_by_user">Avbruten av användaren</string>
|
||||
<string name="error_canceled_by_other_peer">Avbruten av motparten</string>
|
||||
<string name="error_invalid_key">Ogiltig nyckel mottagen</string>
|
||||
<string name="encryption_info_title">Krypteringsinformation</string>
|
||||
<string name="encryption_info_msg_no_ssl">Den andra apparaten använder inte en aktuell version av KDE-anslut. Använder den föråldrade krypteringsmetoden.</string>
|
||||
<string name="my_device_fingerprint">SHA1-fingeravtryck för din apparats certifikat är:</string>
|
||||
<string name="remote_device_fingerprint">SHA1-fingeravtryck för den andra apparatens certifikat är:</string>
|
||||
<string name="pair_requested">Ihopparning begärd</string>
|
||||
<string name="pairing_request_from">Begäran om ihopparning från %1s</string>
|
||||
<string name="received_url_title">Tog emot länk från %1s</string>
|
||||
@@ -133,9 +152,15 @@
|
||||
<string name="device_rename_title">Byt namn på apparat</string>
|
||||
<string name="device_rename_confirm">Byt namn</string>
|
||||
<string name="refresh">Uppdatera</string>
|
||||
<string name="unreachable_description">Den här ihopparade apparaten kan inte nås. Försälkra dig om att den är ansluten till samma nätverk.</string>
|
||||
<string name="unreachable_description">Den här ihopparade apparaten kan inte nås. Försäkra dig om att den är ansluten till samma nätverk.</string>
|
||||
<string name="no_file_browser">Det finns inga filbläddrare installerade.</string>
|
||||
<string name="pref_plugin_telepathy">Skicka SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Skicka textmeddelanden från skrivbordet</string>
|
||||
<string name="plugin_not_supported">Insticksprogrammet stöds inte av apparaten</string>
|
||||
<string name="findmyphone_title">Hitta min telefon</string>
|
||||
<string name="findmyphone_title_tablet">Hitta min surfplatta</string>
|
||||
<string name="findmyphone_description">Ringer till apparaten så att du kan hitta den</string>
|
||||
<string name="findmyphone_found">Hittade den</string>
|
||||
<string name="open">Öppna</string>
|
||||
<string name="close">Stäng</string>
|
||||
</resources>
|
||||
|
@@ -5,17 +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_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_mousepad_desc">Скористайтеся телефоном або планшетом як замінником сенсорної панелі і клавіатури</string>
|
||||
<string name="pref_plugin_mpris">Керування відтворенням</string>
|
||||
<string name="pref_plugin_mpris_desc">Керування відтворенням звуку та відео з вашого телефону</string>
|
||||
<string name="pref_plugin_mpris_desc">Надає можливість віддаленого керування вашим мультимедійним програвачем</string>
|
||||
<string name="pref_plugin_runcommand">Виконати команду</string>
|
||||
<string name="pref_plugin_runcommand_desc">Віддалені команди з вашого телефону або планшета</string>
|
||||
<string name="pref_plugin_ping">Підтримання зв’язку</string>
|
||||
<string name="pref_plugin_ping_desc">Надсилання і отримання сигналів підтримання зв’язку</string>
|
||||
<string name="pref_plugin_notifications">Синхронізація сповіщень</string>
|
||||
<string name="pref_plugin_notifications_desc">Доступ до ваших сповіщень з інших пристроїв</string>
|
||||
<string name="pref_plugin_receive_notifications">Отримати сповіщення</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Отримання сповіщень з іншого пристрою і показ їх у Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Надання і отримання</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Спільне використання файлів і адрес між пристроями</string>
|
||||
<string name="plugin_not_available">Ця можливість є недоступною для вашої версії для Android</string>
|
||||
@@ -30,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>
|
||||
@@ -37,6 +43,14 @@
|
||||
</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>
|
||||
@@ -44,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>
|
||||
@@ -53,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>
|
||||
@@ -138,4 +157,10 @@
|
||||
<string name="pref_plugin_telepathy">Надіслати SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Надсилати текстові повідомлення з вашої робочої станції</string>
|
||||
<string name="plugin_not_supported">Підтримки цього додатка не передбачено на пристрої</string>
|
||||
<string name="findmyphone_title">Знайти телефон</string>
|
||||
<string name="findmyphone_title_tablet">Знайти планшет</string>
|
||||
<string name="findmyphone_description">Відтворити дзвінок, щоб цей пристрій було простіше знайти</string>
|
||||
<string name="findmyphone_found">Знайдено</string>
|
||||
<string name="open">Відкрити</string>
|
||||
<string name="close">Закрити</string>
|
||||
</resources>
|
||||
|
8
res/values-v21/styles.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="KdeConnectTheme.NoActionBar" parent="KdeConnectThemeBase.NoActionBar">
|
||||
<item name="android:windowTranslucentStatus">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@@ -5,16 +5,17 @@
|
||||
<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_desc">从手机控制音频或视频</string>
|
||||
<string name="pref_plugin_mpris">多媒体控制</string>
|
||||
<string name="pref_plugin_runcommand">执行命令</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_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">确认</string>
|
||||
@@ -22,6 +23,8 @@
|
||||
<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>
|
||||
@@ -32,6 +35,13 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">右</string>
|
||||
<string name="mousepad_triple_default">中</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">已连接设备</string>
|
||||
<string name="category_not_paired_devices">可用设备</string>
|
||||
<string name="category_remembered_devices">已记住设备</string>
|
||||
@@ -39,6 +49,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>
|
||||
@@ -103,6 +114,8 @@
|
||||
<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>
|
||||
@@ -119,4 +132,19 @@
|
||||
<string name="no_players_connected">未找到播放器</string>
|
||||
<string name="custom_dev_list_help">仅当你的设备没有被自动检测出时再使用本选项。在下方输入IP地址或主机名,然后点击按钮以添加其到列表中。点击已有条目来从列表中删除它。</string>
|
||||
<string name="mpris_player_on_device">%2$s上的%1$s</string>
|
||||
<string name="send_files">发送文件</string>
|
||||
<string name="pairing_title">KDE Connect 设备</string>
|
||||
<string name="pairing_description">其他在同一网络运行 KDE Connect 的设备会在此处显示。</string>
|
||||
<string name="device_paired">已配对设备</string>
|
||||
<string name="device_rename_title">重命名设备</string>
|
||||
<string name="device_rename_confirm">重命名</string>
|
||||
<string name="refresh">刷新</string>
|
||||
<string name="unreachable_description">此配对设备不可达。请确认它已经连接到与您相同的网络。</string>
|
||||
<string name="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_found">找到</string>
|
||||
<string name="open">打开</string>
|
||||
<string name="close">关闭</string>
|
||||
</resources>
|
||||
|
@@ -6,19 +6,21 @@
|
||||
<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 the phone\'s filesystem remotely</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 as a mouse and keyboard</string>
|
||||
<string name="pref_plugin_mousepad_desc">Use your phone or tablet as a touchpad and keyboard</string>
|
||||
<string name="pref_plugin_mpris">Multimedia controls</string>
|
||||
<string name="pref_plugin_mpris_desc">Control audio/video from your phone</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">Runs a command on your system</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>
|
||||
@@ -33,8 +35,12 @@
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Set touchpad sensitivity</string>
|
||||
<string name="mousepad_double_tap_key" translatable="false">mousepad_double_tap_key</string>
|
||||
<string name="mousepad_triple_tap_key" translatable="false">mousepad_triple_tap_key</string>
|
||||
<string name="mousepad_sensitivity_key" translatable="false">mousepad_sensitivity_key</string>
|
||||
<string name="mousepad_scroll_direction_title">Reverse Scrolling Direction</string>
|
||||
<string name="mousepad_scroll_direction" translatable="false">mousepad_scroll_direction</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
@@ -42,11 +48,26 @@
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">right</string>
|
||||
<string name="mousepad_triple_default">middle</string>
|
||||
<string name="mousepad_sensitivity_default">default</string>
|
||||
<string-array name="mousepad_tap_values" translatable="false">
|
||||
<item>right</item>
|
||||
<item>middle</item>
|
||||
<item>none</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_values" translatable="false">
|
||||
<item>slowest</item>
|
||||
<item>aboveSlowest</item>
|
||||
<item>default</item>
|
||||
<item>aboveDefault</item>
|
||||
<item>fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Connected devices</string>
|
||||
<string name="category_not_paired_devices">Available devices</string>
|
||||
<string name="category_remembered_devices">Remembered devices</string>
|
||||
@@ -54,6 +75,7 @@
|
||||
<string name="device_menu_plugins">Plugin settings</string>
|
||||
<string name="device_menu_unpair">Unpair</string>
|
||||
<string name="device_not_reachable">Paired device not reachable</string>
|
||||
<string name="pair_new_device">Pair new device</string>
|
||||
<string name="unknown_device">Unknown device</string>
|
||||
<string name="error_not_reachable">Device not reachable</string>
|
||||
<string name="error_already_requested">Pairing already requested</string>
|
||||
@@ -63,6 +85,10 @@
|
||||
<string name="error_canceled_by_user">Canceled by user</string>
|
||||
<string name="error_canceled_by_other_peer">Canceled 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>
|
||||
@@ -158,7 +184,11 @@
|
||||
<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_description">Rings this phone so you can find it.</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>
|
||||
</resources>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<color name="accent">#4ebffa</color>
|
||||
|
||||
<!-- NoActionBar because we use a Toolbar widget as ActionBar -->
|
||||
<style name="KdeConnectTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<style name="KdeConnectThemeBase" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- The three colors used by system widgets, according to https://chris.banes.me/2014/10/17/appcompat-v21/ -->
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primaryDark</item>
|
||||
@@ -13,9 +13,15 @@
|
||||
<item name="android:textColor">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="KdeConnectTheme.NoActionBar" parent="KdeConnectTheme">
|
||||
<style name="KdeConnectThemeBase.NoActionBar" parent="KdeConnectThemeBase">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="KdeConnectTheme" parent="KdeConnectThemeBase">
|
||||
</style>
|
||||
|
||||
<style name="KdeConnectTheme.NoActionBar" parent="KdeConnectThemeBase.NoActionBar">
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@@ -21,4 +21,18 @@
|
||||
android:entryValues="@array/mousepad_tap_values"
|
||||
android:defaultValue="@string/mousepad_triple_default" />
|
||||
|
||||
<ListPreference
|
||||
android:id="@+id/mousepad_sensitivity_preference"
|
||||
android:key="@string/mousepad_sensitivity_key"
|
||||
android:title="@string/mousepad_sensitivity_settings_title"
|
||||
android:summary="%s"
|
||||
android:entries="@array/mousepad_sensitivity_entries"
|
||||
android:entryValues="@array/mousepad_sensitivity_values"
|
||||
android:defaultValue="@string/mousepad_sensitivity_default" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/mousepad_scroll_preference"
|
||||
android:key="@string/mousepad_scroll_direction"
|
||||
android:title="@string/mousepad_scroll_direction_title"
|
||||
android:defaultValue="false" />
|
||||
</PreferenceScreen>
|
@@ -20,6 +20,8 @@
|
||||
|
||||
package org.kde.kdeconnect.Backends;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
@@ -30,9 +32,7 @@ import java.util.ArrayList;
|
||||
|
||||
public abstract class BaseLink {
|
||||
|
||||
public enum ConnectionStarted {
|
||||
Locally, Remotely;
|
||||
};
|
||||
protected final Context context;
|
||||
|
||||
public interface PackageReceiver {
|
||||
void onPackageReceived(NetworkPackage np);
|
||||
@@ -43,17 +43,16 @@ public abstract class BaseLink {
|
||||
private final ArrayList<PackageReceiver> receivers = new ArrayList<>();
|
||||
protected PrivateKey privateKey;
|
||||
|
||||
protected ConnectionStarted connectionSource; // If the other device sent me a broadcast,
|
||||
// I should not close the connection with it
|
||||
// because it's probably trying to find me and
|
||||
// potentially ask for pairing.
|
||||
|
||||
protected BaseLink(String deviceId, BaseLinkProvider linkProvider, ConnectionStarted connectionSource) {
|
||||
protected BaseLink(Context context, String deviceId, BaseLinkProvider linkProvider) {
|
||||
this.context = context;
|
||||
this.linkProvider = linkProvider;
|
||||
this.deviceId = deviceId;
|
||||
this.connectionSource = connectionSource;
|
||||
}
|
||||
|
||||
/* To be implemented by each link for pairing handlers */
|
||||
public abstract String getName();
|
||||
public abstract BasePairingHandler getPairingHandler(Device device, BasePairingHandler.PairingHandlerCallback callback);
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
@@ -66,8 +65,9 @@ public abstract class BaseLink {
|
||||
return linkProvider;
|
||||
}
|
||||
|
||||
public ConnectionStarted getConnectionSource() {
|
||||
return connectionSource;
|
||||
//The daemon will periodically destroy unpaired links if this returns false
|
||||
public boolean linkShouldBeKeptAlive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addPackageReceiver(PackageReceiver pr) {
|
||||
@@ -90,5 +90,6 @@ public abstract class BaseLink {
|
||||
|
||||
//TO OVERRIDE, should be sync
|
||||
public abstract void sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback);
|
||||
@Deprecated
|
||||
public abstract void sendPackageEncrypted(NetworkPackage np,Device.SendPackageStatusCallback callback, PublicKey key);
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@ package org.kde.kdeconnect.Backends;
|
||||
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public abstract class BaseLinkProvider {
|
||||
|
84
src/org/kde/kdeconnect/Backends/BasePairingHandler.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2015 Vineet Garg <grg.vineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Backends;
|
||||
|
||||
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,
|
||||
* for Bluetooth link they should be paired via bluetooth etc.
|
||||
* Each "Device" instance maintains a hash map for these pairing handlers so that there can be single pairing handler per
|
||||
* per link type per device.
|
||||
* Pairing handler keeps information about device, latest link, and pair status of the link
|
||||
* During first pairing process, the pairing process is nearly same as old process.
|
||||
* After that if any one of the link is paired, then we can say that device is paired, so new link will pair automatically
|
||||
*/
|
||||
|
||||
public abstract class BasePairingHandler {
|
||||
|
||||
protected enum PairStatus{
|
||||
NotPaired,
|
||||
Requested,
|
||||
RequestedByPeer,
|
||||
Paired
|
||||
}
|
||||
|
||||
public interface PairingHandlerCallback {
|
||||
void incomingRequest();
|
||||
void pairingDone();
|
||||
void pairingFailed(String error);
|
||||
void unpaired();
|
||||
}
|
||||
|
||||
|
||||
protected Device mDevice;
|
||||
protected PairStatus mPairStatus;
|
||||
protected PairingHandlerCallback mCallback;
|
||||
|
||||
public BasePairingHandler(Device device, PairingHandlerCallback callback) {
|
||||
this.mDevice = device;
|
||||
this.mCallback = callback;
|
||||
}
|
||||
|
||||
public boolean isPaired() {
|
||||
return mPairStatus == PairStatus.Paired;
|
||||
}
|
||||
|
||||
public boolean isPairRequested() {
|
||||
return mPairStatus == PairStatus.Requested;
|
||||
}
|
||||
|
||||
public boolean isPairRequestedByPeer() {
|
||||
return mPairStatus == PairStatus.RequestedByPeer;
|
||||
}
|
||||
|
||||
/* To be implemented by respective pairing handler */
|
||||
public abstract void packageReceived(NetworkPackage np) throws Exception;
|
||||
public abstract void requestPairing();
|
||||
public abstract void acceptPairing();
|
||||
public abstract void rejectPairing();
|
||||
public abstract void unpair();
|
||||
|
||||
}
|
@@ -20,51 +20,130 @@
|
||||
|
||||
package org.kde.kdeconnect.Backends.LanBackend;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.mina.core.future.WriteFuture;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.json.JSONObject;
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Helpers.StringsHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
public class LanLink extends BaseLink {
|
||||
|
||||
private IoSession session = null;
|
||||
public interface LinkDisconnectedCallback {
|
||||
void linkDisconnected(LanLink brokenLink);
|
||||
}
|
||||
|
||||
public enum ConnectionStarted {
|
||||
Locally, Remotely;
|
||||
};
|
||||
|
||||
private ConnectionStarted connectionSource; // If the other device sent me a broadcast,
|
||||
// I should not close the connection with it
|
||||
// because it's probably trying to find me and
|
||||
// potentially ask for pairing.
|
||||
|
||||
private Socket socket = null;
|
||||
|
||||
private LinkDisconnectedCallback callback;
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
closeSocket();
|
||||
super.disconnect();
|
||||
}
|
||||
|
||||
public void closeSocket() {
|
||||
if (session == null) {
|
||||
Log.e("KDE/LanLink", "Not yet connected");
|
||||
return;
|
||||
Log.i("LanLink/Disconnect","socket:"+ socket.hashCode());
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
session.close(true);
|
||||
}
|
||||
|
||||
public LanLink(IoSession session, String deviceId, BaseLinkProvider linkProvider, ConnectionStarted connectionSource) {
|
||||
super(deviceId, linkProvider, connectionSource);
|
||||
this.session = session;
|
||||
//Returns the old socket
|
||||
public Socket reset(final Socket newSocket, ConnectionStarted connectionSource) throws IOException {
|
||||
|
||||
Socket oldSocket = socket;
|
||||
socket = newSocket;
|
||||
|
||||
this.connectionSource = connectionSource;
|
||||
|
||||
if (oldSocket != null) {
|
||||
oldSocket.close(); //This should cancel the readThread
|
||||
}
|
||||
|
||||
//Log.e("LanLink", "Start listening");
|
||||
//Create a thread to take care of incoming data for the new socket
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(newSocket.getInputStream(), StringsHelper.UTF8));
|
||||
while (true) {
|
||||
String packet;
|
||||
try {
|
||||
packet = reader.readLine();
|
||||
} catch (SocketTimeoutException e) {
|
||||
continue;
|
||||
}
|
||||
if (packet == null) {
|
||||
throw new IOException("End of stream");
|
||||
}
|
||||
if (packet.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
NetworkPackage np = NetworkPackage.unserialize(packet);
|
||||
receivedNetworkPackage(np);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.i("LanLink", "Socket closed: " + newSocket.hashCode() + ". Reason: " + e.getMessage());
|
||||
try { Thread.sleep(300); } catch (InterruptedException ignored) {} // Wait a bit because we might receive a new socket meanwhile
|
||||
boolean thereIsaANewSocket = (newSocket != socket);
|
||||
if (!thereIsaANewSocket) {
|
||||
callback.linkDisconnected(LanLink.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
return oldSocket;
|
||||
}
|
||||
|
||||
public LanLink(Context context, String deviceId, LanLinkProvider linkProvider, Socket socket, ConnectionStarted connectionSource) throws IOException {
|
||||
super(context, deviceId, linkProvider);
|
||||
callback = linkProvider;
|
||||
reset(socket, connectionSource);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LanLink";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePairingHandler getPairingHandler(Device device, BasePairingHandler.PairingHandlerCallback callback) {
|
||||
return new LanPairingHandler(device, callback);
|
||||
}
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
private void sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
if (session == null) {
|
||||
if (socket == null) {
|
||||
Log.e("KDE/sendPackage", "Not yet connected");
|
||||
callback.sendFailure(new NotYetConnectedException());
|
||||
return;
|
||||
@@ -75,7 +154,7 @@ public class LanLink extends BaseLink {
|
||||
//Prepare socket for the payload
|
||||
final ServerSocket server;
|
||||
if (np.hasPayload()) {
|
||||
server = openTcpSocketOnFreePort();
|
||||
server = LanLinkProvider.openServerSocketOnFreePort(LanLinkProvider.PAYLOAD_TRANSFER_MIN_PORT);
|
||||
JSONObject payloadTransferInfo = new JSONObject();
|
||||
payloadTransferInfo.put("port", server.getLocalPort());
|
||||
np.setPayloadTransferInfo(payloadTransferInfo);
|
||||
@@ -85,52 +164,67 @@ public class LanLink extends BaseLink {
|
||||
|
||||
//Encrypt if key provided
|
||||
if (key != null) {
|
||||
np = np.encrypt(key);
|
||||
np = RsaHelper.encrypt(np, key);
|
||||
}
|
||||
|
||||
//Log.e("LanLink/sendPackage", np.getType());
|
||||
|
||||
//Send body of the network package
|
||||
WriteFuture future = session.write(np.serialize());
|
||||
future.awaitUninterruptibly();
|
||||
if (!future.isWritten()) {
|
||||
//Log.e("KDE/sendPackage", "!future.isWritten()");
|
||||
callback.sendFailure(future.getException());
|
||||
try {
|
||||
OutputStream writter = socket.getOutputStream();
|
||||
writter.write(np.serialize().getBytes(StringsHelper.UTF8));
|
||||
writter.flush();
|
||||
} catch (Exception e) {
|
||||
callback.sendFailure(e);
|
||||
e.printStackTrace();
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
//Send payload
|
||||
if (server != null) {
|
||||
OutputStream socket = null;
|
||||
Socket payloadSocket = null;
|
||||
OutputStream outputStream = null;
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
//Wait a maximum of 10 seconds for the other end to establish a connection with our socket, close it afterwards
|
||||
server.setSoTimeout(10*1000);
|
||||
socket = server.accept().getOutputStream();
|
||||
|
||||
payloadSocket = server.accept();
|
||||
|
||||
//Convert to SSL if needed
|
||||
if (socket instanceof SSLSocket) {
|
||||
payloadSocket = SslHelper.convertToSslSocket(context, payloadSocket, getDeviceId(), true, false);
|
||||
}
|
||||
|
||||
outputStream = payloadSocket.getOutputStream();
|
||||
inputStream = np.getPayload();
|
||||
|
||||
Log.i("KDE/LanLink", "Beginning to send payload");
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
long progress = 0;
|
||||
InputStream stream = np.getPayload();
|
||||
while ((bytesRead = stream.read(buffer)) != -1) {
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
//Log.e("ok",""+bytesRead);
|
||||
progress += bytesRead;
|
||||
socket.write(buffer, 0, bytesRead);
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
if (np.getPayloadSize() > 0) {
|
||||
callback.sendProgress((int)(progress / np.getPayloadSize()));
|
||||
}
|
||||
}
|
||||
socket.flush();
|
||||
stream.close();
|
||||
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 {
|
||||
if (socket != null) {
|
||||
try { socket.close(); } catch (Exception e) { }
|
||||
}
|
||||
try { server.close(); } catch (Exception e) { }
|
||||
try { payloadSocket.close(); } catch (Exception e) { }
|
||||
try { inputStream.close(); } catch (Exception e) { }
|
||||
try { outputStream.close(); } catch (Exception e) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +246,6 @@ public class LanLink extends BaseLink {
|
||||
@Override
|
||||
public void sendPackage(NetworkPackage np,Device.SendPackageStatusCallback callback) {
|
||||
sendPackageInternal(np, callback, null);
|
||||
|
||||
}
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
@@ -161,30 +254,31 @@ public class LanLink extends BaseLink {
|
||||
sendPackageInternal(np, callback, key);
|
||||
}
|
||||
|
||||
public void injectNetworkPackage(NetworkPackage np) {
|
||||
private void receivedNetworkPackage(NetworkPackage np) {
|
||||
|
||||
if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_ENCRYPTED)) {
|
||||
|
||||
try {
|
||||
np = np.decrypt(privateKey);
|
||||
np = RsaHelper.decrypt(np, privateKey);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/onPackageReceived","Exception reading the key needed to decrypt the package");
|
||||
Log.e("KDE/onPackageReceived","Exception decrypting the package");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (np.hasPayloadTransferInfo()) {
|
||||
|
||||
Socket socket = null;
|
||||
Socket payloadSocket = new Socket();
|
||||
try {
|
||||
socket = new Socket();
|
||||
int tcpPort = np.getPayloadTransferInfo().getInt("port");
|
||||
InetSocketAddress address = (InetSocketAddress)session.getRemoteAddress();
|
||||
socket.connect(new InetSocketAddress(address.getAddress(), tcpPort));
|
||||
np.setPayload(socket.getInputStream(), np.getPayloadSize());
|
||||
InetSocketAddress deviceAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
|
||||
payloadSocket.connect(new InetSocketAddress(deviceAddress.getAddress(), tcpPort));
|
||||
// Use ssl if existing link is on ssl
|
||||
if (socket instanceof SSLSocket) {
|
||||
payloadSocket = SslHelper.convertToSslSocket(context, payloadSocket, getDeviceId(), true, true);
|
||||
}
|
||||
np.setPayload(payloadSocket.getInputStream(), np.getPayloadSize());
|
||||
} catch (Exception e) {
|
||||
try { socket.close(); } catch(Exception ignored) { }
|
||||
try { payloadSocket.close(); } catch(Exception ignored) { }
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/LanLink", "Exception connecting to payload remote socket");
|
||||
}
|
||||
@@ -194,27 +288,14 @@ public class LanLink extends BaseLink {
|
||||
packageReceived(np);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean linkShouldBeKeptAlive() {
|
||||
|
||||
return true; //FIXME: Current implementation is broken, so for now we will keep links always established
|
||||
|
||||
//We keep the remotely initiated connections, since the remotes require them if they want to request
|
||||
//pairing to us, or connections that are already paired.
|
||||
//return (connectionSource == ConnectionStarted.Remotely);
|
||||
|
||||
static ServerSocket openTcpSocketOnFreePort() throws IOException {
|
||||
boolean success = false;
|
||||
int tcpPort = 1739;
|
||||
ServerSocket candidateServer = null;
|
||||
while(!success) {
|
||||
try {
|
||||
candidateServer = new ServerSocket();
|
||||
candidateServer.bind(new InetSocketAddress(tcpPort));
|
||||
success = true;
|
||||
Log.i("KDE/LanLink", "Using port "+tcpPort);
|
||||
} catch(IOException e) {
|
||||
//Log.e("LanLink", "Exception openning serversocket: "+e);
|
||||
tcpPort++;
|
||||
if (tcpPort >= 1764) {
|
||||
Log.e("KDE/LanLink", "No more ports available");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidateServer;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,303 +21,341 @@
|
||||
package org.kde.kdeconnect.Backends.LanBackend;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.future.IoFuture;
|
||||
import org.apache.mina.core.future.IoFutureListener;
|
||||
import org.apache.mina.core.service.IoHandler;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
||||
import org.apache.mina.filter.codec.textline.LineDelimiter;
|
||||
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
|
||||
import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Helpers.StringsHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.UserInterface.CustomDevicesActivity;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class LanLinkProvider extends BaseLinkProvider {
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.HandshakeCompletedEvent;
|
||||
import javax.net.ssl.HandshakeCompletedListener;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
public static final String KEY_CUSTOM_DEVLIST_PREFERENCE = "device_list_preference";
|
||||
private final static int port = 1714;
|
||||
public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDisconnectedCallback {
|
||||
|
||||
public static final int MIN_VERSION_WITH_SSL_SUPPORT = 6;
|
||||
public static final int MIN_VERSION_WITH_NEW_PORT_SUPPORT = 7;
|
||||
|
||||
final static int MIN_PORT_LEGACY = 1714;
|
||||
final static int MIN_PORT = 1716;
|
||||
final static int MAX_PORT = 1764;
|
||||
final static int PAYLOAD_TRANSFER_MIN_PORT = 1739;
|
||||
|
||||
private final Context context;
|
||||
private final HashMap<String, LanLink> visibleComputers = new HashMap<>();
|
||||
private final LongSparseArray<LanLink> nioSessions = new LongSparseArray<>();
|
||||
private final LongSparseArray<NioSocketConnector> nioConnectors = new LongSparseArray<>();
|
||||
|
||||
private NioSocketAcceptor tcpAcceptor = null;
|
||||
private NioDatagramAcceptor udpAcceptor = null;
|
||||
private final HashMap<String, LanLink> visibleComputers = new HashMap<>(); //Links by device id
|
||||
|
||||
private final IoHandler tcpHandler = new IoHandlerAdapter() {
|
||||
@Override
|
||||
public void sessionClosed(IoSession session) throws Exception {
|
||||
try {
|
||||
long id = session.getId();
|
||||
final LanLink brokenLink = nioSessions.get(id);
|
||||
NioSocketConnector connector = nioConnectors.get(id);
|
||||
if (connector != null) {
|
||||
connector.dispose();
|
||||
nioConnectors.remove(id);
|
||||
}
|
||||
if (brokenLink != null) {
|
||||
nioSessions.remove(id);
|
||||
//Log.i("KDE/LanLinkProvider", "nioSessions.size(): " + nioSessions.size() + " (-)");
|
||||
try {
|
||||
brokenLink.closeSocket();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/LanLinkProvider", "Exception. Already disconnected?");
|
||||
}
|
||||
//Log.i("KDE/LanLinkProvider", "Disconnected!");
|
||||
String deviceId = brokenLink.getDeviceId();
|
||||
if (visibleComputers.get(deviceId) == brokenLink) {
|
||||
visibleComputers.remove(deviceId);
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//Wait a bit before emiting connectionLost, in case the same device re-appears
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
connectionLost(brokenLink);
|
||||
private ServerSocket tcpServer;
|
||||
private DatagramSocket udpServer;
|
||||
private DatagramSocket udpServerOldPort;
|
||||
|
||||
}
|
||||
}).start();
|
||||
private boolean listening = false;
|
||||
|
||||
}
|
||||
} catch (Exception e) { //If we don't catch it here, Mina will swallow it :/
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/LanLinkProvider", "sessionClosed exception");
|
||||
}
|
||||
// To prevent infinte loop between Android < IceCream because both device can only broadcast identity package but cannot connect via TCP
|
||||
private ArrayList<InetAddress> reverseConnectionBlackList = new ArrayList<>();
|
||||
|
||||
@Override // SocketClosedCallback
|
||||
public void linkDisconnected(LanLink brokenLink) {
|
||||
String deviceId = brokenLink.getDeviceId();
|
||||
visibleComputers.remove(deviceId);
|
||||
connectionLost(brokenLink);
|
||||
}
|
||||
|
||||
//They received my UDP broadcast and are connecting to me. The first thing they sned should be their identity.
|
||||
public void tcpPackageReceived(Socket socket) throws Exception {
|
||||
|
||||
NetworkPackage networkPackage;
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
String message = reader.readLine();
|
||||
networkPackage = NetworkPackage.unserialize(message);
|
||||
//Log.e("TcpListener","Received TCP package: "+networkPackage.serialize());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(IoSession session, Object message) throws Exception {
|
||||
super.messageReceived(session, message);
|
||||
if (!networkPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
|
||||
Log.e("KDE/LanLinkProvider", "Expecting an identity package instead of " + networkPackage.getType());
|
||||
return;
|
||||
}
|
||||
|
||||
//Log.e("LanLinkProvider","Incoming package, address: "+session.getRemoteAddress()).toString());
|
||||
//Log.e("LanLinkProvider","Received:"+message);
|
||||
Log.i("KDE/LanLinkProvider", "Identity package received from a TCP connection from " + networkPackage.getString("deviceName"));
|
||||
identityPackageReceived(networkPackage, socket, LanLink.ConnectionStarted.Locally);
|
||||
}
|
||||
|
||||
String theMessage = (String) message;
|
||||
if (theMessage.isEmpty()) {
|
||||
Log.w("KDE/LanLinkProvider","Empty package received");
|
||||
//I've received their broadcast and should connect to their TCP socket and send my identity.
|
||||
protected void udpPacketReceived(DatagramPacket packet) throws Exception {
|
||||
|
||||
final InetAddress address = packet.getAddress();
|
||||
|
||||
try {
|
||||
|
||||
String message = new String(packet.getData(), StringsHelper.UTF8);
|
||||
final NetworkPackage identityPackage = NetworkPackage.unserialize(message);
|
||||
final String deviceId = identityPackage.getString("deviceId");
|
||||
if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
|
||||
Log.e("KDE/LanLinkProvider", "Expecting an UDP identity package");
|
||||
return;
|
||||
} else {
|
||||
String myId = DeviceHelper.getDeviceId(context);
|
||||
if (deviceId.equals(myId)) {
|
||||
//Ignore my own broadcast
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (identityPackage.getInt("protocolVersion") >= MIN_VERSION_WITH_NEW_PORT_SUPPORT && identityPackage.getInt("tcpPort") < MIN_PORT) {
|
||||
Log.w("KDE/LanLinkProvider", "Ignoring a udp broadcast from legacy port because it comes from a device which knows about the new port.");
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkPackage np = NetworkPackage.unserialize(theMessage);
|
||||
Log.i("KDE/LanLinkProvider", "Broadcast identity package received from " + identityPackage.getString("deviceName"));
|
||||
|
||||
if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
|
||||
String myId = DeviceHelper.getDeviceId(context);
|
||||
if (np.getString("deviceId").equals(myId)) {
|
||||
return;
|
||||
}
|
||||
int tcpPort = identityPackage.getInt("tcpPort", MIN_PORT);
|
||||
|
||||
//Log.i("KDE/LanLinkProvider", "Identity package received from " + np.getString("deviceName"));
|
||||
SocketFactory socketFactory = SocketFactory.getDefault();
|
||||
Socket socket = socketFactory.createSocket(address, tcpPort);
|
||||
configureSocket(socket);
|
||||
|
||||
LanLink link = new LanLink(session, np.getString("deviceId"), LanLinkProvider.this, BaseLink.ConnectionStarted.Locally);
|
||||
nioSessions.put(session.getId(),link);
|
||||
//Log.e("KDE/LanLinkProvider","nioSessions.size(): " + nioSessions.size());
|
||||
addLink(np, link);
|
||||
} else {
|
||||
LanLink prevLink = nioSessions.get(session.getId());
|
||||
if (prevLink == null) {
|
||||
Log.e("KDE/LanLinkProvider","Expecting an identity package (A)");
|
||||
} else {
|
||||
prevLink.injectNetworkPackage(np);
|
||||
}
|
||||
}
|
||||
OutputStream out = socket.getOutputStream();
|
||||
NetworkPackage myIdentity = NetworkPackage.createIdentityPackage(context);
|
||||
out.write(myIdentity.serialize().getBytes());
|
||||
out.flush();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private final IoHandler udpHandler = new IoHandlerAdapter() {
|
||||
@Override
|
||||
public void messageReceived(IoSession udpSession, Object message) throws Exception {
|
||||
super.messageReceived(udpSession, message);
|
||||
|
||||
//Log.e("LanLinkProvider", "Udp message received (" + message.getClass() + ") " + message.toString());
|
||||
|
||||
try {
|
||||
//We should receive a string thanks to the TextLineCodecFactory filter
|
||||
String theMessage = (String) message;
|
||||
final NetworkPackage identityPackage = NetworkPackage.unserialize(theMessage);
|
||||
|
||||
if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
|
||||
Log.e("KDE/LanLinkProvider", "Expecting an identity package (B)");
|
||||
return;
|
||||
} else {
|
||||
String myId = DeviceHelper.getDeviceId(context);
|
||||
if (identityPackage.getString("deviceId").equals(myId)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Log.i("KDE/LanLinkProvider", "Identity package received, creating link");
|
||||
|
||||
final InetSocketAddress address = (InetSocketAddress) udpSession.getRemoteAddress();
|
||||
|
||||
final NioSocketConnector connector = new NioSocketConnector();
|
||||
connector.setHandler(tcpHandler);
|
||||
connector.getSessionConfig().setKeepAlive(true);
|
||||
//TextLineCodecFactory will buffer incoming data and emit a message very time it finds a \n
|
||||
TextLineCodecFactory textLineFactory = new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.UNIX, LineDelimiter.UNIX);
|
||||
textLineFactory.setDecoderMaxLineLength(512*1024); //Allow to receive up to 512kb of data
|
||||
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(textLineFactory));
|
||||
|
||||
int tcpPort = identityPackage.getInt("tcpPort", port);
|
||||
final ConnectFuture future = connector.connect(new InetSocketAddress(address.getAddress(), tcpPort));
|
||||
future.addListener(new IoFutureListener<IoFuture>() {
|
||||
identityPackageReceived(identityPackage, socket, LanLink.ConnectionStarted.Remotely);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/LanLinkProvider", "Cannot connect to " + address);
|
||||
e.printStackTrace();
|
||||
if (!reverseConnectionBlackList.contains(address)) {
|
||||
Log.w("KDE/LanLinkProvider","Blacklisting "+address);
|
||||
reverseConnectionBlackList.add(address);
|
||||
new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void operationComplete(IoFuture ioFuture) {
|
||||
public void run() {
|
||||
reverseConnectionBlackList.remove(address);
|
||||
}
|
||||
}, 5*1000);
|
||||
|
||||
// Try to cause a reverse connection
|
||||
onNetworkChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void configureSocket(Socket socket) {
|
||||
try {
|
||||
socket.setKeepAlive(true);
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void identityPackageReceived(final NetworkPackage identityPackage, final Socket socket, final LanLink.ConnectionStarted connectionStarted) {
|
||||
|
||||
String myId = DeviceHelper.getDeviceId(context);
|
||||
final String deviceId = identityPackage.getString("deviceId");
|
||||
if (deviceId.equals(myId)) {
|
||||
Log.e("KDE/LanLinkProvider", "Somehow I'm connected to myself, ignoring. This should not happen.");
|
||||
return;
|
||||
}
|
||||
|
||||
// If I'm the TCP server I will be the SSL client and viceversa.
|
||||
final boolean clientMode = (connectionStarted == LanLink.ConnectionStarted.Locally);
|
||||
|
||||
// Add ssl handler if device uses new protocol
|
||||
try {
|
||||
if (identityPackage.getInt("protocolVersion") >= MIN_VERSION_WITH_SSL_SUPPORT) {
|
||||
|
||||
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
|
||||
boolean isDeviceTrusted = preferences.getBoolean(deviceId, false);
|
||||
|
||||
Log.i("KDE/LanLinkProvider","Starting SSL handshake with " + identityPackage.getString("deviceName") + " trusted:"+isDeviceTrusted);
|
||||
|
||||
final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
|
||||
sslsocket.addHandshakeCompletedListener(new HandshakeCompletedListener() {
|
||||
@Override
|
||||
public void handshakeCompleted(HandshakeCompletedEvent event) {
|
||||
String mode = clientMode? "client" : "server";
|
||||
try {
|
||||
future.removeListener(this);
|
||||
final IoSession session = ioFuture.getSession();
|
||||
Log.i("KDE/LanLinkProvider", "Connection successful: " + session.isConnected());
|
||||
|
||||
final LanLink link = new LanLink(session, identityPackage.getString("deviceId"), LanLinkProvider.this, BaseLink.ConnectionStarted.Remotely);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NetworkPackage np2 = NetworkPackage.createIdentityPackage(context);
|
||||
link.sendPackage(np2,new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
nioSessions.put(session.getId(), link);
|
||||
nioConnectors.put(session.getId(), connector);
|
||||
//Log.e("KDE/LanLinkProvider","nioSessions.size(): " + nioSessions.size());
|
||||
addLink(identityPackage, link);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable e) {
|
||||
Log.e("KDE/LanLinkProvider", "Connection failed: could not send identity package back");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}).start();
|
||||
} catch (Exception e) { //If we don't catch it here, Mina will swallow it :/
|
||||
Certificate certificate = event.getPeerCertificates()[0];
|
||||
identityPackage.set("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
|
||||
Log.i("KDE/LanLinkProvider","Handshake as " + mode + " successful with " + identityPackage.getString("deviceName") + " secured with " + event.getCipherSuite());
|
||||
addLink(identityPackage, sslsocket, connectionStarted);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/LanLinkProvider","Handshake as " + mode + " failed with " + identityPackage.getString("deviceName"));
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/LanLinkProvider", "sessionClosed exception");
|
||||
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
if (device == null) return;
|
||||
device.unpair();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/LanLinkProvider","Exception receiving udp package!!");
|
||||
e.printStackTrace();
|
||||
//Handshake is blocking, so do it on another thread and free this thread to keep receiving new connection
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
sslsocket.startHandshake();
|
||||
} 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
addLink(identityPackage, socket, connectionStarted);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
|
||||
private void addLink(NetworkPackage identityPackage, LanLink link) {
|
||||
}
|
||||
|
||||
private void addLink(final NetworkPackage identityPackage, Socket socket, LanLink.ConnectionStarted connectionOrigin) throws IOException {
|
||||
|
||||
String deviceId = identityPackage.getString("deviceId");
|
||||
Log.i("KDE/LanLinkProvider","addLink to "+deviceId);
|
||||
LanLink oldLink = visibleComputers.get(deviceId);
|
||||
if (oldLink == link) {
|
||||
Log.e("KDE/LanLinkProvider", "oldLink == link. This should not happen!");
|
||||
return;
|
||||
}
|
||||
visibleComputers.put(deviceId, link);
|
||||
connectionAccepted(identityPackage, link);
|
||||
if (oldLink != null) {
|
||||
Log.i("KDE/LanLinkProvider","Removing old connection to same device");
|
||||
oldLink.closeSocket();
|
||||
connectionLost(oldLink);
|
||||
LanLink currentLink = visibleComputers.get(deviceId);
|
||||
if (currentLink != null) {
|
||||
//Update old link
|
||||
Log.i("KDE/LanLinkProvider", "Reusing same link for device " + deviceId);
|
||||
final Socket oldSocket = currentLink.reset(socket, connectionOrigin);
|
||||
//Log.e("KDE/LanLinkProvider", "Replacing socket. old: "+ oldSocket.hashCode() + " - new: "+ socket.hashCode());
|
||||
} else {
|
||||
Log.i("KDE/LanLinkProvider", "Creating a new link for device " + deviceId);
|
||||
//Let's create the link
|
||||
LanLink link = new LanLink(context, deviceId, this, socket, connectionOrigin);
|
||||
visibleComputers.put(deviceId, link);
|
||||
connectionAccepted(identityPackage, link);
|
||||
}
|
||||
}
|
||||
|
||||
public LanLinkProvider(Context context) {
|
||||
|
||||
this.context = context;
|
||||
|
||||
//This handles the case when I'm the new device in the network and somebody answers my introduction package
|
||||
tcpAcceptor = new NioSocketAcceptor();
|
||||
tcpAcceptor.setHandler(tcpHandler);
|
||||
tcpAcceptor.getSessionConfig().setKeepAlive(true);
|
||||
tcpAcceptor.getSessionConfig().setReuseAddress(true);
|
||||
//TextLineCodecFactory will buffer incoming data and emit a message very time it finds a \n
|
||||
TextLineCodecFactory textLineFactory = new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.UNIX, LineDelimiter.UNIX);
|
||||
textLineFactory.setDecoderMaxLineLength(512*1024); //Allow to receive up to 512kb of data
|
||||
tcpAcceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(textLineFactory));
|
||||
|
||||
udpAcceptor = new NioDatagramAcceptor();
|
||||
udpAcceptor.getSessionConfig().setReuseAddress(true); //Share port if existing
|
||||
//TextLineCodecFactory will buffer incoming data and emit a message very time it finds a \n
|
||||
//This one will have the default MaxLineLength of 1KB
|
||||
udpAcceptor.getFilterChain().addLast("codec",
|
||||
new ProtocolCodecFilter(
|
||||
new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.UNIX, LineDelimiter.UNIX)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
//This handles the case when I'm the existing device in the network and receive a "hello" UDP package
|
||||
|
||||
Set<SocketAddress> addresses = udpAcceptor.getLocalAddresses();
|
||||
for (SocketAddress address : addresses) {
|
||||
Log.i("KDE/LanLinkProvider", "UDP unbind old address");
|
||||
udpAcceptor.unbind(address);
|
||||
private DatagramSocket setupUdpListener(int udpPort) {
|
||||
final DatagramSocket server;
|
||||
try {
|
||||
server = new DatagramSocket(udpPort);
|
||||
server.setReuseAddress(true);
|
||||
server.setBroadcast(true);
|
||||
} catch (SocketException e) {
|
||||
Log.e("LanLinkProvider", "Error creating udp server");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (listening) {
|
||||
final int bufferSize = 1024 * 512;
|
||||
byte[] data = new byte[bufferSize];
|
||||
DatagramPacket packet = new DatagramPacket(data, bufferSize);
|
||||
try {
|
||||
server.receive(packet);
|
||||
udpPacketReceived(packet);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("LanLinkProvider", "UdpReceive exception");
|
||||
}
|
||||
}
|
||||
Log.w("UdpListener","Stopping UDP listener");
|
||||
}
|
||||
}).start();
|
||||
return server;
|
||||
}
|
||||
|
||||
//Log.i("KDE/LanLinkProvider", "UDP Bind.");
|
||||
udpAcceptor.setHandler(udpHandler);
|
||||
private void setupTcpListener() {
|
||||
|
||||
try {
|
||||
udpAcceptor.bind(new InetSocketAddress(port));
|
||||
} catch(Exception e) {
|
||||
Log.e("KDE/LanLinkProvider", "Error: Could not bind udp socket");
|
||||
tcpServer = openServerSocketOnFreePort(MIN_PORT);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (listening) {
|
||||
try {
|
||||
Socket socket = tcpServer.accept();
|
||||
configureSocket(socket);
|
||||
tcpPackageReceived(socket);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("LanLinkProvider", "TcpReceive exception");
|
||||
}
|
||||
}
|
||||
Log.w("TcpListener", "Stopping TCP listener");
|
||||
}
|
||||
}).start();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
int tcpPort = port;
|
||||
while(!success) {
|
||||
static ServerSocket openServerSocketOnFreePort(int minPort) throws IOException {
|
||||
int tcpPort = minPort;
|
||||
while(tcpPort < MAX_PORT) {
|
||||
try {
|
||||
tcpAcceptor.bind(new InetSocketAddress(tcpPort));
|
||||
success = true;
|
||||
} catch(Exception e) {
|
||||
ServerSocket candidateServer = new ServerSocket();
|
||||
candidateServer.bind(new InetSocketAddress(tcpPort));
|
||||
Log.i("KDE/LanLink", "Using port "+tcpPort);
|
||||
return candidateServer;
|
||||
} catch(IOException e) {
|
||||
tcpPort++;
|
||||
}
|
||||
}
|
||||
Log.e("KDE/LanLink", "No ports available");
|
||||
throw new IOException("No ports available");
|
||||
}
|
||||
|
||||
Log.i("KDE/LanLinkProvider","Using tcpPort "+tcpPort);
|
||||
void broadcastUdpPackage() {
|
||||
|
||||
//I'm on a new network, let's be polite and introduce myself
|
||||
final int finalTcpPort = tcpPort;
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
String deviceListPrefs = PreferenceManager.getDefaultSharedPreferences(context).getString(
|
||||
KEY_CUSTOM_DEVLIST_PREFERENCE, "");
|
||||
String deviceListPrefs = PreferenceManager.getDefaultSharedPreferences(context).getString(CustomDevicesActivity.KEY_CUSTOM_DEVLIST_PREFERENCE, "");
|
||||
ArrayList<String> iplist = new ArrayList<>();
|
||||
if (!deviceListPrefs.isEmpty()) {
|
||||
iplist = CustomDevicesActivity.deserializeIpList(deviceListPrefs);
|
||||
@@ -325,14 +363,14 @@ public class LanLinkProvider extends BaseLinkProvider {
|
||||
iplist.add("255.255.255.255"); //Default: broadcast.
|
||||
|
||||
NetworkPackage identity = NetworkPackage.createIdentityPackage(context);
|
||||
identity.set("tcpPort", finalTcpPort);
|
||||
identity.set("tcpPort", MIN_PORT);
|
||||
DatagramSocket socket = null;
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
socket = new DatagramSocket();
|
||||
socket.setReuseAddress(true);
|
||||
socket.setBroadcast(true);
|
||||
bytes = identity.serialize().getBytes("UTF-8");
|
||||
bytes = identity.serialize().getBytes(StringsHelper.UTF8);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/LanLinkProvider","Failed to create DatagramSocket");
|
||||
@@ -343,9 +381,9 @@ public class LanLinkProvider extends BaseLinkProvider {
|
||||
for (String ipstr : iplist) {
|
||||
try {
|
||||
InetAddress client = InetAddress.getByName(ipstr);
|
||||
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, client, port);
|
||||
socket.send(packet);
|
||||
//Log.i("KDE/LanLinkProvider","Udp identity package sent to address "+packet.getAddress());
|
||||
socket.send(new DatagramPacket(bytes, bytes.length, client, MIN_PORT));
|
||||
socket.send(new DatagramPacket(bytes, bytes.length, client, MIN_PORT_LEGACY));
|
||||
//Log.i("KDE/LanLinkProvider","Udp identity package sent to address "+client);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/LanLinkProvider", "Sending udp identity package failed. Invalid address? (" + ipstr + ")");
|
||||
@@ -353,34 +391,62 @@ public class LanLinkProvider extends BaseLinkProvider {
|
||||
}
|
||||
}
|
||||
|
||||
socket.close();
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@Override
|
||||
public void onStart() {
|
||||
//Log.i("KDE/LanLinkProvider", "onStart");
|
||||
if (!listening) {
|
||||
|
||||
listening = true;
|
||||
|
||||
udpServer = setupUdpListener(MIN_PORT);
|
||||
udpServerOldPort = setupUdpListener(MIN_PORT_LEGACY);
|
||||
|
||||
// Due to certificate request from SSL server to client, the certificate request message from device with latest android version to device with
|
||||
// old android version causes a FATAL ALERT message stating that incorrect certificate request
|
||||
// Server is disabled on these devices and using a reverse connection strategy. This works well for connection of these devices with kde
|
||||
// and newer android versions. Although devices with android version less than ICS cannot connect to other devices who also have android version less
|
||||
// than ICS because server is disabled on both
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
Log.w("KDE/LanLinkProvider","Not starting a TCP server because it's not supported on Android < 14. Operating only as client.");
|
||||
} else {
|
||||
setupTcpListener();
|
||||
}
|
||||
|
||||
broadcastUdpPackage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkChange() {
|
||||
//Log.e("KDE/LanLinkProvider","onNetworkChange");
|
||||
|
||||
//FilesHelper.LogOpenFileCount();
|
||||
|
||||
//Keep existing connections open while unbinding the socket
|
||||
tcpAcceptor.setCloseOnDeactivation(false);
|
||||
onStop();
|
||||
tcpAcceptor.setCloseOnDeactivation(true);
|
||||
|
||||
//FilesHelper.LogOpenFileCount();
|
||||
|
||||
onStart();
|
||||
|
||||
//FilesHelper.LogOpenFileCount();
|
||||
broadcastUdpPackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
udpAcceptor.unbind();
|
||||
tcpAcceptor.unbind();
|
||||
//Log.i("KDE/LanLinkProvider", "onStop");
|
||||
listening = false;
|
||||
try {
|
||||
tcpServer.close();
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
udpServer.close();
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
udpServerOldPort.close();
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -388,6 +454,4 @@ public class LanLinkProvider extends BaseLinkProvider {
|
||||
return "LanLinkProvider";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright 2015 Vineet Garg <grg.vineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Backends.LanBackend;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class LanPairingHandler extends BasePairingHandler {
|
||||
|
||||
private Timer mPairingTimer;
|
||||
|
||||
public LanPairingHandler(Device device, final PairingHandlerCallback callback) {
|
||||
super(device, callback);
|
||||
|
||||
if (device.isPaired()) {
|
||||
mPairStatus = PairStatus.Paired;
|
||||
} else {
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
}
|
||||
}
|
||||
|
||||
private NetworkPackage createPairPackage() {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", true);
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(mDevice.getContext());
|
||||
String publicKey = "-----BEGIN PUBLIC KEY-----\n" + globalSettings.getString("publicKey", "").trim()+ "\n-----END PUBLIC KEY-----\n";
|
||||
np.set("publicKey", publicKey);
|
||||
return np;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packageReceived(NetworkPackage np) throws Exception{
|
||||
|
||||
boolean wantsPair = np.getBoolean("pair");
|
||||
|
||||
if (wantsPair == isPaired()) {
|
||||
if (mPairStatus == PairStatus.Requested) {
|
||||
//Log.e("Device","Unpairing (pair rejected)");
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
hidePairingNotification();
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (wantsPair) {
|
||||
|
||||
//Retrieve their public key
|
||||
try {
|
||||
String publicKeyContent = np.getString("publicKey").replace("-----BEGIN PUBLIC KEY-----\n","").replace("-----END PUBLIC KEY-----\n", "");
|
||||
byte[] publicKeyBytes = Base64.decode(publicKeyContent, 0);
|
||||
mDevice.publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
} catch (Exception e) {
|
||||
//IGNORE
|
||||
}
|
||||
|
||||
if (mPairStatus == PairStatus.Requested) { //We started pairing
|
||||
|
||||
hidePairingNotification();
|
||||
|
||||
pairingDone();
|
||||
|
||||
} else {
|
||||
|
||||
// If device is already paired, accept pairing silently
|
||||
if (mDevice.isPaired()) {
|
||||
acceptPairing();
|
||||
return;
|
||||
}
|
||||
|
||||
// Pairing notifications are still managed by device as there is no other way to
|
||||
// know about notificationId to cancel notification when PairActivity is started
|
||||
// Even putting notificationId in intent does not work because PairActivity can be
|
||||
// started from MainActivity too, so then notificationId cannot be set
|
||||
hidePairingNotification();
|
||||
mDevice.displayPairingNotification();
|
||||
|
||||
mPairingTimer = new Timer();
|
||||
|
||||
mPairingTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.w("KDE/Device","Unpairing (timeout B)");
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
hidePairingNotification();
|
||||
}
|
||||
}, 25*1000); //Time to show notification, waiting for user to accept (peer will timeout in 30 seconds)
|
||||
mPairStatus = PairStatus.RequestedByPeer;
|
||||
mCallback.incomingRequest();
|
||||
|
||||
}
|
||||
} else {
|
||||
Log.i("KDE/Pairing", "Unpair request");
|
||||
|
||||
if (mPairStatus == PairStatus.Requested) {
|
||||
hidePairingNotification();
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer));
|
||||
} else if (mPairStatus == PairStatus.Paired) {
|
||||
mCallback.unpaired();
|
||||
}
|
||||
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPairing() {
|
||||
|
||||
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
hidePairingNotification(); //Will stop the pairingTimer if it was running
|
||||
mPairingTimer = new Timer();
|
||||
mPairingTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_timed_out));
|
||||
Log.w("KDE/Device","Unpairing (timeout A)");
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
}
|
||||
}, 30*1000); //Time to wait for the other to accept
|
||||
mPairStatus = PairStatus.Requested;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable e) {
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_could_not_send_package));
|
||||
}
|
||||
};
|
||||
mDevice.sendPackage(createPairPackage(), statusCallback);
|
||||
}
|
||||
|
||||
public void hidePairingNotification() {
|
||||
mDevice.hidePairingNotification();
|
||||
if (mPairingTimer != null) {
|
||||
mPairingTimer .cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptPairing() {
|
||||
hidePairingNotification();
|
||||
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
pairingDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable e) {
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_not_reachable));
|
||||
}
|
||||
};
|
||||
mDevice.sendPackage(createPairPackage(), statusCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rejectPairing() {
|
||||
hidePairingNotification();
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", false);
|
||||
mDevice.sendPackage(np);
|
||||
}
|
||||
|
||||
public 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();
|
||||
|
||||
if (mDevice.publicKey != null) {
|
||||
try {
|
||||
String encodedPublicKey = Base64.encodeToString(mDevice.publicKey.getEncoded(), 0);
|
||||
editor.putString("publicKey", encodedPublicKey);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/PairingDone", "Error encoding public key");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String encodedCertificate = Base64.encodeToString(mDevice.certificate.getEncoded(), 0);
|
||||
editor.putString("certificate", encodedCertificate);
|
||||
} catch (NullPointerException n) {
|
||||
Log.w("KDE/PairingDone", "Certificate is null, remote device does not support ssl");
|
||||
} catch (CertificateEncodingException c) {
|
||||
Log.e("KDE/PairingDOne", "Error encoding certificate");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/Pairng", "Exception");
|
||||
}
|
||||
editor.apply();
|
||||
|
||||
mPairStatus = PairStatus.Paired;
|
||||
mCallback.pairingDone();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpair() {
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", false);
|
||||
mDevice.sendPackage(np);
|
||||
}
|
||||
}
|
@@ -20,8 +20,11 @@
|
||||
|
||||
package org.kde.kdeconnect.Backends.LoopbackBackend;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
@@ -29,35 +32,33 @@ import java.security.PublicKey;
|
||||
|
||||
public class LoopbackLink extends BaseLink {
|
||||
|
||||
public LoopbackLink(BaseLinkProvider linkProvider) {
|
||||
super("loopback", linkProvider, ConnectionStarted.Remotely);
|
||||
public LoopbackLink(Context context, BaseLinkProvider linkProvider) {
|
||||
super(context, "loopback", linkProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LoopbackLink";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePairingHandler getPairingHandler(Device device, BasePairingHandler.PairingHandlerCallback callback) {
|
||||
return new LoopbackPairingHandler(device, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackage(NetworkPackage in, Device.SendPackageStatusCallback callback) {
|
||||
sendPackageEncrypted(in, callback, null);
|
||||
packageReceived(in);
|
||||
if (in.hasPayload()) {
|
||||
callback.sendProgress(0);
|
||||
in.setPayload(in.getPayload(), in.getPayloadSize());
|
||||
callback.sendProgress(100);
|
||||
}
|
||||
callback.sendSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPackageEncrypted(NetworkPackage in, Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
try {
|
||||
if (key != null) {
|
||||
in = in.encrypt(key);
|
||||
}
|
||||
String s = in.serialize();
|
||||
NetworkPackage out= NetworkPackage.unserialize(s);
|
||||
if (key != null) {
|
||||
out = out.decrypt(privateKey);
|
||||
}
|
||||
packageReceived(out);
|
||||
if (in.hasPayload()) {
|
||||
callback.sendProgress(0);
|
||||
out.setPayload(in.getPayload(), in.getPayloadSize());
|
||||
callback.sendProgress(100);
|
||||
}
|
||||
callback.sendSuccess();
|
||||
} catch(Exception e) {
|
||||
callback.sendFailure(e);
|
||||
}
|
||||
public void sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
sendPackage(np, callback);
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ public class LoopbackLinkProvider extends BaseLinkProvider {
|
||||
@Override
|
||||
public void onNetworkChange() {
|
||||
NetworkPackage np = NetworkPackage.createIdentityPackage(context);
|
||||
connectionAccepted(np, new LoopbackLink(this));
|
||||
connectionAccepted(np, new LoopbackLink(context, this));
|
||||
}
|
||||
/*
|
||||
@Override
|
||||
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2015 Vineet Garg <grg.vineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Backends.LoopbackBackend;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
public class LoopbackPairingHandler extends BasePairingHandler {
|
||||
|
||||
public LoopbackPairingHandler(Device device, PairingHandlerCallback callback) {
|
||||
super(device, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packageReceived(NetworkPackage np) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPairing() {
|
||||
Log.i("LoopbackPairing", "requestPairing");
|
||||
mCallback.pairingDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptPairing() {
|
||||
Log.i("LoopbackPairing", "acceptPairing");
|
||||
mCallback.pairingDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rejectPairing() {
|
||||
Log.i("LoopbackPairing", "rejectPairing");
|
||||
mCallback.unpaired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpair() {
|
||||
Log.i("LoopbackPairing", "unpair");
|
||||
mCallback.unpaired();
|
||||
}
|
||||
|
||||
}
|
@@ -20,7 +20,6 @@
|
||||
|
||||
package org.kde.kdeconnect;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -29,18 +28,15 @@ import android.content.SharedPreferences;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||
import org.kde.kdeconnect.Backends.LoopbackBackend.LoopbackLinkProvider;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -67,11 +63,13 @@ public class BackgroundService extends Service {
|
||||
if (wasEmpty) {
|
||||
onNetworkChange();
|
||||
}
|
||||
//Log.e("acquireDiscoveryMode",key.getClass().getName() +" ["+discoveryModeAcquisitions.size()+"]");
|
||||
return wasEmpty;
|
||||
}
|
||||
|
||||
public void releaseDiscoveryMode(Object key) {
|
||||
boolean removed = discoveryModeAcquisitions.remove(key);
|
||||
//Log.e("releaseDiscoveryMode",key.getClass().getName() +" ["+discoveryModeAcquisitions.size()+"]");
|
||||
if (removed && discoveryModeAcquisitions.isEmpty()) {
|
||||
cleanDevices();
|
||||
}
|
||||
@@ -144,16 +142,14 @@ public class BackgroundService extends Service {
|
||||
|
||||
private void registerLinkProviders() {
|
||||
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
//linkProviders.add(new LoopbackLinkProvider(this));
|
||||
|
||||
//if (settings.getBoolean("loopback_link", true)) {
|
||||
// linkProviders.add(new LoopbackLinkProvider(this));
|
||||
//}
|
||||
linkProviders.add(new LanLinkProvider(this));
|
||||
|
||||
if (settings.getBoolean("lan_link", true)) {
|
||||
linkProviders.add(new LanLinkProvider(this));
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<BaseLinkProvider> getLinkProviders() {
|
||||
return linkProviders;
|
||||
}
|
||||
|
||||
public Device getDevice(String id) {
|
||||
@@ -161,11 +157,16 @@ public class BackgroundService extends Service {
|
||||
}
|
||||
|
||||
private void cleanDevices() {
|
||||
for(Device d : devices.values()) {
|
||||
if (!d.isPaired() && !d.isPairRequested() && !d.isPairRequestedByOtherEnd() && d.getConnectionSource() == BaseLink.ConnectionStarted.Remotely) {
|
||||
d.disconnect();
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for(Device d : devices.values()) {
|
||||
if (!d.isPaired() && !d.isPairRequested() && !d.isPairRequestedByPeer() && !d.deviceShouldBeKeptAlive()) {
|
||||
d.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private final BaseLinkProvider.ConnectionReceiver deviceListener = new BaseLinkProvider.ConnectionReceiver() {
|
||||
@@ -182,8 +183,8 @@ public class BackgroundService extends Service {
|
||||
} else {
|
||||
Log.i("KDE/BackgroundService", "addLink,unknown device: " + deviceId);
|
||||
device = new Device(BackgroundService.this, identityPackage, link);
|
||||
if (device.isPaired() || device.isPairRequested() || device.isPairRequestedByOtherEnd()
|
||||
|| link.getConnectionSource() == BaseLink.ConnectionStarted.Locally
|
||||
if (device.isPaired() || device.isPairRequested() || device.isPairRequestedByPeer()
|
||||
|| link.linkShouldBeKeptAlive()
|
||||
||!discoveryModeAcquisitions.isEmpty() )
|
||||
{
|
||||
devices.put(deviceId, device);
|
||||
@@ -254,7 +255,7 @@ public class BackgroundService extends Service {
|
||||
|
||||
Log.i("KDE/BackgroundService", "Service not started yet, initializing...");
|
||||
|
||||
initializeRsaKeys();
|
||||
initializeSecurityParameters();
|
||||
loadRememberedDevicesFromSettings();
|
||||
registerLinkProviders();
|
||||
|
||||
@@ -264,62 +265,11 @@ public class BackgroundService extends Service {
|
||||
for (BaseLinkProvider a : linkProviders) {
|
||||
a.onStart();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initializeRsaKeys() {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
if (!settings.contains("publicKey") || !settings.contains("privateKey")) {
|
||||
|
||||
KeyPair keyPair;
|
||||
try {
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||
keyGen.initialize(2048);
|
||||
keyPair = keyGen.genKeyPair();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/initializeRsaKeys","Exception");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||
byte[] privateKey = keyPair.getPrivate().getEncoded();
|
||||
|
||||
SharedPreferences.Editor edit = settings.edit();
|
||||
edit.putString("publicKey",Base64.encodeToString(publicKey, 0).trim()+"\n");
|
||||
edit.putString("privateKey",Base64.encodeToString(privateKey, 0));
|
||||
edit.apply();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Encryption and decryption test
|
||||
//================================
|
||||
|
||||
try {
|
||||
|
||||
NetworkPackage np = NetworkPackage.createIdentityPackage(this);
|
||||
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
byte[] publicKeyBytes = Base64.decode(globalSettings.getString("publicKey",""), 0);
|
||||
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
|
||||
np.encrypt(publicKey);
|
||||
|
||||
byte[] privateKeyBytes = Base64.decode(globalSettings.getString("privateKey",""), 0);
|
||||
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
|
||||
|
||||
NetworkPackage decrypted = np.decrypt(privateKey);
|
||||
Log.e("ENCRYPTION AND DECRYPTION TEST", decrypted.serialize());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("ENCRYPTION AND DECRYPTION TEST","Exception: "+e);
|
||||
}
|
||||
*/
|
||||
|
||||
void initializeSecurityParameters() {
|
||||
RsaHelper.initialiseRsaKeys(this);
|
||||
SslHelper.initialiseCertificate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -350,11 +300,14 @@ public class BackgroundService extends Service {
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
//This will be called for each intent launch, even if the service is already started and it is reused
|
||||
mutex.lock();
|
||||
for (InstanceCallback c : callbacks) {
|
||||
c.onServiceStart(this);
|
||||
try {
|
||||
for (InstanceCallback c : callbacks) {
|
||||
c.onServiceStart(this);
|
||||
}
|
||||
callbacks.clear();
|
||||
} finally {
|
||||
mutex.unlock();
|
||||
}
|
||||
callbacks.clear();
|
||||
mutex.unlock();
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
@@ -368,8 +321,11 @@ public class BackgroundService extends Service {
|
||||
public void run() {
|
||||
if (callback != null) {
|
||||
mutex.lock();
|
||||
callbacks.add(callback);
|
||||
mutex.unlock();
|
||||
try {
|
||||
callbacks.add(callback);
|
||||
} finally {
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
Intent serviceIntent = new Intent(c, BackgroundService.class);
|
||||
c.startService(serviceIntent);
|
||||
|
@@ -28,8 +28,6 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
@@ -37,22 +35,28 @@ import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.UserInterface.MaterialActivity;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.Plugins.PluginFactory;
|
||||
import org.kde.kdeconnect.UserInterface.MaterialActivity;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class Device implements BaseLink.PackageReceiver {
|
||||
@@ -62,18 +66,22 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
private final String deviceId;
|
||||
private String name;
|
||||
public PublicKey publicKey;
|
||||
public Certificate certificate;
|
||||
private int notificationId;
|
||||
private int protocolVersion;
|
||||
|
||||
private DeviceType deviceType;
|
||||
private PairStatus pairStatus;
|
||||
|
||||
private final CopyOnWriteArrayList<PairingCallback> pairingCallback = new CopyOnWriteArrayList<>();
|
||||
private Timer pairingTimer;
|
||||
private Map<String, BasePairingHandler> pairingHandlers = new HashMap<>();
|
||||
|
||||
private final CopyOnWriteArrayList<BaseLink> links = new CopyOnWriteArrayList<>();
|
||||
|
||||
private final HashMap<String, Plugin> plugins = new HashMap<>();
|
||||
private final HashMap<String, Plugin> failedPlugins = new HashMap<>();
|
||||
private List<String> m_supportedPlugins = new ArrayList<>();
|
||||
private final ConcurrentHashMap<String, Plugin> plugins = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Plugin> failedPlugins = new ConcurrentHashMap<>();
|
||||
private Map<String, ArrayList<String>> pluginsByIncomingInterface;
|
||||
|
||||
private final SharedPreferences settings;
|
||||
|
||||
@@ -85,8 +93,6 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
|
||||
public enum PairStatus {
|
||||
NotPaired,
|
||||
Requested,
|
||||
RequestedByPeer,
|
||||
Paired
|
||||
}
|
||||
|
||||
@@ -130,15 +136,18 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
this.deviceType = DeviceType.FromString(settings.getString("deviceType", "desktop"));
|
||||
|
||||
try {
|
||||
byte[] publicKeyBytes = Base64.decode(settings.getString("publicKey", ""), 0);
|
||||
publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
String publicKeyStr = settings.getString("publicKey", null);
|
||||
if (publicKeyStr != null) {
|
||||
byte[] publicKeyBytes = Base64.decode(publicKeyStr, 0);
|
||||
publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
unpair();
|
||||
Log.e("KDE/Device","Exception");
|
||||
Log.e("KDE/Device","Exception deserializing stored public key for device");
|
||||
}
|
||||
|
||||
reloadPluginsFromSettings();
|
||||
//Do not load plugins yet, the device is not present
|
||||
//reloadPluginsFromSettings();
|
||||
}
|
||||
|
||||
//Device known via an incoming connection sent to us via a devicelink, we know everything but we don't trust it yet
|
||||
@@ -182,6 +191,10 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
//Returns 0 if the version matches, < 0 if it is older or > 0 if it is newer
|
||||
public int compareProtocolVersion() {
|
||||
return protocolVersion - NetworkPackage.ProtocolVersion;
|
||||
@@ -190,7 +203,6 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Pairing-related functions
|
||||
//
|
||||
@@ -199,17 +211,28 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
return pairStatus == PairStatus.Paired;
|
||||
}
|
||||
|
||||
/* Asks all pairing handlers that, is pair requested? */
|
||||
public boolean isPairRequested() {
|
||||
return pairStatus == PairStatus.Requested;
|
||||
boolean pairRequested = false;
|
||||
for (BasePairingHandler ph: pairingHandlers.values()) {
|
||||
pairRequested = pairRequested || ph.isPairRequested();
|
||||
}
|
||||
return pairRequested;
|
||||
}
|
||||
|
||||
public boolean isPairRequestedByOtherEnd() {
|
||||
return pairStatus == PairStatus.RequestedByPeer;
|
||||
/* Asks all pairing handlers that, is pair requested by peer? */
|
||||
public boolean isPairRequestedByPeer() {
|
||||
boolean pairRequestedByPeer = false;
|
||||
for (BasePairingHandler ph : pairingHandlers.values()) {
|
||||
pairRequestedByPeer = pairRequestedByPeer || ph.isPairRequestedByPeer();
|
||||
}
|
||||
return pairRequestedByPeer;
|
||||
}
|
||||
|
||||
public void addPairingCallback(PairingCallback callback) {
|
||||
pairingCallback.add(callback);
|
||||
}
|
||||
|
||||
public void removePairingCallback(PairingCallback callback) {
|
||||
pairingCallback.remove(callback);
|
||||
}
|
||||
@@ -224,15 +247,6 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
cb.pairingFailed(res.getString(R.string.error_already_paired));
|
||||
}
|
||||
return;
|
||||
case Requested:
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(res.getString(R.string.error_already_requested));
|
||||
}
|
||||
return;
|
||||
case RequestedByPeer:
|
||||
Log.d("requestPairing", "Pairing already started by the other end, accepting their request.");
|
||||
acceptPairing();
|
||||
return;
|
||||
case NotPaired:
|
||||
;
|
||||
}
|
||||
@@ -244,59 +258,35 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
return;
|
||||
}
|
||||
|
||||
//Send our own public key
|
||||
NetworkPackage np = NetworkPackage.createPublicKeyPackage(context);
|
||||
sendPackage(np, new SendPackageStatusCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
hidePairingNotification(); //Will stop the pairingTimer if it was running
|
||||
pairingTimer = new Timer();
|
||||
pairingTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(context.getString(R.string.error_timed_out));
|
||||
}
|
||||
Log.e("KDE/Device", "Unpairing (timeout A)");
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
}
|
||||
}, 30 * 1000); //Time to wait for the other to accept
|
||||
pairStatus = PairStatus.Requested;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(context.getString(R.string.error_could_not_send_package));
|
||||
}
|
||||
Log.e("KDE/Device", "Unpairing (sendFailed A)");
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void hidePairingNotification() {
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(notificationId);
|
||||
if (pairingTimer != null) {
|
||||
pairingTimer.cancel();
|
||||
for (BasePairingHandler ph : pairingHandlers.values()) {
|
||||
ph.requestPairing();
|
||||
}
|
||||
BackgroundService.removeGuiInUseCounter(context);
|
||||
|
||||
}
|
||||
|
||||
public void unpair() {
|
||||
|
||||
//Log.e("Device","Unpairing (unpair)");
|
||||
for (BasePairingHandler ph : pairingHandlers.values()) {
|
||||
ph.unpair();
|
||||
}
|
||||
unpairInternal(); // Even if there are no pairing handlers, unpair
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does not send an unpair package, instead it unpairs internally by deleting trusted device info. . Likely to be called after sending package from
|
||||
* pairing handler
|
||||
*/
|
||||
private void unpairInternal() {
|
||||
|
||||
//Log.e("Device","Unpairing (unpairInternal)");
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
|
||||
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
|
||||
preferences.edit().remove(deviceId).apply();
|
||||
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", false);
|
||||
sendPackage(np);
|
||||
// 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();
|
||||
|
||||
for (PairingCallback cb : pairingCallback) cb.unpaired();
|
||||
|
||||
@@ -304,6 +294,7 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
|
||||
}
|
||||
|
||||
/* This method should be called after pairing is done from pairing handler. Calling this method again should not create any problem as most of the things will get over writter*/
|
||||
private void pairingDone() {
|
||||
|
||||
//Log.e("Device", "Storing as trusted, deviceId: "+deviceId);
|
||||
@@ -316,12 +307,9 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
|
||||
preferences.edit().putBoolean(deviceId,true).apply();
|
||||
|
||||
//Store device information needed to create a Device object in a future
|
||||
SharedPreferences.Editor editor = settings.edit();
|
||||
editor.putString("deviceName", getName());
|
||||
SharedPreferences.Editor editor = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE).edit();
|
||||
editor.putString("deviceName", name);
|
||||
editor.putString("deviceType", deviceType.toString());
|
||||
String encodedPublicKey = Base64.encodeToString(publicKey.getEncoded(), 0);
|
||||
editor.putString("publicKey", encodedPublicKey);
|
||||
editor.apply();
|
||||
|
||||
reloadPluginsFromSettings();
|
||||
@@ -332,39 +320,28 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
|
||||
}
|
||||
|
||||
/* This method is called after accepting pair request form GUI */
|
||||
public void acceptPairing() {
|
||||
|
||||
Log.i("KDE/Device","Accepted pair request started by the other device");
|
||||
Log.i("KDE/Device", "Accepted pair request started by the other device");
|
||||
|
||||
//Send our own public key
|
||||
NetworkPackage np = NetworkPackage.createPublicKeyPackage(context);
|
||||
sendPackage(np, new SendPackageStatusCallback() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
pairingDone();
|
||||
}
|
||||
@Override
|
||||
protected void onFailure(Throwable e) {
|
||||
Log.e("Device","Unpairing (sendFailed B)");
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(context.getString(R.string.error_not_reachable));
|
||||
}
|
||||
}
|
||||
});
|
||||
for (BasePairingHandler ph : pairingHandlers.values()) {
|
||||
ph.acceptPairing();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* This method is called after rejecting pairing from GUI */
|
||||
public void rejectPairing() {
|
||||
|
||||
Log.i("KDE/Device","Rejected pair request started by the other device");
|
||||
Log.i("KDE/Device", "Rejected pair request started by the other device");
|
||||
|
||||
//Log.e("Device","Unpairing (rejectPairing)");
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", false);
|
||||
sendPackage(np);
|
||||
for (BasePairingHandler ph : pairingHandlers.values()) {
|
||||
ph.rejectPairing();
|
||||
}
|
||||
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(context.getString(R.string.error_canceled_by_user));
|
||||
@@ -372,8 +349,52 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Notification related methods used during pairing
|
||||
//
|
||||
public int getNotificationId() {
|
||||
return notificationId;
|
||||
}
|
||||
|
||||
public void displayPairingNotification() {
|
||||
|
||||
hidePairingNotification();
|
||||
|
||||
notificationId = (int)System.currentTimeMillis();
|
||||
|
||||
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);
|
||||
|
||||
Resources res = getContext().getResources();
|
||||
|
||||
Notification noti = new NotificationCompat.Builder(getContext())
|
||||
.setContentTitle(res.getString(R.string.pairing_request_from, getName()))
|
||||
.setContentText(res.getString(R.string.tap_to_answer))
|
||||
.setContentIntent(pendingIntent)
|
||||
.setTicker(res.getString(R.string.pair_requested))
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.build();
|
||||
|
||||
final NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
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!/
|
||||
}
|
||||
}
|
||||
|
||||
public void hidePairingNotification() {
|
||||
final NotificationManager notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancel(notificationId);
|
||||
BackgroundService.removeGuiInUseCounter(context);
|
||||
}
|
||||
|
||||
//
|
||||
// ComputerLink-related functions
|
||||
@@ -399,6 +420,20 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
this.deviceType = DeviceType.FromString(identityPackage.getString("deviceType", "desktop"));
|
||||
}
|
||||
|
||||
if (identityPackage.has("certificate")) {
|
||||
String certificateString = identityPackage.getString("certificate");
|
||||
|
||||
try {
|
||||
byte[] certificateBytes = Base64.decode(certificateString, 0);
|
||||
certificate = SslHelper.parseCertificate(certificateBytes);
|
||||
Log.i("KDE/Device", "Got certificate ");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/Device", "Error getting certificate");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
links.add(link);
|
||||
|
||||
@@ -414,28 +449,67 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
|
||||
Log.i("KDE/Device","addLink "+link.getLinkProvider().getName()+" -> "+getName() + " active links: "+ links.size());
|
||||
|
||||
/*
|
||||
Collections.sort(links, new Comparator<BaseLink>() {
|
||||
@Override
|
||||
public int compare(BaseLink o, BaseLink o2) {
|
||||
return o2.getLinkProvider().getPriority() - o.getLinkProvider().getPriority();
|
||||
}
|
||||
});
|
||||
*/
|
||||
if (!pairingHandlers.containsKey(link.getName())) {
|
||||
BasePairingHandler.PairingHandlerCallback callback = new BasePairingHandler.PairingHandlerCallback() {
|
||||
@Override
|
||||
public void incomingRequest() {
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.incomingRequest();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pairingDone() {
|
||||
Device.this.pairingDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pairingFailed(String error) {
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(error);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpaired() {
|
||||
unpairInternal();
|
||||
}
|
||||
};
|
||||
pairingHandlers.put(link.getName(), link.getPairingHandler(this, callback));
|
||||
}
|
||||
|
||||
Set<String> outgoingCapabilities = identityPackage.getStringSet("outgoingCapabilities", null);
|
||||
Set<String> incomingCapabilities = identityPackage.getStringSet("incomingCapabilities", null);
|
||||
if (incomingCapabilities != null && outgoingCapabilities != null) {
|
||||
m_supportedPlugins = new Vector<>(PluginFactory.pluginsForCapabilities(context, incomingCapabilities, outgoingCapabilities));
|
||||
} else {
|
||||
m_supportedPlugins = new Vector<>(PluginFactory.getAvailablePlugins());
|
||||
}
|
||||
|
||||
link.addPackageReceiver(this);
|
||||
|
||||
if (links.size() == 1) {
|
||||
reloadPluginsFromSettings();
|
||||
}
|
||||
reloadPluginsFromSettings();
|
||||
|
||||
}
|
||||
|
||||
public void removeLink(BaseLink link) {
|
||||
//FilesHelper.LogOpenFileCount();
|
||||
|
||||
/* Remove pairing handler corresponding to that link too if it was the only link*/
|
||||
boolean linkPresent = false;
|
||||
for (BaseLink bl : links) {
|
||||
if (bl.getName().equals(link.getName())) {
|
||||
linkPresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!linkPresent) {
|
||||
pairingHandlers.remove(link.getName());
|
||||
}
|
||||
|
||||
link.removePackageReceiver(this);
|
||||
links.remove(link);
|
||||
Log.i("KDE/Device","removeLink: "+link.getLinkProvider().getName() + " -> "+getName() + " active links: "+ links.size());
|
||||
Log.i("KDE/Device", "removeLink: " + link.getLinkProvider().getName() + " -> " + getName() + " active links: " + links.size());
|
||||
if (links.isEmpty()) {
|
||||
reloadPluginsFromSettings();
|
||||
}
|
||||
@@ -444,143 +518,63 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
@Override
|
||||
public void onPackageReceived(NetworkPackage np) {
|
||||
|
||||
if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR)) {
|
||||
hackToMakeRetrocompatiblePacketTypes(np);
|
||||
|
||||
Log.i("KDE/Device","Pair package");
|
||||
if (NetworkPackage.PACKAGE_TYPE_PAIR.equals(np.getType())) {
|
||||
|
||||
boolean wantsPair = np.getBoolean("pair");
|
||||
Log.i("KDE/Device", "Pair package");
|
||||
|
||||
if (wantsPair == isPaired()) {
|
||||
if (pairStatus == PairStatus.Requested) {
|
||||
//Log.e("Device","Unpairing (pair rejected)");
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
hidePairingNotification();
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(context.getString(R.string.error_canceled_by_other_peer));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (wantsPair) {
|
||||
|
||||
//Retrieve their public key
|
||||
for (BasePairingHandler ph: pairingHandlers.values()) {
|
||||
try {
|
||||
String publicKeyContent = np.getString("publicKey").replace("-----BEGIN PUBLIC KEY-----\n","").replace("-----END PUBLIC KEY-----\n","");
|
||||
byte[] publicKeyBytes = Base64.decode(publicKeyContent, 0);
|
||||
publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
} catch(Exception e) {
|
||||
ph.packageReceived(np);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/Device","Pairing exception: Received incorrect key");
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(context.getString(R.string.error_invalid_key));
|
||||
}
|
||||
return;
|
||||
Log.e("PairingPackageReceived","Exception");
|
||||
}
|
||||
|
||||
if (pairStatus == PairStatus.Requested) { //We started pairing
|
||||
|
||||
Log.i("KDE/Pairing","Pair answer");
|
||||
|
||||
hidePairingNotification();
|
||||
|
||||
pairingDone();
|
||||
|
||||
} else {
|
||||
|
||||
Log.i("KDE/Pairing","Pair request");
|
||||
|
||||
Intent intent = new Intent(context, MaterialActivity.class);
|
||||
intent.putExtra("deviceId", deviceId);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
|
||||
|
||||
Resources res = context.getResources();
|
||||
|
||||
hidePairingNotification();
|
||||
|
||||
Notification noti = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(res.getString(R.string.pairing_request_from, getName()))
|
||||
.setContentText(res.getString(R.string.tap_to_answer))
|
||||
.setContentIntent(pendingIntent)
|
||||
.setTicker(res.getString(R.string.pair_requested))
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.build();
|
||||
|
||||
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationId = (int)System.currentTimeMillis();
|
||||
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!/
|
||||
}
|
||||
|
||||
pairingTimer = new Timer();
|
||||
pairingTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.e("KDE/Device","Unpairing (timeout B)");
|
||||
hidePairingNotification();
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
}
|
||||
}, 25*1000); //Time to show notification, waiting for user to accept (peer will timeout in 30 seconds)
|
||||
pairStatus = PairStatus.RequestedByPeer;
|
||||
for (PairingCallback cb : pairingCallback) cb.incomingRequest();
|
||||
|
||||
}
|
||||
} else {
|
||||
Log.i("KDE/Pairing","Unpair request");
|
||||
|
||||
if (pairStatus == PairStatus.Requested) {
|
||||
hidePairingNotification();
|
||||
for (PairingCallback cb : pairingCallback) {
|
||||
cb.pairingFailed(context.getString(R.string.error_canceled_by_other_peer));
|
||||
}
|
||||
} else if (pairStatus == PairStatus.Paired) {
|
||||
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
|
||||
preferences.edit().remove(deviceId).apply();
|
||||
}
|
||||
|
||||
pairStatus = PairStatus.NotPaired;
|
||||
|
||||
reloadPluginsFromSettings();
|
||||
|
||||
for (PairingCallback cb : pairingCallback) cb.unpaired();
|
||||
|
||||
}
|
||||
} else if (isPaired()) {
|
||||
|
||||
for (Plugin plugin : plugins.values()) {
|
||||
try {
|
||||
plugin.onPackageReceived(np);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/Device", "Exception in "+plugin.getDisplayName()+"'s onPackageReceived()");
|
||||
//If capabilities are not supported, iterate all plugins
|
||||
Collection<String> targetPlugins = pluginsByIncomingInterface.get(np.getType());
|
||||
if (targetPlugins != null && !targetPlugins.isEmpty()) {
|
||||
for (String pluginKey : targetPlugins) {
|
||||
Plugin plugin = plugins.get(pluginKey);
|
||||
try {
|
||||
plugin.onPackageReceived(np);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/Device", "Exception in " + plugin.getPluginKey() + "'s onPackageReceived()");
|
||||
//try { Log.e("KDE/Device", "NetworkPackage:" + np.serialize()); } catch (Exception _) { }
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.w("Device", "Ignoring packet with type " + np.getType() + " because no plugin can handle it");
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
//Log.e("KDE/onPackageReceived","Device not paired, will pass package to unpairedPackageListeners");
|
||||
|
||||
if (pairStatus != PairStatus.Requested) {
|
||||
unpair();
|
||||
}
|
||||
// If it is pair package, it should be captured by "if" at start
|
||||
// If not and device is paired, it should be captured by isPaired
|
||||
// Else unpair, this handles the situation when one device unpairs, but other dont know like unpairing when wi-fi is off
|
||||
|
||||
for (Plugin plugin : plugins.values()) {
|
||||
try {
|
||||
plugin.onUnpairedDevicePackageReceived(np);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/Device", "Exception in "+plugin.getDisplayName()+"'s onPackageReceived() in unPairedPackageListeners");
|
||||
unpair();
|
||||
|
||||
//If capabilities are not supported, iterate all plugins
|
||||
Collection<String> targetPlugins = pluginsByIncomingInterface.get(np.getType());
|
||||
if (targetPlugins != null && !targetPlugins.isEmpty()) {
|
||||
for (String pluginKey : targetPlugins) {
|
||||
Plugin plugin = plugins.get(pluginKey);
|
||||
try {
|
||||
plugin.onUnpairedDevicePackageReceived(np);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/Device", "Exception in " + plugin.getDisplayName() + "'s onPackageReceived() in unPairedPackageListeners");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e("Device", "Ignoring packet with type " + np.getType() + " because no plugin can handle it");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -620,6 +614,16 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
//Async
|
||||
public void sendPackage(final NetworkPackage np, final SendPackageStatusCallback callback) {
|
||||
|
||||
hackToMakeRetrocompatiblePacketTypes(np);
|
||||
|
||||
|
||||
/*
|
||||
if (!m_outgoingCapabilities.contains(np.getType()) && !NetworkPackage.protocolPackageTypes.contains(np.getType())) {
|
||||
Log.e("Device/sendPackage", "Plugin tried to send an undeclared package: " + np.getType());
|
||||
Log.w("Device/sendPackage", "Declared outgoing package types: " + Arrays.toString(m_outgoingCapabilities.toArray()));
|
||||
}
|
||||
*/
|
||||
|
||||
//Log.e("sendPackage", "Sending package...");
|
||||
//Log.e("sendPackage", np.serialize());
|
||||
|
||||
@@ -628,7 +632,7 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
boolean useEncryption = (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired());
|
||||
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) {
|
||||
@@ -675,46 +679,41 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
private synchronized void addPlugin(final String pluginKey) {
|
||||
private synchronized boolean addPlugin(final String pluginKey) {
|
||||
Plugin existing = plugins.get(pluginKey);
|
||||
if (existing != null) {
|
||||
Log.w("KDE/addPlugin","plugin already present:" + pluginKey);
|
||||
return;
|
||||
//Log.w("KDE/addPlugin","plugin already present:" + pluginKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
final Plugin plugin = PluginFactory.instantiatePluginForDevice(context, pluginKey, this);
|
||||
if (plugin == null) {
|
||||
Log.e("KDE/addPlugin","could not instantiate plugin: "+pluginKey);
|
||||
failedPlugins.put(pluginKey, null);
|
||||
return;
|
||||
//Can't put a null
|
||||
//failedPlugins.put(pluginKey, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean success;
|
||||
try {
|
||||
success = plugin.onCreate();
|
||||
} catch (Exception e) {
|
||||
success = false;
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/addPlugin", "Exception loading plugin " + pluginKey);
|
||||
}
|
||||
|
||||
boolean success;
|
||||
try {
|
||||
success = plugin.onCreate();
|
||||
} catch (Exception e) {
|
||||
success = false;
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/addPlugin", "Exception loading plugin " + pluginKey);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
//Log.e("addPlugin","added " + pluginKey);
|
||||
failedPlugins.remove(pluginKey);
|
||||
plugins.put(pluginKey, plugin);
|
||||
} else {
|
||||
Log.e("KDE/addPlugin", "plugin failed to load " + pluginKey);
|
||||
plugins.remove(pluginKey);
|
||||
failedPlugins.put(pluginKey, plugin);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
if (success) {
|
||||
//Log.e("addPlugin","added " + pluginKey);
|
||||
failedPlugins.remove(pluginKey);
|
||||
plugins.put(pluginKey, plugin);
|
||||
} else {
|
||||
Log.e("KDE/addPlugin", "plugin failed to load " + pluginKey);
|
||||
plugins.remove(pluginKey);
|
||||
failedPlugins.put(pluginKey, plugin);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private synchronized boolean removePlugin(String pluginKey) {
|
||||
@@ -738,22 +737,12 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
Log.e("KDE/removePlugin","Exception calling onDestroy for plugin "+pluginKey);
|
||||
}
|
||||
|
||||
for (PluginsChangedListener listener : pluginsChangedListeners) {
|
||||
listener.onPluginsChanged(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setPluginEnabled(String pluginKey, boolean value) {
|
||||
settings.edit().putBoolean(pluginKey,value).apply();
|
||||
if (value && isPaired() && isReachable()) addPlugin(pluginKey);
|
||||
else removePlugin(pluginKey);
|
||||
|
||||
for (PluginsChangedListener listener : pluginsChangedListeners) {
|
||||
listener.onPluginsChanged(Device.this);
|
||||
}
|
||||
|
||||
reloadPluginsFromSettings();
|
||||
}
|
||||
|
||||
public boolean isPluginEnabled(String pluginKey) {
|
||||
@@ -762,40 +751,55 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public boolean hasPluginsLoaded() {
|
||||
return !plugins.isEmpty() || !failedPlugins.isEmpty();
|
||||
}
|
||||
|
||||
public void reloadPluginsFromSettings() {
|
||||
|
||||
failedPlugins.clear();
|
||||
|
||||
Set<String> availablePlugins = PluginFactory.getAvailablePlugins();
|
||||
HashMap<String, ArrayList<String>> newPluginsByIncomingInterface = new HashMap<>();
|
||||
|
||||
for(String pluginKey : availablePlugins) {
|
||||
boolean enabled = false;
|
||||
boolean listenToUnpaired = PluginFactory.getPluginInfo(context, pluginKey).listenToUnpaired();
|
||||
for (String pluginKey : m_supportedPlugins) {
|
||||
|
||||
PluginFactory.PluginInfo pluginInfo = PluginFactory.getPluginInfo(context, pluginKey);
|
||||
|
||||
boolean pluginEnabled = false;
|
||||
boolean listenToUnpaired = pluginInfo.listenToUnpaired();
|
||||
if ((isPaired() || listenToUnpaired) && isReachable()) {
|
||||
enabled = isPluginEnabled(pluginKey);
|
||||
pluginEnabled = isPluginEnabled(pluginKey);
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
addPlugin(pluginKey);
|
||||
if (pluginEnabled) {
|
||||
boolean success = addPlugin(pluginKey);
|
||||
if (success) {
|
||||
for (String packageType : pluginInfo.getSupportedPackageTypes()) {
|
||||
packageType = hackToMakeRetrocompatiblePacketTypes(packageType);
|
||||
ArrayList<String> plugins = newPluginsByIncomingInterface.get(packageType);
|
||||
if (plugins == null) plugins = new ArrayList<>();
|
||||
plugins.add(pluginKey);
|
||||
newPluginsByIncomingInterface.put(packageType, plugins);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removePlugin(pluginKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pluginsByIncomingInterface = newPluginsByIncomingInterface;
|
||||
|
||||
onPluginsChanged();
|
||||
}
|
||||
|
||||
public void onPluginsChanged() {
|
||||
for (PluginsChangedListener listener : pluginsChangedListeners) {
|
||||
listener.onPluginsChanged(Device.this);
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<String,Plugin> getLoadedPlugins() {
|
||||
public ConcurrentHashMap<String,Plugin> getLoadedPlugins() {
|
||||
return plugins;
|
||||
}
|
||||
|
||||
public HashMap<String,Plugin> getFailedPlugins() {
|
||||
public ConcurrentHashMap<String,Plugin> getFailedPlugins() {
|
||||
return failedPlugins;
|
||||
}
|
||||
|
||||
@@ -813,13 +817,33 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
public BaseLink.ConnectionStarted getConnectionSource() {
|
||||
public boolean deviceShouldBeKeptAlive() {
|
||||
|
||||
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
|
||||
if (preferences.contains(getDeviceId())) {
|
||||
//Log.e("DeviceShouldBeKeptAlive", "because it's a paired device");
|
||||
return true; //Already paired
|
||||
}
|
||||
|
||||
for(BaseLink l : links) {
|
||||
if (l.getConnectionSource() == BaseLink.ConnectionStarted.Locally) {
|
||||
return BaseLink.ConnectionStarted.Locally;
|
||||
if (l.linkShouldBeKeptAlive()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return BaseLink.ConnectionStarted.Remotely;
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<String> getSupportedPlugins() {
|
||||
return m_supportedPlugins;
|
||||
}
|
||||
|
||||
public void hackToMakeRetrocompatiblePacketTypes(NetworkPackage np) {
|
||||
if (protocolVersion >= 6) return;
|
||||
np.mType = np.getType().replace(".request","");
|
||||
}
|
||||
public String hackToMakeRetrocompatiblePacketTypes(String type) {
|
||||
if (protocolVersion >= 6) return type;
|
||||
return type.replace(".request", "");
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -20,47 +20,96 @@
|
||||
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.ContactsContract.PhoneLookup;
|
||||
import android.util.Base64;
|
||||
import android.util.Base64OutputStream;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ContactsHelper {
|
||||
|
||||
public static String phoneNumberLookup(Context context, String number) {
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public static Map<String, String> phoneNumberLookup(Context context, String number) {
|
||||
|
||||
//Log.e("PhoneNumberLookup", number);
|
||||
|
||||
Map<String, String> contactInfo = new HashMap<>();
|
||||
|
||||
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = context.getContentResolver().query(
|
||||
uri,
|
||||
new String[] {
|
||||
PhoneLookup.DISPLAY_NAME
|
||||
PhoneLookup.DISPLAY_NAME,
|
||||
ContactsContract.PhoneLookup.PHOTO_URI
|
||||
/*, PhoneLookup.TYPE
|
||||
, PhoneLookup.LABEL
|
||||
, PhoneLookup.ID */
|
||||
},
|
||||
null, null, null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return number;
|
||||
return contactInfo;
|
||||
}
|
||||
|
||||
// Take the first match only
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
int nameIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
|
||||
if (nameIndex != -1) {
|
||||
String name = cursor.getString(nameIndex);
|
||||
//Log.e("PhoneNumberLookup", "success: " + name);
|
||||
cursor.close();
|
||||
return name + " (" + number + ")";
|
||||
contactInfo.put("name", cursor.getString(nameIndex));
|
||||
}
|
||||
|
||||
nameIndex = cursor.getColumnIndex(PhoneLookup.PHOTO_URI);
|
||||
if (nameIndex != -1) {
|
||||
contactInfo.put("photoID", cursor.getString(nameIndex));
|
||||
}
|
||||
|
||||
try { cursor.close(); } catch (Exception e) {}
|
||||
|
||||
if (!contactInfo.isEmpty()) {
|
||||
return contactInfo;
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor != null) cursor.close();
|
||||
return contactInfo;
|
||||
}
|
||||
|
||||
return number;
|
||||
public static String photoId64Encoded(Context context, String photoId) {
|
||||
if (photoId == null) {
|
||||
return "";
|
||||
}
|
||||
Uri photoUri = Uri.parse(photoId);
|
||||
|
||||
InputStream input = null;
|
||||
Base64OutputStream output= null;
|
||||
try {
|
||||
ByteArrayOutputStream encodedPhoto = new ByteArrayOutputStream();
|
||||
output = new Base64OutputStream(encodedPhoto, Base64.DEFAULT);
|
||||
input = context.getContentResolver().openInputStream(photoUri);
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = input.read(buffer)) != -1) {
|
||||
output.write(buffer, 0, len);
|
||||
}
|
||||
return encodedPhoto.toString();
|
||||
} catch (Exception ex) {
|
||||
Log.e("ContactsHelper", ex.toString());
|
||||
return "";
|
||||
} finally {
|
||||
try { input.close(); } catch(Exception ignored) { };
|
||||
try { output.close(); } catch(Exception ignored) { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -37,7 +37,7 @@ public class DeviceHelper {
|
||||
|
||||
//from https://github.com/meetup/android-device-names
|
||||
//Converted to java using:
|
||||
//cat android_models.properties | awk -F'=' '{sub(/ *$/, "", $1)} sub(/^ */, "", $2) { if ($2 != "") print "humanReadableNames.put(\""$1"\",\"" $2 "\");"}'
|
||||
//cat android_models.properties | awk -F'=' '{sub(/ *$/, "", $1)} sub(/^ */, "", $2) { if ($2 != "") print "humanReadableNames.put(\""$1"\",\"" $2 "\");"}' | sed -e 's/\\ /_/g'
|
||||
private final static HashMap<String,String> humanReadableNames = new HashMap<>();
|
||||
static {
|
||||
humanReadableNames.put("5860E","Coolpad Quattro 4G");
|
||||
@@ -55,6 +55,7 @@ public class DeviceHelper {
|
||||
humanReadableNames.put("ALCATEL_ONE_TOUCH_7041X","Alcatel One Touch Pop C7");
|
||||
humanReadableNames.put("ASUS_T00J","Asus ZenFone 5");
|
||||
humanReadableNames.put("ASUS_Transformer_Pad_TF300T","Asus Transformer Pad");
|
||||
humanReadableNames.put("ASUS_Transformer_Pad_TF700T","Asus Transformer Pad");
|
||||
humanReadableNames.put("Aquaris_E4.5","bq Aquaris E4.5");
|
||||
humanReadableNames.put("C1905","Sony Xperia M");
|
||||
humanReadableNames.put("C2105","Sony Xperia L");
|
||||
@@ -168,6 +169,7 @@ public class DeviceHelper {
|
||||
humanReadableNames.put("HTC_PH39100","HTC Vivid 4G");
|
||||
humanReadableNames.put("HTC_PN071","HTC One");
|
||||
humanReadableNames.put("HTC_Sensation_Z710e","HTC Sensation");
|
||||
humanReadableNames.put("HTC_Sensation_4G","HTC Sensation");
|
||||
humanReadableNames.put("HTC_VLE_U","HTC One S");
|
||||
humanReadableNames.put("HUAWEI_G510-0251","Huawei Ascend G510");
|
||||
humanReadableNames.put("HUAWEI_P6-U06","Huawei Ascend P6");
|
||||
@@ -236,9 +238,13 @@ public class DeviceHelper {
|
||||
humanReadableNames.put("MOTWX435KT","Motorola Triumph");
|
||||
humanReadableNames.put("N3","Star NO.1 N3");
|
||||
humanReadableNames.put("N860","ZTE Warp N860");
|
||||
humanReadableNames.put("NEXUS 4","Nexus 4");
|
||||
humanReadableNames.put("NEXUS 5","Nexus 5");
|
||||
humanReadableNames.put("NEXUS 6","Nexus 6");
|
||||
humanReadableNames.put("NEXUS_4","Nexus 4");
|
||||
humanReadableNames.put("NEXUS_5","Nexus 5");
|
||||
humanReadableNames.put("NEXUS_5X","Nexus 5X");
|
||||
humanReadableNames.put("LG-D820","Nexus 5");
|
||||
humanReadableNames.put("LG-D821","Nexus 5");
|
||||
humanReadableNames.put("NEXUS_6","Nexus 6");
|
||||
humanReadableNames.put("NEXUS_6P","Nexus 6P");
|
||||
humanReadableNames.put("Nexus_10","Google Nexus 10");
|
||||
humanReadableNames.put("Nexus_4","Google Nexus 4");
|
||||
humanReadableNames.put("Nexus_7","Asus Nexus 7");
|
||||
@@ -400,8 +406,8 @@ public class DeviceHelper {
|
||||
humanReadableNames.put("ST21i","Sony Xperia Tipo");
|
||||
humanReadableNames.put("ST25i","Sony Xperia U");
|
||||
humanReadableNames.put("ST26i","Sony Xperia J");
|
||||
humanReadableNames.put("Transformer_Prime_TF201","Asus Eee Pad Transformer Prime");
|
||||
humanReadableNames.put("Transformer_TF101","Asus Eee Pad Transformer");
|
||||
humanReadableNames.put("Transformer_Prime_TF201","Asus Transformer Prime");
|
||||
humanReadableNames.put("Transformer_TF101","Asus Transformer");
|
||||
humanReadableNames.put("VM670","LG Optimus V");
|
||||
humanReadableNames.put("VS840_4G","LG Lucid 4G");
|
||||
humanReadableNames.put("VS870_4G","LG Lucid 2");
|
||||
|
@@ -1,12 +0,0 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class NotificationsHelper {
|
||||
|
||||
private final static AtomicInteger c = new AtomicInteger((int)System.currentTimeMillis());
|
||||
public static int getUniqueId() {
|
||||
return c.incrementAndGet();
|
||||
}
|
||||
|
||||
}
|
7
src/org/kde/kdeconnect/Helpers/ObjectsHelper.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
public class ObjectsHelper {
|
||||
public static boolean equals(Object a, Object b) {
|
||||
return (a == null) ? (b == null) : a.equals(b);
|
||||
}
|
||||
}
|
22
src/org/kde/kdeconnect/Helpers/RandomHelper.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class RandomHelper {
|
||||
public static SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
private static final char[] symbols = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"+
|
||||
"abcdefghijklmnopqrstuvwxyz"+
|
||||
"1234567890").toCharArray();
|
||||
|
||||
|
||||
public static String randomString(int length) {
|
||||
char[] buffer= new char[length];
|
||||
for (int idx = 0; idx < length; ++idx) {
|
||||
buffer[idx] = symbols[secureRandom.nextInt(symbols.length)];
|
||||
}
|
||||
return new String(buffer);
|
||||
}
|
||||
|
||||
}
|
161
src/org/kde/kdeconnect/Helpers/SecurityHelpers/RsaHelper.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2015 Albert Vaca Cintora <albertvaka@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Helpers.SecurityHelpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class RsaHelper {
|
||||
|
||||
public static void initialiseRsaKeys(Context context) {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
if (!settings.contains("publicKey") || !settings.contains("privateKey")) {
|
||||
|
||||
KeyPair keyPair;
|
||||
try {
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||
keyGen.initialize(2048);
|
||||
keyPair = keyGen.genKeyPair();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/initializeRsaKeys", "Exception");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||
byte[] privateKey = keyPair.getPrivate().getEncoded();
|
||||
|
||||
SharedPreferences.Editor edit = settings.edit();
|
||||
edit.putString("publicKey", Base64.encodeToString(publicKey, 0).trim()+"\n");
|
||||
edit.putString("privateKey",Base64.encodeToString(privateKey, 0));
|
||||
edit.apply();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKey (Context context) throws Exception{
|
||||
try {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
byte[] publicKeyBytes = Base64.decode(settings.getString("publicKey", ""), 0);
|
||||
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
return publicKey;
|
||||
}catch (Exception e){
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKey(Context context, String deviceId) throws Exception{
|
||||
try {
|
||||
SharedPreferences settings = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
|
||||
byte[] publicKeyBytes = Base64.decode(settings.getString("publicKey", ""), 0);
|
||||
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
return publicKey;
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKey(Context context) throws Exception{
|
||||
|
||||
try {
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
byte[] privateKeyBytes = Base64.decode(globalSettings.getString("privateKey", ""), 0);
|
||||
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
|
||||
return privateKey;
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static NetworkPackage encrypt(NetworkPackage np, PublicKey publicKey) throws GeneralSecurityException, JSONException {
|
||||
|
||||
String serialized = np.serialize();
|
||||
|
||||
int chunkSize = 128;
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
|
||||
JSONArray chunks = new JSONArray();
|
||||
while (serialized.length() > 0) {
|
||||
if (serialized.length() < chunkSize) {
|
||||
chunkSize = serialized.length();
|
||||
}
|
||||
String chunk = serialized.substring(0, chunkSize);
|
||||
serialized = serialized.substring(chunkSize);
|
||||
byte[] chunkBytes = chunk.getBytes(Charset.defaultCharset());
|
||||
byte[] encryptedChunk;
|
||||
encryptedChunk = cipher.doFinal(chunkBytes);
|
||||
chunks.put(Base64.encodeToString(encryptedChunk, Base64.NO_WRAP));
|
||||
}
|
||||
|
||||
//Log.i("NetworkPackage", "Encrypted " + chunks.length()+" chunks");
|
||||
|
||||
NetworkPackage encrypted = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_ENCRYPTED);
|
||||
encrypted.set("data", chunks);
|
||||
encrypted.setPayload(np.getPayload(), np.getPayloadSize());
|
||||
return encrypted;
|
||||
|
||||
}
|
||||
|
||||
public static NetworkPackage decrypt(NetworkPackage np, PrivateKey privateKey) throws GeneralSecurityException, JSONException {
|
||||
|
||||
JSONArray chunks = np.getJSONArray("data");
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
|
||||
String decryptedJson = "";
|
||||
for (int i = 0; i < chunks.length(); i++) {
|
||||
byte[] encryptedChunk = Base64.decode(chunks.getString(i), Base64.NO_WRAP);
|
||||
String decryptedChunk = new String(cipher.doFinal(encryptedChunk));
|
||||
decryptedJson += decryptedChunk;
|
||||
}
|
||||
|
||||
NetworkPackage decrypted = NetworkPackage.unserialize(decryptedJson);
|
||||
decrypted.setPayload(np.getPayload(), np.getPayloadSize());
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
|
||||
}
|
256
src/org/kde/kdeconnect/Helpers/SecurityHelpers/SslHelper.java
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright 2015 Vineet Garg <grg.vineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Helpers.SecurityHelpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.kde.kdeconnect.Helpers.RandomHelper;
|
||||
import org.spongycastle.asn1.x500.X500NameBuilder;
|
||||
import org.spongycastle.asn1.x500.style.BCStyle;
|
||||
import org.spongycastle.cert.X509CertificateHolder;
|
||||
import org.spongycastle.cert.X509v3CertificateBuilder;
|
||||
import org.spongycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||
import org.spongycastle.cert.jcajce.JcaX509v3CertificateBuilder;
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.spongycastle.operator.ContentSigner;
|
||||
import org.spongycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyStore;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Formatter;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public class SslHelper {
|
||||
|
||||
public enum SslMode{
|
||||
Client,
|
||||
Server
|
||||
}
|
||||
|
||||
public static X509Certificate certificate; //my device's certificate
|
||||
|
||||
public static final BouncyCastleProvider BC = new BouncyCastleProvider();
|
||||
|
||||
public static void initialiseCertificate(Context context){
|
||||
PrivateKey privateKey;
|
||||
PublicKey publicKey;
|
||||
|
||||
try {
|
||||
privateKey = RsaHelper.getPrivateKey(context);
|
||||
publicKey = RsaHelper.getPublicKey(context);
|
||||
}catch (Exception e){
|
||||
Log.e("SslHelper", "Error getting keys, can't create certificate");
|
||||
return;
|
||||
}
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (!settings.contains("certificate")) {
|
||||
try {
|
||||
|
||||
X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
|
||||
nameBuilder.addRDN(BCStyle.CN, DeviceHelper.getDeviceId(context));
|
||||
nameBuilder.addRDN(BCStyle.OU, "KDE Connect");
|
||||
nameBuilder.addRDN(BCStyle.O, "KDE");
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.YEAR, -1);
|
||||
Date notBefore = calendar.getTime();
|
||||
calendar.add(Calendar.YEAR, 10);
|
||||
Date notAfter = calendar.getTime();
|
||||
X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(
|
||||
nameBuilder.build(),
|
||||
BigInteger.ONE,
|
||||
notBefore,
|
||||
notAfter,
|
||||
nameBuilder.build(),
|
||||
publicKey
|
||||
);
|
||||
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(BC).build(privateKey);
|
||||
certificate = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateBuilder.build(contentSigner));
|
||||
|
||||
SharedPreferences.Editor edit = settings.edit();
|
||||
edit.putString("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
|
||||
edit.apply();
|
||||
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("KDE/initialiseCert", "Exception");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
byte[] certificateBytes = Base64.decode(globalSettings.getString("certificate", ""), 0);
|
||||
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
|
||||
certificate = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/SslHelper", "Exception reading own certificate");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SSLContext getSslContext(Context context, String deviceId, boolean isDeviceTrusted) {
|
||||
//TODO: Cache
|
||||
try {
|
||||
// Get device private key
|
||||
PrivateKey privateKey = RsaHelper.getPrivateKey(context);
|
||||
|
||||
// Get remote device certificate if trusted
|
||||
X509Certificate remoteDeviceCertificate = null;
|
||||
if (isDeviceTrusted){
|
||||
SharedPreferences devicePreferences = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
|
||||
byte[] certificateBytes = Base64.decode(devicePreferences.getString("certificate", ""), 0);
|
||||
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
|
||||
remoteDeviceCertificate = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
|
||||
}
|
||||
|
||||
// Setup keystore
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(null, null);
|
||||
keyStore.setKeyEntry("key", privateKey, "".toCharArray(), new Certificate[]{certificate});
|
||||
// Set certificate if device trusted
|
||||
if (remoteDeviceCertificate != null){
|
||||
keyStore.setCertificateEntry(deviceId, remoteDeviceCertificate);
|
||||
}
|
||||
|
||||
// Setup key manager factory
|
||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
keyManagerFactory.init(keyStore, "".toCharArray());
|
||||
|
||||
|
||||
// Setup default trust manager
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init(keyStore);
|
||||
|
||||
// Setup custom trust manager if device not trusted
|
||||
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
SSLContext tlsContext = SSLContext.getInstance("TLSv1"); //Newer TLS versions are only supported on API 16+
|
||||
if (isDeviceTrusted) {
|
||||
tlsContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), RandomHelper.secureRandom);
|
||||
}else {
|
||||
tlsContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, RandomHelper.secureRandom);
|
||||
}
|
||||
return tlsContext;
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/SslHelper", "Error creating tls context");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public static void configureSslSocket(SSLSocket socket, boolean isDeviceTrusted, boolean isClient) {
|
||||
|
||||
socket.setEnabledProtocols(new String[]{ "TLSv1" }); //Newer TLS versions are only supported on API 16+
|
||||
|
||||
// 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");
|
||||
} 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");
|
||||
}
|
||||
socket.setEnabledCipherSuites(supportedCiphers.toArray(new String[supportedCiphers.size()]));
|
||||
|
||||
if (isClient){
|
||||
socket.setUseClientMode(true);
|
||||
}else{
|
||||
socket.setUseClientMode(false);
|
||||
if (isDeviceTrusted) {
|
||||
socket.setNeedClientAuth(true);
|
||||
} else {
|
||||
socket.setWantClientAuth(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static SSLSocket convertToSslSocket(Context context, Socket socket, String deviceId, boolean isDeviceTrusted, boolean clientMode) throws IOException {
|
||||
SSLSocketFactory sslsocketFactory = SslHelper.getSslContext(context, deviceId, isDeviceTrusted).getSocketFactory();
|
||||
SSLSocket sslsocket = (SSLSocket)sslsocketFactory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true);
|
||||
SslHelper.configureSslSocket(sslsocket, isDeviceTrusted, clientMode);
|
||||
return sslsocket;
|
||||
}
|
||||
|
||||
public static String getCertificateHash(Certificate certificate) {
|
||||
try {
|
||||
byte[] hash = MessageDigest.getInstance("SHA-1").digest(certificate.getEncoded());
|
||||
Formatter formatter = new Formatter();
|
||||
int i;
|
||||
for (i = 0; i < hash.length-1; i++) {
|
||||
formatter.format("%02x:", hash[i]);
|
||||
}
|
||||
formatter.format("%02x", hash[i]);
|
||||
return formatter.toString();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Certificate parseCertificate(byte[] certificateBytes) throws IOException, CertificateException {
|
||||
X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
|
||||
return new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateHolder);
|
||||
}
|
||||
|
||||
}
|
9
src/org/kde/kdeconnect/Helpers/StringsHelper.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class StringsHelper {
|
||||
|
||||
public static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
}
|
@@ -21,47 +21,37 @@
|
||||
package org.kde.kdeconnect;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.kde.kdeconnect.Plugins.PluginFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class NetworkPackage {
|
||||
|
||||
public final static int ProtocolVersion = 5;
|
||||
public final static int ProtocolVersion = 7;
|
||||
|
||||
//TODO: Move these to their respective plugins
|
||||
public final static String PACKAGE_TYPE_IDENTITY = "kdeconnect.identity";
|
||||
public final static String PACKAGE_TYPE_PAIR = "kdeconnect.pair";
|
||||
public final static String PACKAGE_TYPE_ENCRYPTED = "kdeconnect.encrypted";
|
||||
public final static String PACKAGE_TYPE_PING = "kdeconnect.ping";
|
||||
public final static String PACKAGE_TYPE_TELEPHONY = "kdeconnect.telephony";
|
||||
public final static String PACKAGE_TYPE_BATTERY = "kdeconnect.battery";
|
||||
public final static String PACKAGE_TYPE_SFTP = "kdeconnect.sftp";
|
||||
public final static String PACKAGE_TYPE_NOTIFICATION = "kdeconnect.notification";
|
||||
public final static String PACKAGE_TYPE_CLIPBOARD = "kdeconnect.clipboard";
|
||||
public final static String PACKAGE_TYPE_MPRIS = "kdeconnect.mpris";
|
||||
public final static String PACKAGE_TYPE_MOUSEPAD = "kdeconnect.mousepad";
|
||||
public final static String PACKAGE_TYPE_SHARE = "kdeconnect.share";
|
||||
|
||||
public static Set<String> protocolPackageTypes = new HashSet<String>() {{
|
||||
add(PACKAGE_TYPE_IDENTITY);
|
||||
add(PACKAGE_TYPE_PAIR);
|
||||
add(PACKAGE_TYPE_ENCRYPTED);
|
||||
}};
|
||||
|
||||
private long mId;
|
||||
private String mType;
|
||||
String mType;
|
||||
private JSONObject mBody;
|
||||
private InputStream mPayload;
|
||||
private JSONObject mPayloadTransferInfo;
|
||||
@@ -106,143 +96,92 @@ public class NetworkPackage {
|
||||
public JSONArray getJSONArray(String key) { return mBody.optJSONArray(key); }
|
||||
public void set(String key, JSONArray value) { try { mBody.put(key,value); } catch(Exception e) { } }
|
||||
|
||||
public ArrayList<String> getStringList(String key) {
|
||||
public Set<String> getStringSet(String key) {
|
||||
JSONArray jsonArray = mBody.optJSONArray(key);
|
||||
if (jsonArray == null) return null;
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
Set<String> list = new HashSet<>();
|
||||
int length = jsonArray.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
try {
|
||||
String str = jsonArray.getString(i);
|
||||
list.add(str);
|
||||
} catch(Exception e) {
|
||||
|
||||
}
|
||||
} catch(Exception e) { }
|
||||
}
|
||||
return list;
|
||||
}
|
||||
public ArrayList<String> getStringList(String key, ArrayList<String> defaultValue) {
|
||||
if (mBody.has(key)) return getStringList(key);
|
||||
public Set<String> getStringSet(String key, Set<String> defaultValue) {
|
||||
if (mBody.has(key)) return getStringSet(key);
|
||||
else return defaultValue;
|
||||
}
|
||||
public void set(String key, ArrayList<String> value) {
|
||||
public void set(String key, Set<String> value) {
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for(String str : value) {
|
||||
jsonArray.put(str);
|
||||
}
|
||||
mBody.put(key,jsonArray);
|
||||
} catch(Exception e) {
|
||||
} catch(Exception e) { }
|
||||
}
|
||||
|
||||
public List<String> getStringList(String key) {
|
||||
JSONArray jsonArray = mBody.optJSONArray(key);
|
||||
if (jsonArray == null) return null;
|
||||
List<String> list = new ArrayList<>();
|
||||
int length = jsonArray.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
try {
|
||||
String str = jsonArray.getString(i);
|
||||
list.add(str);
|
||||
} catch(Exception e) { }
|
||||
}
|
||||
return list;
|
||||
}
|
||||
public List<String> getStringList(String key, List<String> defaultValue) {
|
||||
if (mBody.has(key)) return getStringList(key);
|
||||
else return defaultValue;
|
||||
}
|
||||
public void set(String key, List<String> value) {
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for(String str : value) {
|
||||
jsonArray.put(str);
|
||||
}
|
||||
mBody.put(key,jsonArray);
|
||||
} catch(Exception e) { }
|
||||
}
|
||||
public boolean has(String key) { return mBody.has(key); }
|
||||
|
||||
public boolean isEncrypted() { return mType.equals(PACKAGE_TYPE_ENCRYPTED); }
|
||||
|
||||
public String serialize() {
|
||||
public String serialize() throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
try {
|
||||
jo.put("id", mId);
|
||||
jo.put("type", mType);
|
||||
jo.put("body", mBody);
|
||||
if (hasPayload()) {
|
||||
jo.put("payloadSize", mPayloadSize);
|
||||
jo.put("payloadTransferInfo", mPayloadTransferInfo);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("NetworkPackage", "Serialization exception");
|
||||
jo.put("id", mId);
|
||||
jo.put("type", mType);
|
||||
jo.put("body", mBody);
|
||||
if (hasPayload()) {
|
||||
jo.put("payloadSize", mPayloadSize);
|
||||
jo.put("payloadTransferInfo", mPayloadTransferInfo);
|
||||
}
|
||||
|
||||
//QJSon does not escape slashes, but Java JSONObject does. Converting to QJson format.
|
||||
String json = jo.toString().replace("\\/","/")+"\n";
|
||||
|
||||
if (!isEncrypted()) {
|
||||
//Log.e("NetworkPackage.serialize", json);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
static public NetworkPackage unserialize(String s) {
|
||||
static public NetworkPackage unserialize(String s) throws JSONException {
|
||||
|
||||
NetworkPackage np = new NetworkPackage();
|
||||
try {
|
||||
JSONObject jo = new JSONObject(s);
|
||||
np.mId = jo.getLong("id");
|
||||
np.mType = jo.getString("type");
|
||||
np.mBody = jo.getJSONObject("body");
|
||||
if (jo.has("payloadSize")) {
|
||||
np.mPayloadTransferInfo = jo.getJSONObject("payloadTransferInfo");
|
||||
np.mPayloadSize = jo.getLong("payloadSize");
|
||||
} else {
|
||||
np.mPayloadTransferInfo = new JSONObject();
|
||||
np.mPayloadSize = 0;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("NetworkPackage", "Unserialization exception unserializing "+s);
|
||||
return null;
|
||||
JSONObject jo = new JSONObject(s);
|
||||
np.mId = jo.getLong("id");
|
||||
np.mType = jo.getString("type");
|
||||
np.mBody = jo.getJSONObject("body");
|
||||
if (jo.has("payloadSize")) {
|
||||
np.mPayloadTransferInfo = jo.getJSONObject("payloadTransferInfo");
|
||||
np.mPayloadSize = jo.getLong("payloadSize");
|
||||
} else {
|
||||
np.mPayloadTransferInfo = new JSONObject();
|
||||
np.mPayloadSize = 0;
|
||||
}
|
||||
|
||||
if (!np.isEncrypted()) {
|
||||
//Log.e("NetworkPackage.unserialize", s);
|
||||
}
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
public NetworkPackage encrypt(PublicKey publicKey) throws GeneralSecurityException {
|
||||
|
||||
String serialized = serialize();
|
||||
|
||||
int chunkSize = 128;
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
|
||||
JSONArray chunks = new JSONArray();
|
||||
while (serialized.length() > 0) {
|
||||
if (serialized.length() < chunkSize) {
|
||||
chunkSize = serialized.length();
|
||||
}
|
||||
String chunk = serialized.substring(0, chunkSize);
|
||||
serialized = serialized.substring(chunkSize);
|
||||
byte[] chunkBytes = chunk.getBytes(Charset.defaultCharset());
|
||||
byte[] encryptedChunk;
|
||||
encryptedChunk = cipher.doFinal(chunkBytes);
|
||||
chunks.put(Base64.encodeToString(encryptedChunk, Base64.NO_WRAP));
|
||||
}
|
||||
|
||||
//Log.i("NetworkPackage", "Encrypted " + chunks.length()+" chunks");
|
||||
|
||||
NetworkPackage encrypted = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_ENCRYPTED);
|
||||
encrypted.set("data", chunks);
|
||||
encrypted.setPayload(mPayload, mPayloadSize);
|
||||
return encrypted;
|
||||
|
||||
}
|
||||
|
||||
public NetworkPackage decrypt(PrivateKey privateKey) throws GeneralSecurityException, JSONException {
|
||||
|
||||
JSONArray chunks = mBody.getJSONArray("data");
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
|
||||
String decryptedJson = "";
|
||||
for (int i = 0; i < chunks.length(); i++) {
|
||||
byte[] encryptedChunk = Base64.decode(chunks.getString(i), Base64.NO_WRAP);
|
||||
String decryptedChunk = new String(cipher.doFinal(encryptedChunk));
|
||||
decryptedJson += decryptedChunk;
|
||||
}
|
||||
|
||||
NetworkPackage decrypted = unserialize(decryptedJson);
|
||||
decrypted.setPayload(mPayload, mPayloadSize);
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
static public NetworkPackage createIdentityPackage(Context context) {
|
||||
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_IDENTITY);
|
||||
@@ -253,6 +192,8 @@ public class NetworkPackage {
|
||||
np.mBody.put("deviceName", DeviceHelper.getDeviceName(context));
|
||||
np.mBody.put("protocolVersion", NetworkPackage.ProtocolVersion);
|
||||
np.mBody.put("deviceType", DeviceHelper.isTablet()? "tablet" : "phone");
|
||||
np.mBody.put("incomingCapabilities", new JSONArray(PluginFactory.getIncomingCapabilities(context)));
|
||||
np.mBody.put("outgoingCapabilities", new JSONArray(PluginFactory.getOutgoingCapabilities(context)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("NetworkPacakge","Exception on createIdentityPackage");
|
||||
@@ -262,21 +203,6 @@ public class NetworkPackage {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static public NetworkPackage createPublicKeyPackage(Context context) {
|
||||
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
|
||||
np.set("pair", true);
|
||||
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String publicKey = "-----BEGIN PUBLIC KEY-----\n" + globalSettings.getString("publicKey", "").trim()+ "\n-----END PUBLIC KEY-----\n";
|
||||
np.set("publicKey", publicKey);
|
||||
|
||||
return np;
|
||||
|
||||
}
|
||||
|
||||
public void setPayload(byte[] data) {
|
||||
setPayload(new ByteArrayInputStream(data), data.length);
|
||||
}
|
||||
|
@@ -33,6 +33,9 @@ import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class BatteryPlugin extends Plugin {
|
||||
|
||||
public final static String PACKAGE_TYPE_BATTERY = "kdeconnect.battery";
|
||||
public final static String PACKAGE_TYPE_BATTERY_REQUEST = "kdeconnect.battery.request";
|
||||
|
||||
// keep these fields in sync with kdeconnect-kded:BatteryPlugin.h:ThresholdBatteryEvent
|
||||
private static final int THRESHOLD_EVENT_NONE= 0;
|
||||
private static final int THRESHOLD_EVENT_BATTERY_LOW = 1;
|
||||
@@ -72,7 +75,7 @@ public class BatteryPlugin extends Plugin {
|
||||
|
||||
} else {
|
||||
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_BATTERY);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_BATTERY);
|
||||
np.set("currentCharge", currentCharge);
|
||||
np.set("isCharging", isCharging);
|
||||
np.set("thresholdEvent", thresholdEvent);
|
||||
@@ -99,7 +102,6 @@ public class BatteryPlugin extends Plugin {
|
||||
|
||||
@Override
|
||||
public boolean onPackageReceived(NetworkPackage np) {
|
||||
if (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_BATTERY)) return false;
|
||||
|
||||
if (np.getBoolean("request")) {
|
||||
if (lastInfo != null) {
|
||||
@@ -110,4 +112,16 @@ public class BatteryPlugin extends Plugin {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
String[] packetTypes = {PACKAGE_TYPE_BATTERY_REQUEST};
|
||||
return packetTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getOutgoingPackageTypes() {
|
||||
String[] packetTypes = {PACKAGE_TYPE_BATTERY};
|
||||
return packetTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -20,13 +20,18 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins.ClibpoardPlugin;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public class ClipboardListener {
|
||||
|
||||
|
||||
@@ -42,28 +47,33 @@ public class ClipboardListener {
|
||||
return;
|
||||
}
|
||||
|
||||
cm = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
listener = new ClipboardManager.OnPrimaryClipChangedListener() {
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void onPrimaryClipChanged() {
|
||||
try {
|
||||
public void run() {
|
||||
cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
listener = new ClipboardManager.OnPrimaryClipChangedListener() {
|
||||
@Override
|
||||
public void onPrimaryClipChanged() {
|
||||
try {
|
||||
|
||||
ClipData.Item item = cm.getPrimaryClip().getItemAt(0);
|
||||
String content = item.coerceToText(context).toString();
|
||||
ClipData.Item item = cm.getPrimaryClip().getItemAt(0);
|
||||
String content = item.coerceToText(context).toString();
|
||||
|
||||
if (!content.equals(currentContent)) {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_CLIPBOARD);
|
||||
np.set("content", content);
|
||||
device.sendPackage(np);
|
||||
currentContent = content;
|
||||
if (!content.equals(currentContent)) {
|
||||
NetworkPackage np = new NetworkPackage(ClipboardPlugin.PACKAGE_TYPE_CLIPBOARD);
|
||||
np.set("content", content);
|
||||
device.sendPackage(np);
|
||||
currentContent = content;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
//Probably clipboard was not text
|
||||
}
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
//Probably clipboard was not text
|
||||
}
|
||||
};
|
||||
cm.addPrimaryClipChangedListener(listener);
|
||||
}
|
||||
};
|
||||
cm.addPrimaryClipChangedListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
|
@@ -20,18 +20,14 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins.ClibpoardPlugin;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class ClipboardPlugin extends Plugin {
|
||||
|
||||
public final static String PACKAGE_TYPE_CLIPBOARD = "kdeconnect.clipboard";
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return context.getResources().getString(R.string.pref_plugin_clipboard);
|
||||
@@ -63,13 +59,23 @@ public class ClipboardPlugin extends Plugin {
|
||||
|
||||
@Override
|
||||
public boolean onPackageReceived(NetworkPackage np) {
|
||||
if (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_CLIPBOARD)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String content = np.getString("content");
|
||||
listener.setText(content);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
String[] packetTypes = {PACKAGE_TYPE_CLIPBOARD};
|
||||
return packetTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getOutgoingPackageTypes() {
|
||||
String[] packetTypes = {PACKAGE_TYPE_CLIPBOARD};
|
||||
return packetTypes;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,55 @@
|
||||
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
|
||||
|
||||
import android.app.Activity;
|
||||
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.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class FindMyPhoneActivity extends Activity {
|
||||
Ringtone ringtone;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_find_my_phone);
|
||||
|
||||
Window window = this.getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
|
||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||
|
||||
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= 21) {
|
||||
AudioAttributes.Builder b = new AudioAttributes.Builder();
|
||||
b.setUsage(AudioAttributes.USAGE_ALARM);
|
||||
ringtone.setAudioAttributes(b.build());
|
||||
} else {
|
||||
ringtone.setStreamType(AudioManager.STREAM_ALARM);
|
||||
}
|
||||
|
||||
ringtone.play();
|
||||
|
||||
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
ringtone.stop();
|
||||
super.finish();
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
|
||||
/**
|
||||
* Created by vineet on 1/11/14.
|
||||
* and David Edmundson 2015
|
||||
*/
|
||||
public class FindMyPhonePlugin extends Plugin {
|
||||
|
||||
public final static String PACKAGE_TYPE_FINDMYPHONE = "kdeconnect.findmyphone";
|
||||
public final static String PACKAGE_TYPE_FINDMYPHONE_REQUEST = "kdeconnect.findmyphone.request";
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return DeviceHelper.isTablet() ? context.getString(R.string.findmyphone_title_tablet) : context.getString(R.string.findmyphone_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return context.getString(R.string.findmyphone_description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPackageReceived(NetworkPackage np) {
|
||||
|
||||
Intent intent = new Intent(context,FindMyPhoneActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
return new String[]{PACKAGE_TYPE_FINDMYPHONE_REQUEST};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getOutgoingPackageTypes() {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
@@ -1,10 +1,6 @@
|
||||
package org.kde.kdeconnect.Plugins.MousePadPlugin;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.view.inputmethod.CorrectionInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
public class KeyInputConnection extends BaseInputConnection {
|
||||
private KeyListenerView view;
|
||||
|
@@ -101,7 +101,7 @@ public class KeyListenerView extends View {
|
||||
}
|
||||
|
||||
public void sendChars(CharSequence chars) {
|
||||
final NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
final NetworkPackage np = new NetworkPackage(MousePadPlugin.PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("key", chars.toString());
|
||||
sendKeyPressPackage(np);
|
||||
}
|
||||
@@ -121,16 +121,21 @@ public class KeyListenerView extends View {
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
|
||||
/* NOTE: Some keyboards, and specifically the Android default keyboard when
|
||||
* entering non-ascii characters, will not trigger KeyEvent events as documented
|
||||
* here: http://developer.android.com/reference/android/view/KeyEvent.html
|
||||
*/
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
//We don't want to swallow the back button press
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: Most keyboards, and specifically the Android default keyboard when
|
||||
// entering non-ascii characters, will not trigger KeyEvent events as documented
|
||||
// here: http://developer.android.com/reference/android/view/KeyEvent.html
|
||||
|
||||
//Log.e("KeyDown", "------------");
|
||||
//Log.e("KeyDown", "keyChar:" + (int) event.getDisplayLabel());
|
||||
//Log.e("KeyDown", "utfChar:" + (char)event.getUnicodeChar());
|
||||
//Log.e("KeyDown", "intUtfChar:" + event.getUnicodeChar());
|
||||
|
||||
final NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
final NetworkPackage np = new NetworkPackage(MousePadPlugin.PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
|
||||
boolean modifier = false;
|
||||
if (event.isAltPressed()) {
|
||||
@@ -159,10 +164,13 @@ public class KeyListenerView extends View {
|
||||
char keyCharacter = event.getDisplayLabel();
|
||||
np.set("key", new String(new char[]{keyCharacter}).toLowerCase());
|
||||
} else {
|
||||
return false; //normal keys will be handled by KeyInputConnection
|
||||
//A normal key, but still not handled by the KeyInputConnection (happens with numbers)
|
||||
np.set("key", new String(new char[]{(char)event.getUnicodeChar()}));
|
||||
}
|
||||
|
||||
sendKeyPressPackage(np);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,27 +28,29 @@ import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class MousePadActivity extends ActionBarActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MousePadGestureDetector.OnGestureListener {
|
||||
|
||||
String deviceId;
|
||||
|
||||
private final static float MinDistanceToSendScroll = 2.5f;
|
||||
private final static float MinDistanceToSendScroll = 2.5f; // touch gesture scroll
|
||||
private final static float MinDistanceToSendGenericScroll = 0.1f; // real mouse scroll wheel event
|
||||
|
||||
private float mPrevX;
|
||||
private float mPrevY;
|
||||
private float mCurrentX;
|
||||
private float mCurrentY;
|
||||
private float mCurrentSensitivity;
|
||||
private int scrollDirection = 1;
|
||||
|
||||
boolean isScrolling = false;
|
||||
float accumulatedDistanceY = 0;
|
||||
@@ -89,14 +91,42 @@ public class MousePadActivity extends ActionBarActivity implements GestureDetect
|
||||
keyListenerView.setDeviceId(deviceId);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
if (prefs.getBoolean(getString(R.string.mousepad_scroll_direction),false)) {
|
||||
scrollDirection = -1;
|
||||
} else {
|
||||
scrollDirection = 1;
|
||||
}
|
||||
String doubleTapSetting = prefs.getString(getString(R.string.mousepad_double_tap_key),
|
||||
getString(R.string.mousepad_double_default));
|
||||
String tripleTapSetting = prefs.getString(getString(R.string.mousepad_triple_tap_key),
|
||||
getString(R.string.mousepad_triple_default));
|
||||
String sensitivitySetting = prefs.getString(getString(R.string.mousepad_sensitivity_key),
|
||||
getString(R.string.mousepad_sensitivity_default));
|
||||
|
||||
doubleTapAction = ClickType.fromString(doubleTapSetting);
|
||||
tripleTapAction = ClickType.fromString(tripleTapSetting);
|
||||
|
||||
switch (sensitivitySetting){
|
||||
case "slowest":
|
||||
mCurrentSensitivity = 0.2f;
|
||||
break;
|
||||
case "aboveSlowest":
|
||||
mCurrentSensitivity = 0.5f;
|
||||
break;
|
||||
case "default":
|
||||
mCurrentSensitivity = 1.0f;
|
||||
break;
|
||||
case "aboveDefault":
|
||||
mCurrentSensitivity = 1.5f;
|
||||
break;
|
||||
case "fastest":
|
||||
mCurrentSensitivity = 2.0f;
|
||||
break;
|
||||
default:
|
||||
mCurrentSensitivity = 1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
final View decorView = getWindow().getDecorView();
|
||||
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
|
||||
@@ -184,7 +214,7 @@ public class MousePadActivity extends ActionBarActivity implements GestureDetect
|
||||
Device device = service.getDevice(deviceId);
|
||||
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
|
||||
if (mousePadPlugin == null) return;
|
||||
mousePadPlugin.sendMouseDelta(mCurrentX - mPrevX, mCurrentY - mPrevY);
|
||||
mousePadPlugin.sendMouseDelta(mCurrentX - mPrevX, mCurrentY - mPrevY, mCurrentSensitivity);
|
||||
mPrevX = mCurrentX;
|
||||
mPrevY = mCurrentY;
|
||||
}
|
||||
@@ -209,6 +239,25 @@ public class MousePadActivity extends ActionBarActivity implements GestureDetect
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onGenericMotionEvent(MotionEvent e)
|
||||
{
|
||||
if (android.os.Build.VERSION.SDK_INT >= 12) { // MotionEvent.getAxisValue is >= 12
|
||||
if (e.getAction() == MotionEvent.ACTION_SCROLL) {
|
||||
final float distanceY = e.getAxisValue(MotionEvent.AXIS_VSCROLL);
|
||||
|
||||
accumulatedDistanceY += distanceY;
|
||||
|
||||
if (accumulatedDistanceY > MinDistanceToSendGenericScroll || accumulatedDistanceY < -MinDistanceToSendGenericScroll) {
|
||||
sendScroll(accumulatedDistanceY);
|
||||
accumulatedDistanceY = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onGenericMotionEvent(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, final float distanceX, final float distanceY) {
|
||||
// If only one thumb is used then cancel the scroll gesture
|
||||
@@ -221,17 +270,7 @@ public class MousePadActivity extends ActionBarActivity implements GestureDetect
|
||||
accumulatedDistanceY += distanceY;
|
||||
if (accumulatedDistanceY > MinDistanceToSendScroll || accumulatedDistanceY < -MinDistanceToSendScroll)
|
||||
{
|
||||
final float scrollToSendY = accumulatedDistanceY;
|
||||
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
|
||||
if (mousePadPlugin == null) return;
|
||||
mousePadPlugin.sendScroll(0, scrollToSendY);
|
||||
}
|
||||
});
|
||||
sendScroll(scrollDirection * accumulatedDistanceY);
|
||||
|
||||
accumulatedDistanceY = 0;
|
||||
}
|
||||
@@ -345,17 +384,30 @@ public class MousePadActivity extends ActionBarActivity implements GestureDetect
|
||||
}
|
||||
});
|
||||
}
|
||||
private void sendSingleHold() {
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
|
||||
if (mousePadPlugin == null) return;
|
||||
mousePadPlugin.sendSingleHold();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendSingleHold() {
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
|
||||
if (mousePadPlugin == null) return;
|
||||
mousePadPlugin.sendSingleHold();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendScroll(final float y) {
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
|
||||
if (mousePadPlugin == null) return;
|
||||
mousePadPlugin.sendScroll(0, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showKeyboard() {
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
@@ -31,6 +31,9 @@ import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class MousePadPlugin extends Plugin {
|
||||
|
||||
//public final static String PACKAGE_TYPE_MOUSEPAD = "kdeconnect.mousepad";
|
||||
public final static String PACKAGE_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return context.getString(R.string.pref_plugin_mousepad);
|
||||
@@ -63,50 +66,66 @@ public class MousePadPlugin extends Plugin {
|
||||
parentActivity.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getOutgoingPackageTypes() {
|
||||
return new String[]{PACKAGE_TYPE_MOUSEPAD_REQUEST};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return context.getString(R.string.open_mousepad);
|
||||
}
|
||||
|
||||
public void sendMouseDelta(float dx, float dy) {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
np.set("dx", dx);
|
||||
np.set("dy", dy);
|
||||
public void sendMouseDelta(float dx, float dy, float sensitivity) {
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
|
||||
if (sensitivity <= 0.0001f) {
|
||||
sensitivity = 1.0f;
|
||||
}
|
||||
|
||||
np.set("dx", dx*sensitivity);
|
||||
np.set("dy", dy*sensitivity);
|
||||
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
public void sendSingleClick() {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("singleclick", true);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
public void sendDoubleClick() {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("doubleclick", true);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
public void sendMiddleClick() {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("middleclick", true);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
public void sendRightClick() {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("rightclick", true);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
public void sendSingleHold(){
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("singlehold", true);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
public void sendScroll(float dx, float dy) {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_MOUSEPAD);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("scroll", true);
|
||||
np.set("dx", dx);
|
||||
np.set("dy", dy);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
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;
|
||||
@@ -33,18 +34,19 @@ 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;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MprisActivity extends ActionBarActivity {
|
||||
|
||||
@@ -89,9 +91,20 @@ public class MprisActivity extends ActionBarActivity {
|
||||
@Override
|
||||
public void run() {
|
||||
String song = mpris.getCurrentSong();
|
||||
((TextView) findViewById(R.id.now_playing_textview)).setText(song);
|
||||
|
||||
if (mpris.getLength() > -1 && mpris.getPosition() > -1 && !"Spotify".equals(mpris.getPlayer())) {
|
||||
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()));
|
||||
|
||||
SeekBar positionSeek = (SeekBar)findViewById(R.id.positionSeek);
|
||||
@@ -120,7 +133,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
mpris.setPlayerListUpdatedHandler("activity", new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
final ArrayList<String> playerList = mpris.getPlayerList();
|
||||
final List<String> playerList = mpris.getPlayerList();
|
||||
final ArrayAdapter<String> adapter = new ArrayAdapter<>(MprisActivity.this,
|
||||
android.R.layout.simple_spinner_item,
|
||||
playerList.toArray(new String[playerList.size()])
|
||||
@@ -154,7 +167,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
mpris.setPlayer(player);
|
||||
//Spotify doesn't support changing the volume yet...
|
||||
//Also doesn't support seeking and telling actual position...
|
||||
if (player.equals("Spotify")) {
|
||||
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);
|
||||
@@ -410,10 +423,13 @@ public class MprisActivity extends ActionBarActivity {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris != null) {
|
||||
positionSeek.setProgress((int) (mpris.getPosition()));
|
||||
if (device != null) {
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris != null) {
|
||||
positionSeek.setProgress((int) (mpris.getPosition()));
|
||||
}
|
||||
}
|
||||
positionSeekUpdateHandler.removeCallbacks(positionSeekUpdateRunnable);
|
||||
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 1000);
|
||||
}
|
||||
});
|
||||
@@ -450,6 +466,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
|
||||
});
|
||||
|
||||
findViewById(R.id.now_playing_textview).setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|