diff --git a/src/main/java/org/kde/kdeconnect/Helpers/FilesHelper.java b/src/main/java/org/kde/kdeconnect/Helpers/FilesHelper.java
new file mode 100644
index 00000000..6854c108
--- /dev/null
+++ b/src/main/java/org/kde/kdeconnect/Helpers/FilesHelper.java
@@ -0,0 +1,18 @@
+package org.kde.kdeconnect.Helpers;
+
+import android.webkit.MimeTypeMap;
+
+public class FilesHelper {
+
+ public static String getFileExt(String fileName) {
+ //return MimeTypeMap.getFileExtensionFromUrl(fileName);
+ return fileName.substring((fileName.lastIndexOf(".") + 1), fileName.length());
+ }
+
+ public static String getMimeTypeFromFile(String file) {
+ String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileExt(file));
+ if (mime == null) mime = "*/*";
+ return mime;
+ }
+
+}
diff --git a/src/main/java/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java b/src/main/java/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java
index c06f37ba..adc48253 100644
--- a/src/main/java/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java
+++ b/src/main/java/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationsPlugin.java
@@ -230,16 +230,21 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
if(notification != null) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- Bundle extras = notification.extras;
- String extraTitle = extras.getString(TITLE_KEY);
- String extraText = extras.getString(TEXT_KEY);
+ try {
+ Bundle extras = notification.extras;
+ String extraTitle = extras.getString(TITLE_KEY);
+ String extraText = extras.getString(TEXT_KEY);
- if(extraTitle != null && extraText != null) {
- ticker = extraTitle + " ‐ " + extraText;
- } else if(extraTitle != null) {
- ticker = extraTitle;
- } else if(extraText != null) {
- ticker = extraText;
+ if (extraTitle != null && extraText != null) {
+ 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");
+ e.printStackTrace();
}
}
diff --git a/src/main/java/org/kde/kdeconnect/Plugins/PluginFactory.java b/src/main/java/org/kde/kdeconnect/Plugins/PluginFactory.java
index e1b5f81a..5b7f1096 100644
--- a/src/main/java/org/kde/kdeconnect/Plugins/PluginFactory.java
+++ b/src/main/java/org/kde/kdeconnect/Plugins/PluginFactory.java
@@ -14,6 +14,7 @@ import org.kde.kdeconnect.Plugins.ClibpoardPlugin.ClipboardPlugin;
import org.kde.kdeconnect.Plugins.MprisPlugin.MprisPlugin;
import org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationsPlugin;
import org.kde.kdeconnect.Plugins.PingPlugin.PingPlugin;
+import org.kde.kdeconnect.Plugins.SharePlugin.SharePlugin;
import org.kde.kdeconnect.Plugins.TelephonyPlugin.TelephonyPlugin;
import java.util.Map;
@@ -73,6 +74,7 @@ public class PluginFactory {
PluginFactory.registerPlugin(SftpPlugin.class);
PluginFactory.registerPlugin(NotificationsPlugin.class);
PluginFactory.registerPlugin(MousePadPlugin.class);
+ PluginFactory.registerPlugin(SharePlugin.class);
}
public static PluginInfo getPluginInfo(Context context, String pluginName) {
diff --git a/src/main/java/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java b/src/main/java/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java
new file mode 100644
index 00000000..9b7b9171
--- /dev/null
+++ b/src/main/java/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java
@@ -0,0 +1,239 @@
+package org.kde.kdeconnect.Plugins.SharePlugin;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Environment;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.TaskStackBuilder;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.Toast;
+
+import org.kde.kdeconnect.Helpers.FilesHelper;
+import org.kde.kdeconnect.NetworkPackage;
+import org.kde.kdeconnect.Plugins.Plugin;
+import org.kde.kdeconnect_tp.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+public class SharePlugin extends Plugin {
+
+ /*static {
+ PluginFactory.registerPlugin(PingPlugin.class);
+ }*/
+
+ @Override
+ public String getPluginName() {
+ return "share_ping";
+ }
+
+ @Override
+ public String getDisplayName() {
+ return context.getResources().getString(R.string.pref_plugin_sharereceiver);
+ }
+
+ @Override
+ public String getDescription() {
+ return context.getResources().getString(R.string.pref_plugin_sharereceiver_desc);
+ }
+
+ @Override
+ public Drawable getIcon() {
+ return context.getResources().getDrawable(R.drawable.icon);
+ }
+
+ @Override
+ public boolean isEnabledByDefault() {
+ return true;
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public void onDestroy() {
+
+ }
+
+ @Override
+ public boolean onPackageReceived(NetworkPackage np) {
+
+ if (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_SHARE)) {
+ return false;
+ }
+
+ try {
+ if (np.hasPayload()) {
+
+ Log.e("SharePlugin", "hasPayload");
+
+ final InputStream input = np.getPayload();
+ final int fileLength = np.getPayloadSize();
+ final String filename = np.getString("filename", new Long(System.currentTimeMillis()).toString());
+
+ //Get the external storage and append "/kdeconnect/DEVICE_NAME/"
+ String destinationDir = Environment.getExternalStorageDirectory().getPath();
+ destinationDir = new File(destinationDir, "kdeconnect").getPath();
+ destinationDir = new File(destinationDir, device.getName()).getPath();
+
+ //Create directories if needed
+ new File(destinationDir).mkdirs();
+
+ //Append filename to the destination path
+ final File destinationFullPath = new File(destinationDir, filename);
+
+ Log.e("SharePlugin", "destinationFullPath:" + destinationFullPath);
+
+ final int notificationId = (int)System.currentTimeMillis();
+ Resources res = context.getResources();
+ Notification noti = 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.ic_dialog_alert)
+ .setAutoCancel(true)
+ .build();
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify(notificationId, noti);
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ OutputStream output = new FileOutputStream(destinationFullPath.getPath());
+
+ byte data[] = new byte[1024];
+ long total = 0;
+ int count;
+ while ((count = input.read(data)) >= 0) {
+ total += count;
+ output.write(data, 0, count);
+ if (fileLength > 0) {
+ if (total >= fileLength) break;
+ float progress = (total * 100 / fileLength);
+ }
+ //else Log.e("SharePlugin", "Infinite loop? :D");
+ }
+
+ output.flush();
+ output.close();
+ input.close();
+
+ Log.e("SharePlugin", "Transfer finished");
+
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(Uri.fromFile(destinationFullPath), FilesHelper.getMimeTypeFromFile(destinationFullPath.getPath()));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ //Do not launch it directly, show a notification instead
+ //context.startActivity(browserIntent);
+
+ TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
+ stackBuilder.addNextIntent(intent);
+ PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
+ 0,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ );
+
+ Resources res = context.getResources();
+ Notification noti = new NotificationCompat.Builder(context)
+ .setContentTitle(res.getString(R.string.received_file_title, device.getName()))
+ .setContentText(res.getString(R.string.received_file_text, filename))
+ .setContentIntent(resultPendingIntent)
+ .setTicker(res.getString(R.string.received_file_title, device.getName()))
+ .setSmallIcon(android.R.drawable.ic_dialog_alert)
+ .setAutoCancel(true)
+ .setDefaults(Notification.DEFAULT_SOUND)
+ .build();
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify(notificationId, noti);
+ } catch (Exception e) {
+ Log.e("SharePlugin", "Receiver thread exception");
+ e.printStackTrace();
+
+ }
+ }
+ }).start();
+
+ } else if (np.has("text")) {
+ Log.e("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();
+ } else if (np.has("url")) {
+
+ String url = np.getString("url");
+
+ Log.e("SharePlugin", "hasUrl: "+url);
+
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ //Do not launch it directly, show a notification instead
+ //context.startActivity(browserIntent);
+
+ 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(android.R.drawable.ic_dialog_alert)
+ .setAutoCancel(true)
+ .setDefaults(Notification.DEFAULT_SOUND)
+ .build();
+
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify((int)System.currentTimeMillis(), noti);
+
+ } else {
+ Log.e("SharePlugin", "Error: Nothing attached!");
+ }
+
+
+ } catch(Exception e) {
+ Log.e("SharePlugin","Exception");
+ e.printStackTrace();
+ }
+
+ return true;
+ }
+
+ @Override
+ public AlertDialog getErrorDialog(Context baseContext) {
+ return null;
+ }
+
+ @Override
+ public Button getInterfaceButton(Activity activity) { return null; }
+
+}
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 716782bd..38c7cf51 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -17,6 +17,8 @@
Send and receive pings
Notification sync
Access your notifications from other devices
+ Share receiver
+ Save incoming files to the phone storage
This feature is not available in your Android version
No devices
OK
@@ -45,6 +47,12 @@
Invalid key received
Pair requested
Pairing request from %1s
+ Received link from %1s
+ Tap to open \'%1s\'
+ Incoming file from %1s
+ %1s
+ Received file from %1s
+ Tap to open \'%1s\'
Tap to answer
Reconnect
Device not paired
@@ -68,5 +76,6 @@
Device name
%s
Invalid device name
+ Received text, saved to clipboard