From 0730c52741701802a9a28c8052ef443be441d2af Mon Sep 17 00:00:00 2001 From: Albert Vaca Date: Fri, 27 Jun 2014 14:44:40 +0200 Subject: [PATCH] Started implementing receiving shared files --- .../kde/kdeconnect/Helpers/FilesHelper.java | 18 ++ .../NotificationsPlugin.java | 23 +- .../kde/kdeconnect/Plugins/PluginFactory.java | 2 + .../Plugins/SharePlugin/SharePlugin.java | 239 ++++++++++++++++++ src/main/res/values/strings.xml | 9 + 5 files changed, 282 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/kde/kdeconnect/Helpers/FilesHelper.java create mode 100644 src/main/java/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java 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