From 79f55d7ac20a36d488420643b754276307901947 Mon Sep 17 00:00:00 2001 From: Albert Vaca Date: Mon, 7 Sep 2015 00:09:28 -0700 Subject: [PATCH] Share Plugin now adds a "send file" item in the device plugins list. --- AndroidManifest.xml | 9 +- .../Plugins/SharePlugin/SendFileActivity.java | 115 ++++++++++ .../Plugins/SharePlugin/ShareActivity.java | 191 +---------------- .../Plugins/SharePlugin/SharePlugin.java | 202 +++++++++++++++++- 4 files changed, 325 insertions(+), 192 deletions(-) create mode 100644 src/org/kde/kdeconnect/Plugins/SharePlugin/SendFileActivity.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 26f0c57c..b3eac07d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -108,6 +108,14 @@ android:name="android.support.PARENT_ACTIVITY" android:value="org.kde.kdeconnect.UserInterface.DeviceActivity" /> + + + - diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/SendFileActivity.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/SendFileActivity.java new file mode 100644 index 00000000..1c0842cd --- /dev/null +++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/SendFileActivity.java @@ -0,0 +1,115 @@ +/* + * Copyright 2014 Albert Vaca Cintora + * + * 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 . +*/ + +package org.kde.kdeconnect.Plugins.SharePlugin; + +import android.app.Activity; +import android.app.Notification; +import android.app.NotificationManager; +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.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.preference.PreferenceManager; +import android.provider.MediaStore; +import android.support.v4.app.NotificationCompat; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +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; +import org.kde.kdeconnect.NetworkPackage; +import org.kde.kdeconnect.UserInterface.List.EntryItem; +import org.kde.kdeconnect.UserInterface.List.ListAdapter; +import org.kde.kdeconnect.UserInterface.List.SectionItem; +import org.kde.kdeconnect_tp.R; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; + + +public class SendFileActivity extends ActionBarActivity { + + String mDeviceId; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mDeviceId = getIntent().getStringExtra("deviceId"); + + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + try { + startActivityForResult( + Intent.createChooser(intent, getString(R.string.send_files)), Activity.RESULT_FIRST_USER); + } catch (android.content.ActivityNotFoundException ex) { + Toast.makeText(this, R.string.no_file_browser, Toast.LENGTH_SHORT).show(); + finish(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case Activity.RESULT_FIRST_USER: + if (resultCode == RESULT_OK) { + final Uri uri = data.getData(); + Log.e("SendFileActivity", "File Uri: " + uri.toString()); + BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { + @Override + public void onServiceStart(BackgroundService service) { + Device device = service.getDevice(mDeviceId); + if (device == null) { + finish(); + } + ArrayList uris = new ArrayList<>(); + uris.add(uri); + SharePlugin.queuedSendUriList(getApplicationContext(), device, uris); + + } + }); + } + finish(); + break; + default: + super.onActivityResult(requestCode, resultCode, data); + } + } + +} diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java index a9a18047..040d3965 100644 --- a/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java +++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java @@ -158,7 +158,7 @@ public class ShareActivity extends ActionBarActivity { uriList.add(uri); } - queuedSendUriList(device, uriList); + SharePlugin.queuedSendUriList(getApplicationContext(), device, uriList); } catch (Exception e) { Log.e("ShareActivity", "Exception"); @@ -204,195 +204,6 @@ public class ShareActivity extends ActionBarActivity { }); } - private void queuedSendUriList(final Device device, final ArrayList uriList) { - try { - Uri uri = uriList.remove(0); - ContentResolver cr = getContentResolver(); - InputStream inputStream = cr.openInputStream(uri); - - NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_SHARE); - long size = -1; - - final NotificationManager notificationManager = (NotificationManager)getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); - final int notificationId = (int)System.currentTimeMillis(); - final NotificationCompat.Builder builder ; - Resources res = getApplicationContext().getResources(); - builder = new NotificationCompat.Builder(getApplicationContext()) - .setContentTitle(res.getString(R.string.outgoing_file_title, device.getName())) - .setTicker(res.getString(R.string.outgoing_file_title, device.getName())) - .setSmallIcon(android.R.drawable.stat_sys_upload) - .setAutoCancel(true) - .setOngoing(true) - .setProgress(100,0,true); - - try { - notificationManager.notify(notificationId,builder.build()); - } catch(Exception e) { - //4.1 will throw an exception about not having the VIBRATE permission, ignore it. - //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ - } - - final Handler progressBarHandler = new Handler(Looper.getMainLooper()); - - if (uri.getScheme().equals("file")) { - // file:// is a non media uri, so we cannot query the ContentProvider - - np.set("filename", uri.getLastPathSegment()); - - try { - size = new File(uri.getPath()).length(); - } catch(Exception e) { - Log.e("ShareActivity", "Could not obtain file size"); - e.printStackTrace(); - } - - np.setPayload(inputStream, size); - - }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 }; - cursor = getContentResolver().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) { - - Log.e("ShareActivity", "Could not resolve media to a file, trying to get info as media"); - - try { - int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME); - cursor.moveToFirst(); - String name = cursor.getString(column_index); - np.set("filename", name); - } catch (Exception e) { - e.printStackTrace(); - Log.e("ShareActivity", "Could not obtain file name"); - } - - try { - int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.SIZE); - cursor.moveToFirst(); - //For some reason this size can differ from the actual file size! - size = cursor.getInt(column_index); - } catch(Exception e) { - Log.e("ShareActivity", "Could not obtain file size"); - e.printStackTrace(); - } - } finally { - cursor.close(); - } - - np.setPayload(inputStream, size); - - } - - final String filename = np.getString("filename"); - - builder.setContentText(res.getString(R.string.outgoing_file_text,filename)); - try { - notificationManager.notify(notificationId,builder.build()); - } catch(Exception e) { - //4.1 will throw an exception about not having the VIBRATE permission, ignore it. - //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ - } - - device.sendPackage(np, new Device.SendPackageStatusCallback() { - - int prevProgress = 0; - - @Override - public void onProgressChanged(final int progress) { - if (progress != prevProgress) { - prevProgress = progress; - progressBarHandler.post(new Runnable() { - @Override - public void run() { - builder.setProgress(100, progress, false); - try { - notificationManager.notify(notificationId,builder.build()); - } catch(Exception e) { - //4.1 will throw an exception about not having the VIBRATE permission, ignore it. - //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ - } - } - }); - } - } - - @Override - public void onSuccess() { - progressBarHandler.post(new Runnable() { - @Override - public void run() { - Resources res = getApplicationContext().getResources(); - NotificationCompat.Builder anotherBuilder = new NotificationCompat.Builder(getApplicationContext()) - .setContentTitle(res.getString(R.string.sent_file_title, device.getName())) - .setContentText(res.getString(R.string.sent_file_text, filename)) - .setTicker(res.getString(R.string.sent_file_title, device.getName())) - .setSmallIcon(android.R.drawable.stat_sys_upload_done) - .setOngoing(false) - .setAutoCancel(true); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - if (prefs.getBoolean("share_notification_preference", true)) { - anotherBuilder.setDefaults(Notification.DEFAULT_ALL); - } - try { - notificationManager.notify(notificationId,anotherBuilder.build()); - } catch(Exception e) { - //4.1 will throw an exception about not having the VIBRATE permission, ignore it. - //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ - } - } - }); - - if (!uriList.isEmpty()) queuedSendUriList(device, uriList); - else Log.i("ShareActivity", "All files sent"); - } - - @Override - public void onFailure(Throwable e) { - progressBarHandler.post(new Runnable() { - @Override - public void run() { - Resources res = getApplicationContext().getResources(); - NotificationCompat.Builder anotherBuilder = new NotificationCompat.Builder(getApplicationContext()) - .setContentTitle(res.getString(R.string.sent_file_failed_title, device.getName())) - .setContentText(res.getString(R.string.sent_file_failed_text, filename)) - .setTicker(res.getString(R.string.sent_file_title, device.getName())) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setOngoing(false) - .setAutoCancel(true); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - if (prefs.getBoolean("share_notification_preference", true)) { - anotherBuilder.setDefaults(Notification.DEFAULT_ALL); - } - try { - notificationManager.notify(notificationId,anotherBuilder.build()); - } catch(Exception e) { - //4.1 will throw an exception about not having the VIBRATE permission, ignore it. - //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ - } - } - }); - - Log.e("ShareActivity", "Failed to send file"); - } - }); - - } catch (Exception e) { - Log.e("ShareActivity", "Exception sending files"); - e.printStackTrace(); - } - - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java index 07ae4ee6..8feb334f 100644 --- a/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java +++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java @@ -25,22 +25,29 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; 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.os.Environment; +import android.os.Handler; +import android.os.Looper; import android.preference.PreferenceManager; +import android.provider.MediaStore; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.support.v4.content.ContextCompat; import android.util.Log; import android.widget.Toast; +import org.kde.kdeconnect.Device; import org.kde.kdeconnect.Helpers.FilesHelper; import org.kde.kdeconnect.NetworkPackage; +import org.kde.kdeconnect.Plugins.MprisPlugin.MprisActivity; import org.kde.kdeconnect.Plugins.Plugin; import org.kde.kdeconnect_tp.R; @@ -48,6 +55,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; public class SharePlugin extends Plugin { @@ -78,7 +86,9 @@ public class SharePlugin extends Plugin { @Override public void startMainActivity(Activity parentActivity) { - //TODO + Intent intent = new Intent(parentActivity, SendFileActivity.class); + intent.putExtra("deviceId", device.getDeviceId()); + parentActivity.startActivity(intent); } @Override @@ -292,4 +302,194 @@ public class SharePlugin extends Plugin { return true; } + + static void queuedSendUriList(final Context context, final Device device, final ArrayList uriList) { + try { + Uri uri = uriList.remove(0); + ContentResolver cr = context.getContentResolver(); + InputStream inputStream = cr.openInputStream(uri); + + NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_SHARE); + long size = -1; + + final NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); + final int notificationId = (int)System.currentTimeMillis(); + final NotificationCompat.Builder builder ; + Resources res = context.getResources(); + builder = new NotificationCompat.Builder(context) + .setContentTitle(res.getString(R.string.outgoing_file_title, device.getName())) + .setTicker(res.getString(R.string.outgoing_file_title, device.getName())) + .setSmallIcon(android.R.drawable.stat_sys_upload) + .setAutoCancel(true) + .setOngoing(true) + .setProgress(100,0,true); + + try { + notificationManager.notify(notificationId,builder.build()); + } catch(Exception e) { + //4.1 will throw an exception about not having the VIBRATE permission, ignore it. + //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ + } + + final Handler progressBarHandler = new Handler(Looper.getMainLooper()); + + if (uri.getScheme().equals("file")) { + // file:// is a non media uri, so we cannot query the ContentProvider + + np.set("filename", uri.getLastPathSegment()); + + try { + size = new File(uri.getPath()).length(); + } catch(Exception e) { + Log.e("SendFileActivity", "Could not obtain file size"); + e.printStackTrace(); + } + + np.setPayload(inputStream, size); + + }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 }; + 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) { + + Log.e("SendFileActivity", "Could not resolve media to a file, trying to get info as media"); + + try { + int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME); + cursor.moveToFirst(); + String name = cursor.getString(column_index); + np.set("filename", name); + } catch (Exception e) { + e.printStackTrace(); + Log.e("SendFileActivity", "Could not obtain file name"); + } + + try { + int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.SIZE); + cursor.moveToFirst(); + //For some reason this size can differ from the actual file size! + size = cursor.getInt(column_index); + } catch(Exception e) { + Log.e("SendFileActivity", "Could not obtain file size"); + e.printStackTrace(); + } + } finally { + cursor.close(); + } + + np.setPayload(inputStream, size); + + } + + final String filename = np.getString("filename"); + + builder.setContentText(res.getString(R.string.outgoing_file_text,filename)); + try { + notificationManager.notify(notificationId,builder.build()); + } catch(Exception e) { + //4.1 will throw an exception about not having the VIBRATE permission, ignore it. + //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ + } + + device.sendPackage(np, new Device.SendPackageStatusCallback() { + + int prevProgress = 0; + + @Override + public void onProgressChanged(final int progress) { + if (progress != prevProgress) { + prevProgress = progress; + progressBarHandler.post(new Runnable() { + @Override + public void run() { + builder.setProgress(100, progress, false); + try { + notificationManager.notify(notificationId,builder.build()); + } catch(Exception e) { + //4.1 will throw an exception about not having the VIBRATE permission, ignore it. + //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ + } + } + }); + } + } + + @Override + public void onSuccess() { + progressBarHandler.post(new Runnable() { + @Override + public void run() { + Resources res = context.getResources(); + NotificationCompat.Builder anotherBuilder = new NotificationCompat.Builder(context) + .setContentTitle(res.getString(R.string.sent_file_title, device.getName())) + .setContentText(res.getString(R.string.sent_file_text, filename)) + .setTicker(res.getString(R.string.sent_file_title, device.getName())) + .setSmallIcon(android.R.drawable.stat_sys_upload_done) + .setOngoing(false) + .setAutoCancel(true); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (prefs.getBoolean("share_notification_preference", true)) { + anotherBuilder.setDefaults(Notification.DEFAULT_ALL); + } + try { + notificationManager.notify(notificationId,anotherBuilder.build()); + } catch(Exception e) { + //4.1 will throw an exception about not having the VIBRATE permission, ignore it. + //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ + } + } + }); + + if (!uriList.isEmpty()) queuedSendUriList(context, device, uriList); + else Log.i("SendFileActivity", "All files sent"); + } + + @Override + public void onFailure(Throwable e) { + progressBarHandler.post(new Runnable() { + @Override + public void run() { + Resources res = context.getResources(); + NotificationCompat.Builder anotherBuilder = new NotificationCompat.Builder(context) + .setContentTitle(res.getString(R.string.sent_file_failed_title, device.getName())) + .setContentText(res.getString(R.string.sent_file_failed_text, filename)) + .setTicker(res.getString(R.string.sent_file_title, device.getName())) + .setSmallIcon(android.R.drawable.stat_notify_error) + .setOngoing(false) + .setAutoCancel(true); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (prefs.getBoolean("share_notification_preference", true)) { + anotherBuilder.setDefaults(Notification.DEFAULT_ALL); + } + try { + notificationManager.notify(notificationId,anotherBuilder.build()); + } catch(Exception e) { + //4.1 will throw an exception about not having the VIBRATE permission, ignore it. + //https://android.googlesource.com/platform/frameworks/base/+/android-4.2.1_r1.2%5E%5E!/ + } + } + }); + + Log.e("SendFileActivity", "Failed to send file"); + } + }); + + } catch (Exception e) { + Log.e("SendFileActivity", "Exception sending files"); + e.printStackTrace(); + } + + } + }