mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-09-01 22:55:10 +00:00
Compare commits
196 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7dd4583a24 | ||
|
c05f13afac | ||
|
de7d944230 | ||
|
b1daf1af0c | ||
|
baeec6afbf | ||
|
2187b273b9 | ||
|
1fa0585100 | ||
|
4e2460bf37 | ||
|
5e3e32d289 | ||
|
167f86affa | ||
|
53dfb299a7 | ||
|
c4e6c66809 | ||
|
1703276f37 | ||
|
91ade6a846 | ||
|
1b62a5ae32 | ||
|
4b21d67da0 | ||
|
5c3fcb1423 | ||
|
79a58e12a1 | ||
|
92300a7d63 | ||
|
e94959f9c3 | ||
|
45bac893d9 | ||
|
fdaa632a39 | ||
|
22696f7c97 | ||
|
7155042da0 | ||
|
d218a10004 | ||
|
c9ca1f4906 | ||
|
ea9a5459fd | ||
|
9eda5bf072 | ||
|
8052994232 | ||
|
8e2757ecf3 | ||
|
52f2067e55 | ||
|
56fc69b3de | ||
|
8538121ed2 | ||
|
c6746e38a0 | ||
|
90f03555c5 | ||
|
e9be9b9c87 | ||
|
ee854bf7ad | ||
|
71106a3de3 | ||
|
0a841b8064 | ||
|
147d8510d5 | ||
|
044261ceb1 | ||
|
cc8330a079 | ||
|
221c6b4fd7 | ||
|
a1c6921696 | ||
|
656268c42e | ||
|
3e229afea2 | ||
|
6c54a3d720 | ||
|
66a120d978 | ||
|
082543f749 | ||
|
bc1befcbb0 | ||
|
53cd5c71ab | ||
|
473e6c8d9c | ||
|
3fc88bb120 | ||
|
30afd0263b | ||
|
001755667a | ||
|
cf8aaa66e0 | ||
|
090815e7f7 | ||
|
45cb0cc393 | ||
|
6859685dd0 | ||
|
9338641a78 | ||
|
de9aeb8416 | ||
|
d4e0386665 | ||
|
eba0a16df2 | ||
|
a54d9c98f7 | ||
|
45b09a0461 | ||
|
8e3232fecc | ||
|
83c8a30a71 | ||
|
1cfddd409d | ||
|
31e2d0b208 | ||
|
f630ea3e3f | ||
|
407ce1ccb0 | ||
|
7a097f7b27 | ||
|
04e9a38a68 | ||
|
bea90521c5 | ||
|
b68c159275 | ||
|
1109f6d728 | ||
|
bbda044d73 | ||
|
fb315e3651 | ||
|
2e1c91929e | ||
|
df568ccad7 | ||
|
23ff4bf64c | ||
|
4e3e0a1d5e | ||
|
d68fec2ab8 | ||
|
0c9f395c55 | ||
|
49ea4cdfe7 | ||
|
8bd54ba153 | ||
|
afbcbb1f44 | ||
|
710dcf6c47 | ||
|
2ffeab0c5e | ||
|
c62a4bb4c4 | ||
|
4d989941b3 | ||
|
e53d3eaff8 | ||
|
29108894a2 | ||
|
4e6dc31247 | ||
|
5d87675586 | ||
|
109d2b4e41 | ||
|
9fb3aaa9e0 | ||
|
69249fe408 | ||
|
5bef181c8f | ||
|
065d22ebda | ||
|
a8842b189c | ||
|
55bc578374 | ||
|
34c84051c9 | ||
|
45f3311b70 | ||
|
7ffd7c2682 | ||
|
8a7f7231b5 | ||
|
17740c63ee | ||
|
1798fd71d1 | ||
|
6e08f2bddd | ||
|
3127cba4ee | ||
|
0ae3d487e3 | ||
|
37aab9a520 | ||
|
c18dc3b724 | ||
|
569ae488a0 | ||
|
70a94a7e1d | ||
|
510000541c | ||
|
18a8f06ce4 | ||
|
5886422d72 | ||
|
09570ec34c | ||
|
b57c22468c | ||
|
1d7594d83b | ||
|
f223fe0812 | ||
|
d0482f1e81 | ||
|
0b83cfe06d | ||
|
e13090066c | ||
|
07ec3f2132 | ||
|
f8bb5d4dd4 | ||
|
6d216b2766 | ||
|
05d728b846 | ||
|
5c3607dde5 | ||
|
d0f3c8eb22 | ||
|
b9a366df09 | ||
|
f392505d21 | ||
|
981685e926 | ||
|
63f8f86cd5 | ||
|
20455f74ab | ||
|
cea712ced9 | ||
|
124a971a1f | ||
|
82b42fda67 | ||
|
7c02f79c22 | ||
|
23d54eaedf | ||
|
7ad141bb6d | ||
|
e68925c852 | ||
|
62cab267b4 | ||
|
40c9b67033 | ||
|
23648a03e5 | ||
|
3f188b5526 | ||
|
2d35b04713 | ||
|
9a5b03c423 | ||
|
ee336aa414 | ||
|
5d7b0a976a | ||
|
a81eba9ea1 | ||
|
c5022358de | ||
|
9d1734406b | ||
|
2d49715891 | ||
|
9e6a4938ed | ||
|
cc4a196334 | ||
|
c39620e33c | ||
|
0dd26e5729 | ||
|
2cdf743bba | ||
|
dbf069cf85 | ||
|
bf230509b8 | ||
|
09cbd444e6 | ||
|
2ace4aaef1 | ||
|
86d0d3065c | ||
|
1f8f39a7f8 | ||
|
64b124aefd | ||
|
05ba2188de | ||
|
d64452bbb6 | ||
|
ba440bd5ea | ||
|
a94e082b68 | ||
|
e8a61e144a | ||
|
def0cad889 | ||
|
c93e4400e2 | ||
|
8935ab5d7f | ||
|
c5a9e7e357 | ||
|
9580154a13 | ||
|
48f5566326 | ||
|
b24010a86e | ||
|
e2a932558a | ||
|
732206ac13 | ||
|
3ea5d43b99 | ||
|
a172430c11 | ||
|
2a732645d2 | ||
|
c91d84b635 | ||
|
b4b7b58cb2 | ||
|
f9ca018e2a | ||
|
8d99de59fc | ||
|
8e36986ffb | ||
|
337cdba68f | ||
|
40b1caaf3a | ||
|
c8469b06b5 | ||
|
7c0880124b | ||
|
b73f5ad6a4 | ||
|
7e8edda808 | ||
|
48ffde66da |
3
.arcconfig
Normal file
3
.arcconfig
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"phabricator.uri" : "https://phabricator.kde.org/project/profile/159/"
|
||||
}
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,3 +12,4 @@ gradlew
|
||||
gradlew.bat
|
||||
*.iml
|
||||
*.keystore
|
||||
.directory
|
||||
|
@@ -1,11 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.kde.kdeconnect_tp"
|
||||
android:versionCode="1610"
|
||||
android:versionName="1.6.1">
|
||||
|
||||
<uses-sdk android:minSdkVersion="9"
|
||||
android:targetSdkVersion="22" />
|
||||
android:versionCode="1720"
|
||||
android:versionName="1.7.2">
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
@@ -18,12 +15,15 @@
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!--<uses-permission android:name="android.permission.BLUETOOTH" />-->
|
||||
<!--<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />-->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.BATTERY_STATS" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" android:required="false" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_SMS" android:required="false" />
|
||||
<uses-permission android:name="android.permission.SEND_SMS" android:required="false" />
|
||||
<uses-permission android:name="android.permission.READ_SMS" android:required="false" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
@@ -32,8 +32,8 @@
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/icon"
|
||||
android:supportsRtl="true"
|
||||
android:label="KDE Connect"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/KdeConnectTheme"
|
||||
>
|
||||
|
||||
@@ -42,8 +42,6 @@
|
||||
android:enabled="true" >
|
||||
</service>
|
||||
|
||||
<!--Commented here and in PluginFactory until we release a desktop version with this feature, so we don't get bad "feature not working" reviews-->
|
||||
<!--
|
||||
<service android:name="org.kde.kdeconnect.Plugins.RemoteKeyboardPlugin.RemoteKeyboardService"
|
||||
android:label="KDE Connect Remote Keyboard"
|
||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
@@ -52,7 +50,7 @@
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/remotekeyboardplugin_method" />
|
||||
</service>
|
||||
-->
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.UserInterface.MaterialActivity"
|
||||
android:label="KDE Connect"
|
||||
@@ -139,9 +137,9 @@
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.FindMyPhonePlugin.FindMyPhoneActivity"
|
||||
android:label="@string/findmyphone_title"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:excludeFromRecents="true"
|
||||
android:label="@string/findmyphone_title"
|
||||
android:launchMode="singleInstance">
|
||||
</activity>
|
||||
|
||||
@@ -193,7 +191,19 @@
|
||||
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.service.chooser.chooser_target_service"
|
||||
android:value="org.kde.kdeconnect.Plugins.SharePlugin.ShareChooserTargetService" />
|
||||
</activity>
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="org.kde.kdeconnect_tp.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/fileprovider_paths" />
|
||||
</provider>
|
||||
<service
|
||||
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationReceiver"
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
|
||||
@@ -201,6 +211,13 @@
|
||||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service
|
||||
android:name="org.kde.kdeconnect.Plugins.SharePlugin.ShareChooserTargetService"
|
||||
android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.chooser.ChooserTargetService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity"
|
||||
|
14
README.md
14
README.md
@@ -4,20 +4,24 @@ KDE Connect is a multi-platform app that allows your devices to communicate (eg:
|
||||
|
||||
## (Some) Features
|
||||
- **Shared clipboard**: copy and paste between your phone and your computer (or any other device).
|
||||
- **Notification sync**: Read your Android notifications from the desktop.
|
||||
- **Notification sync**: Read and reply to your Android notifications from the desktop.
|
||||
- **Share files and URLs** instantly from one device to another.
|
||||
- **Multimedia remote control**: Use your phone as a remote for Linux media players.
|
||||
- **Virtual touchpad**: Use your phone screen as your computer's touchpad.
|
||||
- **Virtual touchpad**: Use your phone screen as your computer's touchpad and keyboard.
|
||||
|
||||
All this without wires, over the already existing WiFi network, and using a secure, encrypted protocol.
|
||||
All this without wires, over the already existing WiFi network, and using TLS encryption.
|
||||
|
||||
## About this app
|
||||
|
||||
This is a native Android port of the KDE Connect Qt app. You will find a more complete readme about KDE Connect [here](https://github.com/albertvaka/kdeconnect-kde).
|
||||
This is a native Android port of the KDE Connect Qt app. You will find a more complete readme about KDE Connect [here](https://github.com/KDE/kdeconnect-kde).
|
||||
|
||||
## How to install this app
|
||||
|
||||
You can install this app from the [Play Store](https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp) as well as [F-Droid](https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp). Note you will also need to install the [desktop app](https://github.com/albertvaka/kdeconnect-kde) for it to work.
|
||||
You can install this app from the [Play Store](https://play.google.com/store/apps/details?id=org.kde.kdeconnect_tp) as well as [F-Droid](https://f-droid.org/repository/browse/?fdid=org.kde.kdeconnect_tp). Note you will also need to install the [desktop app](https://github.com/KDE/kdeconnect-kde) for it to work.
|
||||
|
||||
## Contributing
|
||||
|
||||
To contribute patches, use [KDE Connect's Phabricator](https://phabricator.kde.org/project/profile/159/). There you can also find a task list with stuff to do, and links to other relevant resources. It is a good idea to also subscribe to the [KDE Connect mailing list](https://mail.kde.org/mailman/listinfo/kdeconnect).
|
||||
|
||||
## License
|
||||
[GNU GPL v2](https://www.gnu.org/licenses/gpl-2.0.html) and [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
35
build.gradle
35
build.gradle
@@ -1,20 +1,24 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.google.com/'
|
||||
name 'Google'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
buildToolsVersion '25.0.2'
|
||||
buildToolsVersion '26.0.2'
|
||||
compileSdkVersion 25
|
||||
defaultConfig {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 22 //Bumping to >22 means we have to support the new permissions model
|
||||
targetSdkVersion 25
|
||||
//multiDexEnabled true
|
||||
//testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
|
||||
}
|
||||
@@ -57,7 +61,7 @@ android {
|
||||
minifyEnabled false
|
||||
useProguard false
|
||||
}
|
||||
release { //keep on 'releae', set to 'all' when testing to make sure proguard is not deleting important stuff
|
||||
release { //keep on 'release', set to 'all' when testing to make sure proguard is not deleting important stuff
|
||||
minifyEnabled true
|
||||
useProguard true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
|
||||
@@ -68,20 +72,25 @@ android {
|
||||
dependencies {
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.google.com/'
|
||||
name 'Google'
|
||||
}
|
||||
}
|
||||
|
||||
compile 'com.android.support:support-v4:25.1.1'
|
||||
compile 'com.android.support:appcompat-v7:25.1.1'
|
||||
compile 'com.android.support:design:25.1.1'
|
||||
implementation 'com.android.support:support-v4:25.4.0'
|
||||
implementation 'com.android.support:appcompat-v7:25.4.0'
|
||||
implementation 'com.android.support:design:25.4.0'
|
||||
|
||||
compile 'org.apache.sshd:sshd-core:0.8.0' //0.9 seems to fail on Android 6 and 1.+ requires java.nio.file, which doesn't exist in Android
|
||||
implementation 'org.apache.sshd:sshd-core:0.8.0' //0.9 seems to fail on Android 6 and 1.+ requires java.nio.file, which doesn't exist in Android
|
||||
|
||||
compile 'com.madgag.spongycastle:pkix:1.54.0.0' //For SSL certificate generation
|
||||
implementation 'com.madgag.spongycastle:pkix:1.54.0.0' //For SSL certificate generation
|
||||
|
||||
// Testing
|
||||
androidTestCompile 'org.mockito:mockito-core:1.10.19'
|
||||
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'// Because mockito has some problems with dex environment
|
||||
androidTestCompile 'org.skyscreamer:jsonassert:1.3.0'
|
||||
androidTestImplementation 'org.mockito:mockito-core:1.10.19'
|
||||
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.1'// Because mockito has some problems with dex environment
|
||||
androidTestImplementation 'org.skyscreamer:jsonassert:1.3.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 823 B |
Binary file not shown.
Before Width: | Height: | Size: 497 B |
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB |
9
res/drawable/ic_fast_forward_black.xml
Normal file
9
res/drawable/ic_fast_forward_black.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
|
||||
</vector>
|
9
res/drawable/ic_next_black.xml
Normal file
9
res/drawable/ic_next_black.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
|
||||
</vector>
|
9
res/drawable/ic_pause_black.xml
Normal file
9
res/drawable/ic_pause_black.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
|
||||
</vector>
|
9
res/drawable/ic_play_black.xml
Normal file
9
res/drawable/ic_play_black.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M8,5v14l11,-7z"/>
|
||||
</vector>
|
9
res/drawable/ic_previous_black.xml
Normal file
9
res/drawable/ic_previous_black.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/>
|
||||
</vector>
|
9
res/drawable/ic_rewind_black.xml
Normal file
9
res/drawable/ic_rewind_black.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
|
||||
</vector>
|
9
res/drawable/ic_volume_black.xml
Normal file
9
res/drawable/ic_volume_black.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
|
||||
</vector>
|
@@ -3,7 +3,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/activity_vertical_margin"
|
||||
tools:context=".DeviceFragment"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.DeviceFragment"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
|
@@ -4,7 +4,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="16dip"
|
||||
android:paddingRight="16dip"
|
||||
tools:context=".MainActivity"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.MaterialActivity"
|
||||
android:id="@+id/listView1"
|
||||
android:addStatesFromChildren="true"
|
||||
android:orientation="vertical">
|
||||
|
17
res/layout/activity_refresh_list.xml
Normal file
17
res/layout/activity_refresh_list.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/refresh_list_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ListView android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="16dip"
|
||||
android:paddingRight="16dip"
|
||||
tools:context=".MainActivity"
|
||||
android:id="@+id/listView1"
|
||||
android:addStatesFromChildren="true"
|
||||
android:orientation="vertical"/>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
@@ -41,12 +41,11 @@
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
|
||||
<org.kde.kdeconnect.UserInterface.MaxWidthImageButton
|
||||
<ImageButton
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="75dip"
|
||||
app:maxWidth="300dip"
|
||||
android:layout_height="75dp"
|
||||
android:id="@+id/play_button"
|
||||
android:src="@android:drawable/ic_media_play"
|
||||
android:src="@drawable/ic_play_black"
|
||||
android:contentDescription="@string/mpris_play"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="0"
|
||||
@@ -65,7 +64,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/prev_button"
|
||||
android:src="@android:drawable/ic_media_previous"
|
||||
android:src="@drawable/ic_previous_black"
|
||||
android:contentDescription="@string/mpris_previous"
|
||||
android:layout_weight="0.25"
|
||||
/>
|
||||
@@ -74,7 +73,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/rew_button"
|
||||
android:src="@android:drawable/ic_media_rew"
|
||||
android:src="@drawable/ic_rewind_black"
|
||||
android:contentDescription="@string/mpris_rew"
|
||||
android:layout_weight="0.25"
|
||||
/>
|
||||
@@ -83,7 +82,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/ff_button"
|
||||
android:src="@android:drawable/ic_media_ff"
|
||||
android:src="@drawable/ic_fast_forward_black"
|
||||
android:contentDescription="@string/mpris_ff"
|
||||
android:layout_weight="0.25"
|
||||
/>
|
||||
@@ -92,7 +91,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/next_button"
|
||||
android:src="@android:drawable/ic_media_next"
|
||||
android:src="@drawable/ic_next_black"
|
||||
android:contentDescription="@string/mpris_next"
|
||||
android:layout_weight="0.25"
|
||||
/>
|
||||
@@ -152,7 +151,7 @@
|
||||
android:id="@+id/imageView"
|
||||
android:layout_weight="0"
|
||||
android:contentDescription="@string/mpris_volume"
|
||||
android:src="@drawable/ic_volume"
|
||||
android:src="@drawable/ic_volume_black"
|
||||
/>
|
||||
|
||||
|
||||
|
@@ -29,7 +29,7 @@
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<!-- Preference will place its actual preference widget here. -->
|
||||
<LinearLayout android:id="@+android:id/widget_frame"
|
||||
<LinearLayout android:id="@android:id/widget_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
@@ -54,7 +54,7 @@
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal" />
|
||||
|
||||
<TextView android:id="@+android:id/summary"
|
||||
<TextView android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
|
@@ -9,14 +9,6 @@
|
||||
android:title="@string/refresh"
|
||||
/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_progress"
|
||||
android:orderInCategory="200"
|
||||
android:visible="false"
|
||||
kdeconnect:showAsAction="ifRoom"
|
||||
kdeconnect:actionViewClass="android.widget.ProgressBar"
|
||||
/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_rename"
|
||||
android:orderInCategory="300"
|
||||
|
@@ -5,16 +5,8 @@
|
||||
android:id="@+id/menu_refresh"
|
||||
android:icon="@drawable/ic_action_refresh"
|
||||
android:orderInCategory="200"
|
||||
kdeconnect:showAsAction="ifRoom"
|
||||
kdeconnect:showAsAction="never"
|
||||
android:title="@string/refresh"
|
||||
/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_progress"
|
||||
android:orderInCategory="200"
|
||||
android:visible="false"
|
||||
kdeconnect:showAsAction="ifRoom"
|
||||
kdeconnect:actionViewClass="android.widget.ProgressBar"
|
||||
/>
|
||||
|
||||
</menu>
|
||||
|
@@ -5,13 +5,23 @@
|
||||
<string name="pref_plugin_battery">تقرير البطّاريّة</string>
|
||||
<string name="pref_plugin_battery_desc">بلّغ عن حالة البطّاريّة دوريًّا</string>
|
||||
<string name="pref_plugin_sftp">اكشف نظام الملفّات</string>
|
||||
<string name="pref_plugin_sftp_desc">تسمح بتصفّح نظام ملفّات هذا الهاتف عن بعد</string>
|
||||
<string name="pref_plugin_clipboard">مزامنة الحافظة</string>
|
||||
<string name="pref_plugin_clipboard_desc">شارك محتوى الحافظة</string>
|
||||
<string name="pref_plugin_mousepad">الدَّخل البعيد</string>
|
||||
<string name="pref_plugin_mousepad">الدّخل البعيد</string>
|
||||
<string name="pref_plugin_mousepad_desc">استخدم الهاتف أو اللوحيّ كفأرة ولوحة مفاتيح</string>
|
||||
<string name="pref_plugin_mpris">تحكّمات الوسائط المتعدّدة</string>
|
||||
<string name="pref_plugin_mpris_desc">توفّر تحكّمًا بعيدًا لمشغّل الوسائط</string>
|
||||
<string name="pref_plugin_runcommand">شغّل أمرًا</string>
|
||||
<string name="pref_plugin_runcommand_desc">تحفّز أوامر عن بعد من الهاتف أو اللوحيّ</string>
|
||||
<string name="pref_plugin_ping">وخزة</string>
|
||||
<string name="pref_plugin_ping_desc">أرسل واستقبل وخزات</string>
|
||||
<string name="pref_plugin_notifications">مزامنة الإخطارات</string>
|
||||
<string name="pref_plugin_notifications_desc">انفذ إلى إخطاراتك من أجهزة أخرى</string>
|
||||
<string name="pref_plugin_receive_notifications">استقبل الإخطارات</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">استقبل الإخطارات من الجهاز الآخر واعرضها على أندرويد</string>
|
||||
<string name="pref_plugin_sharereceiver">شارك واستقبل</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">شارك الملفّات والعناوين بين الجهازين</string>
|
||||
<string name="plugin_not_available">هذه الميزة غير متوفّرة في إصدار أندرويد لديك</string>
|
||||
<string name="device_list_empty">لا أجهزة</string>
|
||||
<string name="ok">حسنًا</string>
|
||||
@@ -19,24 +29,32 @@
|
||||
<string name="open_settings">افتح الإعدادات</string>
|
||||
<string name="no_permissions">عليك إعطاء التّطبيق صلاحيّات للنّفاذ إلى الإخطارات</string>
|
||||
<string name="send_ping">أرسل وخزة</string>
|
||||
<string name="open_mpris_controls">تحكّمات الوسائط المتعدّدة</string>
|
||||
<string name="open_mousepad">الدّخل البعيد</string>
|
||||
<string name="mousepad_double_tap_settings_title">اضبط إجراء اللمس بإصبعين</string>
|
||||
<string name="mousepad_triple_tap_settings_title">اضبط إجراء اللمس بثلاث أصابع</string>
|
||||
<string name="mousepad_sensitivity_settings_title">اضبط حساسيّة لوحة اللمس</string>
|
||||
<string name="mousepad_scroll_direction_title">اعكس اتّجاه التّمرير</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item/>
|
||||
<item/>
|
||||
<item>Nothing</item>
|
||||
<item>النّقر باليمين</item>
|
||||
<item>النّقر بالوسط</item>
|
||||
<item>لا شيء</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
<item>الأبطأ</item>
|
||||
<item>الأقل بطئًا</item>
|
||||
<item>الافتراضيّ</item>
|
||||
<item>الأسرع قليلًا</item>
|
||||
<item>الأسرع</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">الأجهزة المقترن بها</string>
|
||||
<string name="category_not_paired_devices">الأجهزة المتوفّرة</string>
|
||||
<string name="category_remembered_devices">الأجهزة المتذكَّرة</string>
|
||||
<string name="plugins_failed_to_load">فشل تحميل الملحقات (المس لمعلومات اكثر):</string>
|
||||
<string name="device_menu_unpair">أزل الاقتران</string>
|
||||
<string name="device_menu_plugins">إعدادات الملحقة</string>
|
||||
<string name="device_menu_unpair">ألغِ الاقتران</string>
|
||||
<string name="device_not_reachable">الجهاز المقترن غير قابل الوصول</string>
|
||||
<string name="pair_new_device">اقرن جهازًا جديدًا</string>
|
||||
<string name="unknown_device">جهاز مجهول</string>
|
||||
<string name="error_not_reachable">الجهاز غير قابل الوصول</string>
|
||||
<string name="error_already_requested">طُلب الاقتران بالفعل</string>
|
||||
@@ -46,14 +64,24 @@
|
||||
<string name="error_canceled_by_user">ألغاه المستخدم</string>
|
||||
<string name="error_canceled_by_other_peer">ألغاه ندّ آخر</string>
|
||||
<string name="error_invalid_key">استُقبل مفتاح غير صالح</string>
|
||||
<string name="encryption_info_title">معلومات التّعمية</string>
|
||||
<string name="encryption_info_msg_no_ssl">لا يستخدم الجهاز الآخر إصدارة حديثة من «كدي المتّصل»، ستُستخدم طريقة التّعمية القديمة.</string>
|
||||
<string name="my_device_fingerprint">بصمة SHA1 لشهادة جهازك هي:</string>
|
||||
<string name="remote_device_fingerprint">بصمة SHA1 لشهادة الجهاز البعيد هي:</string>
|
||||
<string name="pair_requested">طُلب الاقتران</string>
|
||||
<string name="pairing_request_from">طلب اقتران من %1s</string>
|
||||
<string name="received_url_title">استُلمت وصلة من %1s</string>
|
||||
<string name="received_url_text">المس لفتح \'%1s\'</string>
|
||||
<string name="incoming_file_title">ملفّ وارد من %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="received_file_title">استُلم ملفّ من %1s</string>
|
||||
<string name="outgoing_file_title">يرسل ملفًّا إلى %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="received_file_title">استُقبل ملفّ من %1s</string>
|
||||
<string name="received_file_fail_title">فشل استقبال الملفّ من %1s</string>
|
||||
<string name="received_file_text">المس لفتح \'%1s\'</string>
|
||||
<string name="sent_file_title">أرسل ملفًّا إلى %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">المس للإجابة</string>
|
||||
<string name="reconnect">أعد الاتّصال</string>
|
||||
<string name="right_click">أرسل نقرة باليمين</string>
|
||||
@@ -74,6 +102,8 @@
|
||||
<string name="mpris_next">التّالي</string>
|
||||
<string name="mpris_volume">المستوى</string>
|
||||
<string name="mpris_settings">إعدادات الوسائط المتعدّدة</string>
|
||||
<string name="mpris_time_settings_title">زرّا التّقدّم والإرجاع</string>
|
||||
<string name="mpris_time_settings_summary">اضبط الوقت عند نقر زرّيّ التّقديم أو الإرجاع.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 ثوان</item>
|
||||
<item>20 ثانية</item>
|
||||
@@ -92,9 +122,13 @@
|
||||
<string name="invalid_device_name">اسم جهاز غير صالح</string>
|
||||
<string name="shareplugin_text_saved">استُقبل نصّ، حُفظ إلى الحافظة</string>
|
||||
<string name="custom_devices_settings">قائمة أجهزة مخصّصة</string>
|
||||
<string name="pair_device_action">اقرن جهازًا جديدًا</string>
|
||||
<string name="unpair_device_action">ألغِ اقتران %s</string>
|
||||
<string name="custom_device_list">أضف أجهزة بميفاق الإنترنت مإ</string>
|
||||
<string name="share_notification_preference">إخطارات مزعجة</string>
|
||||
<string name="share_notification_preference_summary">اهتزّ وشغّل صوتًا عند استقبال ملفّ</string>
|
||||
<string name="title_activity_notification_filter">مرشّح الإخطارات</string>
|
||||
<string name="filter_apps_info">ستُزامن الإخطارات من التّطبيقات المحدّدة.</string>
|
||||
<string name="sftp_internal_storage">التّخزين الدّاخليّ</string>
|
||||
<string name="sftp_all_files">كلّ الملفّات</string>
|
||||
<string name="sftp_sdcard_num">بطاقة SD %d</string>
|
||||
@@ -102,7 +136,26 @@
|
||||
<string name="sftp_readonly">(للقراءة فقط)</string>
|
||||
<string name="sftp_camera">صور الكاميرا</string>
|
||||
<string name="add_host">أضف مضيفًا/مإ</string>
|
||||
<string name="add_host_hint">اسم المضيف أو عنوان IP</string>
|
||||
<string name="no_players_connected">لم يُعثر على مشغّلات</string>
|
||||
<string name="custom_dev_list_help">استخدم هذا الخيار فقط إن لم يُكتَشف جهازك آليًّا. أدخِل عنوان مإ أو اسم المضيف أدناه والمس الزرّ لإضافته إلى القائمة. المس عنصرًا موجودًا لإزالته من القائمة.</string>
|
||||
<string name="mpris_player_on_device">%1$s على %2$s</string>
|
||||
<string name="send_files">أرسل ملفّات</string>
|
||||
<string name="pairing_title">أجهزة «كدي المتّصل»</string>
|
||||
<string name="pairing_description">الأجهزة الأخرى التي تشغّل «كدي المتّصل» وعلى نفس الشّبكة ستظهر هنا.</string>
|
||||
<string name="device_paired">اقتُرن الجهاز</string>
|
||||
<string name="device_rename_title">أعد تسمية الجهاز</string>
|
||||
<string name="device_rename_confirm">أعد التّسمية</string>
|
||||
<string name="refresh">أنعش</string>
|
||||
<string name="unreachable_description">الجهاز المقترن هذا لا يمكن الوصول إليه. تأكّد من اتّصاله بنفس الشّبكة.</string>
|
||||
<string name="no_file_browser">لا متصفّحات ملفّات مثبّتة.</string>
|
||||
<string name="pref_plugin_telepathy">أرسل SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">أرسل رسائل نصّيّة من سطح المكتب</string>
|
||||
<string name="plugin_not_supported">لا يدعم جهازك هذه الملحقة</string>
|
||||
<string name="findmyphone_title">جِد جهازي</string>
|
||||
<string name="findmyphone_title_tablet">جِد جهازي اللوحيّ</string>
|
||||
<string name="findmyphone_description">يرّن هذا الجهاز لتجده</string>
|
||||
<string name="findmyphone_found">وُجد</string>
|
||||
<string name="open">افتح</string>
|
||||
<string name="close">أغلق</string>
|
||||
</resources>
|
||||
|
@@ -1,33 +1,39 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Notificador telefónicu</string>
|
||||
<string name="pref_plugin_telephony">Avisador telefónicu</string>
|
||||
<string name="pref_plugin_telephony_desc">Unvia avisos pa SMS y llamaes</string>
|
||||
<string name="pref_plugin_battery">Informe de batería</string>
|
||||
<string name="pref_plugin_battery_desc">Infoma davezu del estáu de la batería</string>
|
||||
<string name="pref_plugin_battery_desc">Informe periódicu del estáu de la batería</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite restolar remotamente a esti preséu</string>
|
||||
<string name="pref_plugin_clipboard">Sincronización del cartafueyu</string>
|
||||
<string name="pref_plugin_clipboard_desc">Comparte\'l conteníu del cartafueyu</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mpris">Controles remotos multimedia</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usa\'l to teléfonu o tableta como panel táutil y tecláu</string>
|
||||
<string name="pref_plugin_remotekeyboard">Pulsaciones remotes</string>
|
||||
<string name="pref_plugin_mpris">Controles multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Forne un control remotu pal to reproductor multimedia</string>
|
||||
<string name="pref_plugin_runcommand">Execución de comandos</string>
|
||||
<string name="pref_plugin_runcommand_desc">Aiciona comandos remotos del to teléfonu o tableta</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Unvia y recibi pings</string>
|
||||
<string name="pref_plugin_ping_desc">Unvia y recibe pings</string>
|
||||
<string name="pref_plugin_notifications">Sincronización d\'avisos</string>
|
||||
<string name="pref_plugin_notifications_desc">Accede a los tos avisos dende otros preseos</string>
|
||||
<string name="pref_plugin_sharereceiver">Unvia y recibi pings</string>
|
||||
<string name="pref_plugin_notifications_desc">Accede a los tos avisos d\'otros preseos</string>
|
||||
<string name="pref_plugin_receive_notifications">Recibir avisos</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Recibe avisos d\'otros preseos y amuésalos n\'Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Compartir y recibir</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Comparte ficheros y URLs ente preseos</string>
|
||||
<string name="plugin_not_available">Esta carauterística nun ta disponible na to versión d\'Android</string>
|
||||
<string name="device_list_empty">Ensin preseos</string>
|
||||
<string name="ok">Aceutar</string>
|
||||
<string name="cancel">Encaboxar</string>
|
||||
<string name="open_settings">Abrir axustes</string>
|
||||
<string name="no_permissions">Necesites garantizar l\'accesu a los avisos</string>
|
||||
<string name="no_permissions">¡</string>
|
||||
<string name="send_ping">Unviar ping</string>
|
||||
<string name="open_mpris_controls">Controles multimedia</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_info">Muevi un deu enriba la pantalla pa mover el mur. calca pa un clic y usa dos/tres deos pa los motones de drecha y mediu. Usa un primíu llargu pa arrastrar y soltar.</string>
|
||||
<string name="open_mpris_controls">Control multimedia</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic drechu</item>
|
||||
<item>Clic d\'en mediu</item>
|
||||
<item>Nada</item>
|
||||
<item>Right click</item>
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
@@ -36,101 +42,16 @@
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Preseos coneutaos</string>
|
||||
<string name="category_not_paired_devices">Preseos disponibles</string>
|
||||
<string name="category_remembered_devices">Preseos recordaos</string>
|
||||
<string name="device_not_reachable">El preséu empareyáu nun ye agamable</string>
|
||||
<string name="unknown_device">Preséu desconocíu</string>
|
||||
<string name="error_not_reachable">Nun ye algamable\'l preséu</string>
|
||||
<string name="error_already_requested">Empareyamientu yá solicitáu</string>
|
||||
<string name="error_already_paired">El preséu yá ta empareyáu</string>
|
||||
<string name="error_could_not_send_package">Nun pudo unviase\'l paquete</string>
|
||||
<string name="error_timed_out">Tiempu escosao</string>
|
||||
<string name="error_canceled_by_user">Encaboxáu pol usuariu</string>
|
||||
<string name="error_canceled_by_other_peer">Encaboxáu pola otra parte</string>
|
||||
<string name="error_invalid_key">Recibióse una clave non válida</string>
|
||||
<string name="pair_requested">Solicitóse l\'empareyamientu</string>
|
||||
<string name="pairing_request_from">Solicitú d\'empareyamientu de %1s</string>
|
||||
<string name="received_url_title">Recibióse l\'enllaz de %1s</string>
|
||||
<string name="received_url_text">Calca p\'abrir «%1s»</string>
|
||||
<string name="incoming_file_title">Ficheru entrante de %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Unviando ficheru a %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="received_file_title">Recibióse\'l ficheru de %1s</string>
|
||||
<string name="received_file_fail_title">Fallu al recibir el ficheru de %1s</string>
|
||||
<string name="received_file_text">Tap to open \'%1s\'</string>
|
||||
<string name="sent_file_title">Unvióse\'l ficheru a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Calca pa responder</string>
|
||||
<string name="reconnect">Reconeutar</string>
|
||||
<string name="show_keyboard">Amosar tecláu</string>
|
||||
<string name="device_not_paired">Preséu non empareyáu</string>
|
||||
<string name="request_pairing">Solicitar empareyamientu</string>
|
||||
<string name="pairing_accept">Aceutar</string>
|
||||
<string name="pairing_reject">Refugar</string>
|
||||
<string name="device">Preséu</string>
|
||||
<string name="pair_device">Empareyar preséu</string>
|
||||
<string name="remote_control">Control remotu</string>
|
||||
<string name="settings">Axustes KDE Connect</string>
|
||||
<string name="mpris_play">Reproducir</string>
|
||||
<string name="mpris_previous">Anterior</string>
|
||||
<string name="mpris_rew">Rebobinar</string>
|
||||
<string name="mpris_ff">Avance rápidu</string>
|
||||
<string name="mpris_next">Siguiente</string>
|
||||
<string name="mpris_volume">Volume</string>
|
||||
<string name="mpris_settings">Axustes multimedia</string>
|
||||
<string name="mpris_time_settings_title">Botones d\'avanzar/rebobinar</string>
|
||||
<string name="mpris_time_settings_summary">Axusta\'l tiempu p\'avanzar/rebobinar al primise</string>
|
||||
<string name="error_timed_out">Escosó\'l tiempu</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 segundos</item>
|
||||
<item>20 segundos</item>
|
||||
<item>30 segundos</item>
|
||||
<item>1 minutu</item>
|
||||
<item>2 minutos</item>
|
||||
<item>10 seconds</item>
|
||||
<item>20 seconds</item>
|
||||
<item>30 seconds</item>
|
||||
<item>1 minute</item>
|
||||
<item>2 minutes</item>
|
||||
</string-array>
|
||||
<string name="protocol_version_older">Esti preséu usa una versión vieya del protocolu</string>
|
||||
<string name="protocol_version_newer">Esti preséu usa una versión anovada del protocolu</string>
|
||||
<string name="general_settings">Axustes xenerales</string>
|
||||
<string name="plugin_settings">Axustes</string>
|
||||
<string name="plugin_settings_with_name">Axustes de %s</string>
|
||||
<string name="device_name">Nome de preséu</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Nome de preséu non válidu</string>
|
||||
<string name="shareplugin_text_saved">Recibióse\'l testu y guardóse nel cartafueyu</string>
|
||||
<string name="custom_devices_settings">Llista de preseos personalizada</string>
|
||||
<string name="pair_device_action">Empareyar con un preséu nuevu</string>
|
||||
<string name="unpair_device_action">Desempareyar %s</string>
|
||||
<string name="custom_device_list">Amestar preseos pola IP</string>
|
||||
<string name="share_notification_preference">Avisos sonoros</string>
|
||||
<string name="share_notification_preference_summary">Fai vibrar y reproduz un soníu al recibir un ficheru</string>
|
||||
<string name="title_activity_notification_filter">Peñera d\'avisos</string>
|
||||
<string name="filter_apps_info">Los avisos sincronizaránse coles aplicaciones esbillaes.</string>
|
||||
<string name="sftp_internal_storage">Almacenamientu internu</string>
|
||||
<string name="sftp_all_files">Tolos ficheros</string>
|
||||
<string name="sftp_sdcard_num">Tarxeta SD %d</string>
|
||||
<string name="sftp_sdcard">Tarxeta SD</string>
|
||||
<string name="sftp_readonly">(namai llectura)</string>
|
||||
<string name="sftp_camera">Semeyes de cámara</string>
|
||||
<string name="add_host">Amestar agospiu/IP</string>
|
||||
<string name="add_host_hint">Nome d\'agospiu o IP</string>
|
||||
<string name="no_players_connected">Nun s\'alcontraron reproductores</string>
|
||||
<string name="custom_dev_list_help">Usa esta opción namái si\'l to preséu nun se deteuta automáticamente. Introduz la direición o\'l nome d\'agospiu y toca\'l botón p\'amestalu a la llista. Toca un elementu esistente pa desanicialu de la llista.</string>
|
||||
<string name="mpris_player_on_device">%1$s en %2$s</string>
|
||||
<string name="send_files">Unviar ficheros</string>
|
||||
<string name="pairing_title">Preseos KDE Connect</string>
|
||||
<string name="pairing_description">Deberíen apaecer equí otros preseos executando KDE Connect.</string>
|
||||
<string name="device_paired">Preséu empareyáu</string>
|
||||
<string name="device_rename_title">Renomar preséu</string>
|
||||
<string name="device_rename_confirm">Renomar</string>
|
||||
<string name="refresh">Refrescar</string>
|
||||
<string name="unreachable_description">Esti preséu empareyáu nun ye algamable. Asegúrate que ta coneutáu a la to mesma rede.</string>
|
||||
<string name="no_file_browser">Nun hai restoladores de ficheros instalaos.</string>
|
||||
<string name="pref_plugin_telepathy">Unviar SMS</string>
|
||||
<string name="no_file_browser">Nun hai restoladores de ficheros instalaos</string>
|
||||
<string name="pref_plugin_telepathy_desc">Unvia mensaxes de testu dende\'l to escritoriu</string>
|
||||
<string name="plugin_not_supported">Esti complementu nun ta sofitáu pol preséu</string>
|
||||
<string name="findmyphone_found">Alcontrar</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Zarrar</string>
|
||||
<string name="plugin_not_supported">Esti complementu nun lu sofita\'l preséu</string>
|
||||
<string name="findmyphone_description">Fai sonar el teléfonu pa qu\'asina pueas alcontralu</string>
|
||||
</resources>
|
||||
|
@@ -19,7 +19,6 @@
|
||||
<string name="open_settings">Otvori postavke</string>
|
||||
<string name="no_permissions">Morate odobriti dopuštenje da pristupite notifikacijama</string>
|
||||
<string name="send_ping">Pošalji ping</string>
|
||||
<string name="mousepad_info">Pomjerite prst na ekranu da opmjerite kursor miša. Tapnite za klik i koristite dva ili tri prsta za srednje i desno dugme. Koristite dugi pritisak za prevlačenje.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Postavite akciju tapa sa dva prsta</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Postavite akciju tapa sa tri prsta</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
@@ -27,8 +26,6 @@
|
||||
<item>Srednji klik</item>
|
||||
<item>Ništa</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">desno</string>
|
||||
<string name="mousepad_triple_default">Srednje</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
|
@@ -10,8 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Comparteix el contingut del porta-retalls</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usa el vostre telèfon o tauleta com un ratolí i un teclat</string>
|
||||
<string name="pref_plugin_remotekeyboard">Rep les pulsacions de tecla remotes</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Rep els esdeveniments de pulsacions de tecla des de dispositius remots</string>
|
||||
<string name="pref_plugin_remotekeyboard">S\'estan rebent pulsacions de tecla remotes</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">S\'estan rebent esdeveniments de pulsacions de tecla des de dispositius remots</string>
|
||||
<string name="pref_plugin_mpris">Controls multimèdia</string>
|
||||
<string name="pref_plugin_mpris_desc">Proporciona un comandament a distància pel reproductor multimèdia</string>
|
||||
<string name="pref_plugin_runcommand">Executa una ordre</string>
|
||||
@@ -33,11 +33,11 @@
|
||||
<string name="send_ping">Envia un ping</string>
|
||||
<string name="open_mpris_controls">Control multimèdia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Fes servir les tecles remotes només en editar</string>
|
||||
<string name="remotekeyboard_not_connected">No hi ha cap connexió activa amb el teclat remot, establiu-ne una al «kdeconnect»</string>
|
||||
<string name="remotekeyboard_not_connected">No hi ha cap connexió activa amb el teclat remot, establiu-ne una al kde-connect</string>
|
||||
<string name="remotekeyboard_connected">La connexió amb el teclat remot està activa</string>
|
||||
<string name="remotekeyboard_multiple_connections">Hi ha més d\'una connexió amb un teclat remot, seleccioneu el dispositiu per configurar-lo</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_info">Moveu un dit per la pantalla per a moure el cursor del ratolí. Toqueu per un clic, i empreu dos/tres dits pels botons dret i mig. Empreu un toc llarg per arrossegar i deixar anar.</string>
|
||||
<string name="mousepad_info">Moveu un dit per la pantalla per a moure el cursor del ratolí. Toqueu per un clic, i empreu dos/tres dits pels botons dret i mig. Useu 2 dits per desplaçar. Empreu un toc llarg per arrossegar i deixar anar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Estableix l\'acció de tocar amb dos dits</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Estableix l\'acció de tocar amb tres dits</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Estableix la sensibilitat del ratolí tàctil</string>
|
||||
@@ -47,9 +47,6 @@
|
||||
<item>Clic del mig</item>
|
||||
<item>No fer res</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">dret</string>
|
||||
<string name="mousepad_triple_default">mig</string>
|
||||
<string name="mousepad_sensitivity_default">Predeterminada</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>La més lenta</item>
|
||||
<item>Lenta</item>
|
||||
@@ -91,7 +88,7 @@
|
||||
<string name="received_file_title">Fitxer rebut des de %1s</string>
|
||||
<string name="received_file_fail_title">Ha fallat en rebre el fitxer des de %1s</string>
|
||||
<string name="received_file_text">Puntegeu per obrir «%1s»</string>
|
||||
<string name="sent_file_title">Envia el fitxer a %1s</string>
|
||||
<string name="sent_file_title">Fitxer enviat a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Ha fallat en enviar el fitxer a %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
@@ -142,7 +139,7 @@
|
||||
<string name="share_notification_preference_summary">Vibra i reprodueix un so en rebre un fitxer</string>
|
||||
<string name="share_destination_customize">Personalitza el directori de destinació</string>
|
||||
<string name="share_destination_customize_summary_disabled">Els fitxers rebuts apareixeran a Baixades</string>
|
||||
<string name="share_destination_customize_summary_enabled">Els fitxers seran emmagatzemats al directori de a sota</string>
|
||||
<string name="share_destination_customize_summary_enabled">Els fitxers seran emmagatzemats al directori de sota</string>
|
||||
<string name="share_destination_folder_preference">Directori de destinació</string>
|
||||
<string name="title_activity_notification_filter">Filtre per a les notificacions</string>
|
||||
<string name="filter_apps_info">Les notificacions se sincronitzaran per a les aplicacions seleccionades.</string>
|
||||
@@ -176,4 +173,14 @@
|
||||
<string name="findmyphone_found">L\'he trobat</string>
|
||||
<string name="open">Obre</string>
|
||||
<string name="close">Tanca</string>
|
||||
<string name="no_permissions_storage">Us caldrà concedir permís per accedir a l\'emmagatzematge</string>
|
||||
<string name="plugins_need_permission">Alguns connectors necessiten permisos per a funcionar (puntegeu per a més informació):</string>
|
||||
<string name="permission_explanation">Aquest connector necessita permisos per a funcionar</string>
|
||||
<string name="optional_permission_explanation">Us caldrà concedir permisos extres per accedir a totes les característiques</string>
|
||||
<string name="plugins_need_optional_permission">Alguns connectors tenen característiques desactivades per la falta de permís (puntegeu per a més informació):</string>
|
||||
<string name="sftp_permission_explanation">Per accedir als fitxers des del PC, l\'aplicació necessita permís per accedir a l\'emmagatzematge del telèfon</string>
|
||||
<string name="share_optional_permission_explanation">Per a compartir fitxers entre el telèfon i l\'escriptori, haureu de donar accés a l\'emmagatzematge del telèfon</string>
|
||||
<string name="telepathy_permission_explanation">Per a llegir i escriure SMS des de l\'escriptori, haureu de donar permís als SMS</string>
|
||||
<string name="telephony_permission_explanation">Per a veure les trucades telefòniques i SMS des de l\'escriptori, haureu de donar permís a les trucades telefòniques i SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Per a veure un nom de contacte en comptes d\'un número de telèfon, haureu de donar permís als contactes del telèfon</string>
|
||||
</resources>
|
||||
|
@@ -22,7 +22,7 @@
|
||||
<string name="pref_plugin_notifications_desc">Zpřístupněte si upozornění z jiných zařízení</string>
|
||||
<string name="pref_plugin_receive_notifications">Přijímat oznámení</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Přijímat oznámení z jiného zařízení a zobrazovat je v Androidu</string>
|
||||
<string name="pref_plugin_sharereceiver">Sdílet s přijmnout</string>
|
||||
<string name="pref_plugin_sharereceiver">Sdílet a přijmout</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Sdílet soubory a odkazy mezi zařízeními</string>
|
||||
<string name="plugin_not_available">Tato vlastnost není pro vaši verzi Androidu platná</string>
|
||||
<string name="device_list_empty">Žádná zařízení</string>
|
||||
@@ -37,7 +37,6 @@
|
||||
<string name="remotekeyboard_connected">Vzdálené připojení klávesnice je aktivní</string>
|
||||
<string name="remotekeyboard_multiple_connections">Je k dispozici více než jedno připojení klávesnice. Vyberte zařízení pro jeho nastavení.</string>
|
||||
<string name="open_mousepad">Vzdálený vstup</string>
|
||||
<string name="mousepad_info">Pohybujte prstem po obrazovce pro pohybování kurzorem myši. Ťukněte pro kliknutí a použijte dva/tři prsty jako pravé a prostřední tlačítko. Pro přetažení dlouze podržte.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Nastavit činnost pro ťuknutí dvěma prsty</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Nastavit činnost pro ťuknutí třemi prsty</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Nastavit citlivost touchpadu</string>
|
||||
@@ -47,9 +46,6 @@
|
||||
<item>Kliknutí prostředním tlačítkem myši</item>
|
||||
<item>Nic</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">pravé</string>
|
||||
<string name="mousepad_triple_default">prostřední</string>
|
||||
<string name="mousepad_sensitivity_default">výchozí</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Nejpomalejší</item>
|
||||
<item>Méně pomalý</item>
|
||||
@@ -165,6 +161,7 @@
|
||||
<string name="device_rename_confirm">Přejmenovat</string>
|
||||
<string name="refresh">Obnovit</string>
|
||||
<string name="unreachable_description">Toto spárované zařízení je nedosažitelné. Ujistěte se, že běží ve stejné síti.</string>
|
||||
<string name="on_data_message">Vypadá to, že jste na mobilním internetovém připojení. KDE Connect funguje pouze na lokální síti.</string>
|
||||
<string name="no_file_browser">Není nainstalován žádný prohlížeč souborů.</string>
|
||||
<string name="pref_plugin_telepathy">Poslat SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Posílejte zprávy ze své pracovní plochy</string>
|
||||
@@ -175,4 +172,14 @@
|
||||
<string name="findmyphone_found">Nalezeno</string>
|
||||
<string name="open">Otevřít</string>
|
||||
<string name="close">Zavřít</string>
|
||||
<string name="no_permissions_storage">Je potřeba povolit přístup k úložišti</string>
|
||||
<string name="plugins_need_permission">Některé moduly potřebují pro práci povolení (ťukněte pro více informací):</string>
|
||||
<string name="permission_explanation">Tento modul potřebuje pro práci povolení</string>
|
||||
<string name="optional_permission_explanation">Pro zpřístupnění všech funkcí potřebujete další oprávnění</string>
|
||||
<string name="plugins_need_optional_permission">Některé moduly mají vypnuté vlastnosti, kvůli nedostatečným oprávněním (ťukněte pro více informací):</string>
|
||||
<string name="sftp_permission_explanation">Pro přístup k souborům z vašeho počítače aplikace potřebuje oprávnění k úložišti telefonu</string>
|
||||
<string name="share_optional_permission_explanation">Pro sdílení souborů mezi telefonem a počítačem potřebujete udělit oprávnění k úložišti telefonu</string>
|
||||
<string name="telepathy_permission_explanation">Pro čtení a psaní SMS z počítače musíte udělit oprávnění k SMS</string>
|
||||
<string name="telephony_permission_explanation">Pro zobrazení telefonátů a SMS v počítači musíte udělit oprávnění k telefonování a SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Pro zobrazení jména kontaktu u telefonního čísla je potřeba udělit oprávnění ke kontaktům v telefonu</string>
|
||||
</resources>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Del indholdet af udklipsholderen</string>
|
||||
<string name="pref_plugin_mousepad">Eksternt input</string>
|
||||
<string name="pref_plugin_mousepad_desc">Brug din telefon eller tablet som mus og tastatur</string>
|
||||
<string name="pref_plugin_remotekeyboard">Modtag eksterne tastetryk</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Modtag tastetryk-hændelser fra eksterne enheder</string>
|
||||
<string name="pref_plugin_mpris">Multimediekontroller</string>
|
||||
<string name="pref_plugin_mpris_desc">Giver en fjernbetjening til din medieafspiller</string>
|
||||
<string name="pref_plugin_runcommand">Kør kommando</string>
|
||||
@@ -30,8 +32,11 @@
|
||||
<string name="no_permissions">Du skal give tilladelse for at tilgå bekendtgørelser</string>
|
||||
<string name="send_ping">Send ping</string>
|
||||
<string name="open_mpris_controls">Multimediekontrol</string>
|
||||
<string name="remotekeyboard_editing_only_title">Håndtér kun eksterne tastetryk under redigering</string>
|
||||
<string name="remotekeyboard_not_connected">Der er ingen aktiv ekstern tastaturforbindelse. Opret en i kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Ekstern tastaturforbindelse er aktiv</string>
|
||||
<string name="remotekeyboard_multiple_connections">Der er mere end en ekstern tastaturforbindelse, vælg den enhed der skal konfigureres</string>
|
||||
<string name="open_mousepad">Eksternt input</string>
|
||||
<string name="mousepad_info">Bevæg en finger på skærmen for at flytte musemarkøren. Tap for at klikke og brug to/tre-fingre for højre og midterste museknap. Brug et langt tryk til at trække og slippe.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Angiv handling for tap med to fingre</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Angiv handling for tap med tre fingre</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Angiv følsomhed for touchpad</string>
|
||||
@@ -41,15 +46,12 @@
|
||||
<item>Midterklik</item>
|
||||
<item>Intet</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">højre</string>
|
||||
<string name="mousepad_triple_default">midter</string>
|
||||
<string name="mousepad_sensitivity_default">standard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Mest langsom</item>
|
||||
<item>Over mest langsom</item>
|
||||
<item>Standard</item>
|
||||
<item>Over standard</item>
|
||||
<item>Hurtigste</item>
|
||||
<item>Hurtigst</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Forbundne enheder</string>
|
||||
<string name="category_not_paired_devices">Tilgængelig enheder</string>
|
||||
@@ -79,12 +81,15 @@
|
||||
<string name="incoming_file_title">Indkommende fil fra %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Sender fil til %1s</string>
|
||||
<string name="outgoing_files_title">Sender filer til %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Sendte %1$d ud af %2$d filer</string>
|
||||
<string name="received_file_title">Modtog fil fra %1s</string>
|
||||
<string name="received_file_fail_title">Kunne ikke modtage fil fra %1s</string>
|
||||
<string name="received_file_text">Tap for at åbne \"%1s\"</string>
|
||||
<string name="sent_file_title">Fil sendt til %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Kunne ikke sende filen til %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tap for at svare</string>
|
||||
<string name="reconnect">Forbind igen</string>
|
||||
@@ -131,6 +136,10 @@
|
||||
<string name="custom_device_list">Tilføj enheder via IP</string>
|
||||
<string name="share_notification_preference">Støjende bekendtgørelser</string>
|
||||
<string name="share_notification_preference_summary">Vibrér og afspil en lyd når en fil modtages</string>
|
||||
<string name="share_destination_customize">Tilpas destinationsmappe</string>
|
||||
<string name="share_destination_customize_summary_disabled">Modtagne filer vil dukke op i Downloads</string>
|
||||
<string name="share_destination_customize_summary_enabled">Filer vil blive gemt i mappen nedenfor</string>
|
||||
<string name="share_destination_folder_preference">Destinationsmappe</string>
|
||||
<string name="title_activity_notification_filter">Bekendtgørelsesfilter</string>
|
||||
<string name="filter_apps_info">Bekendtgørelser vil blive synkroniseret for de valgte apps.</string>
|
||||
<string name="sftp_internal_storage">Intern lagring</string>
|
||||
@@ -152,6 +161,7 @@
|
||||
<string name="device_rename_confirm">Omdøb</string>
|
||||
<string name="refresh">Genopfrisk</string>
|
||||
<string name="unreachable_description">Denne parrede enhed kan ikke nås. Sørg for at den er forbundet til samme netværk som dig.</string>
|
||||
<string name="on_data_message">Det lader til at du er på en mobil dataforbindelse. KDE Connect virker kun på lokale netværk.</string>
|
||||
<string name="no_file_browser">Der er ingen filhåndtering installeret.</string>
|
||||
<string name="pref_plugin_telepathy">Send SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Send SMS-beskeder fra din desktop</string>
|
||||
@@ -162,4 +172,14 @@
|
||||
<string name="findmyphone_found">Fundet</string>
|
||||
<string name="open">Åbn</string>
|
||||
<string name="close">Luk</string>
|
||||
<string name="no_permissions_storage">Du skal give tilladelse for at tilgå datalagret</string>
|
||||
<string name="plugins_need_permission">Nogle plugins kræver tilladelser for at virke (tap for mere info):</string>
|
||||
<string name="permission_explanation">Dette plugin kræver tilladelser for at virke</string>
|
||||
<string name="optional_permission_explanation">Du skal give ekstra tilladelser for at aktivere alle funktioner</string>
|
||||
<string name="plugins_need_optional_permission">Nogle plugins har deaktiverede funktioner pga. manglende tilladelser (tap for mere info):</string>
|
||||
<string name="sftp_permission_explanation">For at tilgå filerne fra din pc, skal app\'en have tilladelse til at til gå telefonens datalager</string>
|
||||
<string name="share_optional_permission_explanation">For at dele filer mellem din telefon og din desktop skal du give adgang til telefonens datalager.</string>
|
||||
<string name="telepathy_permission_explanation">For at læse og skrive sms\'er fra din desktop, skal du give tilladelse til sms</string>
|
||||
<string name="telephony_permission_explanation">For at se telefonopkald og sms\'er fra desktoppen, skal du give tilladelse til telefonopkald og sms.</string>
|
||||
<string name="telephony_optional_permission_explanation">For at se et kontaktnavn i stedet for et telefonnummer, skal du give adgang til telefonens kontakter</string>
|
||||
</resources>
|
||||
|
@@ -9,15 +9,17 @@
|
||||
<string name="pref_plugin_clipboard">Abgleich der Zwischenablage</string>
|
||||
<string name="pref_plugin_clipboard_desc">Inhalt der Zwischenablage freigeben</string>
|
||||
<string name="pref_plugin_mousepad">Ferneingabe</string>
|
||||
<string name="pref_plugin_mousepad_desc">Verwendet Ihr Handy als Tablett, Touchpad und Tastatur</string>
|
||||
<string name="pref_plugin_mousepad_desc">Verwendet Ihr Handy als Tablet, Touchpad und Tastatur</string>
|
||||
<string name="pref_plugin_mpris">Multimedia-Bedienung</string>
|
||||
<string name="pref_plugin_mpris_desc">Eine Fernbedienung für Ihre Medienwiedergabe</string>
|
||||
<string name="pref_plugin_runcommand">Befehl ausführen</string>
|
||||
<string name="pref_plugin_runcommand_desc">Von Ihrem Telefon oder Tablett Befehle auf anderen Geräten ausführen</string>
|
||||
<string name="pref_plugin_runcommand_desc">Von Ihrem Telefon oder Tablet Befehle auf anderen Geräten ausführen</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Senden und Empfangen von Pings</string>
|
||||
<string name="pref_plugin_notifications">Benachrichtigungs-Abgleich</string>
|
||||
<string name="pref_plugin_notifications_desc">Zugriff auf Ihre Benachrichtigungen von anderen Geräten</string>
|
||||
<string name="pref_plugin_receive_notifications">Benachrichtigungen empfangen</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Empfangen und Anzeigen von Benachrichtigungen des anderen Geräts</string>
|
||||
<string name="pref_plugin_sharereceiver">Veröffentlichen und Empfangen</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Dateien und Adressen (URLs) zwischen Geräten teilen</string>
|
||||
<string name="plugin_not_available">Diese Funktion ist in Ihrer Android-Version nicht verfügbar</string>
|
||||
@@ -38,14 +40,11 @@
|
||||
<item>Mittelklick</item>
|
||||
<item>Nichts</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Rechts</string>
|
||||
<string name="mousepad_triple_default">Mitte</string>
|
||||
<string name="mousepad_sensitivity_default">Standard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Langsamste</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Langsam</item>
|
||||
<item>Standard</item>
|
||||
<item>Above Default</item>
|
||||
<item>Schnell</item>
|
||||
<item>Schnellste</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Verbundene Geräte</string>
|
||||
@@ -66,19 +65,25 @@
|
||||
<string name="error_canceled_by_other_peer">Abbruch durch Gegenstelle</string>
|
||||
<string name="error_invalid_key">Ungültiger Schlüssel empfangen</string>
|
||||
<string name="encryption_info_title">Verschlüsselungsinformationen</string>
|
||||
<string name="encryption_info_msg_no_ssl">Das andere Gerät verwendet eine ältere Version von KDE-Connect, eine veraltete Verschlüsselungsmethode wird verwendet.</string>
|
||||
<string name="my_device_fingerprint">Der SHA1-Fingerabdruck Ihres Gerätezertifikats lautet:</string>
|
||||
<string name="remote_device_fingerprint">Der SHA1-Fingerabdruck des Gerätezertifikats der Gegenstelle lautet:</string>
|
||||
<string name="pair_requested">Verbindung angefordert</string>
|
||||
<string name="pairing_request_from">Verbindungsanfrage von %1s</string>
|
||||
<string name="received_url_title">Verknüpfung von %1s erhalten</string>
|
||||
<string name="received_url_text">Tippen um „%1s“ zu öffnen</string>
|
||||
<string name="incoming_file_title">Eingehende Datei von %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Datei wird an %1s gesendet</string>
|
||||
<string name="outgoing_files_title">Datei wird an %1s gesendet</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">%1$d von %2$d Dateien gesendet</string>
|
||||
<string name="received_file_title">Datei von %1s erhalten</string>
|
||||
<string name="received_file_fail_title">Der Empfang der Datei %1s ist fehlgeschlagen</string>
|
||||
<string name="received_file_text">Tippen um „%1s“ zu öffnen</string>
|
||||
<string name="sent_file_title">Datei an %1s gesendet</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Das Senden der Datei an %1s ist fehlgeschlagen</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tippen zum Antworten</string>
|
||||
<string name="reconnect">Erneut verbinden</string>
|
||||
@@ -86,7 +91,7 @@
|
||||
<string name="middle_click">Mittelklick senden</string>
|
||||
<string name="show_keyboard">Tastatur anzeigen</string>
|
||||
<string name="device_not_paired">Das Gerät ist nicht verbunden</string>
|
||||
<string name="request_pairing">Verbindung angefordert</string>
|
||||
<string name="request_pairing">Verbindung anfordern</string>
|
||||
<string name="pairing_accept">Annehmen</string>
|
||||
<string name="pairing_reject">Ablehnen</string>
|
||||
<string name="device">Gerät</string>
|
||||
@@ -101,6 +106,7 @@
|
||||
<string name="mpris_volume">Lautstärke</string>
|
||||
<string name="mpris_settings">Multimedia-Einstellungen</string>
|
||||
<string name="mpris_time_settings_title">Knöpfe Vorwärts/Rückwärts</string>
|
||||
<string name="mpris_time_settings_summary">Sprungweite für Vorlauf/Rücklauf anpassen.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 Sekunden</item>
|
||||
<item>20 Sekunden</item>
|
||||
@@ -121,9 +127,13 @@
|
||||
<string name="custom_devices_settings">Benutzerdefinierte Geräteliste</string>
|
||||
<string name="pair_device_action">Ein neues Gerät verbinden</string>
|
||||
<string name="unpair_device_action">Verbindung %s trennen</string>
|
||||
<string name="custom_device_list">Geräte nach IP hinzufügen</string>
|
||||
<string name="custom_device_list">Geräte nach IP-Adresse hinzufügen</string>
|
||||
<string name="share_notification_preference">Ausführliche Benachrichtigungen</string>
|
||||
<string name="share_notification_preference_summary">Beim Empfang einer Datei vibrieren und einen Sound abspielen</string>
|
||||
<string name="share_destination_customize">Zielverzeichnis anpassen</string>
|
||||
<string name="share_destination_customize_summary_disabled">Empfangene Dateien werden in Downloads gespeichert</string>
|
||||
<string name="share_destination_customize_summary_enabled">Dateien werden im folgenden Verzeichnis gespeichert</string>
|
||||
<string name="share_destination_folder_preference">Zielverzeichnis</string>
|
||||
<string name="title_activity_notification_filter">Benachrichtigungs-Filter</string>
|
||||
<string name="filter_apps_info">Benachrichtigungen werden zwischen den ausgewählten Anwendungen abgeglichen.</string>
|
||||
<string name="sftp_internal_storage">Interner Speicher</string>
|
||||
@@ -132,24 +142,27 @@
|
||||
<string name="sftp_sdcard">SD-Karte</string>
|
||||
<string name="sftp_readonly">(Nur lesen)</string>
|
||||
<string name="sftp_camera">Kamerabilder</string>
|
||||
<string name="add_host">Rechner/IP hinzufügen</string>
|
||||
<string name="add_host_hint">Rechnername oder IP</string>
|
||||
<string name="add_host">Rechner/IP-Adresse hinzufügen</string>
|
||||
<string name="add_host_hint">Rechnername oder IP-Adresse</string>
|
||||
<string name="no_players_connected">Keine Medienspieler gefunden</string>
|
||||
<string name="custom_dev_list_help">Benutzen Sie diese Funktion nur, wenn Ihr Gerät nicht automatisch erkannt wird. Geben hier Sie IP-Adresse oder Hostnamen ein und bestätigen Sie, um es zu der Liste hinzuzufügen. Tippen Sie ein bestehendes Gerät an, um es aus der Liste zu entfernen.</string>
|
||||
<string name="mpris_player_on_device">%1$s auf %2$s</string>
|
||||
<string name="send_files">Dateien senden</string>
|
||||
<string name="pairing_title">KDE-Connect-Geräte</string>
|
||||
<string name="pairing_description">Andere Geräte, auf denen KDE-Connect läuft im gleichen Netzwerk,sollte hier angezeigt werden.</string>
|
||||
<string name="pairing_description">Andere Geräte im selben Netzwerk, auf denen KDE-Connect läuft, sollten hier angezeigt werden.</string>
|
||||
<string name="device_paired">Gerät verbunden</string>
|
||||
<string name="device_rename_title">Geräte umbenennen</string>
|
||||
<string name="device_rename_confirm">Umbenennen</string>
|
||||
<string name="refresh">Aktualisieren</string>
|
||||
<string name="unreachable_description">Das verbundene Gerät ist nicht erreichbar. Stellen Sie sicher, dass es mit demselben Netzwerk verbunden ist.</string>
|
||||
<string name="on_data_message">Sie benutzen anscheinend eine mobile Datenverbindung. KDE-Connect funktioniert nur in lokalen Netzwerken.</string>
|
||||
<string name="no_file_browser">Es sind keine Dateiverwaltungsprogramme installiert.</string>
|
||||
<string name="pref_plugin_telepathy">SMS senden</string>
|
||||
<string name="pref_plugin_telepathy_desc">Text-Nachrichten von Ihrer Arbeitsfläche senden</string>
|
||||
<string name="plugin_not_supported">Dieses Modul wird durch das Gerät nicht unterstützt</string>
|
||||
<string name="findmyphone_title">Mein Telefon suchen</string>
|
||||
<string name="findmyphone_title_tablet">Mein Tablett suchen</string>
|
||||
<string name="findmyphone_description">Ruft dieses Gerät an, um es zu suchen.</string>
|
||||
<string name="findmyphone_title_tablet">Mein Tablet suchen</string>
|
||||
<string name="findmyphone_description">Ruft dieses Gerät an, damit sie es finden können</string>
|
||||
<string name="findmyphone_found">Gefunden</string>
|
||||
<string name="open">Öffnen</string>
|
||||
<string name="close">Schließen</string>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Διαμοιρασμός περιεχομένου προχείρου</string>
|
||||
<string name="pref_plugin_mousepad">Απομακρυσμένη είσοδος στοιχείων</string>
|
||||
<string name="pref_plugin_mousepad_desc">Χρήση του τηλεφώνου ή της ταμπλέτας σας ως επιφάνεια αφής και πληκτρολόγιο</string>
|
||||
<string name="pref_plugin_remotekeyboard">Λήψη απομακρυσμένων πληκτρολογήσεων</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Λήψη συμβάντων πληκτρολόγησης από απομακρυσμένες συσκευές</string>
|
||||
<string name="pref_plugin_mpris">Κονσόλα πολυμέσων</string>
|
||||
<string name="pref_plugin_mpris_desc">Παρέχει ένα τηλεχειριστήριο για την αναπαραγωγή πολυμέσων</string>
|
||||
<string name="pref_plugin_runcommand">Εκτέλεση εντολής</string>
|
||||
@@ -30,8 +32,11 @@
|
||||
<string name="no_permissions">Απαιτείται παραχώρηση δικαιωμάτων για την πρόσβαση σε ειδοποιήσεις</string>
|
||||
<string name="send_ping">Αποστολή ping</string>
|
||||
<string name="open_mpris_controls">Έλεγχος πολυμέσων</string>
|
||||
<string name="remotekeyboard_editing_only_title">Χειρισμός απομακρυσμένων πλήκτρων μόνο στην επεξεργασία</string>
|
||||
<string name="remotekeyboard_not_connected">Δεν υπάρχει ενεργή σύνδεση με απομακρυσμένο πληκτρολόγιο, άνοιξε μία στο kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Η σύνδεση με απομακρυσμένο πληκτρολόγιο είναι ενεργή</string>
|
||||
<string name="remotekeyboard_multiple_connections">Υπάρχουν περισσότερες της μίας συνδέσεις με απομακρυσμένο πληκτρολόγιο, επιλέξτε ποια συσκευή θα διαμορφώσετε</string>
|
||||
<string name="open_mousepad">Απομακρυσμένη είσοδος στοιχείων</string>
|
||||
<string name="mousepad_info">Μετακινείστε το δάκτυλο στην οθόνη για να μετακινηθεί ο δρομέας του ποντικιού. Χτυπήστε για κλικ και χρησιμοποιήστε δύο/τρία δάκτυλα για δεξί και μεσαίο κλικ. Πιέστε με διάρκεια για μετακίνηση και απόθεση.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ρύθμιση δύο δακτύλων για την ενέργεια χτυπήματος</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ρύθμιση τριών δακτύλων για την ενέργεια χτυπήματος</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Ρύθμιση ευαισθησίας της οθόνης αφής</string>
|
||||
@@ -41,9 +46,6 @@
|
||||
<item>Μεσαίο κλικ</item>
|
||||
<item>Τίποτα</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">δεξί</string>
|
||||
<string name="mousepad_triple_default">μεσαίο</string>
|
||||
<string name="mousepad_sensitivity_default">προκαθορισμένο</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Το πιο αργό</item>
|
||||
<item>Πάνω από το πιο αργό</item>
|
||||
@@ -79,12 +81,15 @@
|
||||
<string name="incoming_file_title">Εισερχόμενο αρχείο από %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Αποστολή αρχείου σε %1s</string>
|
||||
<string name="outgoing_files_title">Αποστολή αρχείων σε %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Εστάλησαν %1$d από %2$d αρχεία</string>
|
||||
<string name="received_file_title">Ελήφθη αρχείο από %1s</string>
|
||||
<string name="received_file_fail_title">Αποτυχία λήψης αρχείου από %1s</string>
|
||||
<string name="received_file_text">Χτυπήστε για άνοιγμα \'%1s\'</string>
|
||||
<string name="sent_file_title">Εστάλη αρχείο στο %1s</string>
|
||||
<string name="sent_file_title">Εστάλη αρχείο σε %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Αποτυχία αποστολής αρχείου σε %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Χτυπήστε για να απαντήσετε</string>
|
||||
<string name="reconnect">Επανασύνδεση</string>
|
||||
@@ -131,6 +136,10 @@
|
||||
<string name="custom_device_list">Προσθήκη συσκευών ανά IP</string>
|
||||
<string name="share_notification_preference">Θορυβώδεις ειδοποιήσεις</string>
|
||||
<string name="share_notification_preference_summary">Δόνηση και ηχητική ένδειξη με τη λήψη αρχείου</string>
|
||||
<string name="share_destination_customize">Προσαρμογή καταλόγου προορισμού</string>
|
||||
<string name="share_destination_customize_summary_disabled">Τα ληφθέντα αρχεία θα εμφανίζονται στις Λήψεις</string>
|
||||
<string name="share_destination_customize_summary_enabled">Τα αρχεία θα αποθηκεύονται στον παρακάτω κατάλογο</string>
|
||||
<string name="share_destination_folder_preference">Κατάλογος προορισμού</string>
|
||||
<string name="title_activity_notification_filter">Φιλτράρισμα ειδοποιήσεων</string>
|
||||
<string name="filter_apps_info">Οι ειδοποιήσεις θα συγχρονίζονται για επιλεγμένες εφαρμογές.</string>
|
||||
<string name="sftp_internal_storage">Εσωτερικός αποθηκευτικός χώρος</string>
|
||||
@@ -152,6 +161,7 @@
|
||||
<string name="device_rename_confirm">Μετονομασία</string>
|
||||
<string name="refresh">Ανανέωση</string>
|
||||
<string name="unreachable_description">Αυτή η συζευγμένη συσκευή δεν είναι προσβάσιμη. Βεβαιωθείτε ότι είναι συνδεδεμένη στο δίκτυό σας.</string>
|
||||
<string name="on_data_message">Φαίνεται ότι είστε σε σύνδεση δεδομένων από κινητό. Το KDE Connect λειτουργεί μόνο σε τοπικά δίκτυα.</string>
|
||||
<string name="no_file_browser">Δεν υπάρχουν εγκατεστημένοι περιηγητές αρχείων.</string>
|
||||
<string name="pref_plugin_telepathy">Αποστολή SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Αποστολή μηνυμάτων κειμένου από τον υπολογιστή σας</string>
|
||||
@@ -162,4 +172,14 @@
|
||||
<string name="findmyphone_found">Βρέθηκε</string>
|
||||
<string name="open">Άνοιγμα</string>
|
||||
<string name="close">Κλείσιμο</string>
|
||||
<string name="no_permissions_storage">Απαιτείται παραχώρηση δικαιωμάτων για την πρόσβαση στον αποθηκευτικό χώρο</string>
|
||||
<string name="plugins_need_permission">Κάποια πρόσθετα απαιτούν δικαιώματα για να λειτουργήσουν (χτυπήστε για περισσότερες πληροφορίες):</string>
|
||||
<string name="permission_explanation">Αυτό το πρόσθετο χρειάζεται δικαιώματα για να λειτουργήσει</string>
|
||||
<string name="optional_permission_explanation">Απαιτείται παραχώρηση επιπλέον δικαιωμάτων για την ενεργοποίηση όλων των λειτουργιών</string>
|
||||
<string name="plugins_need_optional_permission">Κάποια πρόσθετα έχουν λειτουργίες ανενεργές εξαιτίας της απουσίας δικαιωμάτων (χτυπήστε για περισσότερες πληροφορίες):</string>
|
||||
<string name="sftp_permission_explanation">Για την πρόσβαση στα αρχεία σας από τον υπολογιστή η εφαρμογή χρειάζεται δικαιώματα πρόσβασης στον αποθηκευτικό χώρο του κινητού σας</string>
|
||||
<string name="share_optional_permission_explanation">Για το διαμοιρασμό αρχείων ανάμεσα στο τηλέφωνο και τον υπολογιστή σας χρειάζεται να παραχωρήσετε πρόσβαση στον αποθηκευτικό χώρο του τηλεφώνου σας</string>
|
||||
<string name="telepathy_permission_explanation">Για να διαβάσετε και να γράψετε SMS από την επιφάνεια εργασίας, χρειάζεται να δώσετε δικαιώματα στο SMS</string>
|
||||
<string name="telephony_permission_explanation">Για να δείτε τηλεφωνικές κλήσεις και SMS από την επιφάνεια εργασίας, χρειάζεται να παραχωρήσετε δικαιώματα σε τηλεφωνικές κλήσεις και SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Για να δείτε το όνομα επαφής αντί για τον αριθμό κλήσης χρειάζεται να παραχωρήσετε πρόσβαση στις επαφές στο τηλέφωνο</string>
|
||||
</resources>
|
||||
|
@@ -37,7 +37,6 @@
|
||||
<string name="remotekeyboard_connected">Remote keyboard connection is active</string>
|
||||
<string name="remotekeyboard_multiple_connections">There is more than one remote keyboard connection, select the device to configure</string>
|
||||
<string name="open_mousepad">Remote input</string>
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Set touchpad sensitivity</string>
|
||||
@@ -47,9 +46,6 @@
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">right</string>
|
||||
<string name="mousepad_triple_default">middle</string>
|
||||
<string name="mousepad_sensitivity_default">default</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
@@ -176,4 +172,14 @@
|
||||
<string name="findmyphone_found">Found</string>
|
||||
<string name="open">Open</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="no_permissions_storage">You need to grant permissions to access the storage</string>
|
||||
<string name="plugins_need_permission">Some Plugins need permissions to work (tap for more info):</string>
|
||||
<string name="permission_explanation">This plugin needs permissions to work</string>
|
||||
<string name="optional_permission_explanation">You need to grant extra permissions to enable all functions</string>
|
||||
<string name="plugins_need_optional_permission">Some plugins have features disabled because of lack of permission (tap for more info):</string>
|
||||
<string name="sftp_permission_explanation">To access your files from your PC the app needs permission to access your phone\'s storage</string>
|
||||
<string name="share_optional_permission_explanation">To share files between your phone and your desktop you need to give access to the phone\'s storage</string>
|
||||
<string name="telepathy_permission_explanation">To read and write SMS from your desktop you need to give permission to SMS</string>
|
||||
<string name="telephony_permission_explanation">To see phone calls and SMS from the desktop you need to give permission to phone calls and SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">To see a contact name instead of a phone number you need to give access to the phone\'s contacts</string>
|
||||
</resources>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Compartir el contenido del portapapeles</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Usar su teléfono o tableta como teclado y teclado táctil</string>
|
||||
<string name="pref_plugin_remotekeyboard">Recibir pulsaciones de teclas remotas</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Recibir eventos de pulsación de teclas desde dispositivos remotos</string>
|
||||
<string name="pref_plugin_mpris">Controles multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Proporciona un control remoto para su reproductor de medios</string>
|
||||
<string name="pref_plugin_runcommand">Ejecutar orden</string>
|
||||
@@ -30,8 +32,12 @@
|
||||
<string name="no_permissions">Debe otorgar permiso para acceder a las notificaciones</string>
|
||||
<string name="send_ping">Enviar ping</string>
|
||||
<string name="open_mpris_controls">Control multimedia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Manejar teclas remotas solo al editar</string>
|
||||
<string name="remotekeyboard_not_connected">No hay ninguna conexión remota de teclado activa, establezca una en kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">La conexión remota de teclado está activa</string>
|
||||
<string name="remotekeyboard_multiple_connections">Hay más de una conexión remota de teclado, seleccione el dispositivo a configurar</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_info">Mueva un dedo sobre la pantalla para mover el cursor del ratón. Pulse para ejecutar un clic y use dos/tres dedos para emular los botones derecho y central. Use una pulsación larga para arrastrar y soltar.</string>
|
||||
<string name="mousepad_info">Mueva un dedo sobre la pantalla para mover el cursor del ratón. Pulse para ejecutar un clic y use dos/tres dedos para emular los botones derecho y central. Use 2 dedos para desplazar las pantalla. Use una pulsación larga para arrastrar y soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Establecer la acción al pulsar con dos dedos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Establecer la acción al pulsar con tres dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Establecer sensibilidad del panel táctil</string>
|
||||
@@ -41,9 +47,6 @@
|
||||
<item>Clic del botón central</item>
|
||||
<item>Nada</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">derecho</string>
|
||||
<string name="mousepad_triple_default">medio</string>
|
||||
<string name="mousepad_sensitivity_default">por defecto</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Muy poco sensible</item>
|
||||
<item>Poco sensible</item>
|
||||
@@ -153,15 +156,16 @@
|
||||
<string name="mpris_player_on_device">%1$s en %2$s</string>
|
||||
<string name="send_files">Enviar archivos</string>
|
||||
<string name="pairing_title">Dispositivos de KDE Connect</string>
|
||||
<string name="pairing_description">Otros dispositivos ejecutando KDE Connect en su misma red deberían aparecer aquí.</string>
|
||||
<string name="pairing_description">Cualquier otro dispositivo ejecutando KDE Connect en su misma red debería aparecer aquí.</string>
|
||||
<string name="device_paired">Dispositivo vinculado</string>
|
||||
<string name="device_rename_title">Renombrar dispositivo</string>
|
||||
<string name="device_rename_confirm">Renombrar</string>
|
||||
<string name="refresh">Actualizar</string>
|
||||
<string name="unreachable_description">Este dispositivo vinculado no está disponible. Asegúrese que está conectado a su misma red.</string>
|
||||
<string name="on_data_message">Parece que se encuentra en una conexión de datos móviles. KDE Connect solo funciona en redes locales.</string>
|
||||
<string name="no_file_browser">No hay navegadores de archivos instalados.</string>
|
||||
<string name="pref_plugin_telepathy">Enviar SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensajes de texto desde el escritorio</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensajes de texto desde su escritorio</string>
|
||||
<string name="plugin_not_supported">Este complemento no está permitido por el dispositivo</string>
|
||||
<string name="findmyphone_title">Encontrar mi teléfono</string>
|
||||
<string name="findmyphone_title_tablet">Encontrar mi tableta</string>
|
||||
@@ -169,4 +173,14 @@
|
||||
<string name="findmyphone_found">Encontrado</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Cerrar</string>
|
||||
<string name="no_permissions_storage">Debe otorgar permisos para acceder al almacenamiento</string>
|
||||
<string name="plugins_need_permission">Algunos complementos necesitan permisos para funcionar (pulse para más información):</string>
|
||||
<string name="permission_explanation">Este complemento necesita permisos para funcionar</string>
|
||||
<string name="optional_permission_explanation">Debe otorgar permisos extra para activar todas las funciones</string>
|
||||
<string name="plugins_need_optional_permission">Algunos complementos tienen funcionalidades desactivadas por falta de permisos (pulse para más información):</string>
|
||||
<string name="sftp_permission_explanation">Para acceder a sus archivos desde su equipo, la aplicación necesita permisos para acceder al almacenamiento de su teléfono</string>
|
||||
<string name="share_optional_permission_explanation">Para compartir archivos entre su teléfono y su escritorio, necesita dar acceso al almacenamiento de su teléfono</string>
|
||||
<string name="telepathy_permission_explanation">Para leer y escribir SMS desde su escritorio, necesita dar permisos para SMS</string>
|
||||
<string name="telephony_permission_explanation">Para ver las llamadas telefónicas y SMS desde su escritorio, necesita dar permisos para llamadas telefónicas y SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Para ver el nombre de un contacto en lugar de un número telefónico, necesita dar acceso a los contactos de su teléfono</string>
|
||||
</resources>
|
||||
|
@@ -31,7 +31,6 @@
|
||||
<string name="send_ping">Saada ping</string>
|
||||
<string name="open_mpris_controls">Multimeedia juhtimine</string>
|
||||
<string name="open_mousepad">Kaugsisestus</string>
|
||||
<string name="mousepad_info">Hiirekursori liigutamiseks liiguta sõrme ekraanil. Koputa klõpsamiseks ja kasuta kaht või kolme sõrme parema ja keskmise nupu jaoks. Pika vajutusega saab lohistada.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Kahe sõrmega koputamise toimingu määramine</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Kolme sõrmega koputamise toimingu määramine</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Puutepadja tundlikkuse määramine</string>
|
||||
@@ -41,9 +40,6 @@
|
||||
<item>Keskklõps</item>
|
||||
<item>Ei tee midagi</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">parem</string>
|
||||
<string name="mousepad_triple_default">keskmine</string>
|
||||
<string name="mousepad_sensitivity_default">vaikimisi</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Kõige aeglasem</item>
|
||||
<item>Kõige aeglasemast kiirem</item>
|
||||
|
185
res/values-eu/strings.xml
Normal file
185
res/values-eu/strings.xml
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Telefonia jakinarazlea</string>
|
||||
<string name="pref_plugin_telephony_desc">Bidali jakinarazpenak SMSak eta deiak jasotzean</string>
|
||||
<string name="pref_plugin_battery">Bateriaren txostena</string>
|
||||
<string name="pref_plugin_battery_desc">Bidali bateriaren egoera aldiro</string>
|
||||
<string name="pref_plugin_sftp">Fitxategi-sistemaren esposaketa</string>
|
||||
<string name="pref_plugin_sftp_desc">Gailu honen fitxategi-sistema urrunetik arakatzea ahalbidetzen du</string>
|
||||
<string name="pref_plugin_clipboard">Arbelaren sinkronizazioa</string>
|
||||
<string name="pref_plugin_clipboard_desc">Partekatu arbelaren edukia</string>
|
||||
<string name="pref_plugin_mousepad">Urruneko sarrera</string>
|
||||
<string name="pref_plugin_mousepad_desc">Erabili zure telefonoa edo tableta ukimen-sagu eta teklatu gisa</string>
|
||||
<string name="pref_plugin_remotekeyboard">Jaso urruneko tekla-sakatzeak</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Jaso tekla-sakatze gertaerak urruneko gailuetatik</string>
|
||||
<string name="pref_plugin_mpris">Multimedia kontrolak</string>
|
||||
<string name="pref_plugin_mpris_desc">Zure media jotzailearen urruneko kontrola ematen dizu</string>
|
||||
<string name="pref_plugin_runcommand">Exekutatu agindua</string>
|
||||
<string name="pref_plugin_runcommand_desc">Abiarazi urruneko aginduak zure telefono edo tabletatik</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Bidali eta jaso pingak</string>
|
||||
<string name="pref_plugin_notifications">Jakinarazpenen sinkronizazioa</string>
|
||||
<string name="pref_plugin_notifications_desc">Atzitu zure jakinarazpenak beste gailuetatik</string>
|
||||
<string name="pref_plugin_receive_notifications">Jaso jakinarazpenak</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Jaso jakinarazpenak beste gailutik eta bistaratu Androiden</string>
|
||||
<string name="pref_plugin_sharereceiver">Partekatu eta jaso</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Partekatu fitxategiak eta URLak gailuen artean</string>
|
||||
<string name="plugin_not_available">Ezaugarri hau ez dago erabilgarri zure Android bertsioan</string>
|
||||
<string name="device_list_empty">Gailurik ez</string>
|
||||
<string name="ok">Ados</string>
|
||||
<string name="cancel">Utzi</string>
|
||||
<string name="open_settings">Ireki ezarpenak</string>
|
||||
<string name="no_permissions">Jakinarazpenak atzitzeko baimena eman behar duzu</string>
|
||||
<string name="send_ping">Bidali ping</string>
|
||||
<string name="open_mpris_controls">Multimedia kontrola</string>
|
||||
<string name="remotekeyboard_editing_only_title">Erabili urruneko teklak editatzean besterik ez</string>
|
||||
<string name="remotekeyboard_not_connected">Ez dago urruneko teklatuarekin konexio aktiborik, ezarri bat kdeconnect erabiliz</string>
|
||||
<string name="remotekeyboard_connected">Urruneko teklatuarekin konexioa aktibo dago</string>
|
||||
<string name="remotekeyboard_multiple_connections">Urruneko teklatuekin konexio bat baino gehiago dago, hautatu konfiguratu beharreko gailua</string>
|
||||
<string name="open_mousepad">Urruneko sarrera</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ezarri bi atzamarren ekintza</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ezarri hiru atzamarren ekintza</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Ezarri ukimen-saguaren sentikortasuna</string>
|
||||
<string name="mousepad_scroll_direction_title">Alderantzikatu korritzearen norabidea</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Eskumako klik</item>
|
||||
<item>Erdiko klik</item>
|
||||
<item>Ezer ez</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Motelena</item>
|
||||
<item>Motelena baino azkarrago</item>
|
||||
<item>Lehenetsia</item>
|
||||
<item>Batezbestekoa baino azkarrago</item>
|
||||
<item>Azkarrena</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Konektatutako gailuak</string>
|
||||
<string name="category_not_paired_devices">Gailu eskuragarriak</string>
|
||||
<string name="category_remembered_devices">Gogoratutako gailuak</string>
|
||||
<string name="plugins_failed_to_load">Pluginak kargatzen huts egin dute (sakatu informazio gehiagorako):</string>
|
||||
<string name="device_menu_plugins">Pluginen ezarpenak</string>
|
||||
<string name="device_menu_unpair">Desparekatu</string>
|
||||
<string name="device_not_reachable">Parekatu gailua ez dago eskuragarri</string>
|
||||
<string name="pair_new_device">Parekatu gailu berria</string>
|
||||
<string name="unknown_device">Gailu ezezaguna</string>
|
||||
<string name="error_not_reachable">Gailua ez dago eskuragarri</string>
|
||||
<string name="error_already_requested">Parekatzea dagoeneko eskatu da</string>
|
||||
<string name="error_already_paired">Gailua dagoeneko parekatuta</string>
|
||||
<string name="error_could_not_send_package">Ezin izan da paketea bidali</string>
|
||||
<string name="error_timed_out">Denbora-muga agortu da</string>
|
||||
<string name="error_canceled_by_user">Erabiltzaileak utzita</string>
|
||||
<string name="error_canceled_by_other_peer">Beste kideak utzita</string>
|
||||
<string name="error_invalid_key">Baliogabeko gakoa jaso da</string>
|
||||
<string name="encryption_info_title">Zifratze informazioa</string>
|
||||
<string name="encryption_info_msg_no_ssl">Beste gailuak ez du oraintsuko KDE Connect bertsio bat erabiltzen, erabili aurreko bertsioetako metodoa.</string>
|
||||
<string name="my_device_fingerprint">Zure gailuaren ziurtagiriaren SHA1 hatz-marka hau da:</string>
|
||||
<string name="remote_device_fingerprint">Urruneko gailuaren ziurtagiriaren SHA1 hatz-marka hau da:</string>
|
||||
<string name="pair_requested">Parekatzea eskatu da</string>
|
||||
<string name="pairing_request_from">Parekatzeko eskaria %1s-tik</string>
|
||||
<string name="received_url_title">Esteka jaso da %1s-tik</string>
|
||||
<string name="received_url_text">Sakatu \'%1s\' irekitzeko</string>
|
||||
<string name="incoming_file_title">Fitxategia jasotzen %1s-tik</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Fitxategia bidaltzen %1s-ra</string>
|
||||
<string name="outgoing_files_title">Fitxategiak bidaltzen %1s-ra</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">%1$d / %2$d fitxategi bidalita</string>
|
||||
<string name="received_file_title">Fitxategia jaso da %1s-tik</string>
|
||||
<string name="received_file_fail_title">Huts egin du fitxategia jasotzea %1s-tik</string>
|
||||
<string name="received_file_text">Sakatu \'%1s\' irekitzeko</string>
|
||||
<string name="sent_file_title">Fitxategia bidalita %1s-ra</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Huts egin du fitxategia bidaltzea %1s-ra</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Sakatu erantzuteko</string>
|
||||
<string name="reconnect">Birkonektatu</string>
|
||||
<string name="right_click">Bidali eskumako klik</string>
|
||||
<string name="middle_click">Bidali erdiko klik</string>
|
||||
<string name="show_keyboard">Erakutsi teklatua</string>
|
||||
<string name="device_not_paired">Gailua parekatu gabe</string>
|
||||
<string name="request_pairing">Eskatu parekatzea</string>
|
||||
<string name="pairing_accept">Onartu</string>
|
||||
<string name="pairing_reject">Ukatu</string>
|
||||
<string name="device">Gailua</string>
|
||||
<string name="pair_device">Parekatu gailua</string>
|
||||
<string name="remote_control">Urruneko kontrola</string>
|
||||
<string name="settings">KDE Connect ezarpenak</string>
|
||||
<string name="mpris_play">Jo</string>
|
||||
<string name="mpris_previous">Aurrekoa</string>
|
||||
<string name="mpris_rew">Atzera eraman</string>
|
||||
<string name="mpris_ff">Aurrera eraman</string>
|
||||
<string name="mpris_next">Hurrengoa</string>
|
||||
<string name="mpris_volume">Bolumena</string>
|
||||
<string name="mpris_settings">Multimedia ezarpenak</string>
|
||||
<string name="mpris_time_settings_title">Atzera eraman / Aurrera eraman botoiak</string>
|
||||
<string name="mpris_time_settings_summary">Doitu zenbat denbora eraman behar den aurrera / atzera sakatzean</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 segundo</item>
|
||||
<item>20 segundo</item>
|
||||
<item>30 segundo</item>
|
||||
<item>minutu 1</item>
|
||||
<item>2 minutu</item>
|
||||
</string-array>
|
||||
<string name="share_to">Partekatu honi...</string>
|
||||
<string name="protocol_version_older">Gailu honek protokoloaren bertsio zahar bat erabiltzen du</string>
|
||||
<string name="protocol_version_newer">Gailu honek protokoloaren bertsio berriago bat erabiltzen du</string>
|
||||
<string name="general_settings">Ezarpen orokorrak</string>
|
||||
<string name="plugin_settings">Ezarpenak</string>
|
||||
<string name="plugin_settings_with_name">%s ezarpenak</string>
|
||||
<string name="device_name">Gailuaren izena</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Gailuaren izen baliogabea</string>
|
||||
<string name="shareplugin_text_saved">Testua jaso da, arbelean kopiatu da</string>
|
||||
<string name="custom_devices_settings">Gailuen zerrenda pertsonalizatua</string>
|
||||
<string name="pair_device_action">Parekatu gailu berria</string>
|
||||
<string name="unpair_device_action">Desparekatu %s</string>
|
||||
<string name="custom_device_list">Gehitu gailuak IP bidez</string>
|
||||
<string name="share_notification_preference">Jakinarazpen zaratatsuak</string>
|
||||
<string name="share_notification_preference_summary">Bibratu eta jo soinua fitxategia jasotzean</string>
|
||||
<string name="share_destination_customize">Pertsonalizatu direktorio xedea</string>
|
||||
<string name="share_destination_customize_summary_disabled">Jasotako fitxategiak Deskargak karpetan agertuko dira</string>
|
||||
<string name="share_destination_customize_summary_enabled">Fitxategiak beheko direktorioan gordeko dira</string>
|
||||
<string name="share_destination_folder_preference">Direktorio xedea</string>
|
||||
<string name="title_activity_notification_filter">Jakinarazpenen iragazkia</string>
|
||||
<string name="filter_apps_info">Aukeratutako aplikazioen jakinarazpenak sinkronizatuko dira</string>
|
||||
<string name="sftp_internal_storage">Barne biltegiratzea</string>
|
||||
<string name="sftp_all_files">Fitxategi guztiak</string>
|
||||
<string name="sftp_sdcard_num">%d SD txartela</string>
|
||||
<string name="sftp_sdcard">SD txartela</string>
|
||||
<string name="sftp_readonly">(irakurri soilik)</string>
|
||||
<string name="sftp_camera">Kamerako irudiak</string>
|
||||
<string name="add_host">Gehitu ostalaria/IP</string>
|
||||
<string name="add_host_hint">Ostalaria edo IP</string>
|
||||
<string name="no_players_connected">Ez da jokalaririk aurkitu</string>
|
||||
<string name="custom_dev_list_help">Erabili aukera hau zure gailua automatikoki antzematen ez denean. Sartu IP helbidea edo ostalaria azpian eta ukitu botoia zerrendara gehitzeko. Ukitu badagoen elementu bat zerrendatik ezabatzeko.</string>
|
||||
<string name="mpris_player_on_device">%1$s - %2$s</string>
|
||||
<string name="send_files">Bidali fitxategiak</string>
|
||||
<string name="pairing_title">KDE Connect gailuak</string>
|
||||
<string name="pairing_description">KDE Connect darabilten sareko beste gailuak hemen agertu beharko lirateke.</string>
|
||||
<string name="device_paired">Gailu parekatua</string>
|
||||
<string name="device_rename_title">Aldatu izena gailuari</string>
|
||||
<string name="device_rename_confirm">Aldatu izena</string>
|
||||
<string name="refresh">Freskatu</string>
|
||||
<string name="unreachable_description">Parekatutako gailu hau ez dago eskuragarri. Egiaztatu sare berera konektatuta dagoela.</string>
|
||||
<string name="on_data_message">Badirudi datu mugikorrak erabiliz konektatu zarela. KDE Connect sare lokalen bitartez besterik ez dabil.</string>
|
||||
<string name="no_file_browser">Ez dago fitxategi arakatzailerik instalatuta.</string>
|
||||
<string name="pref_plugin_telepathy">Bidali SMSa</string>
|
||||
<string name="pref_plugin_telepathy_desc">Bidali testu-mezuak zure mahaigainetik</string>
|
||||
<string name="plugin_not_supported">Gailu honek ez du plugin honentzako euskarririk</string>
|
||||
<string name="findmyphone_title">Bilatu nire telefonoa</string>
|
||||
<string name="findmyphone_title_tablet">Bilatu nire tableta</string>
|
||||
<string name="findmyphone_description">Gailuaren dei-doinua jotzen du aurki dezazun</string>
|
||||
<string name="findmyphone_found">Aurkituta</string>
|
||||
<string name="open">Ireki</string>
|
||||
<string name="close">Itxi</string>
|
||||
<string name="no_permissions_storage">Biltegiratzea atzitzeko baimena eman behar duzu</string>
|
||||
<string name="plugins_need_permission">Plugin batzuk baimenak behar dituzte funtzionatzeko (sakatu informazio gehiagorako):</string>
|
||||
<string name="permission_explanation">Plugin honek baimena behar du funtzionatzeko</string>
|
||||
<string name="optional_permission_explanation">Baimen gehiago eman behar dituzu funtzio guztiak gaitzeko</string>
|
||||
<string name="plugins_need_optional_permission">Plugin batzuk desgaitutako funtzioak dituzte baimenak faltan dituztelako (sakatu informazio gehiagorako):</string>
|
||||
<string name="sftp_permission_explanation">Zure fitxategiak PCtik atzitzeko aplikazioak zure telefonoaren biltegiratzea atzitzeko baimena behar du</string>
|
||||
<string name="share_optional_permission_explanation">Zure telefonoa eta mahaigainaren artean fitxategiak partekatzeko telefonoaren biltegiratzea atzitzeko baimena eman behar duzu</string>
|
||||
<string name="telepathy_permission_explanation">SMSak zure mahaigainetik bidali ahal izateko, SMSak erabiltzeko baimena eman behar duzu</string>
|
||||
<string name="telephony_permission_explanation">Telefono deiak eta SMSak zure mahaigainetik ikusteko, telefono deiak eta SMSak erabiltzeko baimena eman behar duzu</string>
|
||||
<string name="telephony_optional_permission_explanation">Telefono zenbakiaren ordez kontaktuaren izena ikusteko telefonoko kontaktuak atzitzeko baimena eman behar duzu</string>
|
||||
</resources>
|
@@ -31,7 +31,6 @@
|
||||
<string name="send_ping">Lähetä tiedustelupaketti</string>
|
||||
<string name="open_mpris_controls">Multimedian ohjaus</string>
|
||||
<string name="open_mousepad">Kauko-ohjaus</string>
|
||||
<string name="mousepad_info">Liikuta hiiren osoitinta liikuttamalla sormeasi näytöllä. Napsauta napauttamalla yhdellä sormella, käytä oikeaa painiketta kahdella sormella ja keskipainiketta kolmella. Vedä ja pudota painamalla pitkään.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Aseta kahden sormen napautuksen toiminto</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Aseta kolmen sormen napautuksen toiminto</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Aseta kosketuslevyn herkkyys</string>
|
||||
@@ -41,9 +40,6 @@
|
||||
<item>Keskinapsautus</item>
|
||||
<item>Ei toimintoa</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Oikea painike</string>
|
||||
<string name="mousepad_triple_default">Keskipainike</string>
|
||||
<string name="mousepad_sensitivity_default">oletus</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Hitain</item>
|
||||
<item>Hitainta suurempi</item>
|
||||
|
@@ -1,18 +1,27 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Notifications du téléphonie</string>
|
||||
<string name="pref_plugin_telephony">Notifications de téléphonie</string>
|
||||
<string name="pref_plugin_telephony_desc">Envoie des notifications pour les SMS et les appels</string>
|
||||
<string name="pref_plugin_battery">Rapport sur la batterie</string>
|
||||
<string name="pref_plugin_battery_desc">Rapport périodique sur l\'état de la batterie</string>
|
||||
<string name="pref_plugin_sftp">Exposer le système de fichiers</string>
|
||||
<string name="pref_plugin_sftp_desc">Permettre de parcourir le système de fichiers du périphérique à distance</string>
|
||||
<string name="pref_plugin_clipboard">Synchronisation avec le presse-papiers</string>
|
||||
<string name="pref_plugin_clipboard_desc">Partage le contenu du presse-papiers</string>
|
||||
<string name="pref_plugin_mousepad">Contrôle distant</string>
|
||||
<string name="pref_plugin_mousepad_desc">Utilisez votre téléphone ou tablette comme un pavé tactile et un clavier</string>
|
||||
<string name="pref_plugin_remotekeyboard">Recevoir les appuis de touches distants</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Recevoir les appuis de touches des périphériques distants</string>
|
||||
<string name="pref_plugin_mpris">Contrôles multimédia</string>
|
||||
<string name="pref_plugin_mpris_desc">Fournit une télécommande pour votre lecteur multimédia</string>
|
||||
<string name="pref_plugin_runcommand">Exécuter une commande</string>
|
||||
<string name="pref_plugin_runcommand_desc">Exécuter des commandes à distance sur votre téléphone ou tablette</string>
|
||||
<string name="pref_plugin_ping">Commande « Ping »</string>
|
||||
<string name="pref_plugin_ping_desc">Envoie et reçoit des commandes « Ping »</string>
|
||||
<string name="pref_plugin_notifications">Synchronisation des notifications</string>
|
||||
<string name="pref_plugin_notifications_desc">Accédez à vos notifications depuis d\'autres périphériques</string>
|
||||
<string name="pref_plugin_receive_notifications">Recevoir les notifications</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Recevoir les notifications du périphérique et les afficher dans Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Partager et recevoir</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Partagez des URLs et des fichiers entre périphériques</string>
|
||||
<string name="plugin_not_available">Cette fonctionnalité n\'est pas disponible dans votre version de Android</string>
|
||||
@@ -23,65 +32,76 @@
|
||||
<string name="no_permissions">Vous devez accorder la permission d\'accéder aux notifications</string>
|
||||
<string name="send_ping">Envoyer un « Ping »</string>
|
||||
<string name="open_mpris_controls">Contrôles multimédia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Gérer les appuis de touches à distance uniquement lors de l\'édition</string>
|
||||
<string name="remotekeyboard_not_connected">Aucune connexion active d\'un clavier sans fil disponible, établissez-en une dans KDE Connect</string>
|
||||
<string name="remotekeyboard_connected">La connexion au clavier sans fil est active</string>
|
||||
<string name="remotekeyboard_multiple_connections">Plusieurs connexions à des claviers sans fil sont disponibles, sélectionnez le périphérique à configurer</string>
|
||||
<string name="open_mousepad">Contrôle distant</string>
|
||||
<string name="mousepad_info">Déplacer le doigt sur l\'écran pour bouger le pointeur de la souris. Appuyez pour cliquer et utiliser deux/trois doigts pour les clic droit et centre. Appuyez longtemps pour faire un glisser déplacer.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Action pour l\'appui à deux doigts</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Action pour l\'appui à trois doigts</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Définir la sensibilité du pavé tactile</string>
|
||||
<string name="mousepad_scroll_direction_title">Inverser la direction du défilement</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic droit</item>
|
||||
<item>Clic central</item>
|
||||
<item>Rien</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Droite</string>
|
||||
<string name="mousepad_triple_default">Milieu</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
<item>Le plus lent</item>
|
||||
<item>Assez lent</item>
|
||||
<item>Par défaut</item>
|
||||
<item>Assez rapide</item>
|
||||
<item>Le plus rapide</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Périphériques connectés</string>
|
||||
<string name="category_not_paired_devices">Périphériques disponibles</string>
|
||||
<string name="category_remembered_devices">Périphériques mémorisés</string>
|
||||
<string name="plugins_failed_to_load">Le chargement des modules externes a échoué (cliquez pour plus d\'informations) :</string>
|
||||
<string name="device_menu_plugins">Paramètres du module externe</string>
|
||||
<string name="device_menu_unpair">Désapparier</string>
|
||||
<string name="device_menu_plugins">Paramètres des modules externes</string>
|
||||
<string name="device_menu_unpair">Dissocier</string>
|
||||
<string name="device_not_reachable">Périphérique inaccessible</string>
|
||||
<string name="pair_new_device">Associer un nouveau périphérique</string>
|
||||
<string name="unknown_device">Périphérique inconnu</string>
|
||||
<string name="error_not_reachable">Périphérique inaccessible</string>
|
||||
<string name="error_already_requested">L\'appariement a déjà été demandé</string>
|
||||
<string name="error_already_paired">Périphérique déjà apparié</string>
|
||||
<string name="error_already_requested">L\'association a déjà été demandée</string>
|
||||
<string name="error_already_paired">Périphérique déjà associé</string>
|
||||
<string name="error_could_not_send_package">Il est impossible d\'envoyer un paquet</string>
|
||||
<string name="error_timed_out">Délai expiré</string>
|
||||
<string name="error_canceled_by_user">Annulé par l\'utilisateur</string>
|
||||
<string name="error_canceled_by_other_peer">Annulé par un autre homologue</string>
|
||||
<string name="error_invalid_key">Clé reçue non valable</string>
|
||||
<string name="encryption_info_title">Informations de chiffrement</string>
|
||||
<string name="encryption_info_msg_no_ssl">Ce périphérique n\'utilise pas une version récente de KDE Connect qui utilise l\'ancienne méthode de chiffrement.</string>
|
||||
<string name="my_device_fingerprint">L\'empreinte SHA1 du certificat de votre appareil est :</string>
|
||||
<string name="remote_device_fingerprint">L\'empreinte SHA1 du certificat du périphérique distant est :</string>
|
||||
<string name="pair_requested">Paire demandée</string>
|
||||
<string name="pairing_request_from">Demande d\'appariement provenant de %1s</string>
|
||||
<string name="pairing_request_from">Demande d\'association provenant de %1s</string>
|
||||
<string name="received_url_title">Lien reçu de %1s</string>
|
||||
<string name="received_url_text">Appuyez pour ouvrir %1s</string>
|
||||
<string name="incoming_file_title">Réception d\'un fichier en cours depuis %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Envoi d\'un fichier à %1s</string>
|
||||
<string name="outgoing_files_title">Envoi de fichiers à %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Envoi de %1$d sur %2$d fichiers</string>
|
||||
<string name="received_file_title">Fichier reçu de %1s</string>
|
||||
<string name="received_file_fail_title">Impossible de recevoir le fichier depuis : %1s</string>
|
||||
<string name="received_file_text">Appuyez pour ouvrir %1s</string>
|
||||
<string name="sent_file_title">Fichier envoyé à %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Impossible d\'envoyer le fichier à %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Cliquer pour répondre</string>
|
||||
<string name="reconnect">Reconnecter</string>
|
||||
<string name="right_click">Envoyer un clic droit</string>
|
||||
<string name="middle_click">Envoyer un clic central</string>
|
||||
<string name="show_keyboard">Afficher le clavier</string>
|
||||
<string name="device_not_paired">Périphérique non apparié</string>
|
||||
<string name="request_pairing">Demande d\'appariement</string>
|
||||
<string name="device_not_paired">Périphérique non associé</string>
|
||||
<string name="request_pairing">Demande d\'association</string>
|
||||
<string name="pairing_accept">Accepter</string>
|
||||
<string name="pairing_reject">Rejeter</string>
|
||||
<string name="device">Périphérique</string>
|
||||
<string name="pair_device">Apparier un périphérique</string>
|
||||
<string name="pair_device">Associer un périphérique</string>
|
||||
<string name="remote_control">Contrôle distant</string>
|
||||
<string name="settings">Paramètres de connexion de KDE</string>
|
||||
<string name="mpris_play">Lire</string>
|
||||
@@ -111,9 +131,15 @@
|
||||
<string name="invalid_device_name">Nom de périphérique non valable</string>
|
||||
<string name="shareplugin_text_saved">Texte reçu et enregistré dans le presse-papiers</string>
|
||||
<string name="custom_devices_settings">Liste personnalisée de périphériques</string>
|
||||
<string name="pair_device_action">Associer un nouveau périphérique</string>
|
||||
<string name="unpair_device_action">Dissocier %s</string>
|
||||
<string name="custom_device_list">Ajouter des périphériques par IP</string>
|
||||
<string name="share_notification_preference">Notifications sonores</string>
|
||||
<string name="share_notification_preference_summary">Vibrer et jouer un son quand un fichier est reçu</string>
|
||||
<string name="share_destination_customize">Personnaliser le dossier de destination</string>
|
||||
<string name="share_destination_customize_summary_disabled">Les fichiers reçus apparaîtront dans le dossier de téléchargement</string>
|
||||
<string name="share_destination_customize_summary_enabled">Les fichiers seront enregistrés dans le dossier ci-dessous</string>
|
||||
<string name="share_destination_folder_preference">Dossier de destination</string>
|
||||
<string name="title_activity_notification_filter">Filtre des notifications</string>
|
||||
<string name="filter_apps_info">Les notifications seront synchronisées pour les applications sélectionnées.</string>
|
||||
<string name="sftp_internal_storage">Stockage interne</string>
|
||||
@@ -123,8 +149,37 @@
|
||||
<string name="sftp_readonly">(lecture seule)</string>
|
||||
<string name="sftp_camera">Images de l\'appareil photo</string>
|
||||
<string name="add_host">Ajouter hôte/IP</string>
|
||||
<string name="add_host_hint">Nom d\'hôte ou adresse IP </string>
|
||||
<string name="add_host_hint">"Nom d\'hôte ou adresse IP "</string>
|
||||
<string name="no_players_connected">Aucun lecteur trouvé</string>
|
||||
<string name="custom_dev_list_help">N\'utilisez cette option que si votre périphérique n\'est pas détecté automatiquement. Saisissez l\'adresse IP ou le nom d\'hôte ci-dessous et appuyez sur le bouton pour l\'ajouter à la liste. Appuyez sur un élément existant pour le retirer de la liste.</string>
|
||||
<string name="mpris_player_on_device">%1$s sur %2$s</string>
|
||||
<string name="send_files">Envoyer des fichiers</string>
|
||||
<string name="pairing_title">Périphériques KDE Connect</string>
|
||||
<string name="pairing_description">Les autres périphériques utilisant KDE Connect dans votre réseau apparaissent ici.</string>
|
||||
<string name="device_paired">Périphérique associé</string>
|
||||
<string name="device_rename_title">Renommer le périphérique</string>
|
||||
<string name="device_rename_confirm">Renommer</string>
|
||||
<string name="refresh">Mettre à jour</string>
|
||||
<string name="unreachable_description">Ce périphérique associé n\'est pas accessible. Assurez-vous qu\'il est bien connecté au même réseau.</string>
|
||||
<string name="on_data_message">Il semble que vous utilisiez une connexion de données mobile. KDE Connect fonctionne uniquement sur un réseau local.</string>
|
||||
<string name="no_file_browser">Aucun navigateur de fichiers installé.</string>
|
||||
<string name="pref_plugin_telepathy">Envoyer un SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Envoyer des SMS depuis votre bureau</string>
|
||||
<string name="plugin_not_supported">Ce module externe n\'est pas géré par le périphérique</string>
|
||||
<string name="findmyphone_title">Trouver mon téléphone</string>
|
||||
<string name="findmyphone_title_tablet">Trouver ma tablette</string>
|
||||
<string name="findmyphone_description">Fait sonner le périphérique pour vous aider à le retrouver</string>
|
||||
<string name="findmyphone_found">Trouvé</string>
|
||||
<string name="open">Ouvrir</string>
|
||||
<string name="close">Fermer</string>
|
||||
<string name="no_permissions_storage">Vous devez accorder la permission d\'accéder à l\'espace de stockage</string>
|
||||
<string name="plugins_need_permission">Certains modules externes nécessitent des permissions pour fonctionner (tapez pour plus d\'informations) :</string>
|
||||
<string name="permission_explanation">Ce module externe nécessite des permissions pour fonctionner</string>
|
||||
<string name="optional_permission_explanation">Vous devez accorder des permissions supplémentaires pour activer toutes les fonctionnalités</string>
|
||||
<string name="plugins_need_optional_permission">Certaines fonctionnalités de modules externes sont désactivées faute de permissions suffisantes (tapez pour plus d\'informations) :</string>
|
||||
<string name="sftp_permission_explanation">Pour accéder aux fichiers de votre ordinateur, l\'application requiert la permission d\'accéder à la mémoire de stockage de votre téléphone</string>
|
||||
<string name="share_optional_permission_explanation">Pour partager des fichiers entre votre téléphone et votre ordinateur, veuillez permettre l\'accès à la mémoire de stockage du téléphone</string>
|
||||
<string name="telepathy_permission_explanation">Pour lire et écrire des SMS depuis votre ordinateur, veuillez permettre l\'accès aux SMS</string>
|
||||
<string name="telephony_permission_explanation">Pour voir les appels et les SMS depuis votre ordinateur, veuillez permettre l\'accès aux appels et aux SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Pour voir le nom du contact au lieu du numéro de téléphone, veuillez permettre l\'accès aux contacts du téléphone</string>
|
||||
</resources>
|
||||
|
@@ -5,15 +5,23 @@
|
||||
<string name="pref_plugin_battery">Informe da batería</string>
|
||||
<string name="pref_plugin_battery_desc">Envíe periodicamente un informe sobre o estado da batería.</string>
|
||||
<string name="pref_plugin_sftp">Revelador do sistema de ficheiros</string>
|
||||
<string name="pref_plugin_sftp_desc">Permite examinar o sistema de ficheiros do dispositivo remotamente.</string>
|
||||
<string name="pref_plugin_clipboard">Sincronización do portapapeis</string>
|
||||
<string name="pref_plugin_clipboard_desc">Comparta o contido do portapapeis.</string>
|
||||
<string name="pref_plugin_mousepad">Entrada remota</string>
|
||||
<string name="pref_plugin_mousepad_desc">Use o teléfono ou tableta como área táctil e teclado.</string>
|
||||
<string name="pref_plugin_remotekeyboard">Recibir teclas premidas remotamente.</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Recibir eventos de teclas premidas de dispositivos remotos.</string>
|
||||
<string name="pref_plugin_mpris">Controis multimedia</string>
|
||||
<string name="pref_plugin_mpris_desc">Fornece un mando a distancia para o reprodutor.</string>
|
||||
<string name="pref_plugin_runcommand">Executar unha orde</string>
|
||||
<string name="pref_plugin_runcommand_desc">Provocar ordes remotas desde o teléfono ou tableta.</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Envíe e reciba pings.</string>
|
||||
<string name="pref_plugin_notifications">Sincronización de notificacións</string>
|
||||
<string name="pref_plugin_notifications_desc">Acceda ás súas notificacións desde outros dispositivos.</string>
|
||||
<string name="pref_plugin_receive_notifications">Recibir notificacións</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Recibir notificacións do outro dispositivo e mostralas en Android.</string>
|
||||
<string name="pref_plugin_sharereceiver">Compartir e recibir</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Comparta ficheiros e enderezos URL entre dispositivos.</string>
|
||||
<string name="plugin_not_available">Esta funcionalidade non está dispoñíbel para a súa versión de Android.</string>
|
||||
@@ -24,29 +32,33 @@
|
||||
<string name="no_permissions">Debe conceder permisos para acceder ás notificacións.</string>
|
||||
<string name="send_ping">Enviar un ping</string>
|
||||
<string name="open_mpris_controls">Control multimedia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Xestionar teclas remotas só ao editar.</string>
|
||||
<string name="remotekeyboard_not_connected">Non hai ningunha conexión de teclado remoto activa, estableza unha en kdeconnect.</string>
|
||||
<string name="remotekeyboard_connected">A conexión de teclado remoto está activa.</string>
|
||||
<string name="remotekeyboard_multiple_connections">Hai máis dunha conexión de teclado remoto, seleccione o dispositivo para configurar.</string>
|
||||
<string name="open_mousepad">Entrada remota</string>
|
||||
<string name="mousepad_info">Mova un dedo na pantalla para mover o cursor. Toque para facer clic, e use dous ou tres dedos para os botóns secundario e central. Prema durante un tempo para arrastrar e soltar.</string>
|
||||
<string name="mousepad_info">Mova un dedo na pantalla para mover o cursor do rato. Toque para facer clic, e use dous ou tres dedos para os botóns secundario e central. Use dous dedos para desprazar. Prema durante un tempo para arrastrar e soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Definir a acción de tocar con dous dedos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Definir a acción de tocar con tres dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do punteiro táctil</string>
|
||||
<string name="mousepad_scroll_direction_title">Inverter a dirección de desprazamento</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Clic dereito</item>
|
||||
<item>Clic central</item>
|
||||
<item>Nada</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">dereita</string>
|
||||
<string name="mousepad_triple_default">medio</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
<item>O máis lento</item>
|
||||
<item>Lento</item>
|
||||
<item>Predeterminado</item>
|
||||
<item>Rápido</item>
|
||||
<item>O máis rápido</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Dispositivos conectados</string>
|
||||
<string name="category_not_paired_devices">Dispositivos dispoñíbeis</string>
|
||||
<string name="category_remembered_devices">Dispositivos coñecidos</string>
|
||||
<string name="plugins_failed_to_load">Non foi posíbel cargar os seguintes complementos (toque para obter máis información):</string>
|
||||
<string name="device_menu_plugins">Configuración do engadido</string>
|
||||
<string name="plugins_failed_to_load">Non se puideron cargar os seguintes complementos (toque para obter máis información):</string>
|
||||
<string name="device_menu_plugins">Configuración do complemento</string>
|
||||
<string name="device_menu_unpair">Desemparellarse</string>
|
||||
<string name="device_not_reachable">O dispositivo emparellado está fóra do alcance.</string>
|
||||
<string name="pair_new_device">Emparellar cun novo dispositivo</string>
|
||||
@@ -54,11 +66,15 @@
|
||||
<string name="error_not_reachable">Dispositivo fóra do alcance</string>
|
||||
<string name="error_already_requested">Xa solicitou emparellarse.</string>
|
||||
<string name="error_already_paired">O dispositivo xa está emparellado.</string>
|
||||
<string name="error_could_not_send_package">Non foi posíbel enviar o paquete.</string>
|
||||
<string name="error_could_not_send_package">Non se puido enviar o paquete.</string>
|
||||
<string name="error_timed_out">Esgotouse o tempo límite</string>
|
||||
<string name="error_canceled_by_user">Cancelouno o usuario.</string>
|
||||
<string name="error_canceled_by_other_peer">Cancelouse remotamente</string>
|
||||
<string name="error_invalid_key">Recibiuse unha clave incorrecta.</string>
|
||||
<string name="encryption_info_title">Información do cifrado</string>
|
||||
<string name="encryption_info_msg_no_ssl">O outro dispositivo non usa unha versión recente de KDE Connect, usarase un método obsoleto de cifrado.</string>
|
||||
<string name="my_device_fingerprint">A pegada SHA1 do certificado do seu dispositivo é:</string>
|
||||
<string name="remote_device_fingerprint">A pegada SHA1 do certificado do dispositivo remoto é:</string>
|
||||
<string name="pair_requested">Solicitude de emparellamento</string>
|
||||
<string name="pairing_request_from">Solicitude de emparellamento de %1s.</string>
|
||||
<string name="received_url_title">Recibiuse unha ligazón de %1s</string>
|
||||
@@ -66,12 +82,15 @@
|
||||
<string name="incoming_file_title">Ficheiro entrande de %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Enviando un ficheiro a %1s</string>
|
||||
<string name="outgoing_files_title">Enviando os ficheiros a %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Enviáronse %1$d de %2$d ficheiros.</string>
|
||||
<string name="received_file_title">Recibiuse un ficheiro de %1s</string>
|
||||
<string name="received_file_fail_title">Non foi posíbel recibir o ficheiro de %1s</string>
|
||||
<string name="received_file_fail_title">A recepción do ficheiro de %1s fallou</string>
|
||||
<string name="received_file_text">Toque para abrir «%1s».</string>
|
||||
<string name="sent_file_title">Enviouse o ficheiro a %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Non se puido enviar o ficheiro a %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Toque para contestar</string>
|
||||
<string name="reconnect">Conectar de novo</string>
|
||||
@@ -118,8 +137,12 @@
|
||||
<string name="custom_device_list">Engadir dispositivos por IP</string>
|
||||
<string name="share_notification_preference">Notificacións sonoras</string>
|
||||
<string name="share_notification_preference_summary">Vibrar e reproducir un son ao recibir un ficheiro.</string>
|
||||
<string name="share_destination_customize">Personalizar o directorio de destino</string>
|
||||
<string name="share_destination_customize_summary_disabled">Os ficheiros recibidos aparecerán en «Descargas».</string>
|
||||
<string name="share_destination_customize_summary_enabled">Os ficheiros almacenaranse no directorio de abaixo.</string>
|
||||
<string name="share_destination_folder_preference">Directorio de destino</string>
|
||||
<string name="title_activity_notification_filter">Filtro de notificacións</string>
|
||||
<string name="filter_apps_info">As notificacións sincronizaranse para os seguintes programas.</string>
|
||||
<string name="filter_apps_info">As notificacións sincronizaranse para os seguintes aplicativos.</string>
|
||||
<string name="sftp_internal_storage">Almacenamento interno</string>
|
||||
<string name="sftp_all_files">Todos os ficheiros</string>
|
||||
<string name="sftp_sdcard_num">Tarxeta SD %d</string>
|
||||
@@ -129,21 +152,35 @@
|
||||
<string name="add_host">Engadir unha nome ou IP</string>
|
||||
<string name="add_host_hint">Nome ou IP do servidor.</string>
|
||||
<string name="no_players_connected">Non se atoparon reprodutores.</string>
|
||||
<string name="custom_dev_list_help">Marque esta opción unicamente se o seu dispositivo non se detecta automaticamente. Escriba o enderezo IP ou o nome de servidor do dispositivo e toque o botón para engadilo á lista. Toque un elemento existente para retiralo da lista.</string>
|
||||
<string name="custom_dev_list_help">Marque esta opción só se o seu dispositivo non se detecta automaticamente. Insira o enderezo IP ou o nome de servidor do dispositivo e toque o botón para engadilo á lista. Toque un elemento existente para retiralo da lista.</string>
|
||||
<string name="mpris_player_on_device">%1$s en %2$s</string>
|
||||
<string name="send_files">Enviar ficheiros</string>
|
||||
<string name="pairing_title">Dispositivos con KDE Connect</string>
|
||||
<string name="pairing_description">Outros dispositivos que estean a executar KDE Connect na mesma rede deberían aparecer aquí.</string>
|
||||
<string name="device_paired">Emparellouse co dispositivo</string>
|
||||
<string name="device_rename_title">Cambiar o nome do dispositivo</string>
|
||||
<string name="device_rename_confirm">Mudar o nome</string>
|
||||
<string name="device_rename_title">Renomear o dispositivo</string>
|
||||
<string name="device_rename_confirm">Renomear</string>
|
||||
<string name="refresh">Actualizar</string>
|
||||
<string name="unreachable_description">Este dispositivo emparellado está fóra do alcance. Asegúrese de que está conectado á mesma rede.</string>
|
||||
<string name="on_data_message">Parece que está usando unha conexión de datos de móbil. KDE Connect só funciona en redes locais.</string>
|
||||
<string name="no_file_browser">Non hai navegadores de ficheiros instalados.</string>
|
||||
<string name="pref_plugin_telepathy">Enviar unha mensaxe de texto</string>
|
||||
<string name="pref_plugin_telepathy_desc">Enviar mensaxes de texto desde un computador de escritorio.</string>
|
||||
<string name="plugin_not_supported">O dispositivo non é compatíbel con este complemento.</string>
|
||||
<string name="findmyphone_title">Atopar o móbil</string>
|
||||
<string name="findmyphone_title_tablet">Atopar a tableta</string>
|
||||
<string name="findmyphone_description">Reproduce un son de chamada no dispositivo para que poida atopalo.</string>
|
||||
<string name="findmyphone_found">Atopado</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Pechar</string>
|
||||
<string name="no_permissions_storage">Debe conceder permisos para acceder ao almacenamento.</string>
|
||||
<string name="plugins_need_permission">Algúns complementos necesitan permisos para funcionar (toque para máis información):</string>
|
||||
<string name="permission_explanation">Este complemento necesita permisos para funcionar.</string>
|
||||
<string name="optional_permission_explanation">Ten que conceder permisos adicionais para activar todas as funcións.</string>
|
||||
<string name="plugins_need_optional_permission">Algúns complementos teñen funcionalidades desactivadas por mor dunha falta de permisos (toque para máis información):</string>
|
||||
<string name="sftp_permission_explanation">Para acceder aos seus ficheiros desde o computador o aplicativo necesita permiso para acceder ao almacenamento do teléfono.</string>
|
||||
<string name="share_optional_permission_explanation">Para compartir ficheiros entre o teléfono e o escritorio ten que dar acceso ao almacenamento do teléfono.</string>
|
||||
<string name="telepathy_permission_explanation">Para ler e escribir SMS desde o escritorio ten que dar permiso de SMS.</string>
|
||||
<string name="telephony_permission_explanation">Para ver as chamadas de teléfono e os SMS desde o escritorio ten que dar permiso a chamadas de teléfono e a SMS.</string>
|
||||
<string name="telephony_optional_permission_explanation">Para ver o nome dun contacto en vez dun número de teléfono ten que dar acceso aos contactos do teléfono.</string>
|
||||
</resources>
|
||||
|
@@ -5,15 +5,23 @@
|
||||
<string name="pref_plugin_battery">דיווח סוללה</string>
|
||||
<string name="pref_plugin_battery_desc">מדווח על אחוז הסוללה למחשב</string>
|
||||
<string name="pref_plugin_sftp">גישה לקבצים</string>
|
||||
<string name="pref_plugin_clipboard">סנכנרון לוח העתקה</string>
|
||||
<string name="pref_plugin_clipboard_desc">שתף בין המחשבים את מה שמועתק</string>
|
||||
<string name="pref_plugin_sftp_desc">אפשר להתקן המרוחק לדפדף בקבצים של הפלאפון מרחוק</string>
|
||||
<string name="pref_plugin_clipboard">סנכרון לוח העתקה</string>
|
||||
<string name="pref_plugin_clipboard_desc">שתף בין המחשבים את כל מה שמועתק</string>
|
||||
<string name="pref_plugin_mousepad">שליטה מרחוק</string>
|
||||
<string name="pref_plugin_mousepad_desc">השתמש בפלאפון כדי לשלוט בעכבר ובמקלדת של ההתקן המרוחק</string>
|
||||
<string name="pref_plugin_remotekeyboard">קבלת לחיצות מרחוק</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">קבלת אירועי מקלדת מהתקן מרוחק</string>
|
||||
<string name="pref_plugin_mpris">שליטה במדיה</string>
|
||||
<string name="pref_plugin_mpris_desc">מספק שליטה מרוחקת על נגן המדיה שלך</string>
|
||||
<string name="pref_plugin_runcommand">הרץ פקודה</string>
|
||||
<string name="pref_plugin_runcommand_desc">הרץ פקודה במחשב מהמכשיר שלך</string>
|
||||
<string name="pref_plugin_ping">פינג</string>
|
||||
<string name="pref_plugin_ping_desc">שלח וקבל פינגים</string>
|
||||
<string name="pref_plugin_notifications">סנכרון התראות</string>
|
||||
<string name="pref_plugin_notifications_desc">הראה את ההתראות מהפלאפון בהתקן אחר</string>
|
||||
<string name="pref_plugin_receive_notifications">קבלת התראות</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">קבל התראות מהתקן אחר והצג אותם במכשיר שלך</string>
|
||||
<string name="pref_plugin_sharereceiver">שתף וקבל קבצים וכתובות</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">שתף וקבל קבצים וכתובת אינטרנט בין התקנים</string>
|
||||
<string name="plugin_not_available">אפשרות זו אינה זמינה בגרסת האנדרואיד שלך</string>
|
||||
@@ -24,8 +32,11 @@
|
||||
<string name="no_permissions">אתה צריך לתת הרשאות לגישה להתראות</string>
|
||||
<string name="send_ping">שלח פינג</string>
|
||||
<string name="open_mpris_controls">שליטה על המדיה</string>
|
||||
<string name="open_mousepad">שלוט על המחשב</string>
|
||||
<string name="mousepad_info">הזז את האצבע על המסך כדי להזיז את סמן העכבר במחשב. לחץ כדי ללחוץ במחשב, השתמש בשנים או שלוש אצבעות כדי ללחוץ על המקש הימני או האמצעי. השתמש בליחצה ארוכה לגרירה ושחרור.</string>
|
||||
<string name="remotekeyboard_editing_only_title">השתמש במקשים מרוחקים רק בעת עריכה</string>
|
||||
<string name="remotekeyboard_not_connected">אין מקלדת מרוחקת מופעלת, הוסף אחת ל־kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">חיבור המקדלת המרוחקת פעיל</string>
|
||||
<string name="remotekeyboard_multiple_connections">ישנם כמה מקלדות מרוחקות מחוברות, בחר את ההתקן להגדרה</string>
|
||||
<string name="open_mousepad">שליטה מרחוק</string>
|
||||
<string name="mousepad_double_tap_settings_title">הגדר פעולה ללחיצת שתי אצבעות</string>
|
||||
<string name="mousepad_triple_tap_settings_title">הגדר פעולה ללחיצת שלוש אצבעות</string>
|
||||
<string name="mousepad_sensitivity_settings_title">הגדר רגישות משטח המגע</string>
|
||||
@@ -35,9 +46,6 @@
|
||||
<item>לחיצה אצמעית (גלגלת)</item>
|
||||
<item>שום דבר</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">ימין</string>
|
||||
<string name="mousepad_triple_default">אמצע</string>
|
||||
<string name="mousepad_sensitivity_default">ברירת מחדל</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>הכי איטי</item>
|
||||
<item>יותר מההכי איטי</item>
|
||||
@@ -59,9 +67,9 @@
|
||||
<string name="error_already_paired">ההתקן כבר מותאם</string>
|
||||
<string name="error_could_not_send_package">לא יכול לשלוח חבילה</string>
|
||||
<string name="error_timed_out">נגמר הזמן</string>
|
||||
<string name="error_canceled_by_user">בוטל ע\"י המשתמש</string>
|
||||
<string name="error_canceled_by_other_peer">בוטל ע\"י מישהו אחר</string>
|
||||
<string name="error_invalid_key">התקבל מפתח לא חוקי</string>
|
||||
<string name="error_canceled_by_user">בוטל על ידי המשתמש</string>
|
||||
<string name="error_canceled_by_other_peer">בוטל על ידי מישהו אחר</string>
|
||||
<string name="error_invalid_key">התקבל מפתח לא תקין</string>
|
||||
<string name="encryption_info_title">פרטי הצפנה</string>
|
||||
<string name="encryption_info_msg_no_ssl">ההתקן השני אינו משתמש בגרסה האחרונה של KDE Connect, משתמש בשיטת ההצפנה הישנה.</string>
|
||||
<string name="my_device_fingerprint">טביעת האצבע SHA1 של ההתקן היא:</string>
|
||||
@@ -69,16 +77,19 @@
|
||||
<string name="pair_requested">בקשת התאמה</string>
|
||||
<string name="pairing_request_from">בוקשה התאמה מ־%1s</string>
|
||||
<string name="received_url_title">התקבל קישור מ־%1s</string>
|
||||
<string name="received_url_text">לחץ כדי לפתוח את \'%1s\'</string>
|
||||
<string name="incoming_file_title">התקבל קובץ ־%1s</string>
|
||||
<string name="received_url_text">לחץ כדי לפתוח את \"%1s\"</string>
|
||||
<string name="incoming_file_title">התקבל קובץ מאת %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">שולח קובץ ל־%1s</string>
|
||||
<string name="outgoing_file_title">שולח קובץ אל %1s</string>
|
||||
<string name="outgoing_files_title">שולח קובצים אל %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="received_file_title">התקבל קובץ מ־%1s</string>
|
||||
<string name="received_file_fail_title">נכשל בקבלת קובץ מ־%1s</string>
|
||||
<string name="received_file_text">לחץ כדי לפתוח את %1s</string>
|
||||
<string name="sent_file_title">הקובץ נשלח ל־%1s</string>
|
||||
<string name="outgoing_files_text">"שולח %1$d מתוך %2$d קבצים "</string>
|
||||
<string name="received_file_title">התקבל קובץ מאת %1s</string>
|
||||
<string name="received_file_fail_title">נכשל בקבלת קובץ מאת %1s</string>
|
||||
<string name="received_file_text">לחץ כדי לפתוח את \"%1s\"</string>
|
||||
<string name="sent_file_title">הקובץ נשלח אל %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">נכשל בשליחת הקובץ אל %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">לחץ כדי לענות</string>
|
||||
<string name="reconnect">התחבר מחדש</string>
|
||||
@@ -109,22 +120,26 @@
|
||||
<item>דקה</item>
|
||||
<item>שתי דקות</item>
|
||||
</string-array>
|
||||
<string name="share_to">שתף ל...</string>
|
||||
<string name="share_to">שתף אל...</string>
|
||||
<string name="protocol_version_older">ההתקן משתמש בגרסה ישנה יותר</string>
|
||||
<string name="protocol_version_newer">ההתקן משתמש בגרסה חדשה יותר</string>
|
||||
<string name="general_settings">הגדרות כלליות</string>
|
||||
<string name="plugin_settings">הגדרות</string>
|
||||
<string name="plugin_settings_with_name">הגדרות %s</string>
|
||||
<string name="device_name">שם המכשיר</string>
|
||||
<string name="device_name">שם ההתקן</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">שם המכשיר לא תקין</string>
|
||||
<string name="invalid_device_name">שם ההתקן לא תקין</string>
|
||||
<string name="shareplugin_text_saved">התקבל טקסט, נשמר ללוח העתקה</string>
|
||||
<string name="custom_devices_settings">רשימת התקנים מותאמת אישית</string>
|
||||
<string name="pair_device_action">התאם התקן חדש</string>
|
||||
<string name="unpair_device_action">בטל את ההתאמה עם %s</string>
|
||||
<string name="custom_device_list">הוסף התקן ע\"י כתובת IP</string>
|
||||
<string name="custom_device_list">הוסף התקן על ידי כתובת IP</string>
|
||||
<string name="share_notification_preference">התראות רועשות</string>
|
||||
<string name="share_notification_preference_summary">רטוט ונגן צליל בעת קבלת קובץ</string>
|
||||
<string name="share_destination_customize">שנה תקיית יעד</string>
|
||||
<string name="share_destination_customize_summary_disabled">קבצים שהתקבלו יהיו בהורדות</string>
|
||||
<string name="share_destination_customize_summary_enabled">קבצים יאוכסנו בתיקיה למטה</string>
|
||||
<string name="share_destination_folder_preference">תיקית יעד</string>
|
||||
<string name="title_activity_notification_filter">סנן התראות</string>
|
||||
<string name="filter_apps_info">התראות יסונכרנו רק לאפליקציות נבחרות</string>
|
||||
<string name="sftp_internal_storage">זיכרון פנימי</string>
|
||||
@@ -133,11 +148,11 @@
|
||||
<string name="sftp_sdcard">כרטיס זיכרון</string>
|
||||
<string name="sftp_readonly">(לקריאה בלבד)</string>
|
||||
<string name="sftp_camera">תמונות מצלמה</string>
|
||||
<string name="add_host">הוסף כתובת שרת או IP</string>
|
||||
<string name="add_host_hint">כתבות שרת או IP</string>
|
||||
<string name="add_host">הוסף כתובת או IP</string>
|
||||
<string name="add_host_hint">כתובת או IP</string>
|
||||
<string name="no_players_connected">לא נמצא נגן</string>
|
||||
<string name="custom_dev_list_help">השתמש באפשרות זו רק אם המכשיר שלך לא מזוהה באופן אוטומטי. הקלד את כתובת הIP או את כינוי ההתקן למטה ולחץ על הכפתור כדי להוסיף לרשימה. לחץ על פריט קיים כדי להסיר אותו מהרשימה.</string>
|
||||
<string name="mpris_player_on_device">%1$s ב־%2$s</string>
|
||||
<string name="mpris_player_on_device">%1$s אצל %2$s</string>
|
||||
<string name="send_files">שלח קובץ</string>
|
||||
<string name="pairing_title">מכשירי KDE Connect</string>
|
||||
<string name="pairing_description">התקנים אחרים המריצים KDE Connect ברשת הנוכחית צריכים להופיע פה.</string>
|
||||
@@ -145,12 +160,15 @@
|
||||
<string name="device_rename_title">שנה שם התקן</string>
|
||||
<string name="device_rename_confirm">שנה שם</string>
|
||||
<string name="refresh">רענן</string>
|
||||
<string name="unreachable_description">ההתקן המתואם לא זמין, וודא שהוא מחובר לאותה רשת אליה התקן זה מחובר.</string>
|
||||
<string name="unreachable_description">ההתקן המתואם לא זמין, וודא שהוא מחובר לאותה רשת אליה אתה מחובר.</string>
|
||||
<string name="on_data_message">נראה שאתה מחובר דרך הרשת הסלולרית. KDE Connect עובד רק עם רשתות מקומיות.</string>
|
||||
<string name="no_file_browser">לא נמצאו מנהלי קבצים מותקנים במכשיר זה.</string>
|
||||
<string name="pref_plugin_telepathy">שלח SMS</string>
|
||||
<string name="pref_plugin_telepathy">שליחת הודעת SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">שלח הודעות מהמחשב שלך</string>
|
||||
<string name="plugin_not_supported">התוסף הזה לא נתמך ע\"י המכשיר שלך</string>
|
||||
<string name="findmyphone_title">מצא את המכשיר שלי</string>
|
||||
<string name="plugin_not_supported">תוסף הזה לא נתמך על ידי המכשיר שלך</string>
|
||||
<string name="findmyphone_title">מצא את הפלאפון שלי</string>
|
||||
<string name="findmyphone_title_tablet">מצא את הטבלט שלי</string>
|
||||
<string name="findmyphone_description">מפעיל רעש במכשיר כדי שתוכל למצוא אותו.</string>
|
||||
<string name="findmyphone_found">נמצא</string>
|
||||
<string name="open">פתח</string>
|
||||
<string name="close">סגור</string>
|
||||
|
@@ -37,7 +37,7 @@
|
||||
<string name="remotekeyboard_connected">La connessione della tastiera remota è attiva</string>
|
||||
<string name="remotekeyboard_multiple_connections">Ci sono più connessioni di tastiere remote, seleziona il dispositivo da configurare</string>
|
||||
<string name="open_mousepad">Impulso remoto</string>
|
||||
<string name="mousepad_info">Muovi un dito sullo schermo per spostare il puntatore del mouse. Tocca per un clic e usa due/tre dita per i pulsanti destro e centrale. Utilizza una pressione lunga per trascinare e rilasciare.</string>
|
||||
<string name="mousepad_info">Muovi un dito sullo schermo per spostare il puntatore del mouse. Tocca per un clic e usa due/tre dita per i pulsanti destro e centrale. Utilizza 2 dita per scorrere. Utilizza una pressione lunga per trascinare e rilasciare.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Imposta azione per il tocco a due dita</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Imposta azione per il tocco a tre dita</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Imposta la sensibilità del touchpad</string>
|
||||
@@ -47,9 +47,6 @@
|
||||
<item>Clic centrale</item>
|
||||
<item>Niente</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">destra</string>
|
||||
<string name="mousepad_triple_default">centro</string>
|
||||
<string name="mousepad_sensitivity_default">predefinita</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Minima</item>
|
||||
<item>Più veloce</item>
|
||||
@@ -165,6 +162,7 @@
|
||||
<string name="device_rename_confirm">Rinomina</string>
|
||||
<string name="refresh">Aggiorna</string>
|
||||
<string name="unreachable_description">Questo dispositivo associato non è raggiungibile. Assicurati che sia connesso alla tua stessa rete.</string>
|
||||
<string name="on_data_message">Sembra che tu stia utilizzando una connessione dati mobile. KDE Connect funziona solo su reti locali.</string>
|
||||
<string name="no_file_browser">Non ci sono navigatori di file installati.</string>
|
||||
<string name="pref_plugin_telepathy">Invia SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Invia messaggi di testo dal tuo desktop</string>
|
||||
@@ -175,4 +173,14 @@
|
||||
<string name="findmyphone_found">Trovato</string>
|
||||
<string name="open">Apri</string>
|
||||
<string name="close">Chiudi</string>
|
||||
<string name="no_permissions_storage">Devi concedere i permessi per l\'accesso all\'archiviazione</string>
|
||||
<string name="plugins_need_permission">Alcune estensioni hanno bisogno di permessi per funzionare (tocca per maggiori informazioni):</string>
|
||||
<string name="permission_explanation">Questa estensione ha bisogno di permessi per funzionare</string>
|
||||
<string name="optional_permission_explanation">Devi concedere permessi aggiuntivi per abilitare tutte le funzioni</string>
|
||||
<string name="plugins_need_optional_permission">Alcune estensioni hanno funzioni disabilitate per una mancanza di permessi (tocca per maggiori informazioni):</string>
|
||||
<string name="sftp_permission_explanation">Per accedere ai tuoi file dal tuo PC, l\'applicazione ha bisogno dell\'autorizzazione di accesso alla memoria del telefono</string>
|
||||
<string name="share_optional_permission_explanation">Per condividere i file tra il telefono e il tuo desktop devi dare accesso alla memoria del telefono</string>
|
||||
<string name="telepathy_permission_explanation">Per leggere e scrivere SMS dal tuo desktop, devi concedere l\'autorizzazione per SMS</string>
|
||||
<string name="telephony_permission_explanation">Per vedere le chiamate telefoniche e gli SMS dal desktop devi dare l\'autorizzazione per telefonate e SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Per vedere il nome di un contatto invece del numero di telefono devi dare accesso alla rubrica del telefono</string>
|
||||
</resources>
|
||||
|
@@ -31,7 +31,6 @@
|
||||
<string name="send_ping">핑 보내기</string>
|
||||
<string name="open_mpris_controls">멀티미디어 제어</string>
|
||||
<string name="open_mousepad">원격 입력</string>
|
||||
<string name="mousepad_info">화면에서 손가락을 움직이면 마우스 커서를 움직입니다. 화면을 누르면 왼쪽 단추를 누르고, 두 손가락과 세 손가락으로 누르면 오른쪽/가운데 단추를 누릅니다. 드래그 앤 드롭을 사용하려면 길게 누르십시오.</string>
|
||||
<string name="mousepad_double_tap_settings_title">두 손가락으로 눌렀을 때 동작 설정</string>
|
||||
<string name="mousepad_triple_tap_settings_title">세 손가락으로 눌렀을 때 동작 설정</string>
|
||||
<string name="mousepad_sensitivity_settings_title">터치패드 감도 설정</string>
|
||||
@@ -41,9 +40,6 @@
|
||||
<item>가운데 단추 누름</item>
|
||||
<item>아무것도 안 함</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">오른쪽</string>
|
||||
<string name="mousepad_triple_default">가운데</string>
|
||||
<string name="mousepad_sensitivity_default">기본값</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>느리게</item>
|
||||
<item>느리게 이상</item>
|
||||
|
@@ -41,14 +41,11 @@
|
||||
<string name="error_already_requested">Jau paprašyta suporuoti</string>
|
||||
<string name="error_already_paired">Įrenginys jau suporuotas</string>
|
||||
<string name="error_could_not_send_package">Nepavyksta išsiųsti paketo</string>
|
||||
<string name="error_timed_out">Skirtasis laikas baigėsi</string>
|
||||
<string name="error_canceled_by_user">Naudotojas atšaukė užduotį</string>
|
||||
<string name="error_canceled_by_other_peer">Porininkas atšaukė užduotį</string>
|
||||
<string name="error_invalid_key">Gautas netinkamas raktas</string>
|
||||
<string name="pair_requested">Paprašyta suporuoti</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Norėdami atsakyti, palieskite</string>
|
||||
<string name="reconnect">Prisijungti iš naujo</string>
|
||||
<string name="show_keyboard">Rodyti klaviatūrą</string>
|
||||
@@ -86,7 +83,6 @@
|
||||
<string name="pair_device_action">Suporuoti naują įrenginį</string>
|
||||
<string name="unpair_device_action">Atrišti %s</string>
|
||||
<string name="custom_device_list">Pridėti įrenginį pagal IP</string>
|
||||
<string name="sftp_internal_storage">Vidinė saugykla</string>
|
||||
<string name="sftp_all_files">Visi failai</string>
|
||||
<string name="sftp_sdcard_num">SD kortelė %d</string>
|
||||
<string name="sftp_sdcard">SD kortelė</string>
|
||||
@@ -100,9 +96,12 @@
|
||||
<string name="pairing_description">Čia turėtų pasirodyti to kiti paties tinklo įrenginiai, kuriuose veikia „KDE Connect“</string>
|
||||
<string name="device_paired">Įrenginys suporuotas</string>
|
||||
<string name="device_rename_title">Pervadinti įrenginį</string>
|
||||
<string name="device_rename_confirm">Pervadinti</string>
|
||||
<string name="refresh">Atnaujinti</string>
|
||||
<string name="unreachable_description">Šis suporuotas įrenginys nepasiekiamas. Patikrinkite, ar jis prisijungęs prie to paties tinklo.</string>
|
||||
<string name="pref_plugin_telepathy">Siųsti SMS</string>
|
||||
<string name="plugin_not_supported">Telefonas nepalaiko šio papildinio</string>
|
||||
<string name="findmyphone_found">Radau</string>
|
||||
<string name="open">Atverti</string>
|
||||
<string name="close">Užverti</string>
|
||||
</resources>
|
||||
|
@@ -37,7 +37,7 @@
|
||||
<string name="remotekeyboard_connected">Verbinding met toetsenbord op afstand is actief</string>
|
||||
<string name="remotekeyboard_multiple_connections">Er is meer dan een verbinding met een toetsenbord op afstand, selecteer het te configureren apparaat</string>
|
||||
<string name="open_mousepad">Invoer op afstand</string>
|
||||
<string name="mousepad_info">Veeg met een vinger op het scherm om de muiscursor te verplaatsen. Tik om te klikken en gebruik twee/drie vingers voor rechter en middelste knop. Druk lang voor slepen en loslaten.</string>
|
||||
<string name="mousepad_info">Veeg met een vinger op het scherm om de muiscursor te verplaatsen. Tik om te klikken en gebruik twee/drie vingers voor rechter en middelste knop. Twee vingers gebruiken voor schuiven. Druk lang voor slepen en loslaten.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Tikactie met twee vingers instellen</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Tikactie met drie vingers instellen</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Gevoeligheid van touchpad instellen</string>
|
||||
@@ -47,9 +47,6 @@
|
||||
<item>Middelste muisklik</item>
|
||||
<item>Niets</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">rechts</string>
|
||||
<string name="mousepad_triple_default">midden</string>
|
||||
<string name="mousepad_sensitivity_default">standaard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Langzaamst</item>
|
||||
<item>Langzaam</item>
|
||||
@@ -67,7 +64,7 @@
|
||||
<string name="pair_new_device">Nieuw apparaat paren</string>
|
||||
<string name="unknown_device">Onbekend apparaat</string>
|
||||
<string name="error_not_reachable">Apparaat niet bereikbaar</string>
|
||||
<string name="error_already_requested">Paar maken is al gevraagd</string>
|
||||
<string name="error_already_requested">Paarvorming is al gevraagd</string>
|
||||
<string name="error_already_paired">Apparaat is al gepaard</string>
|
||||
<string name="error_could_not_send_package">Kon pakket niet verzenden</string>
|
||||
<string name="error_timed_out">Tijdslimiet overschreden</string>
|
||||
@@ -78,22 +75,22 @@
|
||||
<string name="encryption_info_msg_no_ssl">Het andere apparaat gebruikt geen recente versie van KDE Connect, de verouderde versleutelingsmethode zal worden gebruikt.</string>
|
||||
<string name="my_device_fingerprint">De SHA1 vingerafdruk van het certificaat van uw apparaat is:</string>
|
||||
<string name="remote_device_fingerprint">De SHA1 vingerafdruk van het certificaat van het apparaat op afstand is:</string>
|
||||
<string name="pair_requested">Paar gevraagd</string>
|
||||
<string name="pair_requested">Paarvorming gevraagd</string>
|
||||
<string name="pairing_request_from">Verzoek om een paar te maken van %1s</string>
|
||||
<string name="received_url_title">Ontvangen koppeling van %1s</string>
|
||||
<string name="received_url_text">Tap om \'%1s\' te openen</string>
|
||||
<string name="incoming_file_title">Inkomend bestand van %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Bezig bestand te verzenden naar %1s</string>
|
||||
<string name="outgoing_files_title">Bestanden verzenden naar %1s</string>
|
||||
<string name="outgoing_files_title">Bezig bestanden te verzenden naar %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Verzonden %1$d van %2$d bestanden</string>
|
||||
<string name="outgoing_files_text">Verzonden %1$d uit %2$d bestanden</string>
|
||||
<string name="received_file_title">Bestand ontvangen van %1s</string>
|
||||
<string name="received_file_fail_title">Bestand ontvangen van %1s is mislukt</string>
|
||||
<string name="received_file_text">Tap om \'%1s\' te openen</string>
|
||||
<string name="sent_file_title">Bestand verzonden naar %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Verzenden van bestanden naar %1s is mislukt</string>
|
||||
<string name="sent_file_failed_title">Verzenden van bestand naar %1s is mislukt</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tap om te antwoorden</string>
|
||||
<string name="reconnect">Opnieuw verbinden</string>
|
||||
@@ -140,7 +137,7 @@
|
||||
<string name="custom_device_list">Voeg apparaten toe per IP-adres</string>
|
||||
<string name="share_notification_preference">Luidruchtige meldingen</string>
|
||||
<string name="share_notification_preference_summary">Vibreer en speel een geluidje bij ontvangen van een bestand</string>
|
||||
<string name="share_destination_customize">Pas bestemmingsmap aan</string>
|
||||
<string name="share_destination_customize">De bestemmingsmap aanpassen</string>
|
||||
<string name="share_destination_customize_summary_disabled">Ontvangen bestanden zullen in Downloads verschijnen</string>
|
||||
<string name="share_destination_customize_summary_enabled">Bestanden zullen opgeslagen worden in de onderstaande map</string>
|
||||
<string name="share_destination_folder_preference">Bestemmingsmap</string>
|
||||
@@ -165,6 +162,7 @@
|
||||
<string name="device_rename_confirm">Hernoemen</string>
|
||||
<string name="refresh">Verversen</string>
|
||||
<string name="unreachable_description">Dit gepaarde apparaat is niet bereikbaar. Ga na dat het is verbonden met uw zelfde netwerk.</string>
|
||||
<string name="on_data_message">Het lijkt of op een mobiele gegevensverbinding zit. KDE Connect werkt alleen op locale netwerken.</string>
|
||||
<string name="no_file_browser">Er zijn geen bestandsbrowsers geïnstalleerd.</string>
|
||||
<string name="pref_plugin_telepathy">SMS verzenden</string>
|
||||
<string name="pref_plugin_telepathy_desc">Stuur tekstberichten van uw bureaublad</string>
|
||||
@@ -175,4 +173,14 @@
|
||||
<string name="findmyphone_found">Gevonden</string>
|
||||
<string name="open">Openen</string>
|
||||
<string name="close">Sluiten</string>
|
||||
<string name="no_permissions_storage">U moet toestemming geven voor toegang tot de opslag</string>
|
||||
<string name="plugins_need_permission">Sommige plug-ins hebben toestemming nodig om te werken (tik voor meer informatie):</string>
|
||||
<string name="permission_explanation">Deze plug-in heeft toestemming nodig om te werken</string>
|
||||
<string name="optional_permission_explanation">U moet toestemming geven om alle functies in te schakelen</string>
|
||||
<string name="plugins_need_optional_permission">Sommige plug-ins hebben functies uitgeschakeld vanwege ontbrekende toestemming (tik voor meer informatie):</string>
|
||||
<string name="sftp_permission_explanation">"Om toegang tot uw bestanden te krijgen vanuit uw PC heeft de app toestemming nodig voor toegang tot de opslag van uw telefoon "</string>
|
||||
<string name="share_optional_permission_explanation">Om bestanden tussen uw telefoon en uw bureaublad te delen moet u toegang geven tot de opslag van uw telefoon</string>
|
||||
<string name="telepathy_permission_explanation">Om een SMS te lezen of te schrijven vanaf uw bureaublad moet u toestemming geven tot SMS</string>
|
||||
<string name="telephony_permission_explanation">Om telefoonoproepen en SMS te zien vanaf het bureaublad moet u toestemming geven tot telefoonoproepen en SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Om een naam van een contactpersoon te zien in plaats van een telefoonnummer moet u toegang geven tot de contacten in uw telefoon</string>
|
||||
</resources>
|
||||
|
@@ -9,13 +9,15 @@
|
||||
<string name="pref_plugin_clipboard">Synkroniser utklippstavle</string>
|
||||
<string name="pref_plugin_clipboard_desc">Del innhaldet på utklippstavla</string>
|
||||
<string name="pref_plugin_mousepad">Fjernstyring</string>
|
||||
<string name="pref_plugin_mousepad_desc">Bruk telefonen eller nettbrettet som styrepute og tastatur</string>
|
||||
<string name="pref_plugin_mousepad_desc">Bruk telefonen eller nettbrettet som styreplate og tastatur</string>
|
||||
<string name="pref_plugin_remotekeyboard">Ta imot eksterne tastetrykk</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Ta imot tastetrykk frå eksterne einingar</string>
|
||||
<string name="pref_plugin_mpris">Mediekontrollar</string>
|
||||
<string name="pref_plugin_mpris_desc">Gjev fjernkontroll til mediespelarar</string>
|
||||
<string name="pref_plugin_mpris_desc">Gje fjernkontroll til mediespelarar</string>
|
||||
<string name="pref_plugin_runcommand">Køyr kommando</string>
|
||||
<string name="pref_plugin_runcommand_desc">Utløys fjernkommandoar frå telefonen eller nettbrettet</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Send og ta imot ping-signal</string>
|
||||
<string name="pref_plugin_ping_desc">Send og ta imot pingsignal</string>
|
||||
<string name="pref_plugin_notifications">Varslingssynkronisering</string>
|
||||
<string name="pref_plugin_notifications_desc">Få tilgang til varslingar frå andre einingar</string>
|
||||
<string name="pref_plugin_receive_notifications">Få varslingar</string>
|
||||
@@ -30,20 +32,21 @@
|
||||
<string name="no_permissions">Du må gje tilgang til lesing av varslingar</string>
|
||||
<string name="send_ping">Send pingsignal</string>
|
||||
<string name="open_mpris_controls">Mediekontroll</string>
|
||||
<string name="remotekeyboard_editing_only_title">Handter eksterne tastetrykk berre ved redigering</string>
|
||||
<string name="remotekeyboard_not_connected">Det finst ikkje noko verksamt tastatursamband (må setjast opp i KDE Connect)</string>
|
||||
<string name="remotekeyboard_connected">Eksternt tastatursamband er verksamt</string>
|
||||
<string name="remotekeyboard_multiple_connections">Det finst meir enn eitt eksternt tastatursamband (vel eining å setja opp)</string>
|
||||
<string name="open_mousepad">Fjernstyring</string>
|
||||
<string name="mousepad_info">Dra ein finger over skjermen for å flytta peikaren på datamaskina. Trykk for å klikka, og bruk to eller tre fingrar for høvesvis høgre- og midtknappen. Trykk og hald for å dra og sleppa.</string>
|
||||
<string name="mousepad_info">Dra ein finger over skjermen for å flytta peikaren på datamaskina. Trykk for å klikka, og bruk to eller tre fingrar for høvesvis høgre- og midtknappen. Bruk to fingrar for å rulla. Trykk lenge for å dra og sleppa.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Vel handling for tofingertrykk</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Vel handling for trefingertrykk</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Vel følsemd for styrepute</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Vel følsemd for styreplate</string>
|
||||
<string name="mousepad_scroll_direction_title">Omvend rulleretning</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Høgreklikk</item>
|
||||
<item>Midtklikk</item>
|
||||
<item>Ingenting</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">høgre</string>
|
||||
<string name="mousepad_triple_default">midt</string>
|
||||
<string name="mousepad_sensitivity_default">standard</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Saktast</item>
|
||||
<item>Raskare enn saktast</item>
|
||||
@@ -55,7 +58,7 @@
|
||||
<string name="category_not_paired_devices">Tilgjengelege einingar</string>
|
||||
<string name="category_remembered_devices">Hugs einingar</string>
|
||||
<string name="plugins_failed_to_load">Klarte ikkje lasta programtillegg (trykk for meir informasjon):</string>
|
||||
<string name="device_menu_plugins">Innstillingar for programtillegg</string>
|
||||
<string name="device_menu_plugins">Programtillegg-oppsett</string>
|
||||
<string name="device_menu_unpair">Løys paring</string>
|
||||
<string name="device_not_reachable">Får ikkje kontakt med para eining</string>
|
||||
<string name="pair_new_device">Par ny eining</string>
|
||||
@@ -70,8 +73,8 @@
|
||||
<string name="error_invalid_key">Fekk ugyldig nøkkel</string>
|
||||
<string name="encryption_info_title">Krypteringsinfo</string>
|
||||
<string name="encryption_info_msg_no_ssl">Den andre eininga brukar ein gammal versjon av KDE Connect, med ein utdatert krypteringsmetode.</string>
|
||||
<string name="my_device_fingerprint">SHA-fingeravtrykk av einingssertifikatet er:</string>
|
||||
<string name="remote_device_fingerprint">SHA-fingeravtrykk av fjerneiningssertifikatet er:</string>
|
||||
<string name="my_device_fingerprint">SHA-fingeravtrykket til einingssertifikatet er:</string>
|
||||
<string name="remote_device_fingerprint">SHA-fingeravtrykket fjerneiningssertifikatet er:</string>
|
||||
<string name="pair_requested">Paringsførespurnad</string>
|
||||
<string name="pairing_request_from">Paringsførespurnad frå %1s</string>
|
||||
<string name="received_url_title">Fekk lenkje frå %1s</string>
|
||||
@@ -79,12 +82,15 @@
|
||||
<string name="incoming_file_title">Får fil frå %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Sender fil til %1s</string>
|
||||
<string name="outgoing_files_title">Sender filer til %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Sende %1$d av %2$d filer</string>
|
||||
<string name="received_file_title">Fekk fil frå %1s</string>
|
||||
<string name="received_file_fail_title">Klarte ikkje ta imot fil frå %1s</string>
|
||||
<string name="received_file_text">Trykk for å opna «%1s»</string>
|
||||
<string name="sent_file_title">Send fil til %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Klarte ikkje senda fil til %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Trykk for å svara</string>
|
||||
<string name="reconnect">Kopla til på nytt</string>
|
||||
@@ -107,7 +113,7 @@
|
||||
<string name="mpris_volume">Lydstyrke</string>
|
||||
<string name="mpris_settings">Medieinnstillingar</string>
|
||||
<string name="mpris_time_settings_title">Spoleknappar</string>
|
||||
<string name="mpris_time_settings_summary">Juster tida for spoling ved trykking.</string>
|
||||
<string name="mpris_time_settings_summary">Juster tida for spoling ved trykking</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 sekund</item>
|
||||
<item>20 sekund</item>
|
||||
@@ -131,6 +137,10 @@
|
||||
<string name="custom_device_list">Legg til eining basert på IP</string>
|
||||
<string name="share_notification_preference">Lydvarsling</string>
|
||||
<string name="share_notification_preference_summary">Vibrer og spel ein lyd ved mottak av fil</string>
|
||||
<string name="share_destination_customize">Sjølvvald målmappe</string>
|
||||
<string name="share_destination_customize_summary_disabled">Mottekne filer vert lagra i nedlastingsmappa</string>
|
||||
<string name="share_destination_customize_summary_enabled">Mottekne filer vert lagra i mappa nedanfor</string>
|
||||
<string name="share_destination_folder_preference">Målmappe</string>
|
||||
<string name="title_activity_notification_filter">Varslingsfilter</string>
|
||||
<string name="filter_apps_info">Varslingar vert synkroniserte for dei valde appane.</string>
|
||||
<string name="sftp_internal_storage">Intern lagring</string>
|
||||
@@ -152,14 +162,25 @@
|
||||
<string name="device_rename_confirm">Endra namn</string>
|
||||
<string name="refresh">Oppdater</string>
|
||||
<string name="unreachable_description">Får ikkje kontakt med den para eininga. Sjå til at ho er kopla til same nettverk.</string>
|
||||
<string name="on_data_message">Det ser ut til at er kopla til eit mobilt samband. KDE Connect verkar berre på lokale nettverk.</string>
|
||||
<string name="no_file_browser">Ingen filhandsamarar er installerte.</string>
|
||||
<string name="pref_plugin_telepathy">Send SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Send tekstmeldingar frå datamaskina</string>
|
||||
<string name="plugin_not_supported">Dette tillegget er ikkje støtta av eininga</string>
|
||||
<string name="findmyphone_title">Finn telefonen min</string>
|
||||
<string name="findmyphone_title_tablet">Finn nettbrettet mitt</string>
|
||||
<string name="findmyphone_description">Ring til eininga, slik at du kan finna ho</string>
|
||||
<string name="findmyphone_description">Spel av lydsignal på eininga, slik at du lett kan finna ho</string>
|
||||
<string name="findmyphone_found">Fann</string>
|
||||
<string name="open">Opna</string>
|
||||
<string name="close">Lukk</string>
|
||||
<string name="no_permissions_storage">Du må gje KDE Connect løyve til å få tilgang til lagringsområdet</string>
|
||||
<string name="plugins_need_permission">Nokre av tillegga treng utvida løyva for å fungera (trykk på dei for meir informasjon):</string>
|
||||
<string name="permission_explanation">Dette tillegget treng utvida løyve for å fungera</string>
|
||||
<string name="optional_permission_explanation">Du må gje utvida løyve for at alle funksjonane skal fungera</string>
|
||||
<string name="plugins_need_optional_permission">På grunn av manglande løyve har nokre av tillegga funksjonar slåtte av (trykk på dei for meir informasjon):</string>
|
||||
<string name="sftp_permission_explanation">For å gje tilgang til filene frå datamaskina treng appen leseløyve til lagringsområdet på telefonen</string>
|
||||
<string name="share_optional_permission_explanation">For å kunna dela filer mellom telefonen og datamaskina må du gje appen lese- og skriveløyve til lagringsområdet på telefonen</string>
|
||||
<string name="telepathy_permission_explanation">For å kunna lesa og skriva tekstmeldingar frå datamaskina må du gje appen tilgang til SMS</string>
|
||||
<string name="telephony_permission_explanation">For å kunna sjå telefonsamtalar og tekstmeldingar frå datamaskina må du gje appen tilgang til telefon- og SMS-funksjonar</string>
|
||||
<string name="telephony_optional_permission_explanation">For å kunna sjå namn på kontaktar i staden for berre telefonnummeret må du gje appen tilgang til kontaktlista di</string>
|
||||
</resources>
|
||||
|
@@ -10,6 +10,8 @@
|
||||
<string name="pref_plugin_clipboard_desc">Udostępnij zawartość schowka</string>
|
||||
<string name="pref_plugin_mousepad">Zdalne sterowanie</string>
|
||||
<string name="pref_plugin_mousepad_desc">Użyj swojego telefonu lub tabletu jako myszy i klawiatury</string>
|
||||
<string name="pref_plugin_remotekeyboard">Odbieraj zdalne naciśnięcia klawiszy</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Odbieraj naciśnięcia klawiszy od urządzeń zdalnych</string>
|
||||
<string name="pref_plugin_mpris">Sterowanie multimediami</string>
|
||||
<string name="pref_plugin_mpris_desc">Zapewnia zdalne sterowanie twoim odtwarzaczem multimedialnym</string>
|
||||
<string name="pref_plugin_runcommand">Wykonaj polecenie</string>
|
||||
@@ -30,8 +32,12 @@
|
||||
<string name="no_permissions">Musisz przydzielić uprawnienia, aby uzyskać dostęp do powiadomień</string>
|
||||
<string name="send_ping">Wyślij ping</string>
|
||||
<string name="open_mpris_controls">Sterowanie multimediami</string>
|
||||
<string name="remotekeyboard_editing_only_title">Obsługuj zdalne naciśnięcia klawiszy tylko podczas edycji</string>
|
||||
<string name="remotekeyboard_not_connected">Nie istnieje połączenie zdalnej klawiatury, nawiąż takie połączenie w kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Połączenie zdalnej klawiatury jest nawiązane</string>
|
||||
<string name="remotekeyboard_multiple_connections">Nawiązano więcej niż jedno połączenie zdalnej klawiatury, wybierz urządzenie do ustawienia</string>
|
||||
<string name="open_mousepad">Zdalne sterowanie</string>
|
||||
<string name="mousepad_info">Przesuń palcem po ekranie, aby przesunąć wskaźnik myszy. Stuknij, aby wywołać naciśniecie lewym przyciskiem myszy i użyj dwóch/trzech palców, aby wywołać naciśniecie prawym i środkowym przyciskiem myszy. Przyciśnij na dłużej, aby przeciągnąć i upuścić.</string>
|
||||
<string name="mousepad_info">Przesuń palcem po ekranie, aby przesunąć wskaźnik myszy. Stuknij, aby wywołać naciśniecie lewym przyciskiem myszy i użyj dwóch/trzech palców, aby wywołać naciśniecie prawym i środkowym przyciskiem myszy. Przewijaj przy użyciu dwóch palców. Przyciśnij na dłużej, aby przeciągnąć i upuścić.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ustaw działanie po dwukrotnym stuknięciu palcem</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ustaw działanie po trzykrotnym stuknięciu palcem</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Ustaw czułość gładzika</string>
|
||||
@@ -41,9 +47,6 @@
|
||||
<item>Kliknięcie środkowym</item>
|
||||
<item>Nic</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">prawo</string>
|
||||
<string name="mousepad_triple_default">środek</string>
|
||||
<string name="mousepad_sensitivity_default">domyślne</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Najmniejsza</item>
|
||||
<item>Ponad najmniejszą</item>
|
||||
@@ -170,4 +173,14 @@
|
||||
<string name="findmyphone_found">Znaleziony</string>
|
||||
<string name="open">Otwórz</string>
|
||||
<string name="close">Zamknij</string>
|
||||
<string name="no_permissions_storage">Musisz nadać uprawnienia, aby uzyskać dostęp do pamięci masowej</string>
|
||||
<string name="plugins_need_permission">Niektóre z wtyczek wymagają uprawnień do działania (stuknij po więcej informacji)</string>
|
||||
<string name="permission_explanation">Ta wtyczka wymaga uprawnień do działania</string>
|
||||
<string name="optional_permission_explanation">Musisz przydzielić dodatkowe uprawnienia, aby włączyć wszystkie funkcje</string>
|
||||
<string name="plugins_need_optional_permission">Niektóre z wtyczek mają ograniczone możliwości ze względu na ograniczone uprawnienia (stuknij po więcej informacji)</string>
|
||||
<string name="sftp_permission_explanation">Aby uzyskać dostęp do plików z twojego PC aplikacja ta potrzebuje uprawnień do dostępu do pamięci twojego telefonu</string>
|
||||
<string name="share_optional_permission_explanation">Aby udostępniać pliki z twojego telefonu na twoim komputerze musisz pozowolić na dostęp do pamięci telefonu</string>
|
||||
<string name="telepathy_permission_explanation">Aby odczytywać i pisać SMSy z twojego komputera musisz nadać uprawnienia do SMSów</string>
|
||||
<string name="telephony_permission_explanation">Aby widzieć rozmowy telefoniczne i SMSy z twojego komputera musisz nadać uprawnienia na rozmowy telefoniczne i SMSy</string>
|
||||
<string name="telephony_optional_permission_explanation">Aby widzieć nazwę kontaktu zamiast numeru telefonu musisz pozwolić na dostęp do kontaktów telefonu</string>
|
||||
</resources>
|
||||
|
@@ -29,7 +29,6 @@
|
||||
<string name="send_ping">Enviar ping</string>
|
||||
<string name="open_mpris_controls">Controle multimídia</string>
|
||||
<string name="open_mousepad">Introdução de dados remota</string>
|
||||
<string name="mousepad_info">Mova um dedo pela tela para mover o ponteiro do mouse. Dê um toque para clicar e use dois/três dedos para os botões da direita e do meio. Use uma pressão longa para arrastar e soltar.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Definir a ação do toque com dois dedos</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Definir a ação do toque com três dedos</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Definir a sensibilidade do touchpad</string>
|
||||
@@ -39,9 +38,6 @@
|
||||
<item>Botão do meio</item>
|
||||
<item>Nada</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">direita</string>
|
||||
<string name="mousepad_triple_default">meio</string>
|
||||
<string name="mousepad_sensitivity_default">padrão</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Mais lento</item>
|
||||
<item>Ainda mais lento</item>
|
||||
|
@@ -47,9 +47,6 @@
|
||||
<item>Botão do meio</item>
|
||||
<item>Nada</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">direita</string>
|
||||
<string name="mousepad_triple_default">meio</string>
|
||||
<string name="mousepad_sensitivity_default">predefinição</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Mais Lento</item>
|
||||
<item>Ainda Mais Lento</item>
|
||||
@@ -176,4 +173,14 @@
|
||||
<string name="findmyphone_found">Encontrado</string>
|
||||
<string name="open">Abrir</string>
|
||||
<string name="close">Fechar</string>
|
||||
<string name="no_permissions_storage">Precisa de dar permissões de acesso ao armazenamento</string>
|
||||
<string name="plugins_need_permission">Alguns \'plugins\' precisam de permissões para funcionar (toque para mais informações):</string>
|
||||
<string name="permission_explanation">Este \'plugin\' precisa de permissões para funcionar</string>
|
||||
<string name="optional_permission_explanation">Precisa de dar permissões extra para activar todas as funcionalidades</string>
|
||||
<string name="plugins_need_optional_permission">Alguns \'plugins\' têm funcionalidades desactivadas devido à falta de permissões (toque para obter mais informações):</string>
|
||||
<string name="sftp_permission_explanation">Para aceder aos seus ficheiros a partir do seu PC, a aplicação precisa de permissão para aceder ao armazenamento do seu telemóvel</string>
|
||||
<string name="share_optional_permission_explanation">Para partilhar ficheiros entre o seu telemóvel e o seu ambiente de trabalho, precisa de permissão para aceder ao armazenamento do seu telemóvel</string>
|
||||
<string name="telepathy_permission_explanation">Para ler e escrever SMS\'s a partir do seu ambiente de trabalho, precisa de dar permissões para os SMS\'s</string>
|
||||
<string name="telephony_permission_explanation">Para ver as chamadas e os SMS\'s a partir do seu ambiente de trabalho, precisa de dar permissões para as chamadas telefónicas e SMS\'s</string>
|
||||
<string name="telephony_optional_permission_explanation">Para ver o nome de um contacto em vez do seu número de telefone, precisa de dar acesso aos contactos do telemóvel</string>
|
||||
</resources>
|
||||
|
@@ -5,15 +5,23 @@
|
||||
<string name="pref_plugin_battery">Состояние батареи</string>
|
||||
<string name="pref_plugin_battery_desc">Периодическое информирование о состоянии батареи</string>
|
||||
<string name="pref_plugin_sftp">Просмотр файловой системы</string>
|
||||
<string name="pref_plugin_sftp_desc">Позволяет удалённо просматривать файловую систему устройства</string>
|
||||
<string name="pref_plugin_clipboard">Синхронизация буфера обмена</string>
|
||||
<string name="pref_plugin_clipboard_desc">Использование общего буфера обмена</string>
|
||||
<string name="pref_plugin_mousepad">Удалённый ввод</string>
|
||||
<string name="pref_plugin_mousepad_desc">Использование телефона или планшета в качестве сенсорной панели и клавиатуры</string>
|
||||
<string name="pref_plugin_remotekeyboard">Получение удалённых нажатий клавиш</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Получение нажатий клавиш с удалённых устройств</string>
|
||||
<string name="pref_plugin_mpris">Управление воспроизведением</string>
|
||||
<string name="pref_plugin_mpris_desc">Обеспечивает дистанционное управление медиапроигрывателем</string>
|
||||
<string name="pref_plugin_runcommand">Запуск команд</string>
|
||||
<string name="pref_plugin_runcommand_desc">Удалённый запуск команд с телефона или планшета</string>
|
||||
<string name="pref_plugin_ping">Пинг</string>
|
||||
<string name="pref_plugin_ping_desc">Отправка и получение тестовых сигналов</string>
|
||||
<string name="pref_plugin_notifications">Синхронизация уведомлений</string>
|
||||
<string name="pref_plugin_notifications_desc">Доступ к уведомлениям с других устройств</string>
|
||||
<string name="pref_plugin_receive_notifications">Получение уведомлений</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Получение уведомлений с другого устройства и показ их на Android</string>
|
||||
<string name="pref_plugin_sharereceiver">Отправка и приём данных</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Пересылка файлов и адресов URL между устройствами</string>
|
||||
<string name="plugin_not_available">Эта функциональность недоступна в вашей версии Android</string>
|
||||
@@ -24,23 +32,26 @@
|
||||
<string name="no_permissions">Нужно разрешить доступ к уведомлениям</string>
|
||||
<string name="send_ping">Отправить тестовый сигнал</string>
|
||||
<string name="open_mpris_controls">Управление воспроизведением</string>
|
||||
<string name="remotekeyboard_editing_only_title">Обрабатывать удалённые нажатия только при редактировании</string>
|
||||
<string name="remotekeyboard_not_connected">Нет активного соединения с удалённой клавиатурой, установите его в KDE Connect</string>
|
||||
<string name="remotekeyboard_connected">Соединение с удалённой клавиатурой активно</string>
|
||||
<string name="remotekeyboard_multiple_connections">Подключено более одной удалённой клавиатуры, выберите устройство для настройки</string>
|
||||
<string name="open_mousepad">Удалённый ввод</string>
|
||||
<string name="mousepad_info">Перемещайте палец по экрану для перемещения курсора мыши. Коснитесь для нажатия, используйте два/три пальца для правой и средней кнопок. Используйте долгое нажатие для перетаскивания.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Действие при нажатии двумя пальцами</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Действие при нажатии тремя пальцами</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Чувствительность сенсорной панели</string>
|
||||
<string name="mousepad_scroll_direction_title">Инвертировать направление прокрутки</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Нажатие правой кнопки</item>
|
||||
<item>Нажатие средней кнопки</item>
|
||||
<item>Ничего не делать</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">Нажатие правой кнопки</string>
|
||||
<string name="mousepad_triple_default">Нажатие средней кнопки</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Slowest</item>
|
||||
<item>Above Slowest</item>
|
||||
<item>Default</item>
|
||||
<item>Above Default</item>
|
||||
<item>Fastest</item>
|
||||
<item>Самая низкая</item>
|
||||
<item>Низкая</item>
|
||||
<item>Обычная</item>
|
||||
<item>Высокая</item>
|
||||
<item>Самая высокая</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Подключённые устройства</string>
|
||||
<string name="category_not_paired_devices">Доступные устройства</string>
|
||||
@@ -49,15 +60,20 @@
|
||||
<string name="device_menu_plugins">Настройка модулей</string>
|
||||
<string name="device_menu_unpair">Снять сопряжение</string>
|
||||
<string name="device_not_reachable">Сопряжённое устройство недоступно</string>
|
||||
<string name="pair_new_device">Подключить новое устройство</string>
|
||||
<string name="unknown_device">Неизвестное устройство</string>
|
||||
<string name="error_not_reachable">Устройство недоступно</string>
|
||||
<string name="error_already_requested">Запрос на сопряжение уже был сделан</string>
|
||||
<string name="error_already_paired">Устройство уже сопряжено</string>
|
||||
<string name="error_could_not_send_package">Не удалось отправить пакет.</string>
|
||||
<string name="error_could_not_send_package">Не удалось отправить пакет</string>
|
||||
<string name="error_timed_out">Истекло время ожидания</string>
|
||||
<string name="error_canceled_by_user">Отменено пользователем</string>
|
||||
<string name="error_canceled_by_other_peer">Отменено другим участником</string>
|
||||
<string name="error_invalid_key">Получен недопустимый ключ</string>
|
||||
<string name="encryption_info_title">Информация о шифровании</string>
|
||||
<string name="encryption_info_msg_no_ssl">На другом устройстве используется старая версия KDE Connect, используется старый метод шифрования.</string>
|
||||
<string name="my_device_fingerprint">Отпечаток SHA-1 сертификата вашего устройства:</string>
|
||||
<string name="remote_device_fingerprint">Отпечаток SHA-1 сертификата удалённого устройства:</string>
|
||||
<string name="pair_requested">Запрошено сопряжение</string>
|
||||
<string name="pairing_request_from">Запрос на сопряжение от %1s</string>
|
||||
<string name="received_url_title">Получена ссылка от %1s</string>
|
||||
@@ -65,12 +81,15 @@
|
||||
<string name="incoming_file_title">Входящий файл с %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Отправка файла на %1s</string>
|
||||
<string name="outgoing_files_title">Отправка файлов на %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Отправлено %1$d из %2$d файлов</string>
|
||||
<string name="received_file_title">Получен файл с %1s</string>
|
||||
<string name="received_file_fail_title">Не удалось получить файл с %1s</string>
|
||||
<string name="received_file_text">Нажмите, чтобы открыть «%1s»</string>
|
||||
<string name="sent_file_title">Файл отправлен на %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Не удалось отправить файл на %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Нажмите, чтобы ответить</string>
|
||||
<string name="reconnect">Подключить заново</string>
|
||||
@@ -102,8 +121,8 @@
|
||||
<item>2 минуты</item>
|
||||
</string-array>
|
||||
<string name="share_to">Отправить на...</string>
|
||||
<string name="protocol_version_older">Это устройство использует старую версию протокола.</string>
|
||||
<string name="protocol_version_newer">Это устройство использует более новую версию протокола.</string>
|
||||
<string name="protocol_version_older">Это устройство использует старую версию протокола</string>
|
||||
<string name="protocol_version_newer">Это устройство использует более новую версию протокола</string>
|
||||
<string name="general_settings">Общие параметры</string>
|
||||
<string name="plugin_settings">Настройка</string>
|
||||
<string name="plugin_settings_with_name">Настройка %s</string>
|
||||
@@ -116,7 +135,11 @@
|
||||
<string name="unpair_device_action">Снять сопряжение с %s</string>
|
||||
<string name="custom_device_list">Добавить устройства по IP</string>
|
||||
<string name="share_notification_preference">Звуковые уведомления</string>
|
||||
<string name="share_notification_preference_summary">Использовать звуковой сигнал и вибрацию при получении файла.</string>
|
||||
<string name="share_notification_preference_summary">Использовать вибрацию и звуковой сигнал при получении файла</string>
|
||||
<string name="share_destination_customize">Задать целевой каталог</string>
|
||||
<string name="share_destination_customize_summary_disabled">Полученные файлы появятся в каталоге Загрузки</string>
|
||||
<string name="share_destination_customize_summary_enabled">Файлы будут сохранены в указанном ниже каталоге</string>
|
||||
<string name="share_destination_folder_preference">Целевой каталог</string>
|
||||
<string name="title_activity_notification_filter">Фильтр уведомлений</string>
|
||||
<string name="filter_apps_info">Уведомления будут синхронизированы для выбранных приложений.</string>
|
||||
<string name="sftp_internal_storage">Встроенная память</string>
|
||||
@@ -138,11 +161,25 @@
|
||||
<string name="device_rename_confirm">Переименовать</string>
|
||||
<string name="refresh">Обновить</string>
|
||||
<string name="unreachable_description">Это сопряжённое устройство недоступно. Проверьте, что оно подключено к той же локальной сети.</string>
|
||||
<string name="on_data_message">Похоже, вы подключены к мобильной сети. KDE Connect работает только в локальных сетях.</string>
|
||||
<string name="no_file_browser">Не удалось открыть диалог выбора файла.</string>
|
||||
<string name="pref_plugin_telepathy">Отправка SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Отправка SMS-сообщений с вашего компьютера</string>
|
||||
<string name="plugin_not_supported">Этот модуль не поддерживается устройством</string>
|
||||
<string name="findmyphone_title">Поиск телефона</string>
|
||||
<string name="findmyphone_title_tablet">Поиск планшета</string>
|
||||
<string name="findmyphone_description">Подача звукового сигнала на устройстве, чтобы вы могли его найти</string>
|
||||
<string name="findmyphone_found">Найден</string>
|
||||
<string name="open">Открыть</string>
|
||||
<string name="close">Закрыть</string>
|
||||
<string name="no_permissions_storage">Необходимо предоставить разрешения на доступ к хранилищу</string>
|
||||
<string name="plugins_need_permission">Некоторым модулям нужны разрешения для работы (нажмите для просмотра подробностей):</string>
|
||||
<string name="permission_explanation">Этому модулю нужны разрешения для работы</string>
|
||||
<string name="optional_permission_explanation">Необходимо предоставить дополнительные разрешения для включения всех функций</string>
|
||||
<string name="plugins_need_optional_permission">Некоторые функции модулей отключены из-за отсутствия необходимых разрешений (нажмите для просмотра подробностей):</string>
|
||||
<string name="sftp_permission_explanation">Для доступа к файлам с вашего компьютера приложению необходимо разрешение на доступ к встроенной памяти телефона</string>
|
||||
<string name="share_optional_permission_explanation">Чтобы обмениваться файлами между телефоном и компьютером, необходимо предоставить доступ к встроенной памяти телефона</string>
|
||||
<string name="telepathy_permission_explanation">Чтобы читать и писать SMS с компьютера, вам необходимо дать разрешение на доступ к SMS</string>
|
||||
<string name="telephony_permission_explanation">Чтобы видеть телефонные звонки и SMS на компьютере, необходимо дать разрешение на телефонные звонки и SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">Чтобы видеть имя контакта вместо номера телефона, необходимо предоставить доступ к контактам</string>
|
||||
</resources>
|
||||
|
@@ -10,8 +10,6 @@
|
||||
<string name="pref_plugin_clipboard_desc">Zdieľať obsah schránky</string>
|
||||
<string name="pref_plugin_mousepad">Vzdialený vstup</string>
|
||||
<string name="pref_plugin_mousepad_desc">Použiť váš telefón alebo tablet ako touchpad a klávesnicu</string>
|
||||
<string name="pref_plugin_remotekeyboard">Prijímať vzdialené stlačenia klávesov</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Prijímať udalosti stlačení klávesov od vzdialených zariadení</string>
|
||||
<string name="pref_plugin_mpris">Multimediálne ovládače</string>
|
||||
<string name="pref_plugin_mpris_desc">Poskytuje vzdialené ovládanie pre váš prehrávač médií</string>
|
||||
<string name="pref_plugin_runcommand">Spustiť príkaz</string>
|
||||
@@ -32,12 +30,7 @@
|
||||
<string name="no_permissions">Musíte povoliť oprávnenia na prístup k pripomienkam</string>
|
||||
<string name="send_ping">Poslať ping</string>
|
||||
<string name="open_mpris_controls">Multimediálny ovládač</string>
|
||||
<string name="remotekeyboard_editing_only_title">Spracúva vzdialené klávesy len pri editácii</string>
|
||||
<string name="remotekeyboard_not_connected">Nie sú žiadne aktívne pripojenia vzdialenej klávesnice, vytvorte nejaké v Kdeconnect</string>
|
||||
<string name="remotekeyboard_connected">Vzdialené pripojenie klávesnice je aktívne</string>
|
||||
<string name="remotekeyboard_multiple_connections">Je viac ako jedno vzdialené pripojenie klávesnice, vyberte zariadenie na nastavenie</string>
|
||||
<string name="open_mousepad">Vzdialený vstup</string>
|
||||
<string name="mousepad_info">Posúvajte prst na obrazovke na posun kurzora. Ťuknutie vyvolá klik a použite dva/tri prsty pre pravé a stredné tlačidlo. Použite dlhé stlačenie pre drag and drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Nastaviť akciu dvoch prstov</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Nastaviť akciu troch prstov</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Nastaviť citlivosť touchpadu</string>
|
||||
@@ -47,9 +40,6 @@
|
||||
<item>Stredný klik</item>
|
||||
<item>Nič</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">vpravo</string>
|
||||
<string name="mousepad_triple_default">stred</string>
|
||||
<string name="mousepad_sensitivity_default">predvolené</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Najpomalšie</item>
|
||||
<item>Nad najpomalším</item>
|
||||
@@ -85,15 +75,12 @@
|
||||
<string name="incoming_file_title">Prichádzajúci súbor od %s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Posielam súbor pre %1s</string>
|
||||
<string name="outgoing_files_title">Posielam súbor pre %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Poslať %1$d z %2$d súborov</string>
|
||||
<string name="received_file_title">Prijatý súbor od %1s</string>
|
||||
<string name="received_file_fail_title">Zlyhalo prijatie súboru od %1s</string>
|
||||
<string name="received_file_text">Ťuknite na otvorenie \'%1s\'</string>
|
||||
<string name="sent_file_title">Poslať súbor pre %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Zlyhalo poslanie súboru %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Tapnite na odpoveď</string>
|
||||
<string name="reconnect">Znovu pripojiť</string>
|
||||
@@ -140,10 +127,6 @@
|
||||
<string name="custom_device_list">Pridať zariadenia podľa IP</string>
|
||||
<string name="share_notification_preference">Hlučné pripomienky</string>
|
||||
<string name="share_notification_preference_summary">Vibrovať a prehrať zvuk pri prijatí súboru</string>
|
||||
<string name="share_destination_customize">Prispôsobiť cieľový adresár</string>
|
||||
<string name="share_destination_customize_summary_disabled">Prijaté súbory sa objavia v Preberaniach</string>
|
||||
<string name="share_destination_customize_summary_enabled">Súbory sa uložia v adresári dolu</string>
|
||||
<string name="share_destination_folder_preference">Cieľový adresár</string>
|
||||
<string name="title_activity_notification_filter">Filter upozornení</string>
|
||||
<string name="filter_apps_info">Upozornenia budú synchronizované pre vybrané aplikácie.</string>
|
||||
<string name="sftp_internal_storage">Interné úložisko</string>
|
||||
@@ -165,7 +148,6 @@
|
||||
<string name="device_rename_confirm">Premenovať</string>
|
||||
<string name="refresh">Obnoviť</string>
|
||||
<string name="unreachable_description">Toto spárované zariadenie nie je dosiahnuteľné. Prosím, uistite sa, že je pripojené do rovnakej siete.</string>
|
||||
<string name="on_data_message">Zdá sa, že ste na mobilom dátovom pripojení. KDE Connect funguje iba na lokálnej sieti.</string>
|
||||
<string name="no_file_browser">Nie sú nainštalované žiadne prehliadače.</string>
|
||||
<string name="pref_plugin_telepathy">Poslať SMS</string>
|
||||
<string name="pref_plugin_telepathy_desc">Posielať textové správy z vášho počítača</string>
|
||||
|
185
res/values-sr/strings.xml
Normal file
185
res/values-sr/strings.xml
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Обавештења телефона</string>
|
||||
<string name="pref_plugin_telephony_desc">Шаље обавештења за СМС и позиве</string>
|
||||
<string name="pref_plugin_battery">Извештај о батерији</string>
|
||||
<string name="pref_plugin_battery_desc">Периодично извештава о стању батерије</string>
|
||||
<string name="pref_plugin_sftp">Приступ фајл систему</string>
|
||||
<string name="pref_plugin_sftp_desc">Дозвољава даљински приступ фајл систему уређаја</string>
|
||||
<string name="pref_plugin_clipboard">Усклађени клипборд</string>
|
||||
<string name="pref_plugin_clipboard_desc">Дељење садржаја клипборда</string>
|
||||
<string name="pref_plugin_mousepad">Даљински унос</string>
|
||||
<string name="pref_plugin_mousepad_desc">Користите телефон или таблет као додирник и тастатуру</string>
|
||||
<string name="pref_plugin_remotekeyboard">Пријем даљинских тастера</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Примање тастерских догађаја са удаљених уређаја</string>
|
||||
<string name="pref_plugin_mpris">Управљање мултимедијом</string>
|
||||
<string name="pref_plugin_mpris_desc">Омогућава даљинско управљање медија плејером</string>
|
||||
<string name="pref_plugin_runcommand">Извршавање наредбе</string>
|
||||
<string name="pref_plugin_runcommand_desc">Даљински окида наредбе са телефона или таблета</string>
|
||||
<string name="pref_plugin_ping">Пинг</string>
|
||||
<string name="pref_plugin_ping_desc">Шаље и прима пингове</string>
|
||||
<string name="pref_plugin_notifications">Усклађена обавештења</string>
|
||||
<string name="pref_plugin_notifications_desc">Приступа вашим обавештењима са другог уређаја</string>
|
||||
<string name="pref_plugin_receive_notifications">Пријем обавештења</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Прима обавештења са других уређаја и приказује их на Андроиду</string>
|
||||
<string name="pref_plugin_sharereceiver">Дели и примај</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Дели фајлове и УРЛ‑ове између уређаја</string>
|
||||
<string name="plugin_not_available">Ова могућност није доступна на вашој верзији Андроида</string>
|
||||
<string name="device_list_empty">Нема уређаја</string>
|
||||
<string name="ok">У реду</string>
|
||||
<string name="cancel">Откажи</string>
|
||||
<string name="open_settings">Отвори поставке</string>
|
||||
<string name="no_permissions">Морате дати дозволу за приступ обавештењима</string>
|
||||
<string name="send_ping">Пошаљи пинг</string>
|
||||
<string name="open_mpris_controls">Контрола мултимедије</string>
|
||||
<string name="remotekeyboard_editing_only_title">Користи даљинске дугмиће само при уређивању</string>
|
||||
<string name="remotekeyboard_not_connected">Нема активне везе даљинске тастатуре. Успоставите је у КДЕ‑конекцији</string>
|
||||
<string name="remotekeyboard_connected">Веза даљинске тастатуре је активна</string>
|
||||
<string name="remotekeyboard_multiple_connections">Постоји више од једне везе даљинске тастатуре. Изаберите уређај да бисте подесили</string>
|
||||
<string name="open_mousepad">Даљински унос</string>
|
||||
<string name="mousepad_double_tap_settings_title">Радња за додир са два прста</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Радња за додир са три прста</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Постави осетљивост додирника</string>
|
||||
<string name="mousepad_scroll_direction_title">Обрни смер клизања</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>десни клик</item>
|
||||
<item>средњи клик</item>
|
||||
<item>ништа</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>најспорије</item>
|
||||
<item>мало спорије</item>
|
||||
<item>подразумевано</item>
|
||||
<item>мало брже</item>
|
||||
<item>најбрже</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Повезани уређаји</string>
|
||||
<string name="category_not_paired_devices">Доступни уређаји</string>
|
||||
<string name="category_remembered_devices">Упамћени уређаји</string>
|
||||
<string name="plugins_failed_to_load">Неуспело учитавање прикључка (тапните за више информација):</string>
|
||||
<string name="device_menu_plugins">Поставке прикључака</string>
|
||||
<string name="device_menu_unpair">Распари</string>
|
||||
<string name="device_not_reachable">Упарени уређај није доступан</string>
|
||||
<string name="pair_new_device">Упари нов уређај</string>
|
||||
<string name="unknown_device">Непознат уређај</string>
|
||||
<string name="error_not_reachable">Уређај није доступан</string>
|
||||
<string name="error_already_requested">Упаривање је већ тражено</string>
|
||||
<string name="error_already_paired">Уређај је већ упарен</string>
|
||||
<string name="error_could_not_send_package">Не могу да пошаљем пакет</string>
|
||||
<string name="error_timed_out">Истекло је време</string>
|
||||
<string name="error_canceled_by_user">Корисник отказао</string>
|
||||
<string name="error_canceled_by_other_peer">Отказала друга страна</string>
|
||||
<string name="error_invalid_key">Примљен је неисправан кључ</string>
|
||||
<string name="encryption_info_title">Подаци о шифровању</string>
|
||||
<string name="encryption_info_msg_no_ssl">Друга страна не користи најновију верзију, стога се користи старији метод шифровања.</string>
|
||||
<string name="my_device_fingerprint">СХА‑1 отисак сертификата вашег уређаја је:</string>
|
||||
<string name="remote_device_fingerprint">СХА‑1 отисак сертификата удаљеног уређаја је:</string>
|
||||
<string name="pair_requested">Упаривање је тражено</string>
|
||||
<string name="pairing_request_from">Захтев за упаривање са %1s</string>
|
||||
<string name="received_url_title">Примљена веза са %1s</string>
|
||||
<string name="received_url_text">Тапните да отворите „%1s“</string>
|
||||
<string name="incoming_file_title">Долазни фајл са %1s</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Шаљем фајл на %1s</string>
|
||||
<string name="outgoing_files_title">Шаљем фајлове на %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">Послато %1$d од %2$d фајлова</string>
|
||||
<string name="received_file_title">Примљен фајл са %1s</string>
|
||||
<string name="received_file_fail_title">Неуспео пријем фајла са %1s</string>
|
||||
<string name="received_file_text">Тапните да отворите „%1s“</string>
|
||||
<string name="sent_file_title">Послат фајл на %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Неуспело слање фајла на %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Тапните да одговорите</string>
|
||||
<string name="reconnect">Поново повежи</string>
|
||||
<string name="right_click">Пошаљи десни клик</string>
|
||||
<string name="middle_click">Пошаљи средњи клик</string>
|
||||
<string name="show_keyboard">Прикажи тастатуру</string>
|
||||
<string name="device_not_paired">Уређај није упарен</string>
|
||||
<string name="request_pairing">Тражи упаривање</string>
|
||||
<string name="pairing_accept">Прихвати</string>
|
||||
<string name="pairing_reject">Одбаци</string>
|
||||
<string name="device">Уређај</string>
|
||||
<string name="pair_device">Упари уређај</string>
|
||||
<string name="remote_control">Даљинско управљање</string>
|
||||
<string name="settings">Поставке за КДЕ‑конекцију</string>
|
||||
<string name="mpris_play">Пусти</string>
|
||||
<string name="mpris_previous">Претходно</string>
|
||||
<string name="mpris_rew">Премотај</string>
|
||||
<string name="mpris_ff">Брзо унапред</string>
|
||||
<string name="mpris_next">Следеће</string>
|
||||
<string name="mpris_volume">Јачина</string>
|
||||
<string name="mpris_settings">Поставке мултимедије</string>
|
||||
<string name="mpris_time_settings_title">Напред/назад дугмад</string>
|
||||
<string name="mpris_time_settings_summary">Подесите време прескакања за напред/назад дугмад.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 секунди</item>
|
||||
<item>20 секунди</item>
|
||||
<item>30 секунди</item>
|
||||
<item>1 минут</item>
|
||||
<item>2 минута</item>
|
||||
</string-array>
|
||||
<string name="share_to">Дели...</string>
|
||||
<string name="protocol_version_older">Овај уређај користи стару верзију протокола</string>
|
||||
<string name="protocol_version_newer">Овај уређај користи новију верзију протокола</string>
|
||||
<string name="general_settings">Опште поставке</string>
|
||||
<string name="plugin_settings">Поставке</string>
|
||||
<string name="plugin_settings_with_name">%s — поставке</string>
|
||||
<string name="device_name">Назив уређаја</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Неисправан назив уређаја</string>
|
||||
<string name="shareplugin_text_saved">Примљен текст, сачуван у клипборд</string>
|
||||
<string name="custom_devices_settings">Списак посебних уређаја</string>
|
||||
<string name="pair_device_action">Упари нови уређај</string>
|
||||
<string name="unpair_device_action">Распари %s</string>
|
||||
<string name="custom_device_list">Додај уређај по ИП адреси</string>
|
||||
<string name="share_notification_preference">Бучна обавештења</string>
|
||||
<string name="share_notification_preference_summary">Вибрирај и пусти звук кад примаш фајл</string>
|
||||
<string name="share_destination_customize">Прилагоди одредишну фасциклу</string>
|
||||
<string name="share_destination_customize_summary_disabled">Фајлови се смештају у Downloads</string>
|
||||
<string name="share_destination_customize_summary_enabled">Фајлови се смештају у фасциклу испод</string>
|
||||
<string name="share_destination_folder_preference">Одредишна фасцикла</string>
|
||||
<string name="title_activity_notification_filter">Филтер обавештења</string>
|
||||
<string name="filter_apps_info">Обавештења ће се синхронизовати за изабране апликације.</string>
|
||||
<string name="sftp_internal_storage">Унутрашња меморија</string>
|
||||
<string name="sftp_all_files">сви фајлови</string>
|
||||
<string name="sftp_sdcard_num">СД картица %d</string>
|
||||
<string name="sftp_sdcard">СД картица</string>
|
||||
<string name="sftp_readonly">(само за читање)</string>
|
||||
<string name="sftp_camera">Слике са камере</string>
|
||||
<string name="add_host">Додај домаћина/ИП</string>
|
||||
<string name="add_host_hint">Име домаћина или ИП</string>
|
||||
<string name="no_players_connected">Нисам нашао плејере</string>
|
||||
<string name="custom_dev_list_help">Користите ову опцију само ако се ваши уређаји не приказују аутоматски. Унесите ИП адресу или име домаћина и додирните дугме да га додате на листу. Додирните постојећу ставку да бисте је уклонили.</string>
|
||||
<string name="mpris_player_on_device">%1$s на %2$s</string>
|
||||
<string name="send_files">Пошаљи фајлове</string>
|
||||
<string name="pairing_title">Уређаји КДЕ‑конекције</string>
|
||||
<string name="pairing_description">Други уређаји на вашој мрежи на којима ради КДЕ‑конекција, појавиће се овде.</string>
|
||||
<string name="device_paired">Уређај упарен</string>
|
||||
<string name="device_rename_title">Преименовање уређаја</string>
|
||||
<string name="device_rename_confirm">Преименуј</string>
|
||||
<string name="refresh">Освежи</string>
|
||||
<string name="unreachable_description">Овај упарени уређај није доступан. Проверите да ли је повезан на исту мрежу.</string>
|
||||
<string name="on_data_message">Чини се да сте на мобилној мрежи. КДЕ‑конекција ради само на локалној мрежи.</string>
|
||||
<string name="no_file_browser">Нема инсталираних прегледача фајлова.</string>
|
||||
<string name="pref_plugin_telepathy">Шаљи СМС</string>
|
||||
<string name="pref_plugin_telepathy_desc">Шаљите текстуалне поруке помоћу рачунара</string>
|
||||
<string name="plugin_not_supported">Уређај не подржава овај прикључак</string>
|
||||
<string name="findmyphone_title">Нађи мој телефон</string>
|
||||
<string name="findmyphone_title_tablet">Нађи мој таблет</string>
|
||||
<string name="findmyphone_description">Активира звоно уређаја како бисте га пронашли</string>
|
||||
<string name="findmyphone_found">Нађен</string>
|
||||
<string name="open">Отвори</string>
|
||||
<string name="close">Затвори</string>
|
||||
<string name="no_permissions_storage">Морате дати дозволе за приступ унутрашњој меморији.</string>
|
||||
<string name="plugins_need_permission">Неки прикључци траже дозволе да би радили (тапните за више информација):</string>
|
||||
<string name="permission_explanation">Овај прикључак тражи дозволе да би радио.</string>
|
||||
<string name="optional_permission_explanation">Морате дати допунске дозволе за активирање свих функција.</string>
|
||||
<string name="plugins_need_optional_permission">Неки прикључци имају деактивиране могућности због недостатка дозвола (тапните за више информација):</string>
|
||||
<string name="sftp_permission_explanation">Програм захтева дозволе да би са рачунара приступио фајловима на телефону.</string>
|
||||
<string name="share_optional_permission_explanation">За дељење фајлова између телефона и рачунара морате дати приступ складишту телефона.</string>
|
||||
<string name="telepathy_permission_explanation">За читање и писање СМС‑ова на рачунару морате дати дозволу за СМС.</string>
|
||||
<string name="telephony_permission_explanation">Да бисте са рачунара видели телефонске позиве и СМС‑ове морате дати дозволу за позиве и СМС‑ове.</string>
|
||||
<string name="telephony_optional_permission_explanation">Да бисте видели име контакта уместо броја телефона морате дати приступ за контакте на телефону.</string>
|
||||
</resources>
|
@@ -8,10 +8,10 @@
|
||||
<string name="pref_plugin_sftp_desc">Gör det möjligt att bläddra i apparatens filsystem från annan apparat</string>
|
||||
<string name="pref_plugin_clipboard">Synkronisera klippbord</string>
|
||||
<string name="pref_plugin_clipboard_desc">Dela klippbordets innehåll</string>
|
||||
<string name="pref_plugin_mousepad">Fjärrinmatning</string>
|
||||
<string name="pref_plugin_mousepad">Extern inmatning</string>
|
||||
<string name="pref_plugin_mousepad_desc">Använd telefonen eller surfplattan som mus och tangentbord</string>
|
||||
<string name="pref_plugin_remotekeyboard">Ta emot fjärrtangentnedtryckningar</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Ta emot tangentnedtryckningar från fjärrenheter</string>
|
||||
<string name="pref_plugin_remotekeyboard">Ta emot externa tangentnedtryckningar</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Ta emot tangentnedtryckningar från externa enheter</string>
|
||||
<string name="pref_plugin_mpris">Multimediakontroller</string>
|
||||
<string name="pref_plugin_mpris_desc">Tillhandahåller en fjärrkontroll för mediaspelaren</string>
|
||||
<string name="pref_plugin_runcommand">Kör kommando</string>
|
||||
@@ -32,12 +32,12 @@
|
||||
<string name="no_permissions">Du måste ge rättighet att komma åt underrättelser</string>
|
||||
<string name="send_ping">Skicka ping</string>
|
||||
<string name="open_mpris_controls">Kontroll av multimedia</string>
|
||||
<string name="remotekeyboard_editing_only_title">Hantera bara fjärrtangenter vid redigering</string>
|
||||
<string name="remotekeyboard_not_connected">Det finns ingen aktiv fjärrtangentbordsanslutning, upprätta en i KDE-anslut</string>
|
||||
<string name="remotekeyboard_connected">Fjärrtangentbordsanslutning är aktiv</string>
|
||||
<string name="remotekeyboard_multiple_connections">Det finns mer än en fjärrtangentbordsanslutning, välj enhet att anpassa</string>
|
||||
<string name="open_mousepad">Fjärrinmatning</string>
|
||||
<string name="mousepad_info">Flytta fingret på skärmen för att röra muspekaren. Rör för att klicka, och använd två eller tre fingrar för höger- och mittenknapparna. Använd en längre beröring för drag och släpp.</string>
|
||||
<string name="remotekeyboard_editing_only_title">Hantera bara externa tangenter vid redigering</string>
|
||||
<string name="remotekeyboard_not_connected">Det finns ingen aktiv anslutning till externt tangentbord, upprätta en i KDE-anslut</string>
|
||||
<string name="remotekeyboard_connected">Anslutning till externt tangentbord är aktiv</string>
|
||||
<string name="remotekeyboard_multiple_connections">Det finns mer än en anslutning till externt tangentbord, välj enhet att anpassa</string>
|
||||
<string name="open_mousepad">Extern inmatning</string>
|
||||
<string name="mousepad_info">Flytta fingret på skärmen för att röra muspekaren. Rör för att klicka, och använd två eller tre fingrar för höger- och mittenknapparna. Använd två fingrar för att panorera. Använd en längre beröring för drag och släpp.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Ställ in åtgärd vid två fingerberöringar</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Ställ in åtgärd vid tre fingerberöringar</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Ställ in tryckplattans känslighet</string>
|
||||
@@ -47,9 +47,6 @@
|
||||
<item>Mittenklick</item>
|
||||
<item>Ingenting</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">höger</string>
|
||||
<string name="mousepad_triple_default">mitten</string>
|
||||
<string name="mousepad_sensitivity_default">normal</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Långsammaste</item>
|
||||
<item>Ovanför långsammaste</item>
|
||||
@@ -176,4 +173,14 @@
|
||||
<string name="findmyphone_found">Hittade den</string>
|
||||
<string name="open">Öppna</string>
|
||||
<string name="close">Stäng</string>
|
||||
<string name="no_permissions_storage">Du måste ge rättighet att komma åt lagringen</string>
|
||||
<string name="plugins_need_permission">Vissa insticksprogram kräver rättigheter för att fungera (rör för mer information):</string>
|
||||
<string name="permission_explanation">Insticksprogrammet behöver rättigheter för att fungera</string>
|
||||
<string name="optional_permission_explanation">Du måste ge extra rättigheter för att aktivera alla funktioner</string>
|
||||
<string name="plugins_need_optional_permission">Vissa insticksprogram har inaktiverade funktioner på grund av att rättigheter saknas (rör för mer information):</string>
|
||||
<string name="sftp_permission_explanation">För att komma åt filerna från din dator behöver applikationen rättighet att komma åt telefonens lagringsutrymme</string>
|
||||
<string name="share_optional_permission_explanation">För att dela filer mellan telefonen och skrivbordet behöver du ge tillgång till telefonens lagringsutrymme</string>
|
||||
<string name="telepathy_permission_explanation">För att läsa och skriva SMS från skrivbordet måste du ge rättigheter för SMS</string>
|
||||
<string name="telephony_permission_explanation">För att se telefonsamtal och SMS från skrivbordet måste du ge rättigheter för telefonsamtal och SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">För att se ett kontaktnamn istället för ett telefonnummer måste du ge tillgång till telefonens kontakter</string>
|
||||
</resources>
|
||||
|
185
res/values-tr/strings.xml
Normal file
185
res/values-tr/strings.xml
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="pref_plugin_telephony">Telefon bildiricisi</string>
|
||||
<string name="pref_plugin_telephony_desc">SMS ve çağrılar için bildirimler yolla</string>
|
||||
<string name="pref_plugin_battery">Batarya raporu</string>
|
||||
<string name="pref_plugin_battery_desc">Batarya durumunu belirli aralıklarla raporla</string>
|
||||
<string name="pref_plugin_sftp">Dosya sistemi gösterme</string>
|
||||
<string name="pref_plugin_sftp_desc">Bu aıygıtın dosya sistemine uzaktan gözatılmasına izin verir</string>
|
||||
<string name="pref_plugin_clipboard">Pano eşitleme</string>
|
||||
<string name="pref_plugin_clipboard_desc">Pano içeriğini paylaş</string>
|
||||
<string name="pref_plugin_mousepad">Uzak girdi</string>
|
||||
<string name="pref_plugin_mousepad_desc">Telefonunuzu veya tabletinizi, dokunmatik veya klavye olarak kullanın</string>
|
||||
<string name="pref_plugin_remotekeyboard">Uzak tuşa basmaları getir</string>
|
||||
<string name="pref_plugin_remotekeyboard_desc">Tuş basma eylemlerini, uzak aygıtlardan getir</string>
|
||||
<string name="pref_plugin_mpris">Çoklu ortam denetimleri</string>
|
||||
<string name="pref_plugin_mpris_desc">Ortam oynatıcınız için uzak denetim sağlar</string>
|
||||
<string name="pref_plugin_runcommand">Komut Çalıştır</string>
|
||||
<string name="pref_plugin_runcommand_desc">Uzak komutları, telefon veya tabletinizden tetikler</string>
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">Ping gönder ve al</string>
|
||||
<string name="pref_plugin_notifications">Bildirim eşitleme</string>
|
||||
<string name="pref_plugin_notifications_desc">Bildirimlerinize, diğer aygıtlardan erişin</string>
|
||||
<string name="pref_plugin_receive_notifications">Bildirimleri al</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">Bildirimleri diğer aygıtlardan al ve Android üzerinde göster</string>
|
||||
<string name="pref_plugin_sharereceiver">Paylaş ve al</string>
|
||||
<string name="pref_plugin_sharereceiver_desc">Dosyaları ve URL\'leri aygıtlar arasında paylaş</string>
|
||||
<string name="plugin_not_available">Bu özellik, sahip olduğunuz Android sürümünde kullanılabilir değil</string>
|
||||
<string name="device_list_empty">Aygıt yok</string>
|
||||
<string name="ok">Tamam</string>
|
||||
<string name="cancel">İptal</string>
|
||||
<string name="open_settings">Ayarları aç</string>
|
||||
<string name="no_permissions">Bildirimler erişebilmek için izine ihtiyacınız var</string>
|
||||
<string name="send_ping">Ping gönder</string>
|
||||
<string name="open_mpris_controls">Çoklu ortam denetimi</string>
|
||||
<string name="remotekeyboard_editing_only_title">Uzak tuşları, sadece düzenleme yaparken işle</string>
|
||||
<string name="remotekeyboard_not_connected">Etkin bir uzak klavye bağlantısı yok, kdeconnect ile bir bağlantı kurun</string>
|
||||
<string name="remotekeyboard_connected">Uzak klavye bağlantısı etkin</string>
|
||||
<string name="remotekeyboard_multiple_connections">Birden çok uzak klavye bağlantısı mevcut, yapılandırmak istediğiniz aygıtı seçin</string>
|
||||
<string name="open_mousepad">Girdi sil</string>
|
||||
<string name="mousepad_double_tap_settings_title">İki parmak dokunma eylemini ayarla</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Üç parmak dokunma eylemini ayarla</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Dokunmatik yüzey hassasiyetini ayarla</string>
|
||||
<string name="mousepad_scroll_direction_title">Ters Kaydırma Yönü</string>
|
||||
<string-array name="mousepad_tap_entries">
|
||||
<item>Sağ tık</item>
|
||||
<item>Orta tık</item>
|
||||
<item>Hiçbiri</item>
|
||||
</string-array>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>En Yavaş</item>
|
||||
<item>En Yavaşın Üstü</item>
|
||||
<item>Varsayıla</item>
|
||||
<item>Varsayılan Üstü</item>
|
||||
<item>En Hızlı</item>
|
||||
</string-array>
|
||||
<string name="category_connected_devices">Bağlı aygıtlar</string>
|
||||
<string name="category_not_paired_devices">Kullanılabilir aygıtlar</string>
|
||||
<string name="category_remembered_devices">Hatırlanan aygıtlar</string>
|
||||
<string name="plugins_failed_to_load">Eklentiler yüklenemedi (daha fazla bilgi için dokunun):</string>
|
||||
<string name="device_menu_plugins">Eklenti ayarları</string>
|
||||
<string name="device_menu_unpair">Ayır</string>
|
||||
<string name="device_not_reachable">Eşleşmiş aygıt ulaşılabilir değil</string>
|
||||
<string name="pair_new_device">Yeni bir aygıt eşleştir</string>
|
||||
<string name="unknown_device">Bİlinmeyen aygıt</string>
|
||||
<string name="error_not_reachable">Aygıt ulaşılabilir değil</string>
|
||||
<string name="error_already_requested">Eşleşme zaten talep edilmiş</string>
|
||||
<string name="error_already_paired">Aygıt zaten eşleşmiş</string>
|
||||
<string name="error_could_not_send_package">Paket gönderilemedi</string>
|
||||
<string name="error_timed_out">Zaman aşımı</string>
|
||||
<string name="error_canceled_by_user">Kullanıcı tarafından iptal edildi</string>
|
||||
<string name="error_canceled_by_other_peer">Diğer eş tarafından iptal edildi</string>
|
||||
<string name="error_invalid_key">Geçersiz anahtar alındı</string>
|
||||
<string name="encryption_info_title">Şifreleme Bilgisi</string>
|
||||
<string name="encryption_info_msg_no_ssl">Diğer aygıt, KDE Connect\'in son sürümünü kullanmıyor, eski şifreleme yöntemini kullanıyor.</string>
|
||||
<string name="my_device_fingerprint">Aygıt sertifikanızın SHA1 parmak izi:</string>
|
||||
<string name="remote_device_fingerprint">Uzak aygıt sertifikanızın SHA1 parmak izi:</string>
|
||||
<string name="pair_requested">Eşleşme talep edildi</string>
|
||||
<string name="pairing_request_from">%1s için eşleşme talebi</string>
|
||||
<string name="received_url_title">%1s üzerinden bağlantı alındı</string>
|
||||
<string name="received_url_text">\'%1s\' açmak için dokunun</string>
|
||||
<string name="incoming_file_title">%1s üzerinden gelen dosya</string>
|
||||
<string name="incoming_file_text">%1s</string>
|
||||
<string name="outgoing_file_title">Dosya şuraya gönderiliyor, %1s</string>
|
||||
<string name="outgoing_files_title">Dosyalar şuraya gönderiliyor, %1s</string>
|
||||
<string name="outgoing_file_text">%1s</string>
|
||||
<string name="outgoing_files_text">%2$d dosyadan %1$d dosya gönderildi</string>
|
||||
<string name="received_file_title">Şuradan dosya alındı, %1s</string>
|
||||
<string name="received_file_fail_title">Şuradan dosya alma başarısız, %1s</string>
|
||||
<string name="received_file_text">\'%1s\' açmak için dokunun</string>
|
||||
<string name="sent_file_title">Dosyayı şuraya gönder, %1s</string>
|
||||
<string name="sent_file_text">%1s</string>
|
||||
<string name="sent_file_failed_title">Dosyayı şuraya gönderme başarısız, %1s</string>
|
||||
<string name="sent_file_failed_text">%1s</string>
|
||||
<string name="tap_to_answer">Cevap için dokunun</string>
|
||||
<string name="reconnect">Yeniden Bağlan</string>
|
||||
<string name="right_click">Sağ Tık Gönder</string>
|
||||
<string name="middle_click">Orta Tık Gönder</string>
|
||||
<string name="show_keyboard">Klavyeyi Göster</string>
|
||||
<string name="device_not_paired">Aygıt eşleşmemiş</string>
|
||||
<string name="request_pairing">Eşleşme isteği</string>
|
||||
<string name="pairing_accept">Onayla</string>
|
||||
<string name="pairing_reject">Reddet</string>
|
||||
<string name="device">Aygıt</string>
|
||||
<string name="pair_device">Aygıt eşleştir</string>
|
||||
<string name="remote_control">Uzak denetim</string>
|
||||
<string name="settings">KDE Connect Ayarları</string>
|
||||
<string name="mpris_play">Oynat</string>
|
||||
<string name="mpris_previous">Önceki</string>
|
||||
<string name="mpris_rew">Geri Sar</string>
|
||||
<string name="mpris_ff">Hızlı İleri Sar</string>
|
||||
<string name="mpris_next">Sonraki</string>
|
||||
<string name="mpris_volume">Ses</string>
|
||||
<string name="mpris_settings">Çoklu Ortam Ayarları</string>
|
||||
<string name="mpris_time_settings_title">İleri/geri düğmeleri</string>
|
||||
<string name="mpris_time_settings_summary">Basıldığında kullanılacak ileri/geri zamanını ayarlayın.</string>
|
||||
<string-array name="mpris_time_entries">
|
||||
<item>10 saniye</item>
|
||||
<item>20 saniye</item>
|
||||
<item>30 saniye</item>
|
||||
<item>1 dakika</item>
|
||||
<item>2 dakika</item>
|
||||
</string-array>
|
||||
<string name="share_to">Paylaş...</string>
|
||||
<string name="protocol_version_older">Bu aygıt, eski bir protokol sürümü kullanıyor</string>
|
||||
<string name="protocol_version_newer">Bu aygıt, daha yeni bir protokol sürümü kullanıyor</string>
|
||||
<string name="general_settings">Genel Ayarlar</string>
|
||||
<string name="plugin_settings">Ayarlar</string>
|
||||
<string name="plugin_settings_with_name">%s ayarları</string>
|
||||
<string name="device_name">Aygıt adı</string>
|
||||
<string name="device_name_preference_summary">%s</string>
|
||||
<string name="invalid_device_name">Geçersiz aygıt adı</string>
|
||||
<string name="shareplugin_text_saved">Gelen ileti, panoya kaydet</string>
|
||||
<string name="custom_devices_settings">Özel aygıt listesi</string>
|
||||
<string name="pair_device_action">Yeni bir aygıt eşleştir</string>
|
||||
<string name="unpair_device_action">Ayır %s</string>
|
||||
<string name="custom_device_list">IP\'ye göre aygıtları ekle</string>
|
||||
<string name="share_notification_preference">Sesli bildirimler</string>
|
||||
<string name="share_notification_preference_summary">Bir dosya alırken, ses çıkar ve titret</string>
|
||||
<string name="share_destination_customize">Hedef dizini özelleştir</string>
|
||||
<string name="share_destination_customize_summary_disabled">Gelen dosyalar İndirilenler\'de gözükecektir</string>
|
||||
<string name="share_destination_customize_summary_enabled">Dosyalar aşağıdaki dizinden depolanacaktır</string>
|
||||
<string name="share_destination_folder_preference">Hedef dizin</string>
|
||||
<string name="title_activity_notification_filter">Bildirim süzgeci</string>
|
||||
<string name="filter_apps_info">Bildirimler, seçili uygulamalar için eşitlenecektir.</string>
|
||||
<string name="sftp_internal_storage">Harici depolama</string>
|
||||
<string name="sftp_all_files">Tüm dosyalar</string>
|
||||
<string name="sftp_sdcard_num">SD kart %d</string>
|
||||
<string name="sftp_sdcard">SD kart</string>
|
||||
<string name="sftp_readonly">(salt okunur)</string>
|
||||
<string name="sftp_camera">Kamera resimleri</string>
|
||||
<string name="add_host">Makine/IP ekle</string>
|
||||
<string name="add_host_hint">Makine adı veya IP</string>
|
||||
<string name="no_players_connected">Onatıcı bulunamadı</string>
|
||||
<string name="custom_dev_list_help">Bu seçeneği, sadece aygıtınız otomatik bulunamadıysa kullanın. Aşağıya IP adresini veya makine adının girin ve listeye eklemek için düğmeye dokunun. Listeden bir ögeyi silmek için, mevcut ögeye tıklayın.</string>
|
||||
<string name="mpris_player_on_device">%2$s üzerindeki %1$s</string>
|
||||
<string name="send_files">Dosyaları gönder</string>
|
||||
<string name="pairing_title">KDE Connect Aygıtları</string>
|
||||
<string name="pairing_description">KDE Connect\'te çalışan, aynı ağdaki diğer aygıtlar burada gözükmelidir.</string>
|
||||
<string name="device_paired">Aygıt eşleştirildi</string>
|
||||
<string name="device_rename_title">Aygıtı yeniden adlandır</string>
|
||||
<string name="device_rename_confirm">Yeniden adlandır</string>
|
||||
<string name="refresh">Tazele</string>
|
||||
<string name="unreachable_description">Eşleştirilmiş aygıt ulaşılabilir değil. Aynı ağa bağlı olduğundan emin olun.</string>
|
||||
<string name="on_data_message">Mobil veri bağlantısında olduğunuz gözüküyor. KDE Connect sadece yerel ağlarda çalışır.</string>
|
||||
<string name="no_file_browser">Yüklü bir dosya tarayıcısı yok.</string>
|
||||
<string name="pref_plugin_telepathy">SMS Gönder</string>
|
||||
<string name="pref_plugin_telepathy_desc">Masaüstünden metin iletisi gönder</string>
|
||||
<string name="plugin_not_supported">Eklenti, aygıt tarafından desteklenmiyor</string>
|
||||
<string name="findmyphone_title">Telefonumu bul</string>
|
||||
<string name="findmyphone_title_tablet">Tabletimi bul</string>
|
||||
<string name="findmyphone_description">Aygıtı bulmak için onu çaldır</string>
|
||||
<string name="findmyphone_found">Bulundu</string>
|
||||
<string name="open">Aç</string>
|
||||
<string name="close">Kapat</string>
|
||||
<string name="no_permissions_storage">Depolamaya erişim için izne ihtiyacınız var</string>
|
||||
<string name="plugins_need_permission">Bazı Eklentiler çalışmak için izne ihtiyaç duyar (daha fazla bilgi için dokunun):</string>
|
||||
<string name="permission_explanation">Bu eklenti, çalışmak için izne ihtiyaç duyuyor</string>
|
||||
<string name="optional_permission_explanation">Tüm işlevleri etkinleştirmek için daha fazla yetkiye ihtiyacınız var</string>
|
||||
<string name="plugins_need_optional_permission">Bazı eklentilerin özellikleri, izin yetersizliğinden kapalı gelmektedir (daha fazla bilgi için dokunun):</string>
|
||||
<string name="sftp_permission_explanation">Bilgisayarınızdaki dosyalara erişmek için, uygulama telefonunuzun depolama alanına erişim izni olmalıdır</string>
|
||||
<string name="share_optional_permission_explanation">Telefon ve masaüstünüz arasında dosya paylaşılabilmesi için, telefonun depolama alanına erişim izni olmalıdır</string>
|
||||
<string name="telepathy_permission_explanation">Masaüstünde SMS yazma ve okuma yapmak için SMS izni gereklidir</string>
|
||||
<string name="telephony_permission_explanation">Masaüstünden telefon çağrılarını ve SMS görebilmek için izin gereklidir</string>
|
||||
<string name="telephony_optional_permission_explanation">Telefon numarası yerine kişi ismi görebilmek için telefonun kişilerine erişim gereklidir</string>
|
||||
</resources>
|
@@ -37,7 +37,7 @@
|
||||
<string name="remotekeyboard_connected">З’єднання з віддаленою клавіатурою є активним</string>
|
||||
<string name="remotekeyboard_multiple_connections">Існує декілька з’єднань із віддаленою клавіатурою. Виберіть пристрій для налаштовування.</string>
|
||||
<string name="open_mousepad">Дистанційне введення</string>
|
||||
<string name="mousepad_info">Проведіть по екрану пальцем, щоб пересунути вказівник миші. Дотик одним пальцем означатиме клацання, дотиком двома або трьома пальцями можна імітувати праву і середню кнопки. Для перетягування зі скиданням скористайтеся тривалим натисканням.</string>
|
||||
<string name="mousepad_info">Проведіть по екрану пальцем, щоб пересунути вказівник миші. Дотик одним пальцем означатиме клацання, дотиком двома або трьома пальцями можна імітувати праву і середню кнопки. Гортання відбувається за допомогою двох пальців. Для перетягування зі скиданням скористайтеся тривалим натисканням.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Встановлення дії для торкання двома пальцями</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Встановлення дії для торкання трьома пальцями</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Встановити чутливість сенсорної панелі</string>
|
||||
@@ -47,9 +47,6 @@
|
||||
<item>Клацання середньою</item>
|
||||
<item>Нічого</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">права</string>
|
||||
<string name="mousepad_triple_default">середня</string>
|
||||
<string name="mousepad_sensitivity_default">типва</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>Найповільніший</item>
|
||||
<item>Швидший за найповільніший</item>
|
||||
@@ -176,4 +173,14 @@
|
||||
<string name="findmyphone_found">Знайдено</string>
|
||||
<string name="open">Відкрити</string>
|
||||
<string name="close">Закрити</string>
|
||||
<string name="no_permissions_storage">Для доступу до сховища даних вам слід надати програмі права доступу</string>
|
||||
<string name="plugins_need_permission">Для роботи деяких додатків потрібні додаткові права доступу (натисніть, щоб дізнатися більше):</string>
|
||||
<string name="permission_explanation">Для роботи цього додатка потрібні додаткові права доступу</string>
|
||||
<string name="optional_permission_explanation">Щоб уможливити використання усіх функцій, вам слід надати програмі додаткові права доступу</string>
|
||||
<string name="plugins_need_optional_permission">Можливості деяких додатків вимкнено, оскільки програмі не вистачає прав доступу (натисніть, щоб дізнатися більше):</string>
|
||||
<string name="sftp_permission_explanation">Для доступу до ваших файлі із персонального комп’ютера програмі потрібні права доступу до сховища даних вашого телефону</string>
|
||||
<string name="share_optional_permission_explanation">Щоб спільного використовувати файли на вашому телефоні і робочому комп’ютері, вам слід надати програмі доступ до сховища даних вашого телефону</string>
|
||||
<string name="telepathy_permission_explanation">Щоб читати і писати SMS з вашого робочого комп’ютера, вам слід надати програмі доступ до SMS</string>
|
||||
<string name="telephony_permission_explanation">"Щоб переглядати дзвінки і SMS з робочого комп’ютера, вам слід надати програмі доступ до дзвінків і SMS"</string>
|
||||
<string name="telephony_optional_permission_explanation">Щоб бачити ім’я контакту замість номеру телефону, вам слід надати програмі доступ до записів контактів на телефоні</string>
|
||||
</resources>
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<string name="pref_plugin_ping">Ping</string>
|
||||
<string name="pref_plugin_ping_desc">发送和接受ping</string>
|
||||
<string name="pref_plugin_notifications">通知同步</string>
|
||||
<string name="pref_plugin_notifications_desc">从其他设备访问你的通知</string>
|
||||
<string name="pref_plugin_notifications_desc">从其他设备访问您的通知</string>
|
||||
<string name="pref_plugin_receive_notifications">接收通知</string>
|
||||
<string name="pref_plugin_receive_notifications_desc">从其他设备接收通知并显示在 Android 上</string>
|
||||
<string name="pref_plugin_sharereceiver">分享和接收</string>
|
||||
@@ -29,7 +29,7 @@
|
||||
<string name="ok">确认</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="open_settings">开启设置</string>
|
||||
<string name="no_permissions">你需要授予权限以便访问通知</string>
|
||||
<string name="no_permissions">您需要授予权限以便访问通知</string>
|
||||
<string name="send_ping">发送ping</string>
|
||||
<string name="open_mpris_controls">多媒体控制</string>
|
||||
<string name="remotekeyboard_editing_only_title">只有在编辑时才接受远程按键</string>
|
||||
@@ -37,7 +37,7 @@
|
||||
<string name="remotekeyboard_connected">远程键盘连接已启用</string>
|
||||
<string name="remotekeyboard_multiple_connections">发现多个远程键盘连接,请选择设备进行配置</string>
|
||||
<string name="open_mousepad">远程输入</string>
|
||||
<string name="mousepad_info">在屏幕上移动手指来移动光标。轻击代表左键,双指或三指点击代表右键或中键。用长按来拖放。</string>
|
||||
<string name="mousepad_info">在屏幕上移动手指来移动光标。轻击代表左键,双指或三指点击代表右键或中键。用双指滚动。用长按来拖放。</string>
|
||||
<string name="mousepad_double_tap_settings_title">设置双指点击动作</string>
|
||||
<string name="mousepad_triple_tap_settings_title">设置三指点击动作</string>
|
||||
<string name="mousepad_sensitivity_settings_title">设置触摸板灵敏度</string>
|
||||
@@ -47,9 +47,6 @@
|
||||
<item>中键点击</item>
|
||||
<item>无</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">右</string>
|
||||
<string name="mousepad_triple_default">中</string>
|
||||
<string name="mousepad_sensitivity_default">默认</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>最慢</item>
|
||||
<item>高于最慢</item>
|
||||
@@ -155,7 +152,7 @@
|
||||
<string name="add_host">增加主机/IP</string>
|
||||
<string name="add_host_hint">主机名或IP</string>
|
||||
<string name="no_players_connected">未找到播放器</string>
|
||||
<string name="custom_dev_list_help">仅当你的设备没有被自动检测出时再使用本选项。在下方输入IP地址或主机名,然后点击按钮以添加其到列表中。点击已有条目来从列表中删除它。</string>
|
||||
<string name="custom_dev_list_help">仅当您的设备没有被自动检测出时再使用本选项。在下方输入IP地址或主机名,然后点击按钮以添加其到列表中。点击已有条目来从列表中删除它。</string>
|
||||
<string name="mpris_player_on_device">%2$s上的%1$s</string>
|
||||
<string name="send_files">发送文件</string>
|
||||
<string name="pairing_title">KDE Connect 设备</string>
|
||||
@@ -170,6 +167,19 @@
|
||||
<string name="pref_plugin_telepathy_desc">从桌面发送短消息</string>
|
||||
<string name="plugin_not_supported">设备不支持此插件</string>
|
||||
<string name="findmyphone_title">找到我的手机</string>
|
||||
<string name="findmyphone_title_tablet">找到我的平板电脑</string>
|
||||
<string name="findmyphone_description">让设备响铃从而找到它</string>
|
||||
<string name="findmyphone_found">找到</string>
|
||||
<string name="open">打开</string>
|
||||
<string name="close">关闭</string>
|
||||
<string name="no_permissions_storage">您需要授予权限以访问存储</string>
|
||||
<string name="plugins_need_permission">某些插件需要权限才能工作 (点击以获取更多信息):</string>
|
||||
<string name="permission_explanation">这个插件需要权限才能工作</string>
|
||||
<string name="optional_permission_explanation">您需要授予额外权限以启用全部功能</string>
|
||||
<string name="plugins_need_optional_permission">因缺少权限,某些插件的一些功能已禁用(点击以查看更多信息):</string>
|
||||
<string name="sftp_permission_explanation">此应用需要手机存储权限才能从您的 PC 访问手机内的文件</string>
|
||||
<string name="share_optional_permission_explanation">您需要给予访问手机存储的权限才能在手机和桌面计算机之间分享文件</string>
|
||||
<string name="telepathy_permission_explanation">从计算机桌面读取、写入短消息需要向应用程序授予 SMS 权限</string>
|
||||
<string name="telephony_permission_explanation">您必须给予访问手机通话和短信的权限才能从桌面计算机查看通话记录和短信</string>
|
||||
<string name="telephony_optional_permission_explanation">要查看联系人姓名而非电话号码,您需要授予访问手机通讯录的权限</string>
|
||||
</resources>
|
||||
|
@@ -31,7 +31,6 @@
|
||||
<string name="send_ping">傳送Ping回應封包</string>
|
||||
<string name="open_mpris_controls">多媒體控制</string>
|
||||
<string name="open_mousepad">遠端輸入</string>
|
||||
<string name="mousepad_info">在您的智慧型手機的螢幕上移動手指頭,用來控制電腦螢幕的鼠標。點擊表示滑鼠的左鍵,使用兩隻/三隻手指頭點擊來表示滑鼠的右鍵/中鍵。長按則表示要拖拉。</string>
|
||||
<string name="mousepad_double_tap_settings_title">設定兩隻手指頭點擊的動作</string>
|
||||
<string name="mousepad_triple_tap_settings_title">設定三隻手指頭點擊的動作</string>
|
||||
<string name="mousepad_sensitivity_settings_title">設定觸碰板的靈敏度</string>
|
||||
@@ -41,9 +40,6 @@
|
||||
<item>中鍵點擊</item>
|
||||
<item>無</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">右</string>
|
||||
<string name="mousepad_triple_default">中</string>
|
||||
<string name="mousepad_sensitivity_default">預設</string>
|
||||
<string-array name="mousepad_sensitivity_entries">
|
||||
<item>慢</item>
|
||||
<item>最慢</item>
|
||||
|
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="MaxWidthImageButton">
|
||||
<attr name="maxWidth" format="dimension" />
|
||||
</declare-styleable>
|
||||
</resources>
|
@@ -39,7 +39,7 @@
|
||||
<string name="remotekeyboard_connected" translatable="true">Remote keyboard connection is active</string>
|
||||
<string name="remotekeyboard_multiple_connections" translatable="true">There is more than one remote keyboard connection, select the device to configure</string>
|
||||
<string name="open_mousepad">Remote input</string>
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_info">Move a finger on the screen to move the mouse cursor. Tap for a click, and use two/three fingers for right and middle buttons. Use 2 fingers to scroll. Use a long press to drag\'n drop.</string>
|
||||
<string name="mousepad_double_tap_settings_title">Set two finger tap action</string>
|
||||
<string name="mousepad_triple_tap_settings_title">Set three finger tap action</string>
|
||||
<string name="mousepad_sensitivity_settings_title">Set touchpad sensitivity</string>
|
||||
@@ -53,9 +53,9 @@
|
||||
<item>Middle click</item>
|
||||
<item>Nothing</item>
|
||||
</string-array>
|
||||
<string name="mousepad_double_default">right</string>
|
||||
<string name="mousepad_triple_default">middle</string>
|
||||
<string name="mousepad_sensitivity_default">default</string>
|
||||
<string name="mousepad_default_double" translatable="false">right</string>
|
||||
<string name="mousepad_default_triple" translatable="false">middle</string>
|
||||
<string name="mousepad_default_sensitivity" translatable="false">default</string>
|
||||
<string-array name="mousepad_tap_values" translatable="false">
|
||||
<item>right</item>
|
||||
<item>middle</item>
|
||||
@@ -206,4 +206,15 @@
|
||||
<string name="open">Open</string>
|
||||
<string name="close">Close</string>
|
||||
|
||||
<string name="no_permissions_storage">You need to grant permissions to access the storage</string>
|
||||
<string name="plugins_need_permission">Some Plugins need permissions to work (tap for more info):</string>
|
||||
<string name="permission_explanation">This plugin needs permissions to work</string>
|
||||
<string name="optional_permission_explanation">You need to grant extra permissions to enable all functions</string>
|
||||
<string name="plugins_need_optional_permission">Some plugins have features disabled because of lack of permission (tap for more info):</string>
|
||||
<string name="sftp_permission_explanation">To access your files from your PC the app needs permission to access your phone\'s storage</string>
|
||||
<string name="share_optional_permission_explanation">To share files between your phone and your desktop you need to give access to the phone\'s storage</string>
|
||||
<string name="telepathy_permission_explanation">To read and write SMS from your desktop you need to give permission to SMS</string>
|
||||
<string name="telephony_permission_explanation">To see phone calls and SMS from the desktop you need to give permission to phone calls and SMS</string>
|
||||
<string name="telephony_optional_permission_explanation">To see a contact name instead of a phone number you need to give access to the phone\'s contacts</string>
|
||||
|
||||
</resources>
|
||||
|
4
res/xml/fileprovider_paths.xml
Normal file
4
res/xml/fileprovider_paths.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<external-path name="external_files" path="." />
|
||||
</paths>
|
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory
|
||||
android:title="@string/general_settings">
|
||||
|
||||
<EditTextPreference
|
||||
android:key="device_name_preference"
|
||||
android:title="@string/device_name"
|
||||
android:summary=""
|
||||
android:dialogTitle="@string/device_name"
|
||||
android:singleLine="true" />
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
@@ -5,30 +5,30 @@
|
||||
|
||||
<ListPreference
|
||||
android:id="@+id/mousepad_double_tap_preference"
|
||||
android:key="@string/mousepad_double_tap_key"
|
||||
android:title="@string/mousepad_double_tap_settings_title"
|
||||
android:summary="%s"
|
||||
android:defaultValue="@string/mousepad_default_double"
|
||||
android:entries="@array/mousepad_tap_entries"
|
||||
android:entryValues="@array/mousepad_tap_values"
|
||||
android:defaultValue="@string/mousepad_double_default" />
|
||||
android:key="@string/mousepad_double_tap_key"
|
||||
android:summary="%s"
|
||||
android:title="@string/mousepad_double_tap_settings_title"/>
|
||||
|
||||
<ListPreference
|
||||
android:id="@+id/mousepad_triple_tap_preference"
|
||||
android:key="@string/mousepad_triple_tap_key"
|
||||
android:title="@string/mousepad_triple_tap_settings_title"
|
||||
android:summary="%s"
|
||||
android:defaultValue="@string/mousepad_default_triple"
|
||||
android:entries="@array/mousepad_tap_entries"
|
||||
android:entryValues="@array/mousepad_tap_values"
|
||||
android:defaultValue="@string/mousepad_triple_default" />
|
||||
android:key="@string/mousepad_triple_tap_key"
|
||||
android:summary="%s"
|
||||
android:title="@string/mousepad_triple_tap_settings_title"/>
|
||||
|
||||
<ListPreference
|
||||
android:id="@+id/mousepad_sensitivity_preference"
|
||||
android:key="@string/mousepad_sensitivity_key"
|
||||
android:title="@string/mousepad_sensitivity_settings_title"
|
||||
android:summary="%s"
|
||||
android:defaultValue="@string/mousepad_default_sensitivity"
|
||||
android:entries="@array/mousepad_sensitivity_entries"
|
||||
android:entryValues="@array/mousepad_sensitivity_values"
|
||||
android:defaultValue="@string/mousepad_sensitivity_default" />
|
||||
android:key="@string/mousepad_sensitivity_key"
|
||||
android:summary="%s"
|
||||
android:title="@string/mousepad_sensitivity_settings_title"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:id="@+id/mousepad_scroll_preference"
|
||||
|
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 2016 Saikrishna Arcot <saiarcot895@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Backends.BluetoothBackend;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothServerSocket;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.PublicKey;
|
||||
import java.util.UUID;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
public class BluetoothLink extends BaseLink {
|
||||
private final BluetoothSocket socket;
|
||||
private final BluetoothLinkProvider linkProvider;
|
||||
|
||||
private boolean continueAccepting = true;
|
||||
|
||||
private Thread receivingThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8");
|
||||
char[] buf = new char[512];
|
||||
while (continueAccepting) {
|
||||
while (sb.indexOf("\n") == -1 && continueAccepting) {
|
||||
int charsRead;
|
||||
if ((charsRead = reader.read(buf)) > 0) {
|
||||
sb.append(buf, 0, charsRead);
|
||||
}
|
||||
}
|
||||
|
||||
int endIndex = sb.indexOf("\n");
|
||||
if (endIndex != -1) {
|
||||
String message = sb.substring(0, endIndex + 1);
|
||||
sb.delete(0, endIndex + 1);
|
||||
processMessage(message);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e("BluetoothLink/receiving", "Connection to " + socket.getRemoteDevice().getAddress() + " likely broken.", e);
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void processMessage(String message) {
|
||||
NetworkPackage np;
|
||||
try {
|
||||
np = NetworkPackage.unserialize(message);
|
||||
} catch (JSONException e) {
|
||||
Log.e("BluetoothLink/receiving", "Unable to parse message.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_ENCRYPTED)) {
|
||||
try {
|
||||
np = RsaHelper.decrypt(np, privateKey);
|
||||
} catch(Exception e) {
|
||||
Log.e("BluetoothLink/receiving", "Exception decrypting the package", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (np.hasPayloadTransferInfo()) {
|
||||
BluetoothSocket transferSocket = null;
|
||||
try {
|
||||
UUID transferUuid = UUID.fromString(np.getPayloadTransferInfo().getString("uuid"));
|
||||
transferSocket = socket.getRemoteDevice().createRfcommSocketToServiceRecord(transferUuid);
|
||||
transferSocket.connect();
|
||||
np.setPayload(transferSocket.getInputStream(), np.getPayloadSize());
|
||||
} catch (Exception e) {
|
||||
if (transferSocket != null) {
|
||||
try { transferSocket.close(); } catch(IOException ignored) { }
|
||||
}
|
||||
Log.e("BluetoothLink/receiving", "Unable to get payload", e);
|
||||
}
|
||||
}
|
||||
|
||||
packageReceived(np);
|
||||
}
|
||||
});
|
||||
|
||||
public BluetoothLink(Context context, BluetoothSocket socket, String deviceId, BluetoothLinkProvider linkProvider) {
|
||||
super(context, deviceId, linkProvider);
|
||||
this.socket = socket;
|
||||
this.linkProvider = linkProvider;
|
||||
}
|
||||
|
||||
public void startListening() {
|
||||
this.receivingThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "BluetoothLink";
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePairingHandler getPairingHandler(Device device, BasePairingHandler.PairingHandlerCallback callback) {
|
||||
return new BluetoothPairingHandler(device, callback);
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
if (socket == null) {
|
||||
return;
|
||||
}
|
||||
continueAccepting = false;
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
linkProvider.disconnectedLink(this, getDeviceId(), socket);
|
||||
}
|
||||
|
||||
private void sendMessage(NetworkPackage np) throws JSONException, IOException {
|
||||
byte[] message = np.serialize().getBytes(Charset.forName("UTF-8"));
|
||||
OutputStream socket = this.socket.getOutputStream();
|
||||
Log.i("BluetoothLink","Beginning to send message");
|
||||
socket.write(message);
|
||||
Log.i("BluetoothLink","Finished sending message");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendPackage(NetworkPackage np, Device.SendPackageStatusCallback callback) {
|
||||
return sendPackageInternal(np, callback, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
return sendPackageInternal(np, callback, key);
|
||||
}
|
||||
|
||||
private boolean sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) {
|
||||
|
||||
/*if (!isConnected()) {
|
||||
Log.e("BluetoothLink", "sendPackageEncrypted failed: not connected");
|
||||
callback.sendFailure(new Exception("Not connected"));
|
||||
return;
|
||||
}*/
|
||||
|
||||
try {
|
||||
BluetoothServerSocket serverSocket = null;
|
||||
if (np.hasPayload()) {
|
||||
UUID transferUuid = UUID.randomUUID();
|
||||
serverSocket = BluetoothAdapter.getDefaultAdapter()
|
||||
.listenUsingRfcommWithServiceRecord("KDE Connect Transfer", transferUuid);
|
||||
JSONObject payloadTransferInfo = new JSONObject();
|
||||
payloadTransferInfo.put("uuid", transferUuid.toString());
|
||||
np.setPayloadTransferInfo(payloadTransferInfo);
|
||||
}
|
||||
|
||||
if (key != null) {
|
||||
try {
|
||||
np = RsaHelper.encrypt(np, key);
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage(np);
|
||||
|
||||
if (serverSocket != null) {
|
||||
BluetoothSocket transferSocket = serverSocket.accept();
|
||||
try {
|
||||
serverSocket.close();
|
||||
|
||||
int idealBufferLength = 4096;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& transferSocket.getMaxReceivePacketSize() > 0) {
|
||||
idealBufferLength = transferSocket.getMaxReceivePacketSize();
|
||||
}
|
||||
byte[] buffer = new byte[idealBufferLength];
|
||||
int bytesRead;
|
||||
long progress = 0;
|
||||
InputStream stream = np.getPayload();
|
||||
while ((bytesRead = stream.read(buffer)) != -1) {
|
||||
progress += bytesRead;
|
||||
transferSocket.getOutputStream().write(buffer, 0, bytesRead);
|
||||
if (np.getPayloadSize() > 0) {
|
||||
callback.onProgressChanged((int) (100 * progress / np.getPayloadSize()));
|
||||
}
|
||||
}
|
||||
transferSocket.getOutputStream().flush();
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
return false;
|
||||
} finally {
|
||||
try { transferSocket.close(); } catch (IOException ignored) { }
|
||||
}
|
||||
}
|
||||
|
||||
callback.onSuccess();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean linkShouldBeKeptAlive() {
|
||||
return receivingThread.isAlive();
|
||||
}
|
||||
|
||||
/*
|
||||
public boolean isConnected() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
|
||||
return socket.isConnected();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright 2016 Saikrishna Arcot <saiarcot895@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Backends.BluetoothBackend;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.bluetooth.BluetoothServerSocket;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.Set;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
public class BluetoothLinkProvider extends BaseLinkProvider {
|
||||
|
||||
private static final UUID SERVICE_UUID = UUID.fromString("185f3df4-3268-4e3f-9fca-d4d5059915bd");
|
||||
private static final int REQUEST_ENABLE_BT = 48;
|
||||
|
||||
private final Context context;
|
||||
private final Map<String, BluetoothLink> visibleComputers = new HashMap<>();
|
||||
private final Map<BluetoothDevice, BluetoothSocket> sockets = new HashMap<>();
|
||||
|
||||
private BluetoothAdapter bluetoothAdapter = null;
|
||||
|
||||
private ServerRunnable serverRunnable;
|
||||
private ClientRunnable clientRunnable;
|
||||
|
||||
private void addLink(NetworkPackage identityPackage, BluetoothLink link) {
|
||||
String deviceId = identityPackage.getString("deviceId");
|
||||
Log.i("BluetoothLinkProvider","addLink to "+deviceId);
|
||||
BluetoothLink oldLink = visibleComputers.get(deviceId);
|
||||
if (oldLink == link) {
|
||||
Log.e("BluetoothLinkProvider", "oldLink == link. This should not happen!");
|
||||
return;
|
||||
}
|
||||
visibleComputers.put(deviceId, link);
|
||||
connectionAccepted(identityPackage, link);
|
||||
link.startListening();
|
||||
if (oldLink != null) {
|
||||
Log.i("BluetoothLinkProvider","Removing old connection to same device");
|
||||
oldLink.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public BluetoothLinkProvider(Context context) {
|
||||
this.context = context;
|
||||
|
||||
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (bluetoothAdapter == null) {
|
||||
Log.e("BluetoothLinkProvider","No bluetooth adapter found.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
if (bluetoothAdapter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bluetoothAdapter.isEnabled()) {
|
||||
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
Log.e("BluetoothLinkProvider","Bluetooth adapter not enabled.");
|
||||
// TODO: next line needs to be called from an existing activity, so move it?
|
||||
// startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
|
||||
// TODO: Check result of the previous command, whether the user allowed bluetooth or not.
|
||||
return;
|
||||
}
|
||||
|
||||
//This handles the case when I'm the existing device in the network and receive a hello package
|
||||
clientRunnable = new ClientRunnable();
|
||||
new Thread(clientRunnable).start();
|
||||
|
||||
// I'm on a new network, let's be polite and introduce myself
|
||||
serverRunnable = new ServerRunnable();
|
||||
new Thread(serverRunnable).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkChange() {
|
||||
onStop();
|
||||
onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
if (bluetoothAdapter == null || clientRunnable == null || serverRunnable == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
clientRunnable.stopProcessing();
|
||||
serverRunnable.stopProcessing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "BluetoothLinkProvider";
|
||||
}
|
||||
|
||||
public void disconnectedLink(BluetoothLink link, String deviceId, BluetoothSocket socket) {
|
||||
sockets.remove(socket.getRemoteDevice());
|
||||
visibleComputers.remove(deviceId);
|
||||
connectionLost(link);
|
||||
}
|
||||
|
||||
private class ServerRunnable implements Runnable {
|
||||
|
||||
private boolean continueProcessing = true;
|
||||
private BluetoothServerSocket serverSocket;
|
||||
|
||||
void stopProcessing() {
|
||||
continueProcessing = false;
|
||||
if (serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
serverSocket = bluetoothAdapter
|
||||
.listenUsingRfcommWithServiceRecord("KDE Connect", SERVICE_UUID);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
if (continueProcessing) {
|
||||
try {
|
||||
BluetoothSocket socket = serverSocket.accept();
|
||||
connect(socket);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void connect(BluetoothSocket socket) throws Exception {
|
||||
//socket.connect();
|
||||
OutputStream outputStream = socket.getOutputStream();
|
||||
if (sockets.containsKey(socket.getRemoteDevice())) {
|
||||
Log.i("BTLinkProvider/Server", "Received duplicate connection from " + socket.getRemoteDevice().getAddress());
|
||||
socket.close();
|
||||
return;
|
||||
} else {
|
||||
sockets.put(socket.getRemoteDevice(), socket);
|
||||
}
|
||||
|
||||
Log.i("BTLinkProvider/Server", "Received connection from " + socket.getRemoteDevice().getAddress());
|
||||
|
||||
NetworkPackage np = NetworkPackage.createIdentityPackage(context);
|
||||
byte[] message = np.serialize().getBytes("UTF-8");
|
||||
outputStream.write(message);
|
||||
|
||||
Log.i("BTLinkProvider/Server", "Sent identity package");
|
||||
|
||||
// Listen for the response
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8");
|
||||
int charsRead;
|
||||
char[] buf = new char[512];
|
||||
while(sb.lastIndexOf("\n") == -1 && (charsRead = reader.read(buf)) != -1) {
|
||||
sb.append(buf, 0, charsRead);
|
||||
}
|
||||
|
||||
String response = sb.toString();
|
||||
final NetworkPackage identityPackage = NetworkPackage.unserialize(response);
|
||||
|
||||
if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
|
||||
Log.e("BTLinkProvider/Server", "2 Expecting an identity package");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i("BTLinkProvider/Server", "Received identity package");
|
||||
|
||||
BluetoothLink link = new BluetoothLink(context, socket,
|
||||
identityPackage.getString("deviceId"), BluetoothLinkProvider.this);
|
||||
|
||||
addLink(identityPackage, link);
|
||||
}
|
||||
}
|
||||
|
||||
private class ClientRunnable extends BroadcastReceiver implements Runnable {
|
||||
|
||||
private boolean continueProcessing = true;
|
||||
private Map<BluetoothDevice, Thread> connectionThreads = new HashMap<>();
|
||||
|
||||
void stopProcessing() {
|
||||
continueProcessing = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_UUID);
|
||||
context.registerReceiver(this, filter);
|
||||
}
|
||||
|
||||
while (continueProcessing) {
|
||||
connectToDevices();
|
||||
try {
|
||||
Thread.sleep(15000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
context.unregisterReceiver(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void connectToDevices() {
|
||||
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
|
||||
Log.i("BluetoothLinkProvider", "Bluetooth adapter paired devices: " + pairedDevices.size());
|
||||
|
||||
// Loop through paired devices
|
||||
for (BluetoothDevice device : pairedDevices) {
|
||||
if (sockets.containsKey(device)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
device.fetchUuidsWithSdp();
|
||||
} else {
|
||||
connectToDevice(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@TargetApi(value=Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(BluetoothDevice.ACTION_UUID)) {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
Parcelable[] activeUuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
|
||||
|
||||
if (sockets.containsKey(device)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeUuids == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Parcelable uuid: activeUuids) {
|
||||
if (uuid.toString().equals(SERVICE_UUID.toString())) {
|
||||
connectToDevice(device);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void connectToDevice(BluetoothDevice device) {
|
||||
if (!connectionThreads.containsKey(device) || !connectionThreads.get(device).isAlive()) {
|
||||
Thread connectionThread = new Thread(new ClientConnect(device));
|
||||
connectionThread.start();
|
||||
connectionThreads.put(device, connectionThread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private class ClientConnect implements Runnable {
|
||||
|
||||
private final BluetoothDevice device;
|
||||
|
||||
public ClientConnect(BluetoothDevice device) {
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
connectToDevice();
|
||||
}
|
||||
|
||||
private void connectToDevice() {
|
||||
BluetoothSocket socket;
|
||||
try {
|
||||
socket = device.createRfcommSocketToServiceRecord(SERVICE_UUID);
|
||||
socket.connect();
|
||||
sockets.put(device, socket);
|
||||
} catch (IOException e) {
|
||||
Log.e("BTLinkProvider/Client", "Could not connect to KDE Connect service on " + device.getAddress(), e);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i("BTLinkProvider/Client", "Connected to " + device.getAddress());
|
||||
|
||||
try {
|
||||
int character;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while(sb.lastIndexOf("\n") == -1 && (character = socket.getInputStream().read()) != -1) {
|
||||
sb.append((char)character);
|
||||
}
|
||||
|
||||
String message = sb.toString();
|
||||
final NetworkPackage identityPackage = NetworkPackage.unserialize(message);
|
||||
|
||||
if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) {
|
||||
Log.e("BTLinkProvider/Client", "1 Expecting an identity package");
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i("BTLinkProvider/Client", "Received identity package");
|
||||
|
||||
String myId = NetworkPackage.createIdentityPackage(context).getString("deviceId");
|
||||
if (identityPackage.getString("deviceId").equals(myId)) {
|
||||
// Probably won't happen, but just to be safe
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (visibleComputers.containsKey(identityPackage.getString("deviceId"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i("BTLinkProvider/Client", "Identity package received, creating link");
|
||||
|
||||
final BluetoothLink link = new BluetoothLink(context, socket,
|
||||
identityPackage.getString("deviceId"), BluetoothLinkProvider.this);
|
||||
|
||||
NetworkPackage np2 = NetworkPackage.createIdentityPackage(context);
|
||||
link.sendPackage(np2,new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
addLink(identityPackage, link);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Log.e("BTLinkProvider/Client", "Connection lost/disconnected on " + device.getAddress(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2015 Vineet Garg <grg.vineet@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Backends.BluetoothBackend;
|
||||
|
||||
import android.util.Log;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class BluetoothPairingHandler extends BasePairingHandler {
|
||||
|
||||
Timer mPairingTimer;
|
||||
public BluetoothPairingHandler(Device device, final PairingHandlerCallback callback) {
|
||||
super(device, callback);
|
||||
|
||||
if (device.isPaired()) {
|
||||
mPairStatus = PairStatus.Paired;
|
||||
} else {
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
public NetworkPackage createPairPackage() {
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", true);
|
||||
return np;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packageReceived(NetworkPackage np) throws Exception{
|
||||
|
||||
boolean wantsPair = np.getBoolean("pair");
|
||||
|
||||
if (wantsPair == isPaired()) {
|
||||
if (mPairStatus == PairStatus.Requested) {
|
||||
//Log.e("Device","Unpairing (pair rejected)");
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
hidePairingNotification();
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (wantsPair) {
|
||||
|
||||
if (mPairStatus == PairStatus.Requested) { //We started pairing
|
||||
hidePairingNotification();
|
||||
pairingDone();
|
||||
} else {
|
||||
|
||||
// If device is already paired, accept pairing silently
|
||||
if (mDevice.isPaired()) {
|
||||
acceptPairing();
|
||||
return;
|
||||
}
|
||||
|
||||
// Pairing notifications are still managed by device as there is no other way to
|
||||
// know about notificationId to cancel notification when PairActivity is started
|
||||
// Even putting notificationId in intent does not work because PairActivity can be
|
||||
// started from MainActivity too, so then notificationId cannot be set
|
||||
hidePairingNotification();
|
||||
mDevice.displayPairingNotification();
|
||||
|
||||
mPairingTimer = new Timer();
|
||||
|
||||
mPairingTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.w("KDE/Device","Unpairing (timeout B)");
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
hidePairingNotification();
|
||||
}
|
||||
}, 25*1000); //Time to show notification, waiting for user to accept (peer will timeout in 30 seconds)
|
||||
mPairStatus = PairStatus.RequestedByPeer;
|
||||
mCallback.incomingRequest();
|
||||
|
||||
}
|
||||
} else {
|
||||
Log.i("KDE/Pairing", "Unpair request");
|
||||
|
||||
if (mPairStatus == PairStatus.Requested) {
|
||||
hidePairingNotification();
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer));
|
||||
} else if (mPairStatus == PairStatus.Paired) {
|
||||
mCallback.unpaired();
|
||||
}
|
||||
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPairing() {
|
||||
|
||||
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
hidePairingNotification(); //Will stop the pairingTimer if it was running
|
||||
mPairingTimer = new Timer();
|
||||
mPairingTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_timed_out));
|
||||
Log.w("KDE/Device","Unpairing (timeout A)");
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
}
|
||||
}, 30*1000); //Time to wait for the other to accept
|
||||
mPairStatus = PairStatus.Requested;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_could_not_send_package));
|
||||
}
|
||||
};
|
||||
mDevice.sendPackage(createPairPackage(), statusCallback);
|
||||
}
|
||||
|
||||
public void hidePairingNotification() {
|
||||
mDevice.hidePairingNotification();
|
||||
if (mPairingTimer != null) {
|
||||
mPairingTimer .cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptPairing() {
|
||||
hidePairingNotification();
|
||||
Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
pairingDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_not_reachable));
|
||||
}
|
||||
};
|
||||
mDevice.sendPackage(createPairPackage(), statusCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rejectPairing() {
|
||||
hidePairingNotification();
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", false);
|
||||
mDevice.sendPackage(np);
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void pairingDone() {
|
||||
// Store device information needed to create a Device object in a future
|
||||
//Log.e("KDE/PairingDone", "Pairing Done");
|
||||
mPairStatus = PairStatus.Paired;
|
||||
mCallback.pairingDone();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpair() {
|
||||
mPairStatus = PairStatus.NotPaired;
|
||||
NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR);
|
||||
np.set("pair", false);
|
||||
mDevice.sendPackage(np);
|
||||
}
|
||||
}
|
@@ -265,7 +265,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
|
||||
}
|
||||
|
||||
private void addLink(final NetworkPackage identityPackage, Socket socket, LanLink.ConnectionStarted connectionOrigin) throws IOException {
|
||||
private synchronized void addLink(final NetworkPackage identityPackage, Socket socket, LanLink.ConnectionStarted connectionOrigin) throws IOException {
|
||||
|
||||
String deviceId = identityPackage.getString("deviceId");
|
||||
LanLink currentLink = visibleComputers.get(deviceId);
|
||||
|
@@ -26,11 +26,13 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BaseLinkProvider;
|
||||
//import org.kde.kdeconnect.Backends.BluetoothBackend.BluetoothLinkProvider;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
@@ -44,6 +46,8 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class BackgroundService extends Service {
|
||||
|
||||
private static BackgroundService instance;
|
||||
|
||||
public interface DeviceListChangedCallback {
|
||||
void onDeviceListChanged();
|
||||
}
|
||||
@@ -56,6 +60,10 @@ public class BackgroundService extends Service {
|
||||
|
||||
private final HashSet<Object> discoveryModeAcquisitions = new HashSet<>();
|
||||
|
||||
public static BackgroundService getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
public boolean acquireDiscoveryMode(Object key) {
|
||||
boolean wasEmpty = discoveryModeAcquisitions.isEmpty();
|
||||
discoveryModeAcquisitions.add(key);
|
||||
@@ -140,11 +148,11 @@ public class BackgroundService extends Service {
|
||||
}
|
||||
|
||||
private void registerLinkProviders() {
|
||||
|
||||
//linkProviders.add(new LoopbackLinkProvider(this));
|
||||
|
||||
linkProviders.add(new LanLinkProvider(this));
|
||||
|
||||
// linkProviders.add(new LoopbackLinkProvider(this));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
// linkProviders.add(new BluetoothLinkProvider(this));
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<BaseLinkProvider> getLinkProviders() {
|
||||
@@ -248,6 +256,8 @@ public class BackgroundService extends Service {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
instance = this;
|
||||
|
||||
// Register screen on listener
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
||||
registerReceiver(new KdeConnectBroadcastReceiver(), filter);
|
||||
|
@@ -28,6 +28,7 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
@@ -82,7 +83,9 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
private List<String> m_supportedPlugins = new ArrayList<>();
|
||||
private final ConcurrentHashMap<String, Plugin> plugins = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Plugin> failedPlugins = new ConcurrentHashMap<>();
|
||||
private Map<String, ArrayList<String>> pluginsByIncomingInterface;
|
||||
private final ConcurrentHashMap<String, Plugin> pluginsWithoutPermissions = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Plugin> pluginsWithoutOptionalPermissions = new ConcurrentHashMap<>();
|
||||
private Map<String, ArrayList<String>> pluginsByIncomingInterface = new HashMap<>();
|
||||
|
||||
private final SharedPreferences settings;
|
||||
|
||||
@@ -691,7 +694,20 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
private synchronized boolean addPlugin(final String pluginKey) {
|
||||
Plugin existing = plugins.get(pluginKey);
|
||||
if (existing != null) {
|
||||
|
||||
if (existing.getMinSdk() > Build.VERSION.SDK_INT) {
|
||||
Log.i("KDE/addPlugin", "Min API level not fulfilled " + pluginKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Log.w("KDE/addPlugin","plugin already present:" + pluginKey);
|
||||
if (existing.checkOptionalPermissions()) {
|
||||
Log.i("KDE/addPlugin", "Optional Permissions OK " + pluginKey);
|
||||
pluginsWithoutOptionalPermissions.remove(pluginKey);
|
||||
} else {
|
||||
Log.e("KDE/addPlugin", "No optional permission " + pluginKey);
|
||||
pluginsWithoutOptionalPermissions.put(pluginKey, existing);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -703,6 +719,11 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plugin.getMinSdk() > Build.VERSION.SDK_INT) {
|
||||
Log.i("KDE/addPlugin", "Min API level not fulfilled" + pluginKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean success;
|
||||
try {
|
||||
success = plugin.onCreate();
|
||||
@@ -722,6 +743,24 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
failedPlugins.put(pluginKey, plugin);
|
||||
}
|
||||
|
||||
if(!plugin.checkRequiredPermissions()){
|
||||
Log.e("KDE/addPlugin", "No permission " + pluginKey);
|
||||
plugins.remove(pluginKey);
|
||||
pluginsWithoutPermissions.put(pluginKey, plugin);
|
||||
success = false;
|
||||
} else {
|
||||
Log.i("KDE/addPlugin", "Permissions OK " + pluginKey);
|
||||
pluginsWithoutPermissions.remove(pluginKey);
|
||||
|
||||
if (plugin.checkOptionalPermissions()) {
|
||||
Log.i("KDE/addPlugin", "Optional Permissions OK " + pluginKey);
|
||||
pluginsWithoutOptionalPermissions.remove(pluginKey);
|
||||
} else {
|
||||
Log.e("KDE/addPlugin", "No optional permission " + pluginKey);
|
||||
pluginsWithoutOptionalPermissions.put(pluginKey, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -812,6 +851,14 @@ public class Device implements BaseLink.PackageReceiver {
|
||||
return failedPlugins;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String, Plugin> getPluginsWithoutPermissions() {
|
||||
return pluginsWithoutPermissions;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String,Plugin> getPluginsWithoutOptionalPermissions() {
|
||||
return pluginsWithoutOptionalPermissions;
|
||||
}
|
||||
|
||||
public void addPluginsChangedListener(PluginsChangedListener listener) {
|
||||
pluginsChangedListeners.add(listener);
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ public class ContactsHelper {
|
||||
, PhoneLookup.ID */
|
||||
},
|
||||
null, null, null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
return contactInfo;
|
||||
}
|
||||
|
||||
|
@@ -2,17 +2,57 @@ package org.kde.kdeconnect.Helpers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.io.LineNumberReader;
|
||||
|
||||
public class NetworkHelper {
|
||||
|
||||
public static boolean isOnMobileNetwork(Context context) {
|
||||
return false; //This looks a bit dangerous and I prefer not to use it in the next stable release.
|
||||
/*final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = connMgr.getActiveNetworkInfo();
|
||||
return (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE);
|
||||
*/
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
return false; //No good way to know it
|
||||
}
|
||||
try {
|
||||
boolean mobile = false;
|
||||
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
Network[] networks = connMgr.getAllNetworks();
|
||||
for (Network network : networks) {
|
||||
NetworkInfo info = connMgr.getNetworkInfo(network);
|
||||
if (info == null) {
|
||||
continue;
|
||||
}
|
||||
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
|
||||
mobile = info.isConnected();
|
||||
continue;
|
||||
}
|
||||
//Log.e(info.getTypeName(),""+info.isAvailable());
|
||||
if (info.isAvailable()) return false; //We are connected to at least one non-mobile network
|
||||
}
|
||||
if (mobile) { //We suspect we are on a mobile net
|
||||
try {
|
||||
//Check the number of network neighbours, on data it should be 0
|
||||
LineNumberReader is = new LineNumberReader(new FileReader("/proc/net/arp"));
|
||||
is.skip(Long.MAX_VALUE);
|
||||
//Log.e("NetworkHelper", "procnetarp has " + is.getLineNumber() + " lines");
|
||||
if (is.getLineNumber() > 1) { //The first line are the headers
|
||||
return false; //I have neighbours, so this doesn't look like a mobile network
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("NetworkHelper", "Exception reading procnetarp");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.d("isOnMobileNetwork", "Something went wrong, but this is non-critical.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -220,6 +220,7 @@ public class SslHelper {
|
||||
// Following ciphers are for and due to old devices
|
||||
supportedCiphers.add("SSL_RSA_WITH_RC4_128_SHA"); // API 9+
|
||||
supportedCiphers.add("SSL_RSA_WITH_RC4_128_MD5"); // API 9+
|
||||
supportedCiphers.add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA"); // API 9+
|
||||
}
|
||||
socket.setEnabledCipherSuites(supportedCiphers.toArray(new String[supportedCiphers.size()]));
|
||||
|
||||
|
@@ -40,7 +40,7 @@ public class BatteryPlugin extends Plugin {
|
||||
private static final int THRESHOLD_EVENT_NONE= 0;
|
||||
private static final int THRESHOLD_EVENT_BATTERY_LOW = 1;
|
||||
|
||||
private NetworkPackage lastInfo = null;
|
||||
private NetworkPackage batteryInfo = new NetworkPackage(PACKAGE_TYPE_BATTERY);
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
@@ -56,18 +56,18 @@ public class BatteryPlugin extends Plugin {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent batteryIntent) {
|
||||
|
||||
Intent batteryChargeIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
int level = batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||
int scale = batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
|
||||
int currentCharge = level*100 / scale;
|
||||
boolean isCharging = (0 != batteryChargeIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
|
||||
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
|
||||
int plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
|
||||
int currentCharge = (level == -1)? batteryInfo.getInt("currentCharge") : level*100 / scale;
|
||||
boolean isCharging = (plugged == -1)? batteryInfo.getBoolean("isCharging") : (0 != plugged);
|
||||
boolean lowBattery = Intent.ACTION_BATTERY_LOW.equals(batteryIntent.getAction());
|
||||
int thresholdEvent = lowBattery? THRESHOLD_EVENT_BATTERY_LOW : THRESHOLD_EVENT_NONE;
|
||||
|
||||
if (lastInfo != null
|
||||
&& isCharging == lastInfo.getBoolean("isCharging")
|
||||
&& currentCharge == lastInfo.getInt("currentCharge")
|
||||
&& thresholdEvent == lastInfo.getInt("thresholdEvent")
|
||||
if (isCharging == batteryInfo.getBoolean("isCharging")
|
||||
&& currentCharge == batteryInfo.getInt("currentCharge")
|
||||
&& thresholdEvent == batteryInfo.getInt("thresholdEvent")
|
||||
) {
|
||||
|
||||
//Do not send again if nothing has changed
|
||||
@@ -75,12 +75,10 @@ public class BatteryPlugin extends Plugin {
|
||||
|
||||
} else {
|
||||
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_BATTERY);
|
||||
np.set("currentCharge", currentCharge);
|
||||
np.set("isCharging", isCharging);
|
||||
np.set("thresholdEvent", thresholdEvent);
|
||||
device.sendPackage(np);
|
||||
lastInfo = np;
|
||||
batteryInfo.set("currentCharge", currentCharge);
|
||||
batteryInfo.set("isCharging", isCharging);
|
||||
batteryInfo.set("thresholdEvent", thresholdEvent);
|
||||
device.sendPackage(batteryInfo);
|
||||
|
||||
}
|
||||
|
||||
@@ -89,8 +87,10 @@ public class BatteryPlugin extends Plugin {
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_LOW));
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
|
||||
context.registerReceiver(receiver, intentFilter);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -104,9 +104,7 @@ public class BatteryPlugin extends Plugin {
|
||||
public boolean onPackageReceived(NetworkPackage np) {
|
||||
|
||||
if (np.getBoolean("request")) {
|
||||
if (lastInfo != null) {
|
||||
device.sendPackage(lastInfo);
|
||||
}
|
||||
device.sendPackage(batteryInfo);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.Ringtone;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -16,13 +16,16 @@ import android.view.WindowManager;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class FindMyPhoneActivity extends Activity {
|
||||
Ringtone ringtone;
|
||||
|
||||
private MediaPlayer mediaPlayer;
|
||||
private int previousVolume;
|
||||
private AudioManager audioManager;
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
|
||||
if(ringtone != null) {
|
||||
if (mediaPlayer != null) {
|
||||
// If this activity was already open and we received the ring packet again, just finish it
|
||||
finish();
|
||||
}
|
||||
@@ -34,10 +37,12 @@ public class FindMyPhoneActivity extends Activity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_find_my_phone);
|
||||
|
||||
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
Window window = this.getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
|
||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||
|
||||
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -51,36 +56,37 @@ public class FindMyPhoneActivity extends Activity {
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
|
||||
if (ringtone == null) {
|
||||
ringtoneUri = RingtoneManager.getValidRingtoneUri(getApplicationContext());
|
||||
if (ringtoneUri == null) {
|
||||
Log.e("FindMyPhone", "Could not find a ringtone to play!");
|
||||
return;
|
||||
try {
|
||||
// Make sure we are heard even when the phone is silent, restore original volume later
|
||||
previousVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM);
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM), 0);
|
||||
|
||||
Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||
if (alert == null) {
|
||||
alert = RingtoneManager.getValidRingtoneUri(getApplicationContext());
|
||||
}
|
||||
ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
|
||||
|
||||
mediaPlayer = new MediaPlayer();
|
||||
mediaPlayer.setDataSource(this, alert);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
|
||||
mediaPlayer.setLooping(true);
|
||||
mediaPlayer.prepare();
|
||||
mediaPlayer.start();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("FindMyPhoneActivity", "Exception", e);
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= 21) {
|
||||
AudioAttributes.Builder b = new AudioAttributes.Builder();
|
||||
b.setUsage(AudioAttributes.USAGE_ALARM);
|
||||
ringtone.setAudioAttributes(b.build());
|
||||
} else {
|
||||
ringtone.setStreamType(AudioManager.STREAM_ALARM);
|
||||
}
|
||||
|
||||
ringtone.play();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if(ringtone != null) {
|
||||
ringtone.stop();
|
||||
ringtone = null;
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.stop();
|
||||
}
|
||||
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, previousVolume, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.Menu;
|
||||
@@ -39,7 +39,7 @@ import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class MousePadActivity extends ActionBarActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MousePadGestureDetector.OnGestureListener {
|
||||
public class MousePadActivity extends AppCompatActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MousePadGestureDetector.OnGestureListener {
|
||||
String deviceId;
|
||||
|
||||
private final static float MinDistanceToSendScroll = 2.5f; // touch gesture scroll
|
||||
@@ -97,11 +97,11 @@ public class MousePadActivity extends ActionBarActivity implements GestureDetect
|
||||
scrollDirection = 1;
|
||||
}
|
||||
String doubleTapSetting = prefs.getString(getString(R.string.mousepad_double_tap_key),
|
||||
getString(R.string.mousepad_double_default));
|
||||
getString(R.string.mousepad_default_double));
|
||||
String tripleTapSetting = prefs.getString(getString(R.string.mousepad_triple_tap_key),
|
||||
getString(R.string.mousepad_triple_default));
|
||||
getString(R.string.mousepad_default_triple));
|
||||
String sensitivitySetting = prefs.getString(getString(R.string.mousepad_sensitivity_key),
|
||||
getString(R.string.mousepad_sensitivity_default));
|
||||
getString(R.string.mousepad_default_sensitivity));
|
||||
|
||||
doubleTapAction = ClickType.fromString(doubleTapSetting);
|
||||
tripleTapAction = ClickType.fromString(tripleTapSetting);
|
||||
|
@@ -26,7 +26,7 @@ import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
@@ -46,12 +46,12 @@ import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MprisActivity extends ActionBarActivity {
|
||||
public class MprisActivity extends AppCompatActivity {
|
||||
|
||||
private String deviceId;
|
||||
private final Handler positionSeekUpdateHandler = new Handler();
|
||||
private Runnable positionSeekUpdateRunnable = null;
|
||||
private String targetPlayer = null;
|
||||
private MprisPlugin.MprisPlayer targetPlayer = null;
|
||||
|
||||
private static String milisToProgress(long milis) {
|
||||
int length = (int)(milis / 1000); //From milis to seconds
|
||||
@@ -69,7 +69,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
text.append(seconds);
|
||||
return text.toString();
|
||||
}
|
||||
protected void connectToPlugin() {
|
||||
protected void connectToPlugin(final String targetPlayerName) {
|
||||
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
@@ -81,6 +81,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
Log.e("MprisActivity", "device has no mpris plugin!");
|
||||
return;
|
||||
}
|
||||
targetPlayer = mpris.getPlayerStatus(targetPlayerName);
|
||||
|
||||
mpris.setPlayerStatusUpdatedHandler("activity", new Handler() {
|
||||
@Override
|
||||
@@ -88,49 +89,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String song = mpris.getCurrentSong();
|
||||
|
||||
TextView nowPlaying = (TextView) findViewById(R.id.now_playing_textview);
|
||||
if (!nowPlaying.getText().toString().equals(song)) {
|
||||
nowPlaying.setText(song);
|
||||
}
|
||||
|
||||
//Hacks for Spotify because it reports incorrect info about what it supports
|
||||
boolean isSpotify = "spotify".equals(mpris.getPlayer().toLowerCase());
|
||||
|
||||
if (mpris.getLength() > -1 && mpris.getPosition() > -1 && !isSpotify) {
|
||||
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(mpris.getLength()));
|
||||
SeekBar positionSeek = (SeekBar)findViewById(R.id.positionSeek);
|
||||
positionSeek.setMax((int)(mpris.getLength()));
|
||||
positionSeek.setProgress((int)(mpris.getPosition()));
|
||||
findViewById(R.id.progress_slider).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.progress_slider).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
int volume = mpris.getVolume();
|
||||
((SeekBar) findViewById(R.id.volume_seek)).setProgress(volume);
|
||||
|
||||
boolean isPlaying = mpris.isPlaying();
|
||||
if (isPlaying) {
|
||||
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_pause);
|
||||
findViewById(R.id.play_button).setVisibility(mpris.isPauseAllowed() ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
((ImageButton) findViewById(R.id.play_button)).setImageResource(android.R.drawable.ic_media_play);
|
||||
findViewById(R.id.play_button).setVisibility(mpris.isPlayAllowed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
if (isSpotify) {
|
||||
findViewById(R.id.volume_layout).setVisibility(View.INVISIBLE);
|
||||
findViewById(R.id.rew_button).setVisibility(View.GONE);
|
||||
findViewById(R.id.ff_button).setVisibility(View.GONE);
|
||||
} else {
|
||||
findViewById(R.id.volume_layout).setVisibility(View.VISIBLE);
|
||||
findViewById(R.id.rew_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.ff_button).setVisibility(mpris.isSeekAllowed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
findViewById(R.id.next_button).setVisibility(mpris.isGoNextAllowed() ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.prev_button).setVisibility(mpris.isGoPreviousAllowed() ? View.VISIBLE : View.GONE);
|
||||
updatePlayerStatus(mpris);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -169,36 +128,28 @@ public class MprisActivity extends ActionBarActivity {
|
||||
if (pos >= playerList.size()) return;
|
||||
|
||||
String player = playerList.get(pos);
|
||||
if (player.equals(mpris.getPlayer())) {
|
||||
if (targetPlayer != null && player.equals(targetPlayer.getPlayer())) {
|
||||
return; //Player hasn't actually changed
|
||||
}
|
||||
mpris.setPlayer(player);
|
||||
|
||||
//Clear values from previous player
|
||||
((TextView) findViewById(R.id.now_playing_textview)).setText("");
|
||||
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(0));
|
||||
((SeekBar)findViewById(R.id.positionSeek)).setMax(0);
|
||||
targetPlayer = mpris.getPlayerStatus(player);
|
||||
updatePlayerStatus(mpris);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> arg0) {
|
||||
mpris.setPlayer(null);
|
||||
targetPlayer = null;
|
||||
}
|
||||
});
|
||||
|
||||
if (targetPlayer != null) {
|
||||
int targetIndex = adapter.getPosition(targetPlayer);
|
||||
int targetIndex = adapter.getPosition(targetPlayer.getPlayer());
|
||||
if (targetIndex >= 0) {
|
||||
spinner.setSelection(targetIndex);
|
||||
}
|
||||
targetPlayer = null;
|
||||
} else {
|
||||
// restore last selected player
|
||||
int position = adapter.getPosition(mpris.getPlayer());
|
||||
if (position >= 0) {
|
||||
spinner.setSelection(position);
|
||||
} else {
|
||||
targetPlayer = null;
|
||||
}
|
||||
}
|
||||
updatePlayerStatus(mpris);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -212,7 +163,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
private final BaseLinkProvider.ConnectionReceiver connectionReceiver = new BaseLinkProvider.ConnectionReceiver() {
|
||||
@Override
|
||||
public void onConnectionReceived(NetworkPackage identityPackage, BaseLink link) {
|
||||
connectToPlugin();
|
||||
connectToPlugin(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,14 +183,59 @@ public class MprisActivity extends ActionBarActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void updatePlayerStatus(MprisPlugin mpris) {
|
||||
MprisPlugin.MprisPlayer playerStatus = targetPlayer;
|
||||
if (playerStatus == null) {
|
||||
//No player with that name found, just display "empty" data
|
||||
playerStatus = mpris.getEmptyPlayer();
|
||||
}
|
||||
String song = playerStatus.getCurrentSong();
|
||||
|
||||
TextView nowPlaying = (TextView) findViewById(R.id.now_playing_textview);
|
||||
if (!nowPlaying.getText().toString().equals(song)) {
|
||||
nowPlaying.setText(song);
|
||||
}
|
||||
|
||||
if (playerStatus.isSeekAllowed()) {
|
||||
((TextView) findViewById(R.id.time_textview)).setText(milisToProgress(playerStatus.getLength()));
|
||||
SeekBar positionSeek = (SeekBar)findViewById(R.id.positionSeek);
|
||||
positionSeek.setMax((int)(playerStatus.getLength()));
|
||||
positionSeek.setProgress((int)(playerStatus.getPosition()));
|
||||
findViewById(R.id.progress_slider).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.progress_slider).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
int volume = playerStatus.getVolume();
|
||||
((SeekBar) findViewById(R.id.volume_seek)).setProgress(volume);
|
||||
|
||||
boolean isPlaying = playerStatus.isPlaying();
|
||||
if (isPlaying) {
|
||||
((ImageButton) findViewById(R.id.play_button)).setImageResource(R.drawable.ic_pause_black);
|
||||
findViewById(R.id.play_button).setVisibility(playerStatus.isPauseAllowed() ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
((ImageButton) findViewById(R.id.play_button)).setImageResource(R.drawable.ic_play_black);
|
||||
findViewById(R.id.play_button).setVisibility(playerStatus.isPlayAllowed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
findViewById(R.id.volume_layout).setVisibility(playerStatus.isSetVolumeAllowed() ? View.VISIBLE : View.INVISIBLE);
|
||||
findViewById(R.id.rew_button).setVisibility(playerStatus.isSeekAllowed() ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.ff_button).setVisibility(playerStatus.isSeekAllowed() ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.next_button).setVisibility(playerStatus.isGoNextAllowed() ? View.VISIBLE : View.GONE);
|
||||
findViewById(R.id.prev_button).setVisibility(playerStatus.isGoPreviousAllowed() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change current volume with provided step.
|
||||
*
|
||||
* @param mpris multimedia controller
|
||||
* @param step step size volume change
|
||||
*/
|
||||
private void updateVolume(MprisPlugin mpris, int step) {
|
||||
final int currentVolume = mpris.getVolume();
|
||||
private void updateVolume(int step) {
|
||||
if (targetPlayer == null) {
|
||||
return;
|
||||
}
|
||||
final int currentVolume = targetPlayer.getVolume();
|
||||
|
||||
if(currentVolume < 100 || currentVolume > 0) {
|
||||
int newVolume = currentVolume + step;
|
||||
if(newVolume > 100) {
|
||||
@@ -247,7 +243,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
} else if (newVolume <0 ) {
|
||||
newVolume = 0;
|
||||
}
|
||||
mpris.setVolume(newVolume);
|
||||
targetPlayer.setVolume(newVolume);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,26 +251,10 @@ public class MprisActivity extends ActionBarActivity {
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
updateVolume(mpris, 5);
|
||||
}
|
||||
});
|
||||
updateVolume(5);
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
updateVolume(mpris, -5);
|
||||
}
|
||||
});
|
||||
updateVolume(-5);
|
||||
return true;
|
||||
default:
|
||||
return super.onKeyDown(keyCode, event);
|
||||
@@ -298,7 +278,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.mpris_control);
|
||||
|
||||
targetPlayer = getIntent().getStringExtra("player");
|
||||
final String targetPlayerName = getIntent().getStringExtra("player");
|
||||
getIntent().removeExtra("player");
|
||||
deviceId = getIntent().getStringExtra("deviceId");
|
||||
|
||||
@@ -313,7 +293,7 @@ public class MprisActivity extends ActionBarActivity {
|
||||
service.addConnectionListener(connectionReceiver);
|
||||
}
|
||||
});
|
||||
connectToPlugin();
|
||||
connectToPlugin(targetPlayerName);
|
||||
|
||||
findViewById(R.id.play_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -321,10 +301,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
mpris.sendAction("PlayPause");
|
||||
if (targetPlayer == null) return;
|
||||
targetPlayer.playPause();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -336,10 +314,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
mpris.sendAction("Previous");
|
||||
if (targetPlayer == null) return;
|
||||
targetPlayer.previous();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -351,10 +327,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
mpris.Seek(interval_time * -1);
|
||||
if (targetPlayer == null) return;
|
||||
targetPlayer.seek(interval_time * -1);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -366,10 +340,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
mpris.Seek(interval_time);
|
||||
if (targetPlayer == null) return;
|
||||
targetPlayer.seek(interval_time);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -381,10 +353,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
mpris.sendAction("Next");
|
||||
if (targetPlayer == null) return;
|
||||
targetPlayer.next();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -404,10 +374,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris == null) return;
|
||||
mpris.setVolume(seekBar.getProgress());
|
||||
if (targetPlayer == null) return;
|
||||
targetPlayer.setVolume(seekBar.getProgress());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -421,12 +389,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
if (device != null) {
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris != null) {
|
||||
positionSeek.setProgress((int) (mpris.getPosition()));
|
||||
}
|
||||
if (targetPlayer != null) {
|
||||
positionSeek.setProgress((int) (targetPlayer.getPosition()));
|
||||
}
|
||||
positionSeekUpdateHandler.removeCallbacks(positionSeekUpdateRunnable);
|
||||
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 1000);
|
||||
@@ -453,10 +417,8 @@ public class MprisActivity extends ActionBarActivity {
|
||||
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(deviceId);
|
||||
MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
|
||||
if (mpris != null) {
|
||||
mpris.setPosition(seekBar.getProgress());
|
||||
if (targetPlayer != null) {
|
||||
targetPlayer.setPosition(seekBar.getProgress());
|
||||
}
|
||||
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 200);
|
||||
}
|
||||
|
@@ -33,29 +33,161 @@ import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class MprisPlugin extends Plugin {
|
||||
public class MprisPlayer {
|
||||
private String player = "";
|
||||
private boolean playing = false;
|
||||
private String currentSong = "";
|
||||
private String title = "";
|
||||
private String artist = "";
|
||||
private String album = "";
|
||||
private int volume = 50;
|
||||
private long length = -1;
|
||||
private long lastPosition = 0;
|
||||
private long lastPositionTime;
|
||||
private boolean playAllowed = true;
|
||||
private boolean pauseAllowed = true;
|
||||
private boolean goNextAllowed = true;
|
||||
private boolean goPreviousAllowed = true;
|
||||
private boolean seekAllowed = true;
|
||||
|
||||
public MprisPlayer() {
|
||||
lastPositionTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public String getCurrentSong() {
|
||||
return currentSong;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
public String getAlbum() {
|
||||
return album;
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
private boolean isSpotify() {
|
||||
return getPlayer().toLowerCase().equals("spotify");
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public long getLength(){ return length; }
|
||||
|
||||
public boolean isPlaying() {
|
||||
return playing;
|
||||
}
|
||||
|
||||
public boolean isPlayAllowed() {
|
||||
return playAllowed;
|
||||
}
|
||||
|
||||
public boolean isPauseAllowed() {
|
||||
return pauseAllowed;
|
||||
}
|
||||
|
||||
public boolean isGoNextAllowed() {
|
||||
return goNextAllowed;
|
||||
}
|
||||
|
||||
public boolean isGoPreviousAllowed() {
|
||||
return goPreviousAllowed;
|
||||
}
|
||||
|
||||
public boolean isSeekAllowed() {
|
||||
return seekAllowed && getLength() >= 0 && getPosition() >= 0 && !isSpotify();
|
||||
}
|
||||
|
||||
public boolean isSetVolumeAllowed() {
|
||||
return !isSpotify();
|
||||
}
|
||||
|
||||
public long getPosition(){
|
||||
if(playing) {
|
||||
return lastPosition + (System.currentTimeMillis() - lastPositionTime);
|
||||
} else {
|
||||
return lastPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public void playPause() {
|
||||
if (isPauseAllowed() || isPlayAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "action", "PlayPause");
|
||||
}
|
||||
}
|
||||
|
||||
public void play() {
|
||||
if (isPlayAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "action", "Play");
|
||||
}
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if (isPauseAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "action", "Pause");
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "action", "Stop");
|
||||
}
|
||||
|
||||
public void previous() {
|
||||
if (isGoPreviousAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "action", "Previous");
|
||||
}
|
||||
}
|
||||
|
||||
public void next() {
|
||||
if (isGoNextAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "action", "Next");
|
||||
}
|
||||
}
|
||||
|
||||
public void setVolume(int volume) {
|
||||
if (isSetVolumeAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "setVolume", volume);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
if (isSeekAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "SetPosition", position);
|
||||
|
||||
lastPosition = position;
|
||||
lastPositionTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
public void seek(int offset) {
|
||||
if (isSeekAllowed()) {
|
||||
MprisPlugin.this.sendCommand(getPlayer(), "Seek", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final static String PACKAGE_TYPE_MPRIS = "kdeconnect.mpris";
|
||||
public final static String PACKAGE_TYPE_MPRIS_REQUEST = "kdeconnect.mpris.request";
|
||||
|
||||
private String player = "";
|
||||
private boolean playing = false;
|
||||
private String currentSong = "";
|
||||
private int volume = 50;
|
||||
private long length = -1;
|
||||
private long lastPosition;
|
||||
private long lastPositionTime;
|
||||
private boolean playAllowed = true;
|
||||
private boolean pauseAllowed = true;
|
||||
private boolean goNextAllowed = true;
|
||||
private boolean goPreviousAllowed = true;
|
||||
private boolean seekAllowed = true;
|
||||
private HashMap<String, MprisPlayer> players = new HashMap<>();
|
||||
private HashMap<String,Handler> playerStatusUpdated = new HashMap<>();
|
||||
|
||||
private List<String> playerList = new ArrayList<>();
|
||||
private HashMap<String,Handler> playerListUpdated = new HashMap<>();
|
||||
|
||||
@Override
|
||||
@@ -81,66 +213,54 @@ public class MprisPlugin extends Plugin {
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
requestPlayerList();
|
||||
lastPositionTime = System.currentTimeMillis();
|
||||
|
||||
//Always request the player list so the data is up-to-date
|
||||
requestPlayerList();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
playerList.clear();
|
||||
players.clear();
|
||||
}
|
||||
|
||||
public void sendAction(String player, String action) {
|
||||
private void sendCommand(String player, String method, String value) {
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
|
||||
np.set("player", player);
|
||||
np.set("action", action);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
public void sendAction(String action) {
|
||||
sendAction(player, action);
|
||||
}
|
||||
|
||||
public void setVolume(int volume) {
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
|
||||
np.set("player", player);
|
||||
np.set("setVolume",volume);
|
||||
np.set(method, value);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
private void sendCommand(String player, String method, int value) {
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
|
||||
np.set("player", player);
|
||||
np.set("SetPosition", position);
|
||||
device.sendPackage(np);
|
||||
this.lastPosition = position;
|
||||
this.lastPositionTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void Seek(int offset) {
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
|
||||
np.set("player", player);
|
||||
np.set("Seek", offset);
|
||||
np.set(method, value);
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPackageReceived(NetworkPackage np) {
|
||||
|
||||
if (np.has("nowPlaying") || np.has("volume") || np.has("isPlaying") || np.has("length") || np.has("pos")) {
|
||||
if (np.getString("player").equals(player)) {
|
||||
currentSong = np.getString("nowPlaying", currentSong);
|
||||
volume = np.getInt("volume", volume);
|
||||
length = np.getLong("length", length);
|
||||
MprisPlayer playerStatus = players.get(np.getString("player"));
|
||||
if (playerStatus != null) {
|
||||
playerStatus.currentSong = np.getString("nowPlaying", playerStatus.currentSong);
|
||||
//Note: title, artist and album will not be available for all desktop clients
|
||||
playerStatus.title = np.getString("title", playerStatus.title);
|
||||
playerStatus.artist = np.getString("artist", playerStatus.artist);
|
||||
playerStatus.album = np.getString("album", playerStatus.album);
|
||||
playerStatus.volume = np.getInt("volume", playerStatus.volume);
|
||||
playerStatus.length = np.getLong("length", playerStatus.length);
|
||||
if(np.has("pos")){
|
||||
lastPosition = np.getLong("pos", lastPosition);
|
||||
lastPositionTime = System.currentTimeMillis();
|
||||
playerStatus.lastPosition = np.getLong("pos", playerStatus.lastPosition);
|
||||
playerStatus.lastPositionTime = System.currentTimeMillis();
|
||||
}
|
||||
playing = np.getBoolean("isPlaying", playing);
|
||||
playAllowed = np.getBoolean("canPlay", playAllowed);
|
||||
pauseAllowed = np.getBoolean("canPause", pauseAllowed);
|
||||
goNextAllowed = np.getBoolean("canGoNext", goNextAllowed);
|
||||
goPreviousAllowed = np.getBoolean("canGoPrevious", goPreviousAllowed);
|
||||
seekAllowed = np.getBoolean("canSeek", seekAllowed);
|
||||
playerStatus.playing = np.getBoolean("isPlaying", playerStatus.playing);
|
||||
playerStatus.playAllowed = np.getBoolean("canPlay", playerStatus.playAllowed);
|
||||
playerStatus.pauseAllowed = np.getBoolean("canPause", playerStatus.pauseAllowed);
|
||||
playerStatus.goNextAllowed = np.getBoolean("canGoNext", playerStatus.goNextAllowed);
|
||||
playerStatus.goPreviousAllowed = np.getBoolean("canGoPrevious", playerStatus.goPreviousAllowed);
|
||||
playerStatus.seekAllowed = np.getBoolean("canSeek", playerStatus.seekAllowed);
|
||||
for (String key : playerStatusUpdated.keySet()) {
|
||||
try {
|
||||
playerStatusUpdated.get(key).dispatchMessage(new Message());
|
||||
@@ -155,18 +275,37 @@ public class MprisPlugin extends Plugin {
|
||||
|
||||
List<String> newPlayerList = np.getStringList("playerList");
|
||||
if (newPlayerList != null) {
|
||||
boolean equals = false;
|
||||
if (newPlayerList.size() == playerList.size()) {
|
||||
equals = true;
|
||||
for (int i=0; i<newPlayerList.size(); i++) {
|
||||
if (!newPlayerList.get(i).equals(playerList.get(i))) {
|
||||
equals = false;
|
||||
boolean equals = true;
|
||||
for (String newPlayer : newPlayerList) {
|
||||
if (!players.containsKey(newPlayer)) {
|
||||
equals = false;
|
||||
|
||||
MprisPlayer player = new MprisPlayer();
|
||||
player.player = newPlayer;
|
||||
players.put(newPlayer, player);
|
||||
|
||||
//Immediately ask for the data of this player
|
||||
requestPlayerStatus(newPlayer);
|
||||
}
|
||||
}
|
||||
Iterator<HashMap.Entry<String, MprisPlayer>> iter = players.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String oldPlayer = iter.next().getKey();
|
||||
|
||||
boolean found = false;
|
||||
for (String newPlayer : newPlayerList) {
|
||||
if (newPlayer.equals(oldPlayer)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
iter.remove();
|
||||
equals = false;
|
||||
}
|
||||
}
|
||||
if (!equals) {
|
||||
playerList = newPlayerList;
|
||||
for (String key : playerListUpdated.keySet()) {
|
||||
try {
|
||||
playerListUpdated.get(key).dispatchMessage(new Message());
|
||||
@@ -196,95 +335,34 @@ public class MprisPlugin extends Plugin {
|
||||
playerStatusUpdated.put(id, h);
|
||||
|
||||
h.dispatchMessage(new Message());
|
||||
}
|
||||
|
||||
//Get the status if this is the first handler we have
|
||||
if (playerListUpdated.size() == 1) {
|
||||
requestPlayerStatus();
|
||||
}
|
||||
public void removePlayerStatusUpdatedHandler(String id) {
|
||||
playerStatusUpdated.remove(id);
|
||||
}
|
||||
|
||||
public void setPlayerListUpdatedHandler(String id, Handler h) {
|
||||
playerListUpdated.put(id,h);
|
||||
|
||||
h.dispatchMessage(new Message());
|
||||
|
||||
//Get the status if this is the first handler we have
|
||||
if (playerListUpdated.size() == 1) {
|
||||
requestPlayerList();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPlayer(String player) {
|
||||
if (player == null || player.equals(this.player)) return;
|
||||
this.player = player;
|
||||
currentSong = "";
|
||||
volume = 50;
|
||||
playing = false;
|
||||
playAllowed = true;
|
||||
pauseAllowed = true;
|
||||
goNextAllowed = true;
|
||||
goPreviousAllowed = true;
|
||||
seekAllowed = true;
|
||||
for (String key : playerStatusUpdated.keySet()) {
|
||||
try {
|
||||
playerStatusUpdated.get(key).dispatchMessage(new Message());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("MprisControl","Exception");
|
||||
playerStatusUpdated.remove(key);
|
||||
}
|
||||
}
|
||||
requestPlayerStatus();
|
||||
public void removePlayerListUpdatedHandler(String id) {
|
||||
playerListUpdated.remove(id);
|
||||
}
|
||||
|
||||
public List<String> getPlayerList() {
|
||||
return playerList;
|
||||
List<String> playerlist = new ArrayList<>(players.keySet());
|
||||
Collections.sort(playerlist);
|
||||
return playerlist;
|
||||
}
|
||||
|
||||
public String getCurrentSong() {
|
||||
return currentSong;
|
||||
public MprisPlayer getPlayerStatus(String player) {
|
||||
return players.get(player);
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public long getLength(){ return length; }
|
||||
|
||||
public boolean isPlaying() {
|
||||
return playing;
|
||||
}
|
||||
|
||||
public boolean isPlayAllowed() {
|
||||
return playAllowed;
|
||||
}
|
||||
|
||||
public boolean isPauseAllowed() {
|
||||
return pauseAllowed;
|
||||
}
|
||||
|
||||
public boolean isGoNextAllowed() {
|
||||
return goNextAllowed;
|
||||
}
|
||||
|
||||
public boolean isGoPreviousAllowed() {
|
||||
return goPreviousAllowed;
|
||||
}
|
||||
|
||||
public boolean isSeekAllowed() {
|
||||
return seekAllowed;
|
||||
}
|
||||
|
||||
public long getPosition(){
|
||||
if(playing) {
|
||||
return lastPosition + (System.currentTimeMillis() - lastPositionTime);
|
||||
} else {
|
||||
return lastPosition;
|
||||
}
|
||||
public MprisPlayer getEmptyPlayer() {
|
||||
return new MprisPlayer();
|
||||
}
|
||||
|
||||
private void requestPlayerList() {
|
||||
@@ -293,9 +371,9 @@ public class MprisPlugin extends Plugin {
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
private void requestPlayerStatus() {
|
||||
private void requestPlayerStatus(String player) {
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_MPRIS_REQUEST);
|
||||
np.set("player",player);
|
||||
np.set("player", player);
|
||||
np.set("requestNowPlaying",true);
|
||||
np.set("requestVolume",true);
|
||||
device.sendPackage(np);
|
||||
|
@@ -28,32 +28,33 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class AppDatabase {
|
||||
class AppDatabase {
|
||||
|
||||
static final private HashSet<String> disabledByDefault = new HashSet<>();
|
||||
|
||||
static {
|
||||
disabledByDefault.add("com.android.messaging"); //We already have sms notifications in the telephony plugin
|
||||
disabledByDefault.add("com.google.android.googlequicksearchbox"); //Google Now notifications re-spawn every few minutes
|
||||
}
|
||||
|
||||
static final String KEY_PACKAGE_NAME = "packageName";
|
||||
static final String KEY_IS_ENABLED = "isEnabled";
|
||||
private static final String KEY_PACKAGE_NAME = "packageName";
|
||||
private static final String KEY_IS_ENABLED = "isEnabled";
|
||||
|
||||
static final String DATABASE_NAME = "Applications";
|
||||
static final String DATABASE_TABLE = "Applications";
|
||||
static final int DATABASE_VERSION = 2;
|
||||
private static final String DATABASE_NAME = "Applications";
|
||||
private static final String DATABASE_TABLE = "Applications";
|
||||
private static final int DATABASE_VERSION = 2;
|
||||
|
||||
final Context ourContext;
|
||||
SQLiteDatabase ourDatabase;
|
||||
DbHelper ourHelper;
|
||||
private final Context ourContext;
|
||||
private SQLiteDatabase ourDatabase;
|
||||
private DbHelper ourHelper;
|
||||
|
||||
public AppDatabase(Context c) {
|
||||
AppDatabase(Context c) {
|
||||
ourContext = c;
|
||||
}
|
||||
|
||||
private static class DbHelper extends SQLiteOpenHelper {
|
||||
|
||||
public DbHelper(Context context) {
|
||||
DbHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@@ -64,7 +65,7 @@ public class AppDatabase {
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int i, int i2) {
|
||||
db.execSQL("DROP TABLE IF EXISTS "+ DATABASE_TABLE);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@@ -79,14 +80,14 @@ public class AppDatabase {
|
||||
ourHelper.close();
|
||||
}
|
||||
|
||||
public void setEnabled(String packageName, boolean isEnabled) {
|
||||
String[] columns = new String []{KEY_IS_ENABLED};
|
||||
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
|
||||
void setEnabled(String packageName, boolean isEnabled) {
|
||||
String[] columns = new String[]{KEY_IS_ENABLED};
|
||||
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ", new String[]{packageName}, null, null, null);
|
||||
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(KEY_IS_ENABLED, isEnabled?"true":"false");
|
||||
cv.put(KEY_IS_ENABLED, isEnabled ? "true" : "false");
|
||||
if (res.getCount() > 0) {
|
||||
ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?",new String[]{packageName});
|
||||
ourDatabase.update(DATABASE_TABLE, cv, KEY_PACKAGE_NAME + "=?", new String[]{packageName});
|
||||
} else {
|
||||
cv.put(KEY_PACKAGE_NAME, packageName);
|
||||
ourDatabase.insert(DATABASE_TABLE, null, cv);
|
||||
@@ -94,9 +95,9 @@ public class AppDatabase {
|
||||
res.close();
|
||||
}
|
||||
|
||||
public boolean isEnabled(String packageName) {
|
||||
String[] columns = new String []{KEY_IS_ENABLED};
|
||||
Cursor res = ourDatabase.query(DATABASE_TABLE,columns,KEY_PACKAGE_NAME + " =? ",new String[]{packageName},null,null,null);
|
||||
boolean isEnabled(String packageName) {
|
||||
String[] columns = new String[]{KEY_IS_ENABLED};
|
||||
Cursor res = ourDatabase.query(DATABASE_TABLE, columns, KEY_PACKAGE_NAME + " =? ", new String[]{packageName}, null, null, null);
|
||||
boolean result;
|
||||
if (res.getCount() > 0) {
|
||||
res.moveToFirst();
|
||||
|
@@ -28,7 +28,7 @@ import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -45,9 +45,9 @@ import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class NotificationFilterActivity extends ActionBarActivity {
|
||||
public class NotificationFilterActivity extends AppCompatActivity {
|
||||
|
||||
AppDatabase appDatabase;
|
||||
private AppDatabase appDatabase;
|
||||
|
||||
static class AppListInfo {
|
||||
String pkg;
|
||||
@@ -56,7 +56,7 @@ public class NotificationFilterActivity extends ActionBarActivity {
|
||||
boolean isEnabled;
|
||||
}
|
||||
|
||||
AppListInfo[] apps;
|
||||
private AppListInfo[] apps;
|
||||
|
||||
class AppListAdapter extends BaseAdapter {
|
||||
|
||||
@@ -80,10 +80,10 @@ public class NotificationFilterActivity extends ActionBarActivity {
|
||||
LayoutInflater inflater = getLayoutInflater();
|
||||
view = inflater.inflate(android.R.layout.simple_list_item_multiple_choice, null, true);
|
||||
}
|
||||
CheckedTextView checkedTextView = (CheckedTextView)view;
|
||||
CheckedTextView checkedTextView = (CheckedTextView) view;
|
||||
checkedTextView.setText(apps[position].name);
|
||||
checkedTextView.setCompoundDrawablesWithIntrinsicBounds(apps[position].icon, null, null, null);
|
||||
checkedTextView.setCompoundDrawablePadding((int)(8*getResources().getDisplayMetrics().density));
|
||||
checkedTextView.setCompoundDrawablePadding((int) (8 * getResources().getDisplayMetrics().density));
|
||||
|
||||
return view;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public class NotificationFilterActivity extends ActionBarActivity {
|
||||
|
||||
}
|
||||
|
||||
void displayAppList() {
|
||||
private void displayAppList() {
|
||||
|
||||
final ListView listView = (ListView) findViewById(R.id.lvFilterApps);
|
||||
AppListAdapter adapter = new AppListAdapter();
|
||||
@@ -151,7 +151,7 @@ public class NotificationFilterActivity extends ActionBarActivity {
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0 ; i < apps.length; i++) {
|
||||
for (int i = 0; i < apps.length; i++) {
|
||||
listView.setItemChecked(i, apps[i].isEnabled);
|
||||
}
|
||||
|
||||
@@ -172,11 +172,11 @@ public class NotificationFilterActivity extends ActionBarActivity {
|
||||
BackgroundService.removeGuiInUseCounter(this);
|
||||
}
|
||||
|
||||
Drawable resizeIcon(Drawable icon, int maxSize) {
|
||||
private Drawable resizeIcon(Drawable icon, int maxSize) {
|
||||
Resources res = getResources();
|
||||
|
||||
//Convert to display pixels
|
||||
maxSize = (int)(maxSize*res.getDisplayMetrics().density);
|
||||
maxSize = (int) (maxSize * res.getDisplayMetrics().density);
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(maxSize, maxSize, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
@@ -23,18 +23,26 @@ package org.kde.kdeconnect.Plugins.NotificationsPlugin;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
public class NotificationReceiver extends NotificationListenerService {
|
||||
|
||||
private boolean connected;
|
||||
|
||||
public interface NotificationListener {
|
||||
void onNotificationPosted(StatusBarNotification statusBarNotification);
|
||||
|
||||
void onNotificationRemoved(StatusBarNotification statusBarNotification);
|
||||
|
||||
void onListenerConnected(NotificationReceiver service);
|
||||
}
|
||||
|
||||
private final ArrayList<NotificationListener> listeners = new ArrayList<>();
|
||||
@@ -42,6 +50,7 @@ public class NotificationReceiver extends NotificationListenerService {
|
||||
public void addListener(NotificationListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(NotificationListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
@@ -49,21 +58,36 @@ public class NotificationReceiver extends NotificationListenerService {
|
||||
@Override
|
||||
public void onNotificationPosted(StatusBarNotification statusBarNotification) {
|
||||
//Log.e("NotificationReceiver.onNotificationPosted","listeners: " + listeners.size());
|
||||
for(NotificationListener listener : listeners) {
|
||||
for (NotificationListener listener : listeners) {
|
||||
listener.onNotificationPosted(statusBarNotification);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
|
||||
for(NotificationListener listener : listeners) {
|
||||
for (NotificationListener listener : listeners) {
|
||||
listener.onNotificationRemoved(statusBarNotification);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListenerConnected() {
|
||||
super.onListenerConnected();
|
||||
for (NotificationListener listener : listeners) {
|
||||
listener.onListenerConnected(this);
|
||||
}
|
||||
connected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListenerDisconnected() {
|
||||
super.onListenerDisconnected();
|
||||
connected = false;
|
||||
}
|
||||
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
//To use the service from the outer (name)space
|
||||
|
||||
|
@@ -24,12 +24,16 @@ import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.RemoteInput;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Helpers.AppsHelper;
|
||||
@@ -39,15 +43,22 @@ import org.kde.kdeconnect.UserInterface.MaterialActivity;
|
||||
import org.kde.kdeconnect.UserInterface.SettingsActivity;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
public class NotificationsPlugin extends Plugin implements NotificationReceiver.NotificationListener {
|
||||
|
||||
public final static String PACKAGE_TYPE_NOTIFICATION = "kdeconnect.notification";
|
||||
public final static String PACKAGE_TYPE_NOTIFICATION_REQUEST = "kdeconnect.notification.request";
|
||||
private final static String PACKAGE_TYPE_NOTIFICATION = "kdeconnect.notification";
|
||||
private final static String PACKAGE_TYPE_NOTIFICATION_REQUEST = "kdeconnect.notification.request";
|
||||
private final static String PACKAGE_TYPE_NOTIFICATION_REPLY = "kdeconnect.notification.reply";
|
||||
|
||||
/*
|
||||
private boolean sendIcons = false;
|
||||
*/
|
||||
private Map<String, RepliableNotification> pendingIntents;
|
||||
private boolean serviceReady;
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
@@ -81,45 +92,51 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
if (hasPermission()) {
|
||||
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(NotificationReceiver service) {
|
||||
try {
|
||||
service.addListener(NotificationsPlugin.this);
|
||||
StatusBarNotification[] notifications = service.getActiveNotifications();
|
||||
for (StatusBarNotification notification : notifications) {
|
||||
sendNotification(notification, true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("NotificationsPlugin", "Exception");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return false;
|
||||
|
||||
if (!hasPermission()) return false;
|
||||
|
||||
pendingIntents = new HashMap<>();
|
||||
|
||||
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(NotificationReceiver service) {
|
||||
|
||||
service.addListener(NotificationsPlugin.this);
|
||||
|
||||
serviceReady = service.isConnected();
|
||||
|
||||
if (serviceReady) {
|
||||
sendCurrentNotifications(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(NotificationReceiver service) {
|
||||
service.removeListener(NotificationsPlugin.this);
|
||||
}
|
||||
});
|
||||
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(NotificationReceiver service) {
|
||||
service.removeListener(NotificationsPlugin.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListenerConnected(NotificationReceiver service) {
|
||||
serviceReady = true;
|
||||
sendCurrentNotifications(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
|
||||
if (statusBarNotification == null) {
|
||||
Log.w("onNotificationRemoved", "notification is null");
|
||||
return;
|
||||
}
|
||||
String id = getNotificationKeyCompat(statusBarNotification);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
|
||||
np.set("id", id);
|
||||
@@ -129,10 +146,10 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
|
||||
@Override
|
||||
public void onNotificationPosted(StatusBarNotification statusBarNotification) {
|
||||
sendNotification(statusBarNotification, false);
|
||||
sendNotification(statusBarNotification);
|
||||
}
|
||||
|
||||
public void sendNotification(StatusBarNotification statusBarNotification, boolean requestAnswer) {
|
||||
private void sendNotification(StatusBarNotification statusBarNotification) {
|
||||
|
||||
Notification notification = statusBarNotification.getNotification();
|
||||
AppDatabase appDatabase = new AppDatabase(context);
|
||||
@@ -145,7 +162,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
}
|
||||
|
||||
appDatabase.open();
|
||||
if (!appDatabase.isEnabled(statusBarNotification.getPackageName())){
|
||||
if (!appDatabase.isEnabled(statusBarNotification.getPackageName())) {
|
||||
return;
|
||||
// we dont want notification from this app
|
||||
}
|
||||
@@ -155,6 +172,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
String packageName = statusBarNotification.getPackageName();
|
||||
String appName = AppsHelper.appNameLookup(context, packageName);
|
||||
|
||||
|
||||
if ("com.facebook.orca".equals(packageName) &&
|
||||
(statusBarNotification.getId() == 10012) &&
|
||||
"Messenger".equals(appName) &&
|
||||
@@ -164,51 +182,181 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
}
|
||||
|
||||
if ("com.android.systemui".equals(packageName) &&
|
||||
"low_battery".equals(statusBarNotification.getTag()))
|
||||
{
|
||||
"low_battery".equals(statusBarNotification.getTag())) {
|
||||
//HACK: Android low battery notification are posted again every few seconds. Ignore them, as we already have a battery indicator.
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_NOTIFICATION);
|
||||
|
||||
if (packageName.equals("org.kde.kdeconnect_tp"))
|
||||
{
|
||||
if (packageName.equals("org.kde.kdeconnect_tp")) {
|
||||
//Make our own notifications silent :)
|
||||
np.set("silent", true);
|
||||
np.set("requestAnswer", true); //For compatibility with old desktop versions of KDE Connect that don't support "silent"
|
||||
}
|
||||
/*
|
||||
if (sendIcons) {
|
||||
try {
|
||||
Drawable drawableAppIcon = AppsHelper.appIconLookup(context, packageName);
|
||||
Bitmap appIcon = ImagesHelper.drawableToBitmap(drawableAppIcon);
|
||||
|
||||
try {
|
||||
Bitmap appIcon = notification.largeIcon;
|
||||
|
||||
if (appIcon != null) {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
if (appIcon.getWidth() > 128) {
|
||||
appIcon = Bitmap.createScaledBitmap(appIcon, 96, 96, true);
|
||||
}
|
||||
appIcon.compress(Bitmap.CompressFormat.PNG, 90, outStream);
|
||||
byte[] bitmapData = outStream.toByteArray();
|
||||
|
||||
np.setPayload(bitmapData);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("NotificationsPlugin", "Error retrieving icon");
|
||||
|
||||
np.set("payloadHash", getChecksum(bitmapData));
|
||||
}
|
||||
}
|
||||
*/
|
||||
np.set("id", key);
|
||||
np.set("appName", appName == null? packageName : appName);
|
||||
np.set("isClearable", statusBarNotification.isClearable());
|
||||
np.set("ticker", getTickerText(notification));
|
||||
np.set("time", Long.toString(statusBarNotification.getPostTime()));
|
||||
if (requestAnswer) {
|
||||
np.set("requestAnswer", true);
|
||||
np.set("silent", true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("NotificationsPlugin", "Error retrieving icon");
|
||||
}
|
||||
|
||||
RepliableNotification rn = extractRepliableNotification(statusBarNotification);
|
||||
if (rn.pendingIntent != null) {
|
||||
np.set("requestReplyId", rn.id);
|
||||
pendingIntents.put(rn.id, rn);
|
||||
}
|
||||
|
||||
np.set("id", key);
|
||||
np.set("appName", appName == null ? packageName : appName);
|
||||
np.set("isClearable", statusBarNotification.isClearable());
|
||||
np.set("ticker", getTickerText(notification));
|
||||
np.set("title", getNotificationTitle(notification));
|
||||
np.set("text", getNotificationText(notification));
|
||||
np.set("time", Long.toString(statusBarNotification.getPostTime()));
|
||||
|
||||
device.sendPackage(np);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
|
||||
private void replyToNotification(String id, String message) {
|
||||
if (pendingIntents.isEmpty() || !pendingIntents.containsKey(id)) {
|
||||
Log.e("NotificationsPlugin", "No such notification");
|
||||
return;
|
||||
}
|
||||
|
||||
RepliableNotification repliableNotification = pendingIntents.get(id);
|
||||
if (repliableNotification == null) {
|
||||
Log.e("NotificationsPlugin", "No such notification");
|
||||
return;
|
||||
}
|
||||
RemoteInput[] remoteInputs = new RemoteInput[repliableNotification.remoteInputs.size()];
|
||||
|
||||
Intent localIntent = new Intent();
|
||||
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
Bundle localBundle = new Bundle();
|
||||
int i = 0;
|
||||
for (RemoteInput remoteIn : repliableNotification.remoteInputs) {
|
||||
getDetailsOfNotification(remoteIn);
|
||||
remoteInputs[i] = remoteIn;
|
||||
localBundle.putCharSequence(remoteInputs[i].getResultKey(), message);
|
||||
i++;
|
||||
}
|
||||
RemoteInput.addResultsToIntent(remoteInputs, localIntent, localBundle);
|
||||
|
||||
try {
|
||||
repliableNotification.pendingIntent.send(context, 0, localIntent);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Log.e("NotificationPlugin", "replyToNotification error: " + e.getMessage());
|
||||
}
|
||||
pendingIntents.remove(id);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
|
||||
private void getDetailsOfNotification(RemoteInput remoteInput) {
|
||||
//Some more details of RemoteInput... no idea what for but maybe it will be useful at some point
|
||||
String resultKey = remoteInput.getResultKey();
|
||||
String label = remoteInput.getLabel().toString();
|
||||
Boolean canFreeForm = remoteInput.getAllowFreeFormInput();
|
||||
if (remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
|
||||
String[] possibleChoices = new String[remoteInput.getChoices().length];
|
||||
for (int i = 0; i < remoteInput.getChoices().length; i++) {
|
||||
possibleChoices[i] = remoteInput.getChoices()[i].toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getNotificationTitle(Notification notification) {
|
||||
final String TITLE_KEY = "android.title";
|
||||
final String TEXT_KEY = "android.text";
|
||||
String title = "";
|
||||
|
||||
if (notification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
Bundle extras = notification.extras;
|
||||
title = extras.getString(TITLE_KEY);
|
||||
} catch (Exception e) {
|
||||
Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Add compat for under Kitkat devices
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
private RepliableNotification extractRepliableNotification(StatusBarNotification statusBarNotification) {
|
||||
RepliableNotification repliableNotification = new RepliableNotification();
|
||||
|
||||
if (statusBarNotification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
try {
|
||||
Boolean reply = false;
|
||||
|
||||
//works for WhatsApp, but not for Telegram
|
||||
if (statusBarNotification.getNotification().actions != null) {
|
||||
for (Notification.Action act : statusBarNotification.getNotification().actions) {
|
||||
if (act != null && act.getRemoteInputs() != null) {
|
||||
repliableNotification.remoteInputs.addAll(Arrays.asList(act.getRemoteInputs()));
|
||||
repliableNotification.pendingIntent = act.actionIntent;
|
||||
reply = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
repliableNotification.packageName = statusBarNotification.getPackageName();
|
||||
|
||||
repliableNotification.tag = statusBarNotification.getTag();//TODO find how to pass Tag with sending PendingIntent, might fix Hangout problem
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w("NotificationPlugin", "problem extracting notification wear for " + statusBarNotification.getNotification().tickerText);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return repliableNotification;
|
||||
}
|
||||
|
||||
private String getNotificationText(Notification notification) {
|
||||
final String TEXT_KEY = "android.text";
|
||||
String text = "";
|
||||
|
||||
if (notification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
Bundle extras = notification.extras;
|
||||
Object extraTextExtra = extras.get(TEXT_KEY);
|
||||
if (extraTextExtra != null) text = extraTextExtra.toString();
|
||||
} catch (Exception e) {
|
||||
Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Add compat for under Kitkat devices
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ticker text of the notification.
|
||||
@@ -220,90 +368,72 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
final String TEXT_KEY = "android.text";
|
||||
String ticker = "";
|
||||
|
||||
if(notification != null) {
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
if (notification != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
try {
|
||||
Bundle extras = notification.extras;
|
||||
String extraTitle = extras.getCharSequence(TITLE_KEY).toString();
|
||||
String extraTitle = extras.getString(TITLE_KEY);
|
||||
String extraText = null;
|
||||
Object extraTextExtra = extras.get(TEXT_KEY);
|
||||
if (extraTextExtra != null) extraText = extraTextExtra.toString();
|
||||
|
||||
if (extraTitle != null && extraText != null && !extraText.isEmpty()) {
|
||||
ticker = extraTitle + " ‐ " + extraText;
|
||||
ticker = extraTitle + ": " + extraText;
|
||||
} else if (extraTitle != null) {
|
||||
ticker = extraTitle;
|
||||
} else if (extraText != null) {
|
||||
ticker = extraText;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
Log.w("NotificationPlugin","problem parsing notification extras for " + notification.tickerText);
|
||||
} catch (Exception e) {
|
||||
Log.w("NotificationPlugin", "problem parsing notification extras for " + notification.tickerText);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (ticker.isEmpty()) {
|
||||
ticker = (notification.tickerText != null)? notification.tickerText.toString() : "";
|
||||
ticker = (notification.tickerText != null) ? notification.tickerText.toString() : "";
|
||||
}
|
||||
}
|
||||
|
||||
return ticker;
|
||||
}
|
||||
|
||||
private void sendCurrentNotifications(NotificationReceiver service) {
|
||||
StatusBarNotification[] notifications = service.getActiveNotifications();
|
||||
for (StatusBarNotification notification : notifications) {
|
||||
sendNotification(notification);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPackageReceived(final NetworkPackage np) {
|
||||
/*
|
||||
if (np.getBoolean("sendIcons")) {
|
||||
sendIcons = true;
|
||||
}
|
||||
*/
|
||||
|
||||
if (np.getBoolean("request")) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
|
||||
private void sendCurrentNotifications(NotificationReceiver service) {
|
||||
StatusBarNotification[] notifications = service.getActiveNotifications();
|
||||
for (StatusBarNotification notification : notifications) {
|
||||
sendNotification(notification, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onServiceStart(final NotificationReceiver service) {
|
||||
try {
|
||||
//If service just started, this call will throw an exception because the answer is not ready yet
|
||||
sendCurrentNotifications(service);
|
||||
} catch(Exception e) {
|
||||
Log.e("onPackageReceived","Error when answering 'request': Service failed to start. Retrying in 100ms...");
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
Log.e("onPackageReceived","Error when answering 'request': Service failed to start. Retrying...");
|
||||
sendCurrentNotifications(service);
|
||||
} catch (Exception e) {
|
||||
Log.e("onPackageReceived","Error when answering 'request': Service failed to start twice!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else if (np.has("cancel")) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
if (serviceReady) {
|
||||
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(NotificationReceiver service) {
|
||||
String dismissedId = np.getString("cancel");
|
||||
cancelNotificationCompat(service, dismissedId);
|
||||
sendCurrentNotifications(service);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else if (np.has("cancel")) {
|
||||
|
||||
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(NotificationReceiver service) {
|
||||
String dismissedId = np.getString("cancel");
|
||||
cancelNotificationCompat(service, dismissedId);
|
||||
}
|
||||
});
|
||||
|
||||
} else if (np.has("requestReplyId") && np.has("message")) {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
||||
replyToNotification(np.getString("requestReplyId"), np.getString("message"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -314,41 +444,29 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
@Override
|
||||
public AlertDialog getErrorDialog(final Activity deviceActivity) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < 18) {
|
||||
return new AlertDialog.Builder(deviceActivity)
|
||||
.setTitle(R.string.pref_plugin_notifications)
|
||||
.setMessage(R.string.plugin_not_available)
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
return new AlertDialog.Builder(deviceActivity)
|
||||
.setTitle(R.string.pref_plugin_notifications)
|
||||
.setMessage(R.string.no_permissions)
|
||||
.setPositiveButton(R.string.open_settings, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
|
||||
deviceActivity.startActivityForResult(intent, MaterialActivity.RESULT_NEEDS_RELOAD);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
//Do nothing
|
||||
}
|
||||
})
|
||||
.create();
|
||||
|
||||
}
|
||||
})
|
||||
.create();
|
||||
} else {
|
||||
return new AlertDialog.Builder(deviceActivity)
|
||||
.setTitle(R.string.pref_plugin_notifications)
|
||||
.setMessage(R.string.no_permissions)
|
||||
.setPositiveButton(R.string.open_settings, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
|
||||
deviceActivity.startActivityForResult(intent, MaterialActivity.RESULT_NEEDS_RELOAD);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
//Do nothing
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
return new String[]{PACKAGE_TYPE_NOTIFICATION_REQUEST};
|
||||
return new String[]{PACKAGE_TYPE_NOTIFICATION_REQUEST, PACKAGE_TYPE_NOTIFICATION_REPLY};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,13 +475,13 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
}
|
||||
|
||||
//For compat with API<21, because lollipop changed the way to cancel notifications
|
||||
public static void cancelNotificationCompat(NotificationReceiver service, String compatKey) {
|
||||
private static void cancelNotificationCompat(NotificationReceiver service, String compatKey) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
service.cancelNotification(compatKey);
|
||||
} else {
|
||||
int first = compatKey.indexOf(':');
|
||||
if (first == -1) {
|
||||
Log.e("cancelNotificationCompa","Not formated like a notification key: "+ compatKey);
|
||||
Log.e("cancelNotificationCompa", "Not formated like a notification key: " + compatKey);
|
||||
return;
|
||||
}
|
||||
int last = compatKey.lastIndexOf(':');
|
||||
@@ -381,7 +499,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
}
|
||||
}
|
||||
|
||||
public static String getNotificationKeyCompat(StatusBarNotification statusBarNotification) {
|
||||
private static String getNotificationKeyCompat(StatusBarNotification statusBarNotification) {
|
||||
String result;
|
||||
// first check if it's one of our remoteIds
|
||||
String tag = statusBarNotification.getTag();
|
||||
@@ -398,4 +516,33 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getChecksum(byte[] data) {
|
||||
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(data);
|
||||
return bytesToHex(md.digest());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log.e("KDEConnect", "Error while generating checksum", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static String bytesToHex(byte[] bytes) {
|
||||
char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||
char[] hexChars = new char[bytes.length * 2];
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
hexChars[j * 2] = hexArray[v >>> 4];
|
||||
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
||||
}
|
||||
return new String(hexChars).toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinSdk() {
|
||||
return Build.VERSION_CODES.JELLY_BEAN_MR2;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package org.kde.kdeconnect.Plugins.NotificationsPlugin;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
class RepliableNotification {
|
||||
String id = UUID.randomUUID().toString();
|
||||
PendingIntent pendingIntent;
|
||||
ArrayList<android.app.RemoteInput> remoteInputs = new ArrayList<>();
|
||||
String packageName;
|
||||
String tag;
|
||||
}
|
@@ -20,23 +20,35 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.UserInterface.MaterialActivity;
|
||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
||||
import org.kde.kdeconnect.UserInterface.SettingsActivity;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public abstract class Plugin {
|
||||
|
||||
protected Device device;
|
||||
protected Context context;
|
||||
protected int permissionExplanation = R.string.permission_explanation;
|
||||
protected int optionalPermissionExplanation = R.string.optional_permission_explanation;
|
||||
|
||||
public final void setContext(Context context, Device device) {
|
||||
this.device = device;
|
||||
@@ -167,14 +179,6 @@ public abstract class Plugin {
|
||||
*/
|
||||
public boolean onPackageReceived(NetworkPackage np) { return false; }
|
||||
|
||||
/**
|
||||
* If onCreate returns false, should create a dialog explaining
|
||||
* the problem (and how to fix it, if possible) to the user.
|
||||
*/
|
||||
public AlertDialog getErrorDialog(Activity deviceActivity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should return the list of NetworkPackage types that this plugin can handle
|
||||
*/
|
||||
@@ -205,4 +209,79 @@ public abstract class Plugin {
|
||||
return b;
|
||||
}
|
||||
|
||||
public String[] getRequiredPermissions() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
public String[] getOptionalPermissions() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
//Permission from Manifest.permission.*
|
||||
protected boolean isPermissionGranted(String permission) {
|
||||
int result = ContextCompat.checkSelfPermission(context, permission);
|
||||
return (result == PackageManager.PERMISSION_GRANTED);
|
||||
}
|
||||
|
||||
protected boolean arePermissionsGranted(String[] permissions) {
|
||||
for(String permission: permissions){
|
||||
if(!isPermissionGranted(permission)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected AlertDialog requestPermissionDialog(Activity activity, String permissions, @StringRes int reason) {
|
||||
return requestPermissionDialog(activity, new String[]{permissions}, reason);
|
||||
}
|
||||
|
||||
protected AlertDialog requestPermissionDialog(final Activity activity, final String[] permissions, @StringRes int reason){
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setTitle(getDisplayName())
|
||||
.setMessage(reason)
|
||||
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
ActivityCompat.requestPermissions(activity, permissions, 0);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
//Do nothing
|
||||
}
|
||||
})
|
||||
.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* If onCreate returns false, should create a dialog explaining
|
||||
* the problem (and how to fix it, if possible) to the user.
|
||||
*/
|
||||
|
||||
public AlertDialog getErrorDialog(Activity deviceActivity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public AlertDialog getPermissionExplanationDialog(Activity deviceActivity) {
|
||||
return requestPermissionDialog(deviceActivity,getRequiredPermissions(), permissionExplanation);
|
||||
}
|
||||
|
||||
public AlertDialog getOptionalPermissionExplanationDialog(Activity deviceActivity) {
|
||||
return requestPermissionDialog(deviceActivity,getOptionalPermissions(), optionalPermissionExplanation);
|
||||
}
|
||||
|
||||
public boolean checkRequiredPermissions(){
|
||||
return arePermissionsGranted(getRequiredPermissions());
|
||||
}
|
||||
|
||||
public boolean checkOptionalPermissions(){
|
||||
return arePermissionsGranted(getOptionalPermissions());
|
||||
}
|
||||
|
||||
public int getMinSdk() {
|
||||
return Build.VERSION_CODES.BASE;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -125,8 +125,7 @@ public class PluginFactory {
|
||||
PluginFactory.registerPlugin(TelepathyPlugin.class);
|
||||
PluginFactory.registerPlugin(FindMyPhonePlugin.class);
|
||||
PluginFactory.registerPlugin(RunCommandPlugin.class);
|
||||
//Commented here and in AndroidManifest until we release a desktop version with this feature, so we don't get bad "feature not working" reviews
|
||||
//PluginFactory.registerPlugin(RemoteKeyboardPlugin.class);
|
||||
PluginFactory.registerPlugin(RemoteKeyboardPlugin.class);
|
||||
}
|
||||
|
||||
public static PluginInfo getPluginInfo(Context context, String pluginKey) {
|
||||
@@ -147,7 +146,7 @@ public class PluginFactory {
|
||||
} catch(Exception e) {
|
||||
Log.e("PluginFactory","getPluginInfo exception");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@
|
||||
package org.kde.kdeconnect.Plugins.RunCommandPlugin;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
@@ -39,7 +39,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class RunCommandActivity extends ActionBarActivity {
|
||||
public class RunCommandActivity extends AppCompatActivity {
|
||||
|
||||
private String deviceId;
|
||||
|
||||
|
@@ -20,8 +20,16 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins.SftpPlugin;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.kde.kdeconnect.Helpers.StorageHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
@@ -38,6 +46,8 @@ public class SftpPlugin extends Plugin {
|
||||
|
||||
private static final SimpleSftpServer server = new SimpleSftpServer();
|
||||
|
||||
private int sftpPermissionExplanation = R.string.sftp_permission_explanation;
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return context.getResources().getString(R.string.pref_plugin_sftp);
|
||||
@@ -51,6 +61,7 @@ public class SftpPlugin extends Plugin {
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
server.init(context, device);
|
||||
permissionExplanation = sftpPermissionExplanation;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,50 +86,48 @@ public class SftpPlugin extends Plugin {
|
||||
//Kept for compatibility, in case "multiPaths" is not possible or the other end does not support it
|
||||
np2.set("path", Environment.getExternalStorageDirectory().getAbsolutePath());
|
||||
|
||||
File root = new File("/");
|
||||
if (root.canExecute() && root.canRead()) {
|
||||
List<StorageHelper.StorageInfo> storageList = StorageHelper.getStorageList();
|
||||
ArrayList<String> paths = new ArrayList<>();
|
||||
ArrayList<String> pathNames = new ArrayList<>();
|
||||
List<StorageHelper.StorageInfo> storageList = StorageHelper.getStorageList();
|
||||
ArrayList<String> paths = new ArrayList<>();
|
||||
ArrayList<String> pathNames = new ArrayList<>();
|
||||
|
||||
for (StorageHelper.StorageInfo storage : storageList) {
|
||||
paths.add(storage.path);
|
||||
StringBuilder res = new StringBuilder();
|
||||
for (StorageHelper.StorageInfo storage : storageList) {
|
||||
paths.add(storage.path);
|
||||
StringBuilder res = new StringBuilder();
|
||||
|
||||
if (storageList.size() > 1) {
|
||||
if (!storage.removable) {
|
||||
res.append(context.getString(R.string.sftp_internal_storage));
|
||||
} else if (storage.number > 1) {
|
||||
res.append(context.getString(R.string.sftp_sdcard_num, storage.number));
|
||||
} else {
|
||||
res.append(context.getString(R.string.sftp_sdcard));
|
||||
}
|
||||
if (storageList.size() > 1) {
|
||||
if (!storage.removable) {
|
||||
res.append(context.getString(R.string.sftp_internal_storage));
|
||||
} else if (storage.number > 1) {
|
||||
res.append(context.getString(R.string.sftp_sdcard_num, storage.number));
|
||||
} else {
|
||||
res.append(context.getString(R.string.sftp_all_files));
|
||||
res.append(context.getString(R.string.sftp_sdcard));
|
||||
}
|
||||
String pathName = res.toString();
|
||||
if (storage.readonly) {
|
||||
res.append(" ");
|
||||
res.append(context.getString(R.string.sftp_readonly));
|
||||
}
|
||||
pathNames.add(res.toString());
|
||||
} else {
|
||||
res.append(context.getString(R.string.sftp_all_files));
|
||||
}
|
||||
String pathName = res.toString();
|
||||
if (storage.readonly) {
|
||||
res.append(" ");
|
||||
res.append(context.getString(R.string.sftp_readonly));
|
||||
}
|
||||
pathNames.add(res.toString());
|
||||
|
||||
//Shortcut for users that only want to browse camera pictures
|
||||
String dcim = storage.path + "/DCIM/Camera";
|
||||
if (new File(dcim).exists()) {
|
||||
paths.add(dcim);
|
||||
if (storageList.size() > 1) {
|
||||
pathNames.add(context.getString(R.string.sftp_camera) + "(" + pathName + ")");
|
||||
} else {
|
||||
pathNames.add(context.getString(R.string.sftp_camera));
|
||||
}
|
||||
//Shortcut for users that only want to browse camera pictures
|
||||
String dcim = storage.path + "/DCIM/Camera";
|
||||
if (new File(dcim).exists()) {
|
||||
paths.add(dcim);
|
||||
if (storageList.size() > 1) {
|
||||
pathNames.add(context.getString(R.string.sftp_camera) + "(" + pathName + ")");
|
||||
} else {
|
||||
pathNames.add(context.getString(R.string.sftp_camera));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paths.size() > 0) {
|
||||
np2.set("multiPaths", paths);
|
||||
np2.set("pathNames", pathNames);
|
||||
|
||||
if (paths.size() > 0) {
|
||||
np2.set("multiPaths", paths);
|
||||
np2.set("pathNames", pathNames);
|
||||
}
|
||||
}
|
||||
|
||||
device.sendPackage(np2);
|
||||
@@ -129,6 +138,12 @@ public class SftpPlugin extends Plugin {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRequiredPermissions() {
|
||||
String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE};
|
||||
return perms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
return new String[]{PACKAGE_TYPE_SFTP_REQUEST};
|
||||
|
@@ -48,7 +48,10 @@ import org.kde.kdeconnect.Helpers.RandomHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
@@ -125,7 +128,7 @@ class SimpleSftpServer {
|
||||
public void stop() {
|
||||
try {
|
||||
started = false;
|
||||
sshd.stop();
|
||||
sshd.stop(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -144,6 +147,17 @@ class SimpleSftpServer {
|
||||
try {
|
||||
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
|
||||
NetworkInterface intf = en.nextElement();
|
||||
|
||||
// Anything with rmnet is related to cellular connections or USB
|
||||
// tethering mechanisms. See:
|
||||
//
|
||||
// https://android.googlesource.com/kernel/msm/+/android-msm-flo-3.4-kitkat-mr1/Documentation/usb/gadget_rmnet.txt
|
||||
//
|
||||
// If we run across an interface that has this, we can safely
|
||||
// ignore it. In fact, it's much safer to do. If we don't, we
|
||||
// might get invalid IP adddresses out of it.
|
||||
if(intf.getDisplayName().contains("rmnet")) continue;
|
||||
|
||||
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
|
||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||
if (!inetAddress.isLoopbackAddress()) {
|
||||
@@ -204,6 +218,32 @@ class SimpleSftpServer {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream createOutputStream(long offset) throws IOException {
|
||||
if (!isWritable()) {
|
||||
throw new IOException("No write permission : " + file.getName());
|
||||
}
|
||||
|
||||
final RandomAccessFile raf = new RandomAccessFile(file, "rw");
|
||||
try {
|
||||
if (offset < raf.length()) {
|
||||
throw new IOException("Your SSHFS is bugged"); //SSHFS 3.0 and 3.2 cause data corruption, abort the transfer if this happens
|
||||
}
|
||||
raf.setLength(offset);
|
||||
raf.seek(offset);
|
||||
|
||||
return new FileOutputStream(raf.getFD()) {
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
raf.close();
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
raf.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
//Log.e("Sshd", "deleting file");
|
||||
|
@@ -74,6 +74,9 @@ class NotificationUpdateCallback extends Device.SendPackageStatusCallback {
|
||||
public void onFailure(Throwable e) {
|
||||
updateDone(false);
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
if (e != null) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateText() {
|
||||
@@ -114,8 +117,7 @@ class NotificationUpdateCallback extends Device.SendPackageStatusCallback {
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
.setSmallIcon(icon)
|
||||
.setProgress(progress, progress, false); //setting progress to 0 out of 0 remove the progress bar
|
||||
|
||||
.setProgress(0, 0, false); //setting progress to 0 out of 0 remove the progress bar
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.kde.kdeconnect_tp.R;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
public class SendFileActivity extends ActionBarActivity {
|
||||
public class SendFileActivity extends AppCompatActivity {
|
||||
|
||||
String mDeviceId;
|
||||
|
||||
|
@@ -23,8 +23,9 @@ package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -32,6 +33,7 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
@@ -46,15 +48,14 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
public class ShareActivity extends ActionBarActivity {
|
||||
public class ShareActivity extends AppCompatActivity {
|
||||
|
||||
private MenuItem menuProgress;
|
||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.refresh, menu);
|
||||
menuProgress = menu.findItem(R.id.menu_progress);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,28 +63,7 @@ public class ShareActivity extends ActionBarActivity {
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_refresh:
|
||||
updateComputerList();
|
||||
BackgroundService.RunCommand(ShareActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
service.onNetworkChange();
|
||||
}
|
||||
});
|
||||
item.setVisible(false);
|
||||
menuProgress.setVisible(true);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try { Thread.sleep(1500); } catch (InterruptedException e) { }
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
menuProgress.setVisible(false);
|
||||
item.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
updateComputerListAction();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -91,6 +71,30 @@ public class ShareActivity extends ActionBarActivity {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateComputerListAction() {
|
||||
updateComputerList();
|
||||
BackgroundService.RunCommand(ShareActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
service.onNetworkChange();
|
||||
}
|
||||
});
|
||||
|
||||
mSwipeRefreshLayout.setRefreshing(true);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try { Thread.sleep(1500); } catch (InterruptedException ignored) { }
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void updateComputerList() {
|
||||
|
||||
final Intent intent = getIntent();
|
||||
@@ -128,58 +132,7 @@ public class ShareActivity extends ActionBarActivity {
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
|
||||
Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
|
||||
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras != null) {
|
||||
if (extras.containsKey(Intent.EXTRA_STREAM)) {
|
||||
|
||||
try {
|
||||
|
||||
ArrayList<Uri> uriList;
|
||||
if (!Intent.ACTION_SEND.equals(intent.getAction())) {
|
||||
uriList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
|
||||
} else {
|
||||
Uri uri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
uriList = new ArrayList<>();
|
||||
uriList.add(uri);
|
||||
}
|
||||
|
||||
SharePlugin.queuedSendUriList(getApplicationContext(), device, uriList);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("ShareActivity", "Exception");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else if (extras.containsKey(Intent.EXTRA_TEXT)) {
|
||||
String text = extras.getString(Intent.EXTRA_TEXT);
|
||||
String subject = extras.getString(Intent.EXTRA_SUBJECT);
|
||||
|
||||
//Hack: Detect shared youtube videos, so we can open them in the browser instead of as text
|
||||
if (subject != null && subject.endsWith("YouTube")) {
|
||||
int index = text.indexOf(": http://youtu.be/");
|
||||
if (index > 0) {
|
||||
text = text.substring(index + 2); //Skip ": "
|
||||
}
|
||||
}
|
||||
|
||||
boolean isUrl;
|
||||
try {
|
||||
new URL(text);
|
||||
isUrl = true;
|
||||
} catch (Exception e) {
|
||||
isUrl = false;
|
||||
}
|
||||
NetworkPackage np = new NetworkPackage(SharePlugin.PACKAGE_TYPE_SHARE_REQUEST);
|
||||
if (isUrl) {
|
||||
np.set("url", text);
|
||||
} else {
|
||||
np.set("text", text);
|
||||
}
|
||||
device.sendPackage(np);
|
||||
}
|
||||
}
|
||||
|
||||
SharePlugin.share(intent, device);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
@@ -193,35 +146,65 @@ public class ShareActivity extends ActionBarActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_list);
|
||||
setContentView(R.layout.activity_refresh_list);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
|
||||
|
||||
setContentView(R.layout.activity_list);
|
||||
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_list_layout);
|
||||
mSwipeRefreshLayout.setOnRefreshListener(
|
||||
new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
updateComputerListAction();
|
||||
}
|
||||
}
|
||||
);
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
service.onNetworkChange();
|
||||
service.addDeviceListChangedCallback("ShareActivity", new BackgroundService.DeviceListChangedCallback() {
|
||||
@Override
|
||||
public void onDeviceListChanged() {
|
||||
updateComputerList();
|
||||
|
||||
final Intent intent = getIntent();
|
||||
final String deviceId = intent.getStringExtra("deviceId");
|
||||
|
||||
if (deviceId!=null) {
|
||||
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback(){
|
||||
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Log.d("DirectShare", "sharing to "+service.getDevice(deviceId).getName());
|
||||
Device device = service.getDevice(deviceId);
|
||||
if (device.isReachable() && device.isPaired()) {
|
||||
SharePlugin.share(intent, device);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
updateComputerList();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
BackgroundService.addGuiInUseCounter(this);
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
service.onNetworkChange();
|
||||
service.addDeviceListChangedCallback("ShareActivity", new BackgroundService.DeviceListChangedCallback() {
|
||||
@Override
|
||||
public void onDeviceListChanged() {
|
||||
updateComputerList();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
updateComputerList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2017 Nicolas Fella <nicolas.fella@gmx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ComponentName;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.service.chooser.ChooserTarget;
|
||||
import android.service.chooser.ChooserTargetService;
|
||||
import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@TargetApi(23)
|
||||
public class ShareChooserTargetService extends ChooserTargetService {
|
||||
@Override
|
||||
public List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) {
|
||||
Log.d("DirectShare", "invoked");
|
||||
final List<ChooserTarget> targets = new ArrayList<>();
|
||||
for(Device d: BackgroundService.getInstance().getDevices().values()){
|
||||
if(d.isReachable() && d.isPaired()) {
|
||||
Log.d("DirectShare", d.getName());
|
||||
final String targetName = d.getName();
|
||||
final Icon targetIcon = Icon.createWithResource(this, R.drawable.icon);
|
||||
final float targetRanking = 1;
|
||||
final ComponentName targetComponentName = new ComponentName(getPackageName(),
|
||||
ShareActivity.class.getCanonicalName());
|
||||
final Bundle targetExtras = new Bundle();
|
||||
targetExtras.putString("deviceId", d.getDeviceId());
|
||||
targets.add(new ChooserTarget(
|
||||
targetName, targetIcon, targetRanking, targetComponentName, targetExtras
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return targets;
|
||||
}
|
||||
}
|
@@ -0,0 +1,123 @@
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
/*
|
||||
* Copyright 2017 Nicolas Fella <nicolas.fella@gmx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v4.content.FileProvider;
|
||||
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ShareNotification {
|
||||
|
||||
private final String filename;
|
||||
private NotificationManager notificationManager;
|
||||
private int notificationId;
|
||||
private NotificationCompat.Builder builder;
|
||||
private Device device;
|
||||
|
||||
public ShareNotification(Device device, String filename) {
|
||||
this.device = device;
|
||||
this.filename = filename;
|
||||
notificationId = (int) System.currentTimeMillis();
|
||||
notificationManager = (NotificationManager) device.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
builder = new NotificationCompat.Builder(device.getContext())
|
||||
.setContentTitle(device.getContext().getResources().getString(R.string.incoming_file_title, device.getName()))
|
||||
.setContentText(device.getContext().getResources().getString(R.string.incoming_file_text, filename))
|
||||
.setTicker(device.getContext().getResources().getString(R.string.incoming_file_title, device.getName()))
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(true)
|
||||
.setProgress(100, 0, true);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return notificationId;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) {
|
||||
builder.setProgress(100, progress, false)
|
||||
.setContentTitle(device.getContext().getResources().getString(R.string.incoming_file_title, device.getName())+" ("+progress+"%)");
|
||||
}
|
||||
|
||||
public void setFinished(boolean success) {
|
||||
String message = success ? device.getContext().getResources().getString(R.string.received_file_title, device.getName()) : device.getContext().getResources().getString(R.string.received_file_fail_title, device.getName());
|
||||
builder = new NotificationCompat.Builder(device.getContext());
|
||||
builder.setContentTitle(message)
|
||||
.setTicker(message)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(false);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(device.getContext());
|
||||
if (prefs.getBoolean("share_notification_preference", true)) {
|
||||
builder.setDefaults(Notification.DEFAULT_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
public void setURI(Uri destinationUri, String mimeType) {
|
||||
/*
|
||||
* We only support file URIs (because sending a content uri to another app does not work for security reasons).
|
||||
* In effect, that means only the default download folder currently works.
|
||||
*
|
||||
* TODO: implement our own content provider (instead of support-v4's FileProvider). It should:
|
||||
* - Proxy to real files (in case of the default download folder)
|
||||
* - Proxy to the underlying content uri (in case of a custom download folder)
|
||||
*/
|
||||
if (!"file".equals(destinationUri.getScheme())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
//Nougat and later require "content://" uris instead of "file://" uris
|
||||
File file = new File(destinationUri.getPath());
|
||||
Uri contentUri = FileProvider.getUriForFile(device.getContext(), "org.kde.kdeconnect_tp.fileprovider", file);
|
||||
intent.setDataAndType(contentUri, mimeType);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
} else {
|
||||
intent.setDataAndType(destinationUri, mimeType);
|
||||
}
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(device.getContext());
|
||||
stackBuilder.addNextIntent(intent);
|
||||
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentText(device.getContext().getResources().getString(R.string.received_file_text, filename))
|
||||
.setContentIntent(resultPendingIntent);
|
||||
}
|
||||
}
|
@@ -20,6 +20,7 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.DownloadManager;
|
||||
import android.app.Notification;
|
||||
@@ -29,12 +30,12 @@ import android.content.ClipboardManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
@@ -53,17 +54,26 @@ import org.kde.kdeconnect.UserInterface.SettingsActivity;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SharePlugin extends Plugin {
|
||||
|
||||
//public final static String PACKAGE_TYPE_SHARE = "kdeconnect.share";
|
||||
public final static String PACKAGE_TYPE_SHARE_REQUEST = "kdeconnect.share.request";
|
||||
|
||||
final static boolean openUrlsDirectly = true;
|
||||
|
||||
private int sharePermissionExplanation = R.string.share_optional_permission_explanation;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
optionalPermissionExplanation = sharePermissionExplanation;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return context.getResources().getString(R.string.pref_plugin_sharereceiver);
|
||||
@@ -108,180 +118,168 @@ public class SharePlugin extends Plugin {
|
||||
if (np.hasPayload()) {
|
||||
|
||||
Log.i("SharePlugin", "hasPayload");
|
||||
|
||||
final InputStream input = np.getPayload();
|
||||
final long fileLength = np.getPayloadSize();
|
||||
final String originalFilename = np.getString("filename", Long.toString(System.currentTimeMillis()));
|
||||
|
||||
//We need to check for already existing files only when storing in the default path.
|
||||
//User-defined paths use the new Storage Access Framework that already handles this.
|
||||
final boolean customDestination = ShareSettingsActivity.isCustomDestinationEnabled(context);
|
||||
final String defaultPath = ShareSettingsActivity.getDefaultDestinationDirectory().getAbsolutePath();
|
||||
final String filename = customDestination? originalFilename : FilesHelper.findNonExistingNameForNewFile(defaultPath, originalFilename);
|
||||
|
||||
String displayName = FilesHelper.getFileNameWithoutExt(filename);
|
||||
final String mimeType = FilesHelper.getMimeTypeFromFile(filename);
|
||||
|
||||
if ("*/*".equals(mimeType)) {
|
||||
displayName = filename;
|
||||
|
||||
if (isPermissionGranted(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
receiveFile(np);
|
||||
} else {
|
||||
Log.i("SharePlugin", "no Permission for Storage");
|
||||
}
|
||||
|
||||
final DocumentFile destinationFolderDocument = ShareSettingsActivity.getDestinationDirectory(context);
|
||||
final DocumentFile destinationDocument = destinationFolderDocument.createFile(mimeType, displayName);
|
||||
final OutputStream destinationOutput = context.getContentResolver().openOutputStream(destinationDocument.getUri());
|
||||
final Uri destinationUri = destinationDocument.getUri();
|
||||
|
||||
final int notificationId = (int)System.currentTimeMillis();
|
||||
Resources res = context.getResources();
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(res.getString(R.string.incoming_file_title, device.getName()))
|
||||
.setContentText(res.getString(R.string.incoming_file_text, filename))
|
||||
.setTicker(res.getString(R.string.incoming_file_title, device.getName()))
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(true)
|
||||
.setProgress(100,0,true);
|
||||
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationHelper.notifyCompat(notificationManager,notificationId, builder.build());
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean successful = true;
|
||||
try {
|
||||
byte data[] = new byte[1024];
|
||||
long progress = 0, prevProgressPercentage = 0;
|
||||
int count;
|
||||
while ((count = input.read(data)) >= 0) {
|
||||
progress += count;
|
||||
destinationOutput.write(data, 0, count);
|
||||
if (fileLength > 0) {
|
||||
if (progress >= fileLength) break;
|
||||
long progressPercentage = (progress * 100 / fileLength);
|
||||
if (progressPercentage != prevProgressPercentage) {
|
||||
prevProgressPercentage = progressPercentage;
|
||||
builder.setProgress(100, (int) progressPercentage, false);
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
}
|
||||
}
|
||||
//else Log.e("SharePlugin", "Infinite loop? :D");
|
||||
}
|
||||
|
||||
destinationOutput.flush();
|
||||
|
||||
} catch (Exception e) {
|
||||
successful = false;
|
||||
Log.e("SharePlugin", "Receiver thread exception");
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try { destinationOutput.close(); } catch (Exception e) {}
|
||||
try { input.close(); } catch (Exception e) {}
|
||||
}
|
||||
|
||||
try {
|
||||
Log.i("SharePlugin", "Transfer finished: "+destinationUri.getPath());
|
||||
|
||||
//Update the notification and allow to open the file from it
|
||||
Resources res = context.getResources();
|
||||
String message = successful? res.getString(R.string.received_file_title, device.getName()) : res.getString(R.string.received_file_fail_title, device.getName());
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(message)
|
||||
.setTicker(message)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||
.setAutoCancel(true);
|
||||
if (successful) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(destinationUri, mimeType);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
|
||||
stackBuilder.addNextIntent(intent);
|
||||
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentText(res.getString(R.string.received_file_text, destinationDocument.getName()))
|
||||
.setContentIntent(resultPendingIntent);
|
||||
}
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (prefs.getBoolean("share_notification_preference", true)) {
|
||||
builder.setDefaults(Notification.DEFAULT_ALL);
|
||||
}
|
||||
NotificationHelper.notifyCompat(notificationManager, notificationId, builder.build());
|
||||
|
||||
if (successful) {
|
||||
if (!customDestination) {
|
||||
Log.i("SharePlugin","Adding to downloads");
|
||||
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.addCompletedDownload(destinationUri.getLastPathSegment(), device.getName(), true, mimeType, destinationUri.getPath(), fileLength, false);
|
||||
} else {
|
||||
//Make sure it is added to the Android Gallery anyway
|
||||
MediaStoreHelper.indexFile(context, destinationUri);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("SharePlugin", "Receiver thread exception");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
} else if (np.has("text")) {
|
||||
Log.i("SharePlugin", "hasText");
|
||||
|
||||
String text = np.getString("text");
|
||||
if(android.os.Build.VERSION.SDK_INT >= 11) {
|
||||
ClipboardManager cm = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setText(text);
|
||||
} else {
|
||||
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
}
|
||||
Toast.makeText(context, R.string.shareplugin_text_saved, Toast.LENGTH_LONG).show();
|
||||
receiveText(np);
|
||||
} else if (np.has("url")) {
|
||||
|
||||
String url = np.getString("url");
|
||||
|
||||
Log.i("SharePlugin", "hasUrl: "+url);
|
||||
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
if (openUrlsDirectly) {
|
||||
context.startActivity(browserIntent);
|
||||
} else {
|
||||
Resources res = context.getResources();
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
|
||||
stackBuilder.addNextIntent(browserIntent);
|
||||
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
|
||||
Notification noti = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(res.getString(R.string.received_url_title, device.getName()))
|
||||
.setContentText(res.getString(R.string.received_url_text, url))
|
||||
.setContentIntent(resultPendingIntent)
|
||||
.setTicker(res.getString(R.string.received_url_title, device.getName()))
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.build();
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationHelper.notifyCompat(notificationManager, (int) System.currentTimeMillis(), noti);
|
||||
}
|
||||
receiveUrl(np);
|
||||
} else {
|
||||
Log.e("SharePlugin", "Error: Nothing attached!");
|
||||
}
|
||||
|
||||
|
||||
} catch(Exception e) {
|
||||
Log.e("SharePlugin","Exception");
|
||||
} catch (Exception e) {
|
||||
Log.e("SharePlugin", "Exception");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void receiveUrl(NetworkPackage np) {
|
||||
String url = np.getString("url");
|
||||
|
||||
Log.i("SharePlugin", "hasUrl: " + url);
|
||||
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
if (openUrlsDirectly) {
|
||||
context.startActivity(browserIntent);
|
||||
} else {
|
||||
Resources res = context.getResources();
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
|
||||
stackBuilder.addNextIntent(browserIntent);
|
||||
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
|
||||
0,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
|
||||
Notification noti = new NotificationCompat.Builder(context)
|
||||
.setContentTitle(res.getString(R.string.received_url_title, device.getName()))
|
||||
.setContentText(res.getString(R.string.received_url_text, url))
|
||||
.setContentIntent(resultPendingIntent)
|
||||
.setTicker(res.getString(R.string.received_url_title, device.getName()))
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(Notification.DEFAULT_ALL)
|
||||
.build();
|
||||
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationHelper.notifyCompat(notificationManager, (int) System.currentTimeMillis(), noti);
|
||||
}
|
||||
}
|
||||
|
||||
private void receiveText(NetworkPackage np) {
|
||||
String text = np.getString("text");
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cm.setText(text);
|
||||
} else {
|
||||
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
}
|
||||
Toast.makeText(context, R.string.shareplugin_text_saved, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void receiveFile(NetworkPackage np) {
|
||||
|
||||
final InputStream input = np.getPayload();
|
||||
final long fileLength = np.getPayloadSize();
|
||||
final String originalFilename = np.getString("filename", Long.toString(System.currentTimeMillis()));
|
||||
|
||||
//We need to check for already existing files only when storing in the default path.
|
||||
//User-defined paths use the new Storage Access Framework that already handles this.
|
||||
final boolean customDestination = ShareSettingsActivity.isCustomDestinationEnabled(context);
|
||||
final String defaultPath = ShareSettingsActivity.getDefaultDestinationDirectory().getAbsolutePath();
|
||||
final String filename = customDestination ? originalFilename : FilesHelper.findNonExistingNameForNewFile(defaultPath, originalFilename);
|
||||
|
||||
String displayName = FilesHelper.getFileNameWithoutExt(filename);
|
||||
final String mimeType = FilesHelper.getMimeTypeFromFile(filename);
|
||||
|
||||
if ("*/*".equals(mimeType)) {
|
||||
displayName = filename;
|
||||
}
|
||||
|
||||
final DocumentFile destinationFolderDocument = ShareSettingsActivity.getDestinationDirectory(context);
|
||||
final DocumentFile destinationDocument = destinationFolderDocument.createFile(mimeType, displayName);
|
||||
final OutputStream destinationOutput;
|
||||
try {
|
||||
destinationOutput = context.getContentResolver().openOutputStream(destinationDocument.getUri());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
final Uri destinationUri = destinationDocument.getUri();
|
||||
|
||||
final ShareNotification notification = new ShareNotification(device, filename);
|
||||
notification.show();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
byte data[] = new byte[4096];
|
||||
long progress = 0, prevProgressPercentage = -1;
|
||||
int count;
|
||||
while ((count = input.read(data)) >= 0) {
|
||||
progress += count;
|
||||
destinationOutput.write(data, 0, count);
|
||||
if (fileLength > 0) {
|
||||
if (progress >= fileLength) break;
|
||||
long progressPercentage = (progress * 100 / fileLength);
|
||||
if (progressPercentage != prevProgressPercentage) {
|
||||
prevProgressPercentage = progressPercentage;
|
||||
notification.setProgress((int) progressPercentage);
|
||||
notification.show();
|
||||
}
|
||||
}
|
||||
//else Log.e("SharePlugin", "Infinite loop? :D");
|
||||
}
|
||||
|
||||
destinationOutput.flush();
|
||||
|
||||
Log.i("SharePlugin", "Transfer finished: " + destinationUri.getPath());
|
||||
|
||||
//Update the notification and allow to open the file from it
|
||||
notification.setFinished(true);
|
||||
notification.setURI(destinationUri, mimeType);
|
||||
notification.show();
|
||||
|
||||
if (!customDestination && Build.VERSION.SDK_INT >= 12) {
|
||||
Log.i("SharePlugin", "Adding to downloads");
|
||||
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.addCompletedDownload(destinationUri.getLastPathSegment(), device.getName(), true, mimeType, destinationUri.getPath(), fileLength, false);
|
||||
} else {
|
||||
//Make sure it is added to the Android Gallery anyway
|
||||
MediaStoreHelper.indexFile(context, destinationUri);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("SharePlugin", "Receiver thread exception");
|
||||
e.printStackTrace();
|
||||
notification.setFinished(false);
|
||||
notification.show();
|
||||
} finally {
|
||||
try {
|
||||
destinationOutput.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
input.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPreferencesActivity(SettingsActivity parentActivity) {
|
||||
Intent intent = new Intent(parentActivity, ShareSettingsActivity.class);
|
||||
@@ -310,7 +308,7 @@ public class SharePlugin extends Plugin {
|
||||
for (NetworkPackage np : toSend) {
|
||||
boolean success = device.sendPackageBlocking(np, notificationUpdateCallback);
|
||||
if (!success) {
|
||||
Log.e("SharePlugin","Error sending files");
|
||||
Log.e("SharePlugin", "Error sending files");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -340,24 +338,24 @@ public class SharePlugin extends Plugin {
|
||||
|
||||
try {
|
||||
size = new File(uri.getPath()).length();
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
Log.e("SendFileActivity", "Could not obtain file size");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}else{
|
||||
} else {
|
||||
// Probably a content:// uri, so we query the Media content provider
|
||||
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
String[] proj = { MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.SIZE, MediaStore.MediaColumns.DISPLAY_NAME };
|
||||
String[] proj = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.SIZE, MediaStore.MediaColumns.DISPLAY_NAME};
|
||||
cursor = cr.query(uri, proj, null, null, null);
|
||||
int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
|
||||
cursor.moveToFirst();
|
||||
String path = cursor.getString(column_index);
|
||||
np.set("filename", Uri.parse(path).getLastPathSegment());
|
||||
size = new File(path).length();
|
||||
} catch(Exception unused) {
|
||||
} catch (Exception unused) {
|
||||
|
||||
Log.w("SendFileActivity", "Could not resolve media to a file, trying to get info as media");
|
||||
|
||||
@@ -376,12 +374,15 @@ public class SharePlugin extends Plugin {
|
||||
cursor.moveToFirst();
|
||||
//For some reason this size can differ from the actual file size!
|
||||
size = cursor.getInt(column_index);
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
Log.e("SendFileActivity", "Could not obtain file size");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
try { cursor.close(); } catch (Exception e) { }
|
||||
try {
|
||||
cursor.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -396,6 +397,59 @@ public class SharePlugin extends Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
public static void share(Intent intent, Device device){
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras != null) {
|
||||
if (extras.containsKey(Intent.EXTRA_STREAM)) {
|
||||
|
||||
try {
|
||||
|
||||
ArrayList<Uri> uriList;
|
||||
if (!Intent.ACTION_SEND.equals(intent.getAction())) {
|
||||
uriList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
|
||||
} else {
|
||||
Uri uri = extras.getParcelable(Intent.EXTRA_STREAM);
|
||||
uriList = new ArrayList<>();
|
||||
uriList.add(uri);
|
||||
}
|
||||
|
||||
SharePlugin.queuedSendUriList(device.getContext(), device, uriList);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e("ShareActivity", "Exception");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else if (extras.containsKey(Intent.EXTRA_TEXT)) {
|
||||
String text = extras.getString(Intent.EXTRA_TEXT);
|
||||
String subject = extras.getString(Intent.EXTRA_SUBJECT);
|
||||
|
||||
//Hack: Detect shared youtube videos, so we can open them in the browser instead of as text
|
||||
if (subject != null && subject.endsWith("YouTube")) {
|
||||
int index = text.indexOf(": http://youtu.be/");
|
||||
if (index > 0) {
|
||||
text = text.substring(index + 2); //Skip ": "
|
||||
}
|
||||
}
|
||||
|
||||
boolean isUrl;
|
||||
try {
|
||||
new URL(text);
|
||||
isUrl = true;
|
||||
} catch (Exception e) {
|
||||
isUrl = false;
|
||||
}
|
||||
NetworkPackage np = new NetworkPackage(SharePlugin.PACKAGE_TYPE_SHARE_REQUEST);
|
||||
if (isUrl) {
|
||||
np.set("url", text);
|
||||
} else {
|
||||
np.set("text", text);
|
||||
}
|
||||
device.sendPackage(np);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedPackageTypes() {
|
||||
@@ -407,5 +461,8 @@ public class SharePlugin extends Plugin {
|
||||
return new String[]{PACKAGE_TYPE_SHARE_REQUEST};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String[] getOptionalPermissions() {
|
||||
return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
|
||||
}
|
||||
}
|
||||
|
@@ -93,6 +93,11 @@ public class ShareSettingsActivity extends PluginSettingsActivity {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
getDefaultDestinationDirectory().mkdirs();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return DocumentFile.fromFile(getDefaultDestinationDirectory());
|
||||
}
|
||||
|
||||
|
@@ -20,9 +20,15 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins.TelepathyPlugin;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.telephony.SmsManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin;
|
||||
@@ -33,6 +39,14 @@ public class TelepathyPlugin extends Plugin {
|
||||
|
||||
public final static String PACKAGE_TYPE_SMS_REQUEST = "kdeconnect.sms.request";
|
||||
|
||||
private int telepathyPermissionExplanation = R.string.telepathy_permission_explanation;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
permissionExplanation = telepathyPermissionExplanation;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return context.getResources().getString(R.string.pref_plugin_telepathy);
|
||||
@@ -43,11 +57,6 @@ public class TelepathyPlugin extends Plugin {
|
||||
return context.getResources().getString(R.string.pref_plugin_telepathy_desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
}
|
||||
@@ -63,8 +72,20 @@ public class TelepathyPlugin extends Plugin {
|
||||
String phoneNo = np.getString("phoneNumber");
|
||||
String sms = np.getString("messageBody");
|
||||
try {
|
||||
SmsManager smsManager = SmsManager.getDefault();
|
||||
smsManager.sendTextMessage(phoneNo, null, sms, null, null);
|
||||
int permissionCheck = ContextCompat.checkSelfPermission(context,
|
||||
Manifest.permission.SEND_SMS);
|
||||
|
||||
if(permissionCheck == PackageManager.PERMISSION_GRANTED) {
|
||||
SmsManager smsManager = SmsManager.getDefault();
|
||||
|
||||
ArrayList<String> parts = smsManager.divideMessage(sms);
|
||||
|
||||
// If this message turns out to fit in a single SMS, sendMultpartTextMessage
|
||||
// properly handles that case
|
||||
smsManager.sendMultipartTextMessage(phoneNo, null, parts, null, null);
|
||||
} else if(permissionCheck == PackageManager.PERMISSION_DENIED){
|
||||
// TODO Request Permission SEND_SMS
|
||||
}
|
||||
//TODO: Notify other end
|
||||
} catch (Exception e) {
|
||||
//TODO: Notify other end
|
||||
@@ -176,4 +197,8 @@ public class TelepathyPlugin extends Plugin {
|
||||
return new String[]{};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRequiredPermissions() {
|
||||
return new String[]{Manifest.permission.SEND_SMS/*, Manifest.permission.READ_CONTACTS*/};
|
||||
}
|
||||
}
|
||||
|
@@ -20,13 +20,16 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins.TelephonyPlugin;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.telephony.SmsMessage;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
@@ -34,8 +37,10 @@ import android.util.Log;
|
||||
import org.kde.kdeconnect.Helpers.ContactsHelper;
|
||||
import org.kde.kdeconnect.NetworkPackage;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
import org.kde.kdeconnect_tp.BuildConfig;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
@@ -49,6 +54,9 @@ public class TelephonyPlugin extends Plugin {
|
||||
private NetworkPackage lastPackage = null;
|
||||
private boolean isMuted = false;
|
||||
|
||||
private int telephonyPermissionExplanation = R.string.telephony_permission_explanation;
|
||||
private int telephonyOptionalPermissionExplanation = R.string.telephony_optional_permission_explanation;
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return context.getResources().getString(R.string.pref_plugin_telephony);
|
||||
@@ -72,11 +80,19 @@ public class TelephonyPlugin extends Plugin {
|
||||
final Bundle bundle = intent.getExtras();
|
||||
if (bundle == null) return;
|
||||
final Object[] pdus = (Object[]) bundle.get("pdus");
|
||||
ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
|
||||
|
||||
for (Object pdu : pdus) {
|
||||
SmsMessage message = SmsMessage.createFromPdu((byte[])pdu);
|
||||
smsBroadcastReceived(message);
|
||||
// I hope, but am not sure, that the pdus array is in the order that the parts
|
||||
// of the SMS message should be
|
||||
// If it is not, I belive the pdu contains the information necessary to put it
|
||||
// in order, but in my testing the order seems to be correct, so I won't worry
|
||||
// about it now.
|
||||
messages.add(SmsMessage.createFromPdu((byte[])pdu));
|
||||
}
|
||||
|
||||
smsBroadcastReceived(messages);
|
||||
|
||||
} else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
|
||||
|
||||
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
|
||||
@@ -102,32 +118,40 @@ public class TelephonyPlugin extends Plugin {
|
||||
|
||||
//Log.e("TelephonyPlugin", "callBroadcastReceived");
|
||||
|
||||
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
|
||||
NetworkPackage np = new NetworkPackage(PACKAGE_TYPE_TELEPHONY);
|
||||
|
||||
if (phoneNumber != null) {
|
||||
np.set("phoneNumber", phoneNumber);
|
||||
}
|
||||
int permissionCheck = ContextCompat.checkSelfPermission(context,
|
||||
Manifest.permission.READ_CONTACTS);
|
||||
|
||||
if(permissionCheck==PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
|
||||
|
||||
if (contactInfo.containsKey("name")) {
|
||||
np.set("contactName", contactInfo.get("name"));
|
||||
}
|
||||
|
||||
if (contactInfo.containsKey("photoID")) {
|
||||
String photoUri = contactInfo.get("photoID");
|
||||
if (photoUri != null) {
|
||||
try {
|
||||
String base64photo = ContactsHelper.photoId64Encoded(context, photoUri);
|
||||
if (base64photo != null && !base64photo.isEmpty()) {
|
||||
np.set("phoneThumbnail", base64photo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("TelephonyPlugin", "Failed to get contact photo");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (contactInfo.containsKey("name")) {
|
||||
np.set("contactName", contactInfo.get("name"));
|
||||
} else {
|
||||
np.set("contactName", phoneNumber);
|
||||
}
|
||||
|
||||
if (contactInfo.containsKey("photoID")) {
|
||||
String photoUri = contactInfo.get("photoID");
|
||||
if (photoUri != null) {
|
||||
try {
|
||||
String base64photo = ContactsHelper.photoId64Encoded(context, photoUri);
|
||||
if (base64photo != null && !base64photo.isEmpty()) {
|
||||
np.set("phoneThumbnail", base64photo);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("TelephonyPlugin", "Failed to get contact photo");
|
||||
}
|
||||
}
|
||||
|
||||
if (phoneNumber != null) {
|
||||
np.set("phoneNumber", phoneNumber);
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
@@ -194,7 +218,14 @@ public class TelephonyPlugin extends Plugin {
|
||||
lastState = state;
|
||||
}
|
||||
|
||||
private void smsBroadcastReceived(SmsMessage message) {
|
||||
private void smsBroadcastReceived(ArrayList<SmsMessage> messages) {
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
if (!(messages.size() > 0))
|
||||
{
|
||||
throw new AssertionError("This method requires at least one message");
|
||||
}
|
||||
}
|
||||
|
||||
//Log.e("SmsBroadcastReceived", message.toString());
|
||||
|
||||
@@ -202,24 +233,33 @@ public class TelephonyPlugin extends Plugin {
|
||||
|
||||
np.set("event","sms");
|
||||
|
||||
String messageBody = message.getMessageBody();
|
||||
if (messageBody != null) {
|
||||
np.set("messageBody",messageBody);
|
||||
StringBuilder messageBody = new StringBuilder();
|
||||
for (int index = 0; index < messages.size(); index ++) {
|
||||
messageBody.append(messages.get(index).getMessageBody());
|
||||
}
|
||||
np.set("messageBody", messageBody.toString());
|
||||
|
||||
String phoneNumber = message.getOriginatingAddress();
|
||||
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
|
||||
String phoneNumber = messages.get(0).getOriginatingAddress();
|
||||
|
||||
int permissionCheck = ContextCompat.checkSelfPermission(context,
|
||||
Manifest.permission.READ_CONTACTS);
|
||||
|
||||
if(permissionCheck==PackageManager.PERMISSION_GRANTED) {
|
||||
Map<String, String> contactInfo = ContactsHelper.phoneNumberLookup(context, phoneNumber);
|
||||
|
||||
if (contactInfo.containsKey("name")) {
|
||||
np.set("contactName", contactInfo.get("name"));
|
||||
}
|
||||
|
||||
if (contactInfo.containsKey("photoID")) {
|
||||
np.set("phoneThumbnail", ContactsHelper.photoId64Encoded(context, contactInfo.get("photoID")));
|
||||
}
|
||||
}
|
||||
if (phoneNumber != null) {
|
||||
np.set("phoneNumber", phoneNumber);
|
||||
}
|
||||
|
||||
if (contactInfo.containsKey("name")) {
|
||||
np.set("contactName", contactInfo.get("name"));
|
||||
}
|
||||
|
||||
if (contactInfo.containsKey("photoID")) {
|
||||
np.set("phoneThumbnail", ContactsHelper.photoId64Encoded(context, contactInfo.get("photoID")));
|
||||
}
|
||||
|
||||
device.sendPackage(np);
|
||||
}
|
||||
@@ -231,6 +271,8 @@ public class TelephonyPlugin extends Plugin {
|
||||
filter.setPriority(500);
|
||||
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
|
||||
context.registerReceiver(receiver, filter);
|
||||
permissionExplanation = telephonyPermissionExplanation;
|
||||
optionalPermissionExplanation = telephonyOptionalPermissionExplanation;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -267,4 +309,13 @@ public class TelephonyPlugin extends Plugin {
|
||||
return new String[]{PACKAGE_TYPE_TELEPHONY};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRequiredPermissions() {
|
||||
return new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_SMS};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getOptionalPermissions() {
|
||||
return new String[]{Manifest.permission.READ_CONTACTS};
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
@@ -42,7 +42,7 @@ import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CustomDevicesActivity extends ActionBarActivity {
|
||||
public class CustomDevicesActivity extends AppCompatActivity {
|
||||
|
||||
private static final String LOG_ID = "CustomDevicesActivity";
|
||||
public static final String KEY_CUSTOM_DEVLIST_PREFERENCE = "device_list_preference";
|
||||
|
@@ -62,31 +62,27 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
public class DeviceFragment extends Fragment {
|
||||
|
||||
static final String ARG_DEVICE_ID = "deviceId";
|
||||
static final String ARG_FROM_DEVICE_LIST = "fromDeviceList";
|
||||
|
||||
View rootView;
|
||||
static String mDeviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
|
||||
Device device;
|
||||
|
||||
TextView errorHeader;
|
||||
|
||||
MaterialActivity mActivity;
|
||||
|
||||
public DeviceFragment() { }
|
||||
ArrayList<ListAdapter.Item> pluginListItems;
|
||||
|
||||
public DeviceFragment(String deviceId) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_DEVICE_ID, deviceId);
|
||||
this.setArguments(args);
|
||||
public DeviceFragment() {
|
||||
}
|
||||
|
||||
public DeviceFragment(String deviceId, boolean fromDeviceList) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_DEVICE_ID, deviceId);
|
||||
args.putBoolean("fromDeviceList", fromDeviceList);
|
||||
args.putBoolean(ARG_FROM_DEVICE_LIST, fromDeviceList);
|
||||
this.setArguments(args);
|
||||
}
|
||||
|
||||
public DeviceFragment(String deviceId, MaterialActivity activity){
|
||||
public DeviceFragment(String deviceId, MaterialActivity activity) {
|
||||
this.mActivity = activity;
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_DEVICE_ID, deviceId);
|
||||
@@ -134,7 +130,7 @@ public class DeviceFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
final Button pairButton = (Button)rootView.findViewById(R.id.pair_button);
|
||||
final Button pairButton = (Button) rootView.findViewById(R.id.pair_button);
|
||||
pairButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
@@ -299,7 +295,7 @@ public class DeviceFragment extends Fragment {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
boolean fromDeviceList = getArguments().getBoolean("fromDeviceList", false);
|
||||
boolean fromDeviceList = getArguments().getBoolean(ARG_FROM_DEVICE_LIST, false);
|
||||
// Handle back button so we go to the list of devices in case we came from there
|
||||
if (fromDeviceList) {
|
||||
mActivity.onDeviceSelected(null);
|
||||
@@ -341,7 +337,7 @@ public class DeviceFragment extends Fragment {
|
||||
rootView.findViewById(R.id.on_data_message).setVisibility((paired && !reachable && onData) ? View.VISIBLE : View.GONE);
|
||||
|
||||
try {
|
||||
ArrayList<ListAdapter.Item> items = new ArrayList<>();
|
||||
pluginListItems = new ArrayList<>();
|
||||
|
||||
//Plugins button list
|
||||
final Collection<Plugin> plugins = device.getLoadedPlugins().values();
|
||||
@@ -349,7 +345,7 @@ public class DeviceFragment extends Fragment {
|
||||
if (!p.hasMainActivity()) continue;
|
||||
if (p.displayInContextMenu()) continue;
|
||||
|
||||
items.add(new PluginItem(p, new View.OnClickListener() {
|
||||
pluginListItems.add(new PluginItem(p, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
p.startMainActivity(mActivity);
|
||||
@@ -357,40 +353,27 @@ public class DeviceFragment extends Fragment {
|
||||
}));
|
||||
}
|
||||
|
||||
//Failed plugins List
|
||||
final ConcurrentHashMap<String, Plugin> failed = device.getFailedPlugins();
|
||||
if (!failed.isEmpty()) {
|
||||
if (errorHeader == null) {
|
||||
errorHeader = new TextView(mActivity);
|
||||
errorHeader.setPadding(
|
||||
0,
|
||||
((int) (28 * getResources().getDisplayMetrics().density)),
|
||||
0,
|
||||
((int) (8 * getResources().getDisplayMetrics().density))
|
||||
);
|
||||
errorHeader.setOnClickListener(null);
|
||||
errorHeader.setOnLongClickListener(null);
|
||||
errorHeader.setText(getResources().getString(R.string.plugins_failed_to_load));
|
||||
createPluginsList(device.getFailedPlugins(), R.string.plugins_failed_to_load, new PluginClickListener() {
|
||||
@Override
|
||||
void action() {
|
||||
plugin.getErrorDialog(mActivity).show();
|
||||
}
|
||||
items.add(new CustomItem(errorHeader));
|
||||
for (Map.Entry<String, Plugin> entry : failed.entrySet()) {
|
||||
String pluginKey = entry.getKey();
|
||||
final Plugin plugin = entry.getValue();
|
||||
if (plugin == null) {
|
||||
items.add(new SmallEntryItem(pluginKey));
|
||||
} else {
|
||||
items.add(new SmallEntryItem(plugin.getDisplayName(), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
plugin.getErrorDialog(mActivity).show();
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
createPluginsList(device.getPluginsWithoutPermissions(), R.string.plugins_need_permission, new PluginClickListener() {
|
||||
@Override
|
||||
void action() {
|
||||
plugin.getPermissionExplanationDialog(mActivity).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
createPluginsList(device.getPluginsWithoutOptionalPermissions(), R.string.plugins_need_optional_permission, new PluginClickListener() {
|
||||
@Override
|
||||
void action() {
|
||||
plugin.getOptionalPermissionExplanationDialog(mActivity).show();
|
||||
}
|
||||
});
|
||||
|
||||
ListView buttonsList = (ListView) rootView.findViewById(R.id.buttons_list);
|
||||
ListAdapter adapter = new ListAdapter(mActivity, items);
|
||||
ListAdapter adapter = new ListAdapter(mActivity, pluginListItems);
|
||||
buttonsList.setAdapter(adapter);
|
||||
|
||||
mActivity.invalidateOptionsMenu();
|
||||
@@ -453,11 +436,15 @@ public class DeviceFragment extends Fragment {
|
||||
|
||||
};
|
||||
|
||||
public static void acceptPairing(final String devId, final MaterialActivity activity){
|
||||
public static void acceptPairing(final String devId, final MaterialActivity activity) {
|
||||
final DeviceFragment frag = new DeviceFragment(devId, activity);
|
||||
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device dev = service.getDevice(devId);
|
||||
if (dev == null) {
|
||||
Log.w("rejectPairing", "Device no longer exists: "+devId);
|
||||
return;
|
||||
}
|
||||
activity.getSupportActionBar().setTitle(dev.getName());
|
||||
|
||||
dev.addPairingCallback(frag.pairingCallback);
|
||||
@@ -472,11 +459,15 @@ public class DeviceFragment extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
public static void rejectPairing(final String devId, final MaterialActivity activity){
|
||||
public static void rejectPairing(final String devId, final MaterialActivity activity) {
|
||||
final DeviceFragment frag = new DeviceFragment(devId, activity);
|
||||
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() {
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device dev = service.getDevice(devId);
|
||||
if (dev == null) {
|
||||
Log.w("rejectPairing", "Device no longer exists: "+devId);
|
||||
return;
|
||||
}
|
||||
activity.getSupportActionBar().setTitle(dev.getName());
|
||||
|
||||
dev.addPairingCallback(frag.pairingCallback);
|
||||
@@ -494,4 +485,58 @@ public class DeviceFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void createPluginsList(ConcurrentHashMap<String, Plugin> plugins, int headerText, PluginClickListener onClickListener) {
|
||||
if (!plugins.isEmpty()) {
|
||||
|
||||
TextView header = new TextView(mActivity);
|
||||
header.setPadding(
|
||||
0,
|
||||
((int) (28 * getResources().getDisplayMetrics().density)),
|
||||
0,
|
||||
((int) (8 * getResources().getDisplayMetrics().density))
|
||||
);
|
||||
header.setOnClickListener(null);
|
||||
header.setOnLongClickListener(null);
|
||||
header.setText(headerText);
|
||||
|
||||
pluginListItems.add(new CustomItem(header));
|
||||
for (Map.Entry<String, Plugin> entry : plugins.entrySet()) {
|
||||
String pluginKey = entry.getKey();
|
||||
final Plugin plugin = entry.getValue();
|
||||
if (device.isPluginEnabled(pluginKey)) {
|
||||
if (plugin == null) {
|
||||
pluginListItems.add(new SmallEntryItem(pluginKey));
|
||||
} else {
|
||||
PluginClickListener listener = onClickListener.clone();
|
||||
listener.plugin = plugin;
|
||||
pluginListItems.add(new SmallEntryItem(plugin.getDisplayName(), listener));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class PluginClickListener implements View.OnClickListener, Cloneable {
|
||||
|
||||
Plugin plugin;
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
action();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginClickListener clone(){
|
||||
try {
|
||||
return (PluginClickListener) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract void action();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,14 +1,17 @@
|
||||
package org.kde.kdeconnect.UserInterface;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
@@ -236,7 +239,7 @@ public class MaterialActivity extends AppCompatActivity {
|
||||
//TODO: Make it accept two parameters, a constant with the type of screen and the device id in
|
||||
//case the screen is for a device, or even three parameters and the third one be the plugin id?
|
||||
//This way we can keep adding more options with null device id (eg: about, help...)
|
||||
public void onDeviceSelected(String deviceId, boolean stack) {
|
||||
public void onDeviceSelected(String deviceId, boolean fromDeviceList) {
|
||||
|
||||
mCurrentDevice = deviceId;
|
||||
|
||||
@@ -251,7 +254,7 @@ public class MaterialActivity extends AppCompatActivity {
|
||||
if (deviceId == null) {
|
||||
fragment = new PairingFragment();
|
||||
} else {
|
||||
fragment = new DeviceFragment(deviceId, stack);
|
||||
fragment = new DeviceFragment(deviceId, fromDeviceList);
|
||||
}
|
||||
|
||||
getSupportFragmentManager()
|
||||
@@ -294,6 +297,22 @@ public class MaterialActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
for (int result : grantResults) {
|
||||
if (result == PackageManager.PERMISSION_GRANTED) {
|
||||
//New permission granted, reload plugins
|
||||
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
Device device = service.getDevice(mCurrentDevice);
|
||||
device.reloadPluginsFromSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void renameDevice() {
|
||||
final TextView nameView = (TextView) mNavigationView.findViewById(R.id.device_name);
|
||||
final EditText deviceNameEdit = new EditText(MaterialActivity.this);
|
||||
@@ -313,6 +332,12 @@ public class MaterialActivity extends AppCompatActivity {
|
||||
String deviceName = deviceNameEdit.getText().toString();
|
||||
DeviceHelper.setDeviceName(MaterialActivity.this, deviceName);
|
||||
nameView.setText(deviceName);
|
||||
BackgroundService.RunCommand(MaterialActivity.this, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(final BackgroundService service) {
|
||||
service.onNetworkChange();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
|
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Albert Vaca Cintora <albertvaka@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.UserInterface;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
public class MaxWidthImageButton extends ImageButton {
|
||||
|
||||
int mMaxWidth = Integer.MAX_VALUE;
|
||||
|
||||
public MaxWidthImageButton(Context context) {
|
||||
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MaxWidthImageButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthImageButton);
|
||||
mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthImageButton_maxWidth, Integer.MAX_VALUE);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if(getMeasuredWidth() > mMaxWidth){
|
||||
setMeasuredDimension(mMaxWidth, getMeasuredHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
@@ -55,10 +56,10 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
||||
private static final int RESULT_PAIRING_SUCCESFUL = Activity.RESULT_FIRST_USER;
|
||||
|
||||
private View rootView;
|
||||
private View listRootView;
|
||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private MaterialActivity mActivity;
|
||||
|
||||
private MenuItem menuProgress;
|
||||
|
||||
boolean listRefreshCalledThisFrame = false;
|
||||
|
||||
TextView headerText;
|
||||
@@ -75,12 +76,21 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
rootView = inflater.inflate(R.layout.activity_list, container, false);
|
||||
|
||||
rootView = inflater.inflate(R.layout.activity_refresh_list, container, false);
|
||||
listRootView = rootView.findViewById(R.id.listView1);
|
||||
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_list_layout);
|
||||
mSwipeRefreshLayout.setOnRefreshListener(
|
||||
new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
updateComputerListAction();
|
||||
}
|
||||
}
|
||||
);
|
||||
headerText = new TextView(inflater.getContext());
|
||||
headerText.setText(getString(R.string.pairing_description));
|
||||
headerText.setPadding(0, (int) (16 * getResources().getDisplayMetrics().density), 0, (int) (12 * getResources().getDisplayMetrics().density));
|
||||
((ListView) rootView).addHeaderView(headerText);
|
||||
((ListView) listRootView).addHeaderView(headerText);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
@@ -91,7 +101,30 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
||||
mActivity = ((MaterialActivity) getActivity());
|
||||
}
|
||||
|
||||
void updateComputerList() {
|
||||
private void updateComputerListAction() {
|
||||
updateComputerList();
|
||||
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
service.onNetworkChange();
|
||||
}
|
||||
});
|
||||
mSwipeRefreshLayout.setRefreshing(true);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try { Thread.sleep(1500); } catch (InterruptedException ignored) { }
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void updateComputerList() {
|
||||
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(final BackgroundService service) {
|
||||
@@ -99,6 +132,11 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (!isAdded()) {
|
||||
//Fragment is not attached to an activity. We will crash if we try to do anything here.
|
||||
return;
|
||||
}
|
||||
|
||||
if (listRefreshCalledThisFrame) {
|
||||
// This makes sure we don't try to call list.getFirstVisiblePosition()
|
||||
// twice per frame, because the second time the list hasn't been drawn
|
||||
@@ -108,6 +146,9 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
||||
listRefreshCalledThisFrame = true;
|
||||
|
||||
headerText.setText(getString(NetworkHelper.isOnMobileNetwork(getContext()) ? R.string.on_data_message : R.string.pairing_description));
|
||||
//Disable tap animation
|
||||
headerText.setOnClickListener(null);
|
||||
headerText.setOnLongClickListener(null);
|
||||
|
||||
try {
|
||||
Collection<Device> devices = service.getDevices().values();
|
||||
@@ -197,6 +238,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mSwipeRefreshLayout.setEnabled(false);
|
||||
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
@@ -227,33 +269,13 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.pairing, menu);
|
||||
menuProgress = menu.findItem(R.id.menu_progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_refresh:
|
||||
updateComputerList();
|
||||
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() {
|
||||
@Override
|
||||
public void onServiceStart(BackgroundService service) {
|
||||
service.onNetworkChange();
|
||||
}
|
||||
});
|
||||
menuProgress.setVisible(true);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try { Thread.sleep(1500); } catch (InterruptedException e) { }
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
menuProgress.setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
updateComputerListAction();
|
||||
break;
|
||||
case R.id.menu_rename:
|
||||
mActivity.renameDevice();
|
||||
|
Reference in New Issue
Block a user