mirror of
https://invent.kde.org/network/kdeconnect-android.git
synced 2025-12-12 20:35:58 +01:00
Add option to cache URLs shared to unreachable devices
This commit is contained in:
committed by
Albert Vaca Cintora
parent
fb327ae35e
commit
80106ccb81
@@ -261,7 +261,9 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
|
||||
<string name="mpris_notification_settings_title">Show media control notification</string>
|
||||
<string name="mpris_notification_settings_summary">Allow controlling your media players without opening KDE Connect</string>
|
||||
<string name="mpris_notification_key" translatable="false">mpris_notification_enabled</string>
|
||||
<string name="share_to">Share To…</string>
|
||||
<string name="share_to">Share to…</string>
|
||||
<string name="unreachable_device">%s (Unreachable)</string>
|
||||
<string name="unreachable_device_url_share_text">URLs shared to an unreachable device will be delivered to it once it becomes reachable.\n\n</string>
|
||||
<string name="protocol_version_newer">This device uses a newer protocol version</string>
|
||||
<string name="plugin_settings_with_name">%s settings</string>
|
||||
<string name="invalid_device_name">Invalid device name</string>
|
||||
|
||||
@@ -241,6 +241,8 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
cb.unpaired();
|
||||
}
|
||||
|
||||
notifyPluginsOfDeviceUnpaired(context, deviceInfo.id);
|
||||
|
||||
reloadPluginsFromSettings();
|
||||
}
|
||||
};
|
||||
@@ -641,6 +643,25 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
return settings.getBoolean(pluginKey, enabledByDefault);
|
||||
}
|
||||
|
||||
public void notifyPluginsOfDeviceUnpaired(Context context, String deviceId) {
|
||||
for (String pluginKey : supportedPlugins) {
|
||||
Plugin plugin = getPlugin(pluginKey);
|
||||
if (plugin != null) {
|
||||
plugin.onDeviceUnpaired(context, deviceId);
|
||||
} else {
|
||||
// This is a hacky way to temporarily create plugins just so that they can be notified of the
|
||||
// device being unpaired. This else part will only come into picture when 1) the user tries to
|
||||
// unpair a device while that device is not reachable or 2) the plugin was never initialized
|
||||
// for this device, e.g., the plugins that need additional permissions from the user, and those
|
||||
// permissions were never granted.
|
||||
plugin = PluginFactory.instantiatePluginForDevice(context, pluginKey, this);
|
||||
if (plugin != null) {
|
||||
plugin.onDeviceUnpaired(context, deviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadPluginsFromSettings() {
|
||||
Log.i("Device", deviceInfo.name +": reloading plugins");
|
||||
MultiValuedMap<String, String> newPluginsByIncomingInterface = new ArrayListValuedHashMap<>();
|
||||
|
||||
@@ -272,6 +272,8 @@ abstract class Plugin {
|
||||
return arePermissionsGranted(optionalPermissions)
|
||||
}
|
||||
|
||||
open fun onDeviceUnpaired(context: Context, deviceId: String) {}
|
||||
|
||||
open val minSdk: Int = Build.VERSION_CODES.BASE
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.webkit.URLUtil;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.Device;
|
||||
@@ -26,11 +29,14 @@ import org.kde.kdeconnect_tp.databinding.ActivityShareBinding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ShareActivity extends AppCompatActivity {
|
||||
private static final String KEY_UNREACHABLE_URL_LIST = "key_unreachable_url_list";
|
||||
private ActivityShareBinding binding;
|
||||
private SharedPreferences mSharedPrefs;
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
@@ -71,13 +77,24 @@ public class ShareActivity extends AppCompatActivity {
|
||||
final ArrayList<Device> devicesList = new ArrayList<>();
|
||||
final ArrayList<ListAdapter.Item> items = new ArrayList<>();
|
||||
|
||||
SectionItem section = new SectionItem(getString(R.string.share_to));
|
||||
boolean intentHasUrl = doesIntentContainUrl(intent);
|
||||
|
||||
String sectionString = getString(R.string.share_to);
|
||||
if (intentHasUrl) {
|
||||
sectionString = getString(R.string.unreachable_device_url_share_text) + getString(R.string.share_to);
|
||||
}
|
||||
SectionItem section = new SectionItem(sectionString);
|
||||
items.add(section);
|
||||
|
||||
for (Device d : devices) {
|
||||
if (d.isReachable() && d.isPaired()) {
|
||||
// Show the paired devices only if they are unreachable and the shared intent has a URL
|
||||
if (d.isPaired() && (intentHasUrl || d.isReachable())) {
|
||||
devicesList.add(d);
|
||||
items.add(new EntryItemWithIcon(d.getName(), d.getIcon()));
|
||||
String deviceName = d.getName();
|
||||
if (!d.isReachable()) {
|
||||
deviceName = getString(R.string.unreachable_device, deviceName);
|
||||
}
|
||||
items.add(new EntryItemWithIcon(deviceName, d.getIcon()));
|
||||
section.isEmpty = false;
|
||||
}
|
||||
}
|
||||
@@ -86,13 +103,38 @@ public class ShareActivity extends AppCompatActivity {
|
||||
binding.devicesListLayout.devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
|
||||
Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
|
||||
SharePlugin plugin = KdeConnect.getInstance().getDevicePlugin(device.getDeviceId(), SharePlugin.class);
|
||||
if (plugin != null) {
|
||||
if (intentHasUrl && !device.isReachable()) {
|
||||
// Store the URL to be delivered once device becomes online
|
||||
storeUrlForFutureDelivery(device, intent.toUri(0));
|
||||
} else if (plugin != null) {
|
||||
plugin.share(intent);
|
||||
}
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
private boolean doesIntentContainUrl(Intent intent) {
|
||||
if (intent != null) {
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras != null) {
|
||||
String url = extras.getString(Intent.EXTRA_TEXT);
|
||||
return URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void storeUrlForFutureDelivery(Device device, String url) {
|
||||
Set<String> oldUrlSet = mSharedPrefs.getStringSet(KEY_UNREACHABLE_URL_LIST + device.getDeviceId(), null);
|
||||
// According to the API docs, we should not directly modify the set returned above
|
||||
Set<String> newUrlSet = new HashSet<>();
|
||||
newUrlSet.add(url);
|
||||
if (oldUrlSet != null) {
|
||||
newUrlSet.addAll(oldUrlSet);
|
||||
}
|
||||
mSharedPrefs.edit().putStringSet(KEY_UNREACHABLE_URL_LIST + device.getDeviceId(), newUrlSet).apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -100,6 +142,8 @@ public class ShareActivity extends AppCompatActivity {
|
||||
binding = ActivityShareBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences (this);
|
||||
|
||||
setSupportActionBar(binding.toolbarLayout.toolbar);
|
||||
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
|
||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.Manifest;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -23,6 +24,7 @@ import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -37,10 +39,11 @@ import org.kde.kdeconnect.async.BackgroundJobHandler;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A Plugin for sharing and receiving files and uris.
|
||||
@@ -68,12 +71,43 @@ public class SharePlugin extends Plugin {
|
||||
private CompositeUploadFileJob uploadFileJob;
|
||||
private final Callback receiveFileJobCallback;
|
||||
|
||||
public static final String KEY_UNREACHABLE_URL_LIST = "key_unreachable_url_list";
|
||||
private SharedPreferences mSharedPrefs;
|
||||
|
||||
public SharePlugin() {
|
||||
backgroundJobHandler = BackgroundJobHandler.newFixedThreadPoolBackgroundJobHander(5);
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
receiveFileJobCallback = new Callback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
super.onCreate();
|
||||
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
// Deliver URLs previously shared to this device now that it's connected
|
||||
deliverPreviouslySentIntents();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void deliverPreviouslySentIntents() {
|
||||
Set<String> currentUrlSet = mSharedPrefs.getStringSet(KEY_UNREACHABLE_URL_LIST + device.getDeviceId(), null);
|
||||
if (currentUrlSet != null) {
|
||||
for (String url : currentUrlSet) {
|
||||
Intent intent;
|
||||
try {
|
||||
intent = Intent.parseUri(url, 0);
|
||||
} catch (URISyntaxException ex) {
|
||||
Log.e("SharePlugin", "Malformed URI");
|
||||
continue;
|
||||
}
|
||||
if (intent != null) {
|
||||
share(intent);
|
||||
}
|
||||
}
|
||||
mSharedPrefs.edit().putStringSet(KEY_UNREACHABLE_URL_LIST + device.getDeviceId(), null).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getOptionalPermissionExplanation() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
@@ -339,4 +373,13 @@ public class SharePlugin extends Plugin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceUnpaired(Context context, String deviceId) {
|
||||
Log.i("KDE/SharePlugin", "onDeviceUnpaired deviceId = " + deviceId);
|
||||
if (mSharedPrefs == null) {
|
||||
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
}
|
||||
mSharedPrefs.edit().remove(KEY_UNREACHABLE_URL_LIST + deviceId).apply();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user