diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 7c14bebf..e5a17246 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -49,6 +49,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted + + + + + + + + + + diff --git a/res/layout-v23/pairing_explanation_text_no_wifi.xml b/res/layout-v23/pairing_explanation_text_no_wifi.xml index e50338ff..7c91edb4 100644 --- a/res/layout-v23/pairing_explanation_text_no_wifi.xml +++ b/res/layout-v23/pairing_explanation_text_no_wifi.xml @@ -1,4 +1,11 @@ + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 1eabcbf1..3b2d3837 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -252,6 +252,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted 60000000 120000000 + The notifications permission is needed to show remote media in the notifications drawer Show media control notification Allow controlling your media players without opening KDE Connect mpris_notification_enabled @@ -331,6 +332,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted You need to grant extra permissions to enable all functions Some plugins have features disabled because of lack of permission (tap for more info): To receive files you need to allow storage access + To see the progress when sending and receiving files you need to allow notifications To read and write SMS from your desktop you need to give permission to SMS To see phone calls on the desktop you need to give permission to phone call logs and phone state To see a contact name instead of a phone number you need to give access to the phone\'s contacts @@ -549,4 +551,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted Enable UDP device discovery + Notifications need to be allowed to receive them from other devices + The notifications permission is needed so the phone can ring when the app is in the background + Notifications are disabled, you won\'t receive incoming pair notifications. + diff --git a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java index 072f67a0..5b324f6f 100644 --- a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java +++ b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java @@ -67,8 +67,6 @@ public class BigscreenActivity extends AppCompatActivity { new PermissionsAlertDialogFragment.Builder() .setTitle(plugin.getDisplayName()) .setMessage(R.string.bigscreen_optional_permission_explanation) - .setPositiveButton(R.string.ok) - .setNegativeButton(R.string.cancel) .setPermissions(new String[]{Manifest.permission.RECORD_AUDIO}) .setRequestCode(MainActivity.RESULT_NEEDS_RELOAD) .create().show(getSupportFragmentManager(), null); diff --git a/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhonePlugin.java b/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhonePlugin.java index 4860b873..07f80db4 100644 --- a/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhonePlugin.java +++ b/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhonePlugin.java @@ -6,6 +6,7 @@ package org.kde.kdeconnect.Plugins.FindMyPhonePlugin; +import android.Manifest; import android.app.Activity; import android.app.NotificationManager; import android.app.PendingIntent; @@ -120,6 +121,9 @@ public class FindMyPhonePlugin extends Plugin { intent.putExtra(FindMyPhoneActivity.EXTRA_DEVICE_ID, device.getDeviceId()); context.startActivity(intent); } else { + if (!checkOptionalPermissions()) { + return false; + } if (powerManager.isInteractive()) { startPlaying(); showBroadcastNotification(); @@ -127,7 +131,6 @@ public class FindMyPhonePlugin extends Plugin { showActivityNotification(); } } - return true; } @@ -219,4 +222,19 @@ public class FindMyPhonePlugin extends Plugin { public PluginSettingsFragment getSettingsFragment(Activity activity) { return FindMyPhoneSettingsFragment.newInstance(getPluginKey(), R.xml.findmyphoneplugin_preferences); } + + @NonNull + @Override + protected String[] getRequiredPermissions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return new String[]{Manifest.permission.POST_NOTIFICATIONS}; + } else { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + } + + @Override + protected int getPermissionExplanation() { + return R.string.findmyphone_notifications_explanation; + } } diff --git a/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisMediaSession.java b/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisMediaSession.java index 2d0f3034..f9e92540 100644 --- a/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisMediaSession.java +++ b/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisMediaSession.java @@ -6,11 +6,13 @@ package org.kde.kdeconnect.Plugins.MprisPlugin; +import android.Manifest; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.media.AudioManager; import android.os.Build; @@ -257,6 +259,14 @@ public class MprisMediaSession implements */ private void updateMediaNotification() { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { + int permissionResult = ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS); + if (permissionResult != PackageManager.PERMISSION_GRANTED) { + closeMediaNotification(); + return; + } + } + //If the user disabled the media notification, do not show it SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); if (!prefs.getBoolean(context.getString(R.string.mpris_notification_key), true)) { diff --git a/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisPlugin.java b/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisPlugin.java index 95fe34e9..682e6979 100644 --- a/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisPlugin.java @@ -6,15 +6,18 @@ package org.kde.kdeconnect.Plugins.MprisPlugin; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; +import android.os.Build; import android.util.Log; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; +import org.apache.commons.lang3.ArrayUtils; import org.kde.kdeconnect.NetworkPacket; import org.kde.kdeconnect.Plugins.Plugin; import org.kde.kdeconnect.Plugins.PluginFactory; @@ -521,4 +524,19 @@ public class MprisPlugin extends Plugin { } return false; } + + @NonNull + @Override + protected String[] getOptionalPermissions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return new String[]{Manifest.permission.POST_NOTIFICATIONS}; + } else { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + } + + @Override + protected int getOptionalPermissionExplanation() { + return R.string.mpris_notifications_explanation; + } } diff --git a/src/org/kde/kdeconnect/Plugins/PingPlugin/PingPlugin.java b/src/org/kde/kdeconnect/Plugins/PingPlugin/PingPlugin.java index b753fb83..a0b45908 100644 --- a/src/org/kde/kdeconnect/Plugins/PingPlugin/PingPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/PingPlugin/PingPlugin.java @@ -6,12 +6,18 @@ package org.kde.kdeconnect.Plugins.PingPlugin; +import android.Manifest; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; import android.util.Log; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat; @@ -66,6 +72,15 @@ public class PingPlugin extends Plugin { id = 42; //A unique id to create only one notification } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + int permissionResult = ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS); + if (permissionResult != PackageManager.PERMISSION_GRANTED) { + // If notifications are not allowed, show a toast instead of a notification + new Handler(Looper.getMainLooper()).post(() -> Toast.makeText(context, message, Toast.LENGTH_LONG).show()); + return true; + } + } + NotificationManager notificationManager = ContextCompat.getSystemService(context, NotificationManager.class); Notification noti = new NotificationCompat.Builder(context, NotificationHelper.Channels.DEFAULT) diff --git a/src/org/kde/kdeconnect/Plugins/Plugin.java b/src/org/kde/kdeconnect/Plugins/Plugin.java index 4935d2b2..5e1cabaf 100644 --- a/src/org/kde/kdeconnect/Plugins/Plugin.java +++ b/src/org/kde/kdeconnect/Plugins/Plugin.java @@ -278,8 +278,6 @@ public abstract class Plugin { return new PermissionsAlertDialogFragment.Builder() .setTitle(getDisplayName()) .setMessage(reason) - .setPositiveButton(R.string.ok) - .setNegativeButton(R.string.cancel) .setPermissions(permissions) .setRequestCode(MainActivity.RESULT_NEEDS_RELOAD) .create(); diff --git a/src/org/kde/kdeconnect/Plugins/ReceiveNotificationsPlugin/ReceiveNotificationsPlugin.java b/src/org/kde/kdeconnect/Plugins/ReceiveNotificationsPlugin/ReceiveNotificationsPlugin.java index 44e57083..cf99052d 100644 --- a/src/org/kde/kdeconnect/Plugins/ReceiveNotificationsPlugin/ReceiveNotificationsPlugin.java +++ b/src/org/kde/kdeconnect/Plugins/ReceiveNotificationsPlugin/ReceiveNotificationsPlugin.java @@ -6,18 +6,21 @@ package org.kde.kdeconnect.Plugins.ReceiveNotificationsPlugin; +import android.Manifest; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; import androidx.core.app.NotificationCompat; import androidx.core.content.ContextCompat; +import org.apache.commons.lang3.ArrayUtils; import org.kde.kdeconnect.Helpers.NotificationHelper; import org.kde.kdeconnect.NetworkPacket; import org.kde.kdeconnect.Plugins.Plugin; @@ -122,4 +125,19 @@ public class ReceiveNotificationsPlugin extends Plugin { public @NonNull String[] getOutgoingPacketTypes() { return new String[]{PACKET_TYPE_NOTIFICATION_REQUEST}; } + + @NonNull + @Override + protected String[] getRequiredPermissions() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return new String[]{Manifest.permission.POST_NOTIFICATIONS}; + } else { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + } + + @Override + protected int getPermissionExplanation() { + return R.string.receive_notifications_permission_explanation; + } } diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java index b5802b09..c7b80f90 100644 --- a/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java +++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/SharePlugin.java @@ -75,7 +75,11 @@ public class SharePlugin extends Plugin { @Override protected int getOptionalPermissionExplanation() { - return R.string.share_optional_permission_explanation; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return R.string.share_notifications_explanation; + } else { + return R.string.share_optional_permission_explanation; + } } @Override @@ -290,7 +294,9 @@ public class SharePlugin extends Plugin { @Override public @NonNull String[] getOptionalPermissions() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return new String[]{Manifest.permission.POST_NOTIFICATIONS}; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { return ArrayUtils.EMPTY_STRING_ARRAY; } else { return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; diff --git a/src/org/kde/kdeconnect/UserInterface/MainActivity.kt b/src/org/kde/kdeconnect/UserInterface/MainActivity.kt index b7731c54..8a9ea08a 100644 --- a/src/org/kde/kdeconnect/UserInterface/MainActivity.kt +++ b/src/org/kde/kdeconnect/UserInterface/MainActivity.kt @@ -22,6 +22,8 @@ import android.widget.TextView import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat import androidx.core.view.GravityCompat import androidx.drawerlayout.widget.DrawerLayout import androidx.fragment.app.Fragment @@ -192,6 +194,15 @@ class MainActivity : AppCompatActivity(), OnSharedPreferenceChangeListener { else -> setContentFragment(PairingFragment()) } } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + val permissionResult = ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) + if (permissionResult != PackageManager.PERMISSION_GRANTED) { + if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.POST_NOTIFICATIONS)) { + ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), RESULT_NOTIFICATIONS_ENABLED) + } + } + } } override fun onDestroy() { @@ -324,25 +335,33 @@ class MainActivity : AppCompatActivity(), OnSharedPreferenceChangeListener { val uri = data.data ShareSettingsFragment.saveStorageLocationPreference(this, uri) } - else -> super.onActivityResult(requestCode, resultCode, data) } } + fun isPermissionGranted(permissions: Array, grantResults: IntArray, permission : String) : Boolean { + val index = ArrayUtils.indexOf(permissions, permission) + return index != ArrayUtils.INDEX_NOT_FOUND && grantResults[index] == PackageManager.PERMISSION_GRANTED + } + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) val permissionsGranted = ArrayUtils.contains(grantResults, PackageManager.PERMISSION_GRANTED) if (permissionsGranted) { - val i = ArrayUtils.indexOf(permissions, Manifest.permission.WRITE_EXTERNAL_STORAGE) - val writeStoragePermissionGranted = i != ArrayUtils.INDEX_NOT_FOUND && - grantResults[i] == PackageManager.PERMISSION_GRANTED - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && writeStoragePermissionGranted) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isPermissionGranted(permissions, grantResults, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // To get a writeable path manually on Android 10 and later for Share and Receive Plugin. // Otherwise, Receiving files will keep failing until the user chooses a path manually to receive files. val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) startActivityForResult(intent, STORAGE_LOCATION_CONFIGURED) } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && isPermissionGranted(permissions, grantResults, Manifest.permission.POST_NOTIFICATIONS)) { + // If PairingFragment is active, reload it + if (mCurrentDevice == null) { + setContentFragment(PairingFragment()) + } + } + //New permission granted, reload plugins KdeConnect.getInstance().getDevice(mCurrentDevice)?.reloadPluginsFromSettings() } @@ -370,6 +389,7 @@ class MainActivity : AppCompatActivity(), OnSharedPreferenceChangeListener { const val PAIRING_REJECTED = "rejected" const val PAIRING_PENDING = "pending" const val RESULT_NEEDS_RELOAD = RESULT_FIRST_USER + const val RESULT_NOTIFICATIONS_ENABLED = RESULT_FIRST_USER+1 const val FLAG_FORCE_OVERVIEW = "forceOverview" } diff --git a/src/org/kde/kdeconnect/UserInterface/PairingFragment.java b/src/org/kde/kdeconnect/UserInterface/PairingFragment.java index f6177fde..fb0f5632 100644 --- a/src/org/kde/kdeconnect/UserInterface/PairingFragment.java +++ b/src/org/kde/kdeconnect/UserInterface/PairingFragment.java @@ -6,10 +6,13 @@ package org.kde.kdeconnect.UserInterface; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Resources; +import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.view.LayoutInflater; @@ -21,6 +24,8 @@ import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import org.kde.kdeconnect.BackgroundService; @@ -34,6 +39,7 @@ import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.databinding.DevicesListBinding; import org.kde.kdeconnect_tp.databinding.PairingExplanationNotTrustedBinding; import org.kde.kdeconnect_tp.databinding.PairingExplanationTextBinding; +import org.kde.kdeconnect_tp.databinding.PairingExplanationTextNoNotificationsBinding; import org.kde.kdeconnect_tp.databinding.PairingExplanationTextNoWifiBinding; import java.util.ArrayList; @@ -52,6 +58,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb private PairingExplanationNotTrustedBinding pairingExplanationNotTrustedBinding; private PairingExplanationTextBinding pairingExplanationTextBinding; private PairingExplanationTextNoWifiBinding pairingExplanationTextNoWifiBinding; + private PairingExplanationTextNoNotificationsBinding pairingExplanationTextNoNotificationsBinding; private MainActivity mActivity; @@ -59,6 +66,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb private TextView headerText; private TextView noWifiHeader; + private TextView noNotificationsHeader; private TextView notTrustedText; @Override @@ -69,23 +77,35 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb setHasOptionsMenu(true); devicesListBinding = DevicesListBinding.inflate(inflater, container, false); + pairingExplanationNotTrustedBinding = PairingExplanationNotTrustedBinding.inflate(inflater); - pairingExplanationTextBinding = PairingExplanationTextBinding.inflate(inflater); - pairingExplanationTextNoWifiBinding = PairingExplanationTextNoWifiBinding.inflate(inflater); - - devicesListBinding.refreshListLayout.setOnRefreshListener(this::refreshDevicesAction); - notTrustedText = pairingExplanationNotTrustedBinding.getRoot(); notTrustedText.setOnClickListener(null); notTrustedText.setOnLongClickListener(null); + pairingExplanationTextBinding = PairingExplanationTextBinding.inflate(inflater); headerText = pairingExplanationTextBinding.getRoot(); headerText.setOnClickListener(null); headerText.setOnLongClickListener(null); + pairingExplanationTextNoWifiBinding = PairingExplanationTextNoWifiBinding.inflate(inflater); noWifiHeader = pairingExplanationTextNoWifiBinding.getRoot(); noWifiHeader.setOnClickListener(view -> startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS))); + + pairingExplanationTextNoNotificationsBinding = PairingExplanationTextNoNotificationsBinding.inflate(inflater); + noNotificationsHeader = pairingExplanationTextNoNotificationsBinding.getRoot(); + noNotificationsHeader.setOnClickListener(view -> ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.POST_NOTIFICATIONS}, MainActivity.RESULT_NOTIFICATIONS_ENABLED)); + noNotificationsHeader.setOnLongClickListener(view -> { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", requireContext().getPackageName(), null); + intent.setData(uri); + startActivity(intent); + return true; + }); + devicesListBinding.devicesList.addHeaderView(headerText); + devicesListBinding.refreshListLayout.setOnRefreshListener(this::refreshDevicesAction); return devicesListBinding.getRoot(); } @@ -207,12 +227,17 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb } } + boolean hasNotificationsPermission = ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED; + devicesListBinding.devicesList.removeHeaderView(headerText); devicesListBinding.devicesList.removeHeaderView(noWifiHeader); devicesListBinding.devicesList.removeHeaderView(notTrustedText); + devicesListBinding.devicesList.removeHeaderView(noNotificationsHeader); if (someDevicesReachable || isConnectedToNonCellularNetwork) { - if (TrustedNetworkHelper.isTrustedNetwork(getContext())) { + if (!hasNotificationsPermission) { + devicesListBinding.devicesList.addHeaderView(noNotificationsHeader); + } else if (TrustedNetworkHelper.isTrustedNetwork(getContext())) { devicesListBinding.devicesList.addHeaderView(headerText); } else { devicesListBinding.devicesList.addHeaderView(notTrustedText); diff --git a/src/org/kde/kdeconnect/UserInterface/PermissionsAlertDialogFragment.java b/src/org/kde/kdeconnect/UserInterface/PermissionsAlertDialogFragment.java index ce63f4a6..7b91f7bf 100644 --- a/src/org/kde/kdeconnect/UserInterface/PermissionsAlertDialogFragment.java +++ b/src/org/kde/kdeconnect/UserInterface/PermissionsAlertDialogFragment.java @@ -11,6 +11,8 @@ import android.os.Bundle; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; +import org.kde.kdeconnect_tp.R; + public class PermissionsAlertDialogFragment extends AlertDialogFragment { private static final String KEY_PERMISSIONS = "Permissions"; private static final String KEY_REQUEST_CODE = "RequestCode"; @@ -43,6 +45,12 @@ public class PermissionsAlertDialogFragment extends AlertDialogFragment { } public static class Builder extends AlertDialogFragment.AbstractBuilder { + + public Builder() { + setPositiveButton(R.string.ok); + setNegativeButton(R.string.cancel); + } + @Override public Builder getThis() { return this; diff --git a/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.java b/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.java index 18a13f95..3d14d66b 100644 --- a/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.java +++ b/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.java @@ -75,8 +75,6 @@ public class TrustedNetworksActivity extends AppCompatActivity { new PermissionsAlertDialogFragment.Builder() .setTitle(R.string.location_permission_needed_title) .setMessage(R.string.location_permission_needed_desc) - .setPositiveButton(R.string.ok) - .setNegativeButton(R.string.cancel) .setPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}) .setRequestCode(0) .create().show(getSupportFragmentManager(), null);