diff --git a/.arcconfig b/.arcconfig new file mode 100644 --- /dev/null +++ b/.arcconfig @@ -0,0 +1,3 @@ +{ + "phabricator.uri" : "https://phabricator.kde.org/project/profile/159/" +} diff --git a/AndroidManifest.xml b/AndroidManifest.xml --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -35,8 +35,8 @@ @@ -140,9 +140,9 @@ @@ -194,14 +194,24 @@ + + + + + + discoveryModeAcquisitions = new HashSet<>(); + public static BackgroundService getInstance(){ + return instance; + } + public boolean acquireDiscoveryMode(Object key) { boolean wasEmpty = discoveryModeAcquisitions.isEmpty(); discoveryModeAcquisitions.add(key); @@ -250,6 +256,8 @@ public void onCreate() { super.onCreate(); + instance = this; + // Register screen on listener IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); registerReceiver(new KdeConnectBroadcastReceiver(), filter); diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java --- a/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java +++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java @@ -33,6 +33,8 @@ 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; @@ -130,57 +132,7 @@ 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 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(); } }); @@ -215,22 +167,44 @@ @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() { diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareChooserTargetService.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareChooserTargetService.java new file mode 100644 --- /dev/null +++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareChooserTargetService.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Nicolas Fella + * + * 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.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 onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) { + Log.d("DirectShare", "invoked"); + final List 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; + } +} \ No newline at end of file diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java --- a/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java +++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java @@ -35,6 +35,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.provider.MediaStore; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; @@ -56,6 +57,7 @@ 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 { @@ -399,6 +401,59 @@ } } + public static void share(Intent intent, Device device){ + Bundle extras = intent.getExtras(); + if (extras != null) { + if (extras.containsKey(Intent.EXTRA_STREAM)) { + + try { + + ArrayList 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() {