mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 18:07:55 +00:00
Migrate from PreferenceActivity to PreferenceFragment because it has been deprecated since Android 3.0 API11
Summary: PreferenceActivity has been deprecated since Android 3.0 API 11 in favour of PreferenceFragment | {F6515113} | {F6515114}| |Before| | {F6515111} | {F6515112}| |After| Test Plan: Apply patch and observe that the DeviceSettings and PluginSettings screen behave as expected and now also follow material design guidelines Reviewers: #kde_connect, nicolasfella Reviewed By: #kde_connect, nicolasfella Subscribers: kdeconnect Tags: #kde_connect Differential Revision: https://phabricator.kde.org/D17859
This commit is contained in:
parent
045e329b53
commit
9fb780f919
@ -87,22 +87,6 @@
|
|||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value="org.kde.kdeconnect.UserInterface.MainActivity" />
|
android:value="org.kde.kdeconnect.UserInterface.MainActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
|
||||||
android:name="org.kde.kdeconnect.UserInterface.PluginSettingsActivity"
|
|
||||||
android:label="@string/device_menu_plugins"
|
|
||||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity">
|
|
||||||
<meta-data
|
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
|
||||||
android:value="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity" />
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:name="org.kde.kdeconnect.Plugins.SharePlugin.ShareSettingsActivity"
|
|
||||||
android:label="@string/device_menu_plugins"
|
|
||||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity">
|
|
||||||
<meta-data
|
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
|
||||||
android:value="org.kde.kdeconnect.Plugins.SharePlugin.ShareSettingsActivity" />
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<receiver android:name="org.kde.kdeconnect.KdeConnectBroadcastReceiver">
|
<receiver android:name="org.kde.kdeconnect.KdeConnectBroadcastReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -268,10 +252,10 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity"
|
android:name="org.kde.kdeconnect.Plugins.NotificationsPlugin.NotificationFilterActivity"
|
||||||
android:label="@string/title_activity_notification_filter"
|
android:label="@string/title_activity_notification_filter"
|
||||||
android:parentActivityName="org.kde.kdeconnect.UserInterface.PluginSettingsActivity">
|
android:parentActivityName="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value="org.kde.kdeconnect.UserInterface.PluginSettingsActivity" />
|
android:value="org.kde.kdeconnect.UserInterface.DeviceSettingsActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
7
res/layout/activity_device_settings.xml
Normal file
7
res/layout/activity_device_settings.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/fragmentPlaceHolder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
@ -34,17 +34,20 @@
|
|||||||
android:id="@android:id/widget_frame"
|
android:id="@android:id/widget_frame"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center_vertical"
|
android:gravity="left|center_vertical|start"
|
||||||
android:orientation="vertical" />
|
android:minWidth="56dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="6dip"
|
android:layout_marginBottom="6dip"
|
||||||
android:layout_marginEnd="4dip"
|
android:layout_marginEnd="4dip"
|
||||||
android:layout_marginLeft="12dip"
|
android:layout_marginLeft="4dip"
|
||||||
android:layout_marginRight="4dip"
|
android:layout_marginRight="4dip"
|
||||||
android:layout_marginStart="12dip"
|
android:layout_marginStart="4dip"
|
||||||
android:layout_marginTop="6dip"
|
android:layout_marginTop="6dip"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
@ -325,4 +325,5 @@
|
|||||||
<string name="block_images">Block images in notifications</string>
|
<string name="block_images">Block images in notifications</string>
|
||||||
<string name="notification_channel_receivenotification">Notifications from other devices</string>
|
<string name="notification_channel_receivenotification">Notifications from other devices</string>
|
||||||
|
|
||||||
|
<string name="findmyphone_preference_key_ringtone" translatable="false">findmyphone_ringtone</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<RingtonePreference
|
<Preference
|
||||||
android:key="select_ringtone"
|
android:key="@string/findmyphone_preference_key_ringtone"
|
||||||
android:showSilent="false"
|
|
||||||
android:title="@string/select_ringtone" />
|
android:title="@string/select_ringtone" />
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -435,5 +435,4 @@ public class BackgroundService extends Service {
|
|||||||
cb.run(plugin);
|
cb.run(plugin);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public class FindMyPhoneActivity extends Activity {
|
|||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
Uri ringtone;
|
Uri ringtone;
|
||||||
String ringtoneString = prefs.getString("select_ringtone", "");
|
String ringtoneString = prefs.getString(getString(R.string.findmyphone_preference_key_ringtone), "");
|
||||||
if (ringtoneString.isEmpty()) {
|
if (ringtoneString.isEmpty()) {
|
||||||
ringtone = Settings.System.DEFAULT_RINGTONE_URI;
|
ringtone = Settings.System.DEFAULT_RINGTONE_URI;
|
||||||
} else {
|
} else {
|
||||||
|
@ -25,6 +25,7 @@ import android.content.Intent;
|
|||||||
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
import org.kde.kdeconnect.Helpers.DeviceHelper;
|
||||||
import org.kde.kdeconnect.NetworkPacket;
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
import org.kde.kdeconnect.Plugins.Plugin;
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
public class FindMyPhonePlugin extends Plugin {
|
public class FindMyPhonePlugin extends Plugin {
|
||||||
@ -75,4 +76,8 @@ public class FindMyPhonePlugin extends Plugin {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginSettingsFragment getSettingsFragment() {
|
||||||
|
return FindMyPhoneSettingsFragment.newInstance(getPluginKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Erik Duisters <e.duisters1@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kde.kdeconnect.Plugins.FindMyPhonePlugin;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
public class FindMyPhoneSettingsFragment extends PluginSettingsFragment {
|
||||||
|
private static final int REQUEST_CODE_SELECT_RINGTONE = 1000;
|
||||||
|
|
||||||
|
private String preferenceKeyRingtone;
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
private Preference ringtonePreference;
|
||||||
|
|
||||||
|
public static FindMyPhoneSettingsFragment newInstance(@NonNull String pluginKey) {
|
||||||
|
FindMyPhoneSettingsFragment fragment = new FindMyPhoneSettingsFragment();
|
||||||
|
fragment.setArguments(pluginKey);
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
super.onCreatePreferences(savedInstanceState, rootKey);
|
||||||
|
|
||||||
|
preferenceKeyRingtone = getString(R.string.findmyphone_preference_key_ringtone);
|
||||||
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||||
|
|
||||||
|
ringtonePreference = getPreferenceScreen().findPreference(preferenceKeyRingtone);
|
||||||
|
|
||||||
|
setRingtoneSummary();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setRingtoneSummary() {
|
||||||
|
String ringtone = sharedPreferences.getString(preferenceKeyRingtone, Settings.System.DEFAULT_RINGTONE_URI.toString());
|
||||||
|
|
||||||
|
Uri ringtoneUri = Uri.parse(ringtone);
|
||||||
|
|
||||||
|
ringtonePreference.setSummary(RingtoneManager.getRingtone(requireContext(), ringtoneUri).getTitle(requireContext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceTreeClick(Preference preference) {
|
||||||
|
/*
|
||||||
|
* There is no RingtonePreference in support library nor androidx, this is the workaround proposed here:
|
||||||
|
* https://issuetracker.google.com/issues/37057453
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (preference.hasKey() && preference.getKey().equals(preferenceKeyRingtone)) {
|
||||||
|
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
|
||||||
|
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
|
||||||
|
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
|
||||||
|
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
|
||||||
|
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, Settings.System.DEFAULT_NOTIFICATION_URI);
|
||||||
|
|
||||||
|
String existingValue = sharedPreferences.getString(preferenceKeyRingtone, null);
|
||||||
|
if (existingValue != null) {
|
||||||
|
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(existingValue));
|
||||||
|
} else {
|
||||||
|
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Settings.System.DEFAULT_RINGTONE_URI);
|
||||||
|
}
|
||||||
|
|
||||||
|
startActivityForResult(intent, REQUEST_CODE_SELECT_RINGTONE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onPreferenceTreeClick(preference);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
if (requestCode == REQUEST_CODE_SELECT_RINGTONE && resultCode == Activity.RESULT_OK) {
|
||||||
|
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
|
||||||
|
|
||||||
|
if (uri != null) {
|
||||||
|
sharedPreferences.edit()
|
||||||
|
.putString(preferenceKeyRingtone, uri.toString())
|
||||||
|
.apply();
|
||||||
|
|
||||||
|
setRingtoneSummary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,6 +48,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
//TODO: Turn this into a PluginSettingsFragment
|
||||||
public class NotificationFilterActivity extends AppCompatActivity {
|
public class NotificationFilterActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private AppDatabase appDatabase;
|
private AppDatabase appDatabase;
|
||||||
|
@ -44,8 +44,8 @@ import android.util.Log;
|
|||||||
import org.kde.kdeconnect.Helpers.AppsHelper;
|
import org.kde.kdeconnect.Helpers.AppsHelper;
|
||||||
import org.kde.kdeconnect.NetworkPacket;
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
import org.kde.kdeconnect.Plugins.Plugin;
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
import org.kde.kdeconnect.UserInterface.DeviceSettingsActivity;
|
|
||||||
import org.kde.kdeconnect.UserInterface.MainActivity;
|
import org.kde.kdeconnect.UserInterface.MainActivity;
|
||||||
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -89,13 +89,14 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startPreferencesActivity(final DeviceSettingsActivity parentActivity) {
|
public PluginSettingsFragment getSettingsFragment() {
|
||||||
if (hasPermission()) {
|
if (hasPermission()) {
|
||||||
Intent intent = new Intent(parentActivity, NotificationFilterActivity.class);
|
Context context = device.getContext();
|
||||||
parentActivity.startActivity(intent);
|
Intent intent = new Intent(context, NotificationFilterActivity.class);
|
||||||
} else {
|
context.startActivity(intent);
|
||||||
getErrorDialog(parentActivity).show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasPermission() {
|
private boolean hasPermission() {
|
||||||
@ -488,10 +489,8 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AlertDialog getErrorDialog(final Activity deviceActivity) {
|
public AlertDialog getErrorDialog(final Activity deviceActivity) {
|
||||||
|
|
||||||
return new AlertDialog.Builder(deviceActivity)
|
return new AlertDialog.Builder(deviceActivity)
|
||||||
.setTitle(R.string.pref_plugin_notifications)
|
.setTitle(R.string.pref_plugin_notifications)
|
||||||
.setMessage(R.string.no_permissions)
|
.setMessage(R.string.no_permissions)
|
||||||
@ -503,7 +502,6 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
|
|||||||
//Do nothing
|
//Do nothing
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -23,7 +23,6 @@ package org.kde.kdeconnect.Plugins;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -31,8 +30,7 @@ import android.widget.Button;
|
|||||||
|
|
||||||
import org.kde.kdeconnect.Device;
|
import org.kde.kdeconnect.Device;
|
||||||
import org.kde.kdeconnect.NetworkPacket;
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
import org.kde.kdeconnect.UserInterface.DeviceSettingsActivity;
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
@ -40,7 +38,6 @@ import androidx.core.app.ActivityCompat;
|
|||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
public abstract class Plugin {
|
public abstract class Plugin {
|
||||||
|
|
||||||
protected Device device;
|
protected Device device;
|
||||||
protected Context context;
|
protected Context context;
|
||||||
protected int permissionExplanation = R.string.permission_explanation;
|
protected int permissionExplanation = R.string.permission_explanation;
|
||||||
@ -125,15 +122,13 @@ public abstract class Plugin {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If hasSettings returns true, this will be called when the user
|
* If hasSettings returns true, this will be called when the user
|
||||||
* wants to access this plugin preferences and should launch some
|
* wants to access this plugin's preferences. The default implementation
|
||||||
* kind of interface. The default implementation will launch a
|
* will return a PluginSettingsFragment with content from "yourplugin"_preferences.xml
|
||||||
* PluginSettingsActivity with content from "yourplugin"_preferences.xml.
|
*
|
||||||
|
* @return The PluginSettingsFragment used to display this plugins settings
|
||||||
*/
|
*/
|
||||||
public void startPreferencesActivity(DeviceSettingsActivity parentActivity) {
|
public PluginSettingsFragment getSettingsFragment() {
|
||||||
Intent intent = new Intent(parentActivity, PluginSettingsActivity.class);
|
return PluginSettingsFragment.newInstance(getPluginKey());
|
||||||
intent.putExtra("plugin_display_name", getDisplayName());
|
|
||||||
intent.putExtra("plugin_key", getPluginKey());
|
|
||||||
parentActivity.startActivity(intent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -387,4 +387,8 @@ public class RemoteKeyboardPlugin extends Plugin {
|
|||||||
np.set("state", state);
|
np.set("state", state);
|
||||||
device.sendPacket(np);
|
device.sendPacket(np);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getDeviceId() {
|
||||||
|
return device.getDeviceId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.kde.kdeconnect.UserInterface.DeviceSettingsActivity;
|
||||||
import org.kde.kdeconnect.UserInterface.MainActivity;
|
import org.kde.kdeconnect.UserInterface.MainActivity;
|
||||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -162,10 +162,10 @@ public class RemoteKeyboardService
|
|||||||
if (instances.size() == 1) { // single instance of RemoteKeyboardPlugin -> access its settings
|
if (instances.size() == 1) { // single instance of RemoteKeyboardPlugin -> access its settings
|
||||||
RemoteKeyboardPlugin plugin = instances.get(0);
|
RemoteKeyboardPlugin plugin = instances.get(0);
|
||||||
if (plugin != null) {
|
if (plugin != null) {
|
||||||
Intent intent = new Intent(this, PluginSettingsActivity.class);
|
Intent intent = new Intent(this, DeviceSettingsActivity.class);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
intent.putExtra("plugin_display_name", plugin.getDisplayName());
|
intent.putExtra(DeviceSettingsActivity.EXTRA_DEVICE_ID, plugin.getDeviceId());
|
||||||
intent.putExtra("plugin_key", plugin.getPluginKey());
|
intent.putExtra(DeviceSettingsActivity.EXTRA_PLUGIN_KEY, plugin.getPluginKey());
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
} else { // != 1 instance of plugin -> show main activity view
|
} else { // != 1 instance of plugin -> show main activity view
|
||||||
|
@ -47,7 +47,7 @@ import org.kde.kdeconnect.Helpers.MediaStoreHelper;
|
|||||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||||
import org.kde.kdeconnect.NetworkPacket;
|
import org.kde.kdeconnect.NetworkPacket;
|
||||||
import org.kde.kdeconnect.Plugins.Plugin;
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
import org.kde.kdeconnect.UserInterface.DeviceSettingsActivity;
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@ -227,12 +227,12 @@ public class SharePlugin extends Plugin implements ReceiveFileRunnable.CallBack
|
|||||||
//We need to check for already existing files only when storing in the default path.
|
//We need to check for already existing files only when storing in the default path.
|
||||||
//User-defined paths use the new Storage Access Framework that already handles this.
|
//User-defined paths use the new Storage Access Framework that already handles this.
|
||||||
//If the file should be opened immediately store it in the standard location to avoid the FileProvider trouble (See ShareNotification::setURI)
|
//If the file should be opened immediately store it in the standard location to avoid the FileProvider trouble (See ShareNotification::setURI)
|
||||||
if (np.getBoolean("open") || !ShareSettingsActivity.isCustomDestinationEnabled(context)) {
|
if (np.getBoolean("open") || !ShareSettingsFragment.isCustomDestinationEnabled(context)) {
|
||||||
final String defaultPath = ShareSettingsActivity.getDefaultDestinationDirectory().getAbsolutePath();
|
final String defaultPath = ShareSettingsFragment.getDefaultDestinationDirectory().getAbsolutePath();
|
||||||
filename = FilesHelper.findNonExistingNameForNewFile(defaultPath, filename);
|
filename = FilesHelper.findNonExistingNameForNewFile(defaultPath, filename);
|
||||||
destinationFolderDocument = DocumentFile.fromFile(new File(defaultPath));
|
destinationFolderDocument = DocumentFile.fromFile(new File(defaultPath));
|
||||||
} else {
|
} else {
|
||||||
destinationFolderDocument = ShareSettingsActivity.getDestinationDirectory(context);
|
destinationFolderDocument = ShareSettingsFragment.getDestinationDirectory(context);
|
||||||
}
|
}
|
||||||
String displayName = FilesHelper.getFileNameWithoutExt(filename);
|
String displayName = FilesHelper.getFileNameWithoutExt(filename);
|
||||||
String mimeType = FilesHelper.getMimeTypeFromFile(filename);
|
String mimeType = FilesHelper.getMimeTypeFromFile(filename);
|
||||||
@ -273,11 +273,8 @@ public class SharePlugin extends Plugin implements ReceiveFileRunnable.CallBack
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startPreferencesActivity(DeviceSettingsActivity parentActivity) {
|
public PluginSettingsFragment getSettingsFragment() {
|
||||||
Intent intent = new Intent(parentActivity, ShareSettingsActivity.class);
|
return ShareSettingsFragment.newInstance(getPluginKey());
|
||||||
intent.putExtra("plugin_display_name", getDisplayName());
|
|
||||||
intent.putExtra("plugin_key", getPluginKey());
|
|
||||||
parentActivity.startActivity(intent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void queuedSendUriList(final ArrayList<Uri> uriList) {
|
void queuedSendUriList(final ArrayList<Uri> uriList) {
|
||||||
@ -489,7 +486,7 @@ public class SharePlugin extends Plugin implements ReceiveFileRunnable.CallBack
|
|||||||
|
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
if (!ShareSettingsActivity.isCustomDestinationEnabled(context)) {
|
if (!ShareSettingsFragment.isCustomDestinationEnabled(context)) {
|
||||||
Log.i("SharePlugin", "Adding to downloads");
|
Log.i("SharePlugin", "Adding to downloads");
|
||||||
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
manager.addCompletedDownload(info.fileDocument.getUri().getLastPathSegment(), device.getName(), true, info.fileDocument.getType(), info.fileDocument.getUri().getPath(), info.fileSize, false);
|
manager.addCompletedDownload(info.fileDocument.getUri().getLastPathSegment(), device.getName(), true, info.fileDocument.getType(), info.fileDocument.getUri().getPath(), info.fileSize, false);
|
||||||
|
@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Richard Wagler <riwag@posteo.de>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.kde.kdeconnect.Plugins.SharePlugin;
|
package org.kde.kdeconnect.Plugins.SharePlugin;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
@ -9,18 +29,20 @@ import android.net.Uri;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.preference.CheckBoxPreference;
|
|
||||||
import android.preference.Preference;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
import org.kde.kdeconnect.UserInterface.PluginSettingsFragment;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.documentfile.provider.DocumentFile;
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
|
import androidx.preference.CheckBoxPreference;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
public class ShareSettingsActivity extends PluginSettingsActivity {
|
public class ShareSettingsFragment extends PluginSettingsFragment {
|
||||||
|
|
||||||
private final static String PREFERENCE_CUSTOMIZE_DESTINATION = "share_destination_custom";
|
private final static String PREFERENCE_CUSTOMIZE_DESTINATION = "share_destination_custom";
|
||||||
private final static String PREFERENCE_DESTINATION = "share_destination_folder_uri";
|
private final static String PREFERENCE_DESTINATION = "share_destination_folder_uri";
|
||||||
@ -29,12 +51,20 @@ public class ShareSettingsActivity extends PluginSettingsActivity {
|
|||||||
|
|
||||||
private Preference filePicker;
|
private Preference filePicker;
|
||||||
|
|
||||||
@Override
|
public static ShareSettingsFragment newInstance(@NonNull String pluginKey) {
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
ShareSettingsFragment fragment = new ShareSettingsFragment();
|
||||||
super.onCreate(savedInstanceState);
|
fragment.setArguments(pluginKey);
|
||||||
|
|
||||||
final CheckBoxPreference customDownloads = (CheckBoxPreference) findPreference("share_destination_custom");
|
return fragment;
|
||||||
filePicker = findPreference("share_destination_folder_preference");
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
super.onCreatePreferences(savedInstanceState, rootKey);
|
||||||
|
|
||||||
|
PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||||
|
final CheckBoxPreference customDownloads = (CheckBoxPreference) preferenceScreen.findPreference("share_destination_custom");
|
||||||
|
filePicker = preferenceScreen.findPreference("share_destination_folder_preference");
|
||||||
|
|
||||||
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
|
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
|
||||||
customDownloads.setOnPreferenceChangeListener((preference, newValue) -> {
|
customDownloads.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
@ -51,13 +81,19 @@ public class ShareSettingsActivity extends PluginSettingsActivity {
|
|||||||
filePicker.setEnabled(false);
|
filePicker.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean customized = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(PREFERENCE_CUSTOMIZE_DESTINATION, false);
|
boolean customized = PreferenceManager
|
||||||
|
.getDefaultSharedPreferences(requireContext())
|
||||||
|
.getBoolean(PREFERENCE_CUSTOMIZE_DESTINATION, false);
|
||||||
|
|
||||||
updateFilePickerStatus(customized);
|
updateFilePickerStatus(customized);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFilePickerStatus(boolean enabled) {
|
private void updateFilePickerStatus(boolean enabled) {
|
||||||
filePicker.setEnabled(enabled);
|
filePicker.setEnabled(enabled);
|
||||||
String path = PreferenceManager.getDefaultSharedPreferences(this).getString(PREFERENCE_DESTINATION, null);
|
String path = PreferenceManager
|
||||||
|
.getDefaultSharedPreferences(requireContext())
|
||||||
|
.getString(PREFERENCE_DESTINATION, null);
|
||||||
|
|
||||||
if (enabled && path != null) {
|
if (enabled && path != null) {
|
||||||
filePicker.setSummary(Uri.parse(path).getPath());
|
filePicker.setSummary(Uri.parse(path).getPath());
|
||||||
} else {
|
} else {
|
||||||
@ -99,22 +135,20 @@ public class ShareSettingsActivity extends PluginSettingsActivity {
|
|||||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
|
||||||
|
|
||||||
if (requestCode == RESULT_PICKER
|
if (requestCode == RESULT_PICKER
|
||||||
&& resultCode == Activity.RESULT_OK
|
&& resultCode == Activity.RESULT_OK
|
||||||
&& resultData != null) {
|
&& resultData != null) {
|
||||||
|
|
||||||
Uri uri = resultData.getData();
|
Uri uri = resultData.getData();
|
||||||
|
|
||||||
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION |
|
requireContext().getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION |
|
||||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
|
|
||||||
Preference filePicker = findPreference("share_destination_folder_preference");
|
Preference filePicker = findPreference("share_destination_folder_preference");
|
||||||
filePicker.setSummary(uri.getPath());
|
filePicker.setSummary(uri.getPath());
|
||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||||
prefs.edit().putString(PREFERENCE_DESTINATION, uri.toString()).apply();
|
prefs.edit().putString(PREFERENCE_DESTINATION, uri.toString()).apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -21,54 +21,81 @@
|
|||||||
package org.kde.kdeconnect.UserInterface;
|
package org.kde.kdeconnect.UserInterface;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceScreen;
|
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import org.kde.kdeconnect.BackgroundService;
|
import org.kde.kdeconnect.BackgroundService;
|
||||||
import org.kde.kdeconnect.Device;
|
import org.kde.kdeconnect.Device;
|
||||||
|
import org.kde.kdeconnect.Plugins.Plugin;
|
||||||
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
import java.util.List;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
public class DeviceSettingsActivity extends AppCompatPreferenceActivity {
|
public class DeviceSettingsActivity
|
||||||
|
extends AppCompatActivity
|
||||||
|
implements PluginPreference.PluginPreferenceCallback {
|
||||||
|
|
||||||
|
public static final String EXTRA_DEVICE_ID = "deviceId";
|
||||||
|
public static final String EXTRA_PLUGIN_KEY = "pluginKey";
|
||||||
|
|
||||||
|
//TODO: Save/restore state
|
||||||
static private String deviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
|
static private String deviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
ThemeUtil.setUserPreferredTheme(this);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
final PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(this);
|
setContentView(R.layout.activity_device_settings);
|
||||||
setPreferenceScreen(preferenceScreen);
|
|
||||||
|
|
||||||
if (getIntent().hasExtra("deviceId")) {
|
if (getSupportActionBar() != null) {
|
||||||
deviceId = getIntent().getStringExtra("deviceId");
|
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BackgroundService.RunCommand(getApplicationContext(), service -> {
|
String pluginKey = null;
|
||||||
final Device device = service.getDevice(deviceId);
|
|
||||||
if (device == null) {
|
if (getIntent().hasExtra(EXTRA_DEVICE_ID)) {
|
||||||
DeviceSettingsActivity.this.runOnUiThread(DeviceSettingsActivity.this::finish);
|
deviceId = getIntent().getStringExtra(EXTRA_DEVICE_ID);
|
||||||
return;
|
|
||||||
|
if (getIntent().hasExtra(EXTRA_PLUGIN_KEY)) {
|
||||||
|
pluginKey = getIntent().getStringExtra(EXTRA_PLUGIN_KEY);
|
||||||
}
|
}
|
||||||
List<String> plugins = device.getSupportedPlugins();
|
} else if (deviceId == null) {
|
||||||
for (final String pluginKey : plugins) {
|
throw new RuntimeException("You must start DeviceSettingActivity using an intent that has a " + EXTRA_DEVICE_ID + " extra");
|
||||||
PluginPreference pref = new PluginPreference(DeviceSettingsActivity.this, pluginKey, device);
|
}
|
||||||
preferenceScreen.addPreference(pref);
|
|
||||||
|
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentPlaceHolder);
|
||||||
|
if (fragment == null) {
|
||||||
|
if (pluginKey == null) {
|
||||||
|
fragment = DeviceSettingsFragment.newInstance(deviceId);
|
||||||
|
} else {
|
||||||
|
Device device = BackgroundService.getInstance().getDevice(deviceId);
|
||||||
|
Plugin plugin = device.getPlugin(pluginKey, true);
|
||||||
|
fragment = plugin.getSettingsFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSupportFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.add(R.id.fragmentPlaceHolder, fragment)
|
||||||
|
.commit();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
//ActionBar's back button
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
if (item.getItemId() == android.R.id.home) {
|
||||||
finish();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
|
|
||||||
|
if (fm.getBackStackEntryCount() > 0) {
|
||||||
|
fm.popBackStack();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
@ -81,4 +108,27 @@ public class DeviceSettingsActivity extends AppCompatPreferenceActivity {
|
|||||||
BackgroundService.removeGuiInUseCounter(this);
|
BackgroundService.removeGuiInUseCounter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartPluginSettingsFragment(Plugin plugin) {
|
||||||
|
setTitle(getString(R.string.plugin_settings_with_name, plugin.getDisplayName()));
|
||||||
|
|
||||||
|
PluginSettingsFragment fragment = plugin.getSettingsFragment();
|
||||||
|
|
||||||
|
//TODO: Remove when NotificationFilterActivity has been turned into a PluginSettingsFragment
|
||||||
|
if (fragment == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSupportFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.fragmentPlaceHolder, fragment)
|
||||||
|
.addToBackStack(null)
|
||||||
|
.commit();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
175
src/org/kde/kdeconnect/UserInterface/DeviceSettingsFragment.java
Normal file
175
src/org/kde/kdeconnect/UserInterface/DeviceSettingsFragment.java
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Erik Duisters <e.duisters1@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kde.kdeconnect.UserInterface;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import org.kde.kdeconnect.BackgroundService;
|
||||||
|
import org.kde.kdeconnect.Device;
|
||||||
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
public class DeviceSettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
private static final String ARG_DEVICE_ID = "deviceId";
|
||||||
|
private static final String KEY_RECYCLERVIEW_LAYOUTMANAGER_STATE = "RecyclerViewLayoutmanagerState";
|
||||||
|
|
||||||
|
private PluginPreference.PluginPreferenceCallback callback;
|
||||||
|
private Parcelable recyclerViewLayoutManagerState;
|
||||||
|
|
||||||
|
/*
|
||||||
|
https://bricolsoftconsulting.com/state-preservation-in-backstack-fragments/
|
||||||
|
When adding a fragment to the backstack the fragments onDestroyView is called (which releases
|
||||||
|
the RecyclerView) but the fragments onSaveInstanceState is not called. When the fragment is destroyed later
|
||||||
|
on, its onSaveInstanceState() is called but I don't have access to the RecyclerView or it's LayoutManager any more
|
||||||
|
*/
|
||||||
|
private boolean stateSaved;
|
||||||
|
|
||||||
|
public static DeviceSettingsFragment newInstance(@NonNull String deviceId) {
|
||||||
|
DeviceSettingsFragment fragment = new DeviceSettingsFragment();
|
||||||
|
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_DEVICE_ID, deviceId);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
if (requireActivity() instanceof PluginPreference.PluginPreferenceCallback) {
|
||||||
|
callback = (PluginPreference.PluginPreferenceCallback) getActivity();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(requireActivity().getClass().getSimpleName()
|
||||||
|
+ " must implement PluginPreference.PluginPreferenceCallback");
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_RECYCLERVIEW_LAYOUTMANAGER_STATE)) {
|
||||||
|
recyclerViewLayoutManagerState = savedInstanceState.getParcelable(KEY_RECYCLERVIEW_LAYOUTMANAGER_STATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
callback = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(requireContext());
|
||||||
|
setPreferenceScreen(preferenceScreen);
|
||||||
|
|
||||||
|
final String deviceId = getArguments().getString(ARG_DEVICE_ID);
|
||||||
|
|
||||||
|
BackgroundService.RunCommand(requireContext(), service -> {
|
||||||
|
final Device device = service.getDevice(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
final FragmentActivity activity = requireActivity();
|
||||||
|
activity.runOnUiThread(() -> activity.finish());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<String> plugins = device.getSupportedPlugins();
|
||||||
|
|
||||||
|
for (final String pluginKey : plugins) {
|
||||||
|
PluginPreference pref = new PluginPreference(requireContext(), pluginKey, device, callback);
|
||||||
|
preferenceScreen.addPreference(pref);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
||||||
|
RecyclerView.Adapter adapter = super.onCreateAdapter(preferenceScreen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
The layoutmanager's state (e.g. scroll position) can only be restored when the recyclerView's
|
||||||
|
adapter has been re-populated with data.
|
||||||
|
*/
|
||||||
|
if (recyclerViewLayoutManagerState != null) {
|
||||||
|
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
|
||||||
|
@Override
|
||||||
|
public void onChanged() {
|
||||||
|
RecyclerView.LayoutManager layoutManager = getListView().getLayoutManager();
|
||||||
|
|
||||||
|
if (layoutManager != null) {
|
||||||
|
layoutManager.onRestoreInstanceState(recyclerViewLayoutManagerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
recyclerViewLayoutManagerState = null;
|
||||||
|
adapter.unregisterAdapterDataObserver(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
stateSaved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
requireActivity().setTitle(getString(R.string.device_menu_plugins));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
if (!stateSaved && getListView() != null && getListView().getLayoutManager() != null) {
|
||||||
|
recyclerViewLayoutManagerState = getListView().getLayoutManager().onSaveInstanceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onDestroyView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
|
||||||
|
Parcelable layoutManagerState = recyclerViewLayoutManagerState;
|
||||||
|
|
||||||
|
if (getListView() != null && getListView().getLayoutManager() != null) {
|
||||||
|
layoutManagerState = getListView().getLayoutManager().onSaveInstanceState();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutManagerState != null) {
|
||||||
|
outState.putParcelable(KEY_RECYCLERVIEW_LAYOUTMANAGER_STATE, layoutManagerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
stateSaved = true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package org.kde.kdeconnect.UserInterface;
|
package org.kde.kdeconnect.UserInterface;
|
||||||
|
|
||||||
import android.preference.CheckBoxPreference;
|
import android.content.Context;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.kde.kdeconnect.Device;
|
import org.kde.kdeconnect.Device;
|
||||||
@ -8,23 +8,28 @@ import org.kde.kdeconnect.Plugins.Plugin;
|
|||||||
import org.kde.kdeconnect.Plugins.PluginFactory;
|
import org.kde.kdeconnect.Plugins.PluginFactory;
|
||||||
import org.kde.kdeconnect_tp.R;
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
class PluginPreference extends CheckBoxPreference {
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.CheckBoxPreference;
|
||||||
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
|
class PluginPreference extends CheckBoxPreference {
|
||||||
private final Device device;
|
private final Device device;
|
||||||
private final String pluginKey;
|
private final String pluginKey;
|
||||||
private final View.OnClickListener listener;
|
private final View.OnClickListener listener;
|
||||||
|
|
||||||
public PluginPreference(final DeviceSettingsActivity activity, final String pluginKey, final Device device) {
|
public PluginPreference(@NonNull final Context context, @NonNull final String pluginKey,
|
||||||
super(activity);
|
@NonNull final Device device, @NonNull PluginPreferenceCallback callback) {
|
||||||
|
super(context);
|
||||||
|
|
||||||
setLayoutResource(R.layout.preference_with_button);
|
setLayoutResource(R.layout.preference_with_button/*R.layout.preference_with_button_androidx*/);
|
||||||
|
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.pluginKey = pluginKey;
|
this.pluginKey = pluginKey;
|
||||||
|
|
||||||
PluginFactory.PluginInfo info = PluginFactory.getPluginInfo(activity, pluginKey);
|
PluginFactory.PluginInfo info = PluginFactory.getPluginInfo(context, pluginKey);
|
||||||
setTitle(info.getDisplayName());
|
setTitle(info.getDisplayName());
|
||||||
setSummary(info.getDescription());
|
setSummary(info.getDescription());
|
||||||
|
setIcon(android.R.color.transparent);
|
||||||
setChecked(device.isPluginEnabled(pluginKey));
|
setChecked(device.isPluginEnabled(pluginKey));
|
||||||
|
|
||||||
Plugin plugin = device.getPlugin(pluginKey, true);
|
Plugin plugin = device.getPlugin(pluginKey, true);
|
||||||
@ -32,30 +37,31 @@ class PluginPreference extends CheckBoxPreference {
|
|||||||
this.listener = v -> {
|
this.listener = v -> {
|
||||||
Plugin plugin1 = device.getPlugin(pluginKey, true);
|
Plugin plugin1 = device.getPlugin(pluginKey, true);
|
||||||
if (plugin1 != null) {
|
if (plugin1 != null) {
|
||||||
plugin1.startPreferencesActivity(activity);
|
callback.onStartPluginSettingsFragment(plugin1);
|
||||||
} else { //Could happen if the device is not connected anymore
|
} else { //Could happen if the device is not connected anymore
|
||||||
activity.finish(); //End this activity so we go to the "device not reachable" screen
|
callback.onFinish();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
this.listener = null;
|
this.listener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBindView(View root) {
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||||
super.onBindView(root);
|
super.onBindViewHolder(holder);
|
||||||
final View button = root.findViewById(R.id.settingsButton);
|
|
||||||
|
final View button = holder.findViewById(R.id.settingsButton);
|
||||||
|
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
button.setVisibility(View.GONE);
|
button.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
button.setEnabled(isChecked());
|
button.setEnabled(isChecked());
|
||||||
|
button.setVisibility(View.VISIBLE);
|
||||||
button.setOnClickListener(listener);
|
button.setOnClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
root.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
boolean newState = !device.isPluginEnabled(pluginKey);
|
boolean newState = !device.isPluginEnabled(pluginKey);
|
||||||
setChecked(newState); //It actually works on API<14
|
setChecked(newState); //It actually works on API<14
|
||||||
button.setEnabled(newState);
|
button.setEnabled(newState);
|
||||||
@ -63,4 +69,8 @@ class PluginPreference extends CheckBoxPreference {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PluginPreferenceCallback {
|
||||||
|
void onStartPluginSettingsFragment(Plugin plugin);
|
||||||
|
void onFinish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 Ronny Yabar Aizcorbe <ronnycontacto@gmail.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kde.kdeconnect.UserInterface;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
import org.kde.kdeconnect.BackgroundService;
|
|
||||||
import org.kde.kdeconnect_tp.R;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class PluginSettingsActivity extends AppCompatPreferenceActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
String pluginDisplayName = getIntent().getStringExtra("plugin_display_name");
|
|
||||||
setTitle(getString(R.string.plugin_settings_with_name, pluginDisplayName));
|
|
||||||
|
|
||||||
String pluginKey = getIntent().getStringExtra("plugin_key");
|
|
||||||
int resFile = getResources().getIdentifier(pluginKey.toLowerCase(Locale.ENGLISH) + "_preferences", "xml", getPackageName());
|
|
||||||
addPreferencesFromResource(resFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
//ActionBar's back button
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStart() {
|
|
||||||
super.onStart();
|
|
||||||
BackgroundService.addGuiInUseCounter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStop() {
|
|
||||||
super.onStop();
|
|
||||||
BackgroundService.removeGuiInUseCounter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Erik Duisters <e.duisters1@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kde.kdeconnect.UserInterface;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.kde.kdeconnect.Plugins.PluginFactory;
|
||||||
|
import org.kde.kdeconnect_tp.R;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
|
||||||
|
public class PluginSettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
public static final String ARG_PLUGIN_KEY = "plugin_key";
|
||||||
|
|
||||||
|
private String pluginKey;
|
||||||
|
|
||||||
|
public static PluginSettingsFragment newInstance(@NonNull String pluginKey) {
|
||||||
|
PluginSettingsFragment fragment = new PluginSettingsFragment();
|
||||||
|
fragment.setArguments(pluginKey);
|
||||||
|
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginSettingsFragment() {}
|
||||||
|
|
||||||
|
protected Bundle setArguments(@NonNull String pluginKey) {
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_PLUGIN_KEY, pluginKey);
|
||||||
|
|
||||||
|
setArguments(args);
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
if (getArguments() == null || !getArguments().containsKey(ARG_PLUGIN_KEY)) {
|
||||||
|
throw new RuntimeException("You must provide a pluginKey by calling setArguments(@NonNull String pluginKey)");
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginKey = getArguments().getString(ARG_PLUGIN_KEY);
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
int resFile = getResources().getIdentifier(pluginKey.toLowerCase(Locale.ENGLISH) + "_preferences", "xml",
|
||||||
|
requireContext().getPackageName());
|
||||||
|
addPreferencesFromResource(resFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
PluginFactory.PluginInfo info = PluginFactory.getPluginInfo(requireContext(), pluginKey);
|
||||||
|
requireActivity().setTitle(getString(R.string.plugin_settings_with_name, info.getDisplayName()));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user