diff --git a/app/build.gradle b/app/build.gradle
index c86b26426..4fd3a5630 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -46,7 +46,7 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
- compileSdkVersion 29
+ compileSdkVersion 31
buildToolsVersion "31.0.0"
defaultConfig {
@@ -101,8 +101,8 @@ android {
resValue "string", "about_activity_title", "@string/about_activity_title_banglejs_main"
resValue "string", "about_description", "@string/about_description_banglejs_main"
resValue "string", "gadgetbridge_running", "@string/gadgetbridge_running_banglejs_main"
- targetSdkVersion 30 // Bangle.js flavor only - We need SDK 30 for play store
- // Note: app/src/banglejs/AndroidManifest.xml contains some extra permissions we need to make SDK 30 work
+ targetSdkVersion 31 // Bangle.js flavor only - We need SDK 31 for updates pushed to Play Store from 2022-11-01
+ // Note: app/src/banglejs/AndroidManifest.xml contains some extra permissions we need to make SDK 30 and up work
}
}
@@ -223,6 +223,8 @@ dependencies {
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.gridlayout:gridlayout:1.0.0"
implementation "androidx.palette:palette:1.0.0"
+ implementation "androidx.activity:activity:1.4.0"
+ implementation "androidx.fragment:fragment:1.4.0"
implementation "com.google.android.material:material:1.4.0"
implementation 'com.google.android.flexbox:flexbox:3.0.0'
diff --git a/app/src/banglejs/AndroidManifest.xml b/app/src/banglejs/AndroidManifest.xml
index f285bad1f..525452a9e 100644
--- a/app/src/banglejs/AndroidManifest.xml
+++ b/app/src/banglejs/AndroidManifest.xml
@@ -12,4 +12,34 @@
-->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d7f79c804..795931d76 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -77,7 +77,8 @@
android:name=".activities.ControlCenterv2"
android:label="@string/title_activity_controlcenter"
android:theme="@style/SplashTheme"
- android:launchMode="singleTop">
+ android:launchMode="singleTop"
+ android:exported="true">
@@ -134,7 +135,8 @@
+ android:parentActivityName=".activities.ControlCenterv2"
+ android:exported="true">
@@ -355,7 +357,8 @@
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
+ android:exported="false">
@@ -368,7 +371,8 @@
+ android:enabled="true"
+ android:exported="false">
@@ -376,13 +380,15 @@
+ android:enabled="true"
+ android:exported="false">
-
+
@@ -390,7 +396,8 @@
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:exported="false">
@@ -583,7 +590,8 @@
+ android:label="@string/appwidget_sleep_alarm_widget_label"
+ android:exported="false">
@@ -595,7 +603,8 @@
+ android:label="@string/widget_listing_label"
+ android:exported="false">
@@ -614,13 +623,15 @@
android:launchMode="singleInstance"
android:theme="@style/Theme.AppCompat.Light.Dialog" />
-
+
-
+
@@ -632,7 +643,8 @@
android:clearTaskOnLaunch="true"
android:label="@string/app_configure"
android:launchMode="singleTask"
- android:parentActivityName=".activities.appmanager.AppManagerActivity">
+ android:parentActivityName=".activities.appmanager.AppManagerActivity"
+ android:exported="true">
@@ -719,7 +731,8 @@
android:name=".activities.GpxReceiverActivity"
android:label="@string/gpx_receiver_activity_title"
android:screenOrientation="portrait"
- android:windowSoftInputMode="stateHidden">
+ android:windowSoftInputMode="stateHidden"
+ android:exported="false">
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java
index 9ce53d3e5..33c817012 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/SleepAlarmWidget.java
@@ -38,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.util.AlarmUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
+import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
import nodomain.freeyourgadget.gadgetbridge.util.WidgetPreferenceStorage;
/**
@@ -62,8 +63,8 @@ public class SleepAlarmWidget extends AppWidgetProvider {
Intent intent = new Intent(context, SleepAlarmWidget.class);
intent.setAction(ACTION_CLICK);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- PendingIntent clickPI = PendingIntent.getBroadcast(
- context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent clickPI = PendingIntentUtils.getBroadcast(
+ context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT, false);
views.setOnClickPendingIntent(R.id.sleepalarmwidget_text, clickPI);
// Instruct the widget manager to update the widget
@@ -147,8 +148,8 @@ public class SleepAlarmWidget extends AppWidgetProvider {
AlarmManager am = (AlarmManager) packageContext.getSystemService(Context.ALARM_SERVICE);
// TODO: launch the alarm configuration activity when clicking the alarm in the status bar
Intent intent = new Intent(packageContext, ConfigureAlarms.class);
- PendingIntent pi = PendingIntent.getBroadcast(packageContext, 0, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent pi = PendingIntentUtils.getBroadcast(packageContext, 0, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT, false);
am.setAlarmClock(new AlarmManager.AlarmClockInfo(triggerTime, pi), pi);
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/Widget.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/Widget.java
index b820a146c..4ea91e834 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/Widget.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/Widget.java
@@ -42,6 +42,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.RemoteViews;
@@ -67,6 +68,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.FormatUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
+import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
import nodomain.freeyourgadget.gadgetbridge.util.WidgetPreferenceStorage;
public class Widget extends AppWidgetProvider {
@@ -108,25 +110,25 @@ public class Widget extends AppWidgetProvider {
Intent intent = new Intent(context, Widget.class);
intent.setAction(WIDGET_CLICK);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- PendingIntent refreshDataIntent = PendingIntent.getBroadcast(
- context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent refreshDataIntent = PendingIntentUtils.getBroadcast(
+ context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT, false);
views.setOnClickPendingIntent(R.id.todaywidget_header_container, refreshDataIntent);
//open GB main window
Intent startMainIntent = new Intent(context, ControlCenterv2.class);
- PendingIntent startMainPIntent = PendingIntent.getActivity(context, 0, startMainIntent, 0);
+ PendingIntent startMainPIntent = PendingIntentUtils.getActivity(context, 0, startMainIntent, 0, false);
views.setOnClickPendingIntent(R.id.todaywidget_header_icon, startMainPIntent);
//alarms popup menu
Intent startAlarmListIntent = new Intent(context, WidgetAlarmsActivity.class);
startAlarmListIntent.putExtra(GBDevice.EXTRA_DEVICE, deviceForWidget);
- PendingIntent startAlarmListPIntent = PendingIntent.getActivity(context, appWidgetId, startAlarmListIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent startAlarmListPIntent = PendingIntentUtils.getActivity(context, appWidgetId, startAlarmListIntent, PendingIntent.FLAG_UPDATE_CURRENT, false);
views.setOnClickPendingIntent(R.id.todaywidget_header_alarm_icon, startAlarmListPIntent);
//charts
Intent startChartsIntent = new Intent(context, ChartsActivity.class);
startChartsIntent.putExtra(GBDevice.EXTRA_DEVICE, deviceForWidget);
- PendingIntent startChartsPIntent = PendingIntent.getActivity(context, appWidgetId, startChartsIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent startChartsPIntent = PendingIntentUtils.getActivity(context, appWidgetId, startChartsIntent, PendingIntent.FLAG_CANCEL_CURRENT, false);
views.setOnClickPendingIntent(R.id.todaywidget_bottom_layout, startChartsPIntent);
long[] dailyTotals = getSteps(deviceForWidget);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java
index 26cdeb3ad..be89f5b18 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ControlCenterv2.java
@@ -32,13 +32,17 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
@@ -284,7 +288,7 @@ public class ControlCenterv2 extends AppCompatActivity
}
}
- if (!android.provider.Settings.canDrawOverlays(getApplicationContext())) {
+ if (!Settings.canDrawOverlays(getApplicationContext())) {
// If diplay over other apps access hasn't been granted
// Put up a dialog explaining why we need permissions (Polite, but also Play Store policy)
// When accepted, we open the Activity for permission to display over other apps.
@@ -294,6 +298,10 @@ public class ControlCenterv2 extends AppCompatActivity
}
}
+
+ // Put up a dialog explaining why we need permissions (Polite, but also Play Store policy)
+ // When accepted, we open the Activity for permission to display over other apps.
+
// Check all the other permissions that we need to for Android M + later
checkAndRequestPermissions(true);
}
@@ -478,12 +486,27 @@ public class ControlCenterv2 extends AppCompatActivity
}
}
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && Build.VERSION.SDK_INT <= Build.VERSION_CODES.S) {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_DENIED) {
wantedPermissions.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
}
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.QUERY_ALL_PACKAGES) == PackageManager.PERMISSION_DENIED) {
+ wantedPermissions.add(Manifest.permission.QUERY_ALL_PACKAGES);
+ }
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_DENIED) {
+ wantedPermissions.add(Manifest.permission.BLUETOOTH_SCAN);
+ }
+ if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED) {
+ wantedPermissions.add(Manifest.permission.BLUETOOTH_CONNECT);
+ }
+ }
+
if (BuildConfig.INTERNET_ACCESS) {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.INTERNET) == PackageManager.PERMISSION_DENIED) {
wantedPermissions.add(Manifest.permission.INTERNET);
@@ -512,22 +535,30 @@ public class ControlCenterv2 extends AppCompatActivity
if (!wantedPermissions.isEmpty()) {
if (showDialogFirst) {
- // Show a dialog - thus will then call checkAndRequestPermissions(false)
+ // Show a dialog - this will then call checkAndRequestPermissions(false)
DialogFragment dialog = new LocationPermissionsDialogFragment();
dialog.show(getSupportFragmentManager(), "LocationPermissionsDialogFragment");
+ //requestMultiplePermissionsLauncher.launch(wantedPermissions.toArray(new String[0]));
} else {
GB.toast(this, getString(R.string.permission_granting_mandatory), Toast.LENGTH_LONG, GB.ERROR);
- ActivityCompat.requestPermissions(this, wantedPermissions.toArray(new String[0]), 0);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+ ActivityCompat.requestPermissions(this, wantedPermissions.toArray(new String[0]), 0);
+ } else {
+ requestMultiplePermissionsLauncher.launch(wantedPermissions.toArray(new String[0]));
+ //ActivityCompat.requestPermissions(this, wantedPermissions.toArray(new String[0]), 0); //Actually this still works if I test it, not sure if the new way is more reliable or not...
+ }
}
}
}
- // HACK: On Lineage we have to do this so that the permission dialog pops up
- if (fakeStateListener == null) {
- fakeStateListener = new PhoneStateListener();
- TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
- telephonyManager.listen(fakeStateListener, PhoneStateListener.LISTEN_CALL_STATE);
- telephonyManager.listen(fakeStateListener, PhoneStateListener.LISTEN_NONE);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { // The enclosed hack in it's current state cause crash on Banglejs builds tarkgetSDK=31 on a Android 13 device.
+ // HACK: On Lineage we have to do this so that the permission dialog pops up
+ if (fakeStateListener == null) {
+ fakeStateListener = new PhoneStateListener();
+ TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
+ telephonyManager.listen(fakeStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ telephonyManager.listen(fakeStateListener, PhoneStateListener.LISTEN_NONE);
+ }
}
}
@@ -583,6 +614,7 @@ public class ControlCenterv2 extends AppCompatActivity
getContext().getString(R.string.app_name),
getContext().getString(R.string.ok)))
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @RequiresApi(api = Build.VERSION_CODES.M)
public void onClick(DialogInterface dialog, int id) {
try {
startActivity(new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS));
@@ -629,6 +661,7 @@ public class ControlCenterv2 extends AppCompatActivity
getContext().getString(R.string.app_name),
getContext().getString(R.string.ok)))
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @RequiresApi(api = Build.VERSION_CODES.M)
public void onClick(DialogInterface dialog, int id) {
Intent enableIntent = new Intent(android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(enableIntent);
@@ -640,6 +673,7 @@ public class ControlCenterv2 extends AppCompatActivity
}
}
+
/// Called from checkAndRequestPermissions - this puts up a dialog explaining we need permissions, and then calls checkAndRequestPermissions (via an intent) when 'ok' pressed
public static class LocationPermissionsDialogFragment extends DialogFragment {
ControlCenterv2 controlCenter;
@@ -661,4 +695,22 @@ public class ControlCenterv2 extends AppCompatActivity
return builder.create();
}
}
+
+ // Register the permissions callback, which handles the user's response to the
+ // system permissions dialog. Save the return value, an instance of
+ // ActivityResultLauncher, as an instance variable.
+ public ActivityResultLauncher requestMultiplePermissionsLauncher =
+ registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), isGranted -> {
+ if (isGranted.containsValue(true)) {
+ // Permission is granted. Continue the action or workflow in your
+ // app.
+ } else {
+ // Explain to the user that the feature is unavailable because the
+ // feature requires a permission that the user has denied. At the
+ // same time, respect the user's decision. Don't link to system
+ // settings in an effort to convince the user to change their
+ // decision.
+ GB.toast(this, getString(R.string.permission_granting_mandatory), Toast.LENGTH_LONG, GB.ERROR);
+ }
+ });
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java
index 7f39d39d8..d113f641b 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java
@@ -116,6 +116,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
+import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
import nodomain.freeyourgadget.gadgetbridge.util.WidgetPreferenceStorage;
@@ -915,15 +916,15 @@ public class DebugActivity extends AbstractGBActivity {
Intent notificationIntent = new Intent(getApplicationContext(), DebugActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
- PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0,
- notificationIntent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getActivity(getApplicationContext(), 0,
+ notificationIntent, 0, false);
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_REPLY)
.build();
Intent replyIntent = new Intent(ACTION_REPLY);
- PendingIntent replyPendingIntent = PendingIntent.getBroadcast(this, 0, replyIntent, 0);
+ PendingIntent replyPendingIntent = PendingIntentUtils.getBroadcast(this, 0, replyIntent, 0, true);
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(android.R.drawable.ic_input_add, "Reply", replyPendingIntent)
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/PeriodicExporter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/PeriodicExporter.java
index fb3ac9610..36861f5a2 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/PeriodicExporter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/PeriodicExporter.java
@@ -22,6 +22,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.SystemClock;
import org.slf4j.Logger;
@@ -33,6 +34,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
+import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
/**
@@ -56,7 +58,7 @@ public class PeriodicExporter extends BroadcastReceiver {
public static void scheduleAlarm(Context context, Integer autoExportInterval, boolean autoExportEnabled) {
Intent i = new Intent(context, PeriodicExporter.class);
- PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
+ PendingIntent pi = PendingIntentUtils.getBroadcast(context, 0, i, 0, false);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi);
if (!autoExportEnabled) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java
index 1b408cf5b..f1a93f9c2 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java
@@ -22,6 +22,7 @@ import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import net.e175.klaus.solarpositioning.DeltaT;
import net.e175.klaus.solarpositioning.SPA;
@@ -37,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
+import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
public class AlarmReceiver extends BroadcastReceiver {
private static final Logger LOG = LoggerFactory.getLogger(AlarmReceiver.class);
@@ -45,7 +47,7 @@ public class AlarmReceiver extends BroadcastReceiver {
Context context = GBApplication.getContext();
Intent intent = new Intent("DAILY_ALARM");
intent.setPackage(BuildConfig.APPLICATION_ID);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getBroadcast(context, 0, intent, 0, false);
AlarmManager am = (AlarmManager) (context.getSystemService(Context.ALARM_SERVICE));
if (am != null) {
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
index 52f15f1cd..a970ab721 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java
@@ -95,6 +95,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec;
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBCallControlReceiver;
import nodomain.freeyourgadget.gadgetbridge.service.receivers.GBMusicControlReceiver;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
+import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.NOTIFICATION_CHANNEL_ID;
@@ -253,7 +254,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
intent.putExtra(FindPhoneActivity.EXTRA_RING, ring);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- PendingIntent pi = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pi = PendingIntentUtils.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, false);
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_HIGH_PRIORITY_ID )
.setSmallIcon(R.drawable.ic_notification)
@@ -389,14 +390,14 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
Uri screenshotURI = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".screenshot_provider", new File(fullpath));
intent.setDataAndType(screenshotURI, "image/*");
- PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);
+ PendingIntent pIntent = PendingIntentUtils.getActivity(context, 0, intent, 0, false);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, screenshotURI);
- PendingIntent pendingShareIntent = PendingIntent.getActivity(context, 0, Intent.createChooser(shareIntent, "share screenshot"),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pendingShareIntent = PendingIntentUtils.getActivity(context, 0, Intent.createChooser(shareIntent, "share screenshot"),
+ PendingIntent.FLAG_UPDATE_CURRENT, false);
NotificationCompat.Action action = new NotificationCompat.Action.Builder(android.R.drawable.ic_menu_share, "share", pendingShareIntent).build();
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java
index a425fb0d9..dbfc5b860 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java
@@ -36,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService;
+import nodomain.freeyourgadget.gadgetbridge.util.PendingIntentUtils;
public class AutoConnectIntervalReceiver extends BroadcastReceiver {
@@ -101,7 +102,7 @@ public class AutoConnectIntervalReceiver extends BroadcastReceiver {
AlarmManager am = (AlarmManager) (GBApplication.getContext().getSystemService(Context.ALARM_SERVICE));
Intent intent = new Intent("GB_RECONNECT");
intent.setPackage(BuildConfig.APPLICATION_ID);
- PendingIntent pendingIntent = PendingIntent.getBroadcast(GBApplication.getContext(), 0, intent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getBroadcast(GBApplication.getContext(), 0, intent, 0, false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, Calendar.getInstance().
getTimeInMillis() + delay * 1000, pendingIntent);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java
index 4b850a78e..edcf372ae 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java
@@ -27,6 +27,7 @@ import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.Html;
@@ -146,8 +147,8 @@ public class GB {
Intent notificationIntent = new Intent(context, ControlCenterv2.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
- notificationIntent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getActivity(context, 0,
+ notificationIntent, 0, false);
return pendingIntent;
}
@@ -188,18 +189,18 @@ public class GB {
Intent deviceCommunicationServiceIntent = new Intent(context, DeviceCommunicationService.class);
if (connected) {
deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_DISCONNECT);
- PendingIntent disconnectPendingIntent = PendingIntent.getService(context, 0, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT);
+ PendingIntent disconnectPendingIntent = PendingIntentUtils.getService(context, 0, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT, false);
builder.addAction(R.drawable.ic_notification_disconnected, context.getString(R.string.controlcenter_disconnect), disconnectPendingIntent);
if (DeviceHelper.getInstance().getCoordinator(device).supportsActivityDataFetching()) {
deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_FETCH_RECORDED_DATA);
deviceCommunicationServiceIntent.putExtra(EXTRA_RECORDED_DATA_TYPES, ActivityKind.TYPE_ACTIVITY);
- PendingIntent fetchPendingIntent = PendingIntent.getService(context, 1, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT);
+ PendingIntent fetchPendingIntent = PendingIntentUtils.getService(context, 1, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT, false);
builder.addAction(R.drawable.ic_refresh, context.getString(R.string.controlcenter_fetch_activity_data), fetchPendingIntent);
}
} else if (device.getState().equals(GBDevice.State.WAITING_FOR_RECONNECT) || device.getState().equals(GBDevice.State.NOT_CONNECTED)) {
deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_CONNECT);
deviceCommunicationServiceIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
- PendingIntent reconnectPendingIntent = PendingIntent.getService(context, 2, deviceCommunicationServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent reconnectPendingIntent = PendingIntentUtils.getService(context, 2, deviceCommunicationServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT, false);
builder.addAction(R.drawable.ic_notification, context.getString(R.string.controlcenter_connect), reconnectPendingIntent);
}
}else{
@@ -243,7 +244,7 @@ public class GB {
Intent deviceCommunicationServiceIntent = new Intent(context, DeviceCommunicationService.class);
deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_FETCH_RECORDED_DATA);
deviceCommunicationServiceIntent.putExtra(EXTRA_RECORDED_DATA_TYPES, ActivityKind.TYPE_ACTIVITY);
- PendingIntent fetchPendingIntent = PendingIntent.getService(context, 1, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT);
+ PendingIntent fetchPendingIntent = PendingIntentUtils.getService(context, 1, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT, false);
builder.addAction(R.drawable.ic_refresh, context.getString(R.string.controlcenter_fetch_activity_data), fetchPendingIntent);
}
}
@@ -272,7 +273,7 @@ public class GB {
if (GBApplication.getPrefs().getString("last_device_address", null) != null) {
Intent deviceCommunicationServiceIntent = new Intent(context, DeviceCommunicationService.class);
deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_CONNECT);
- PendingIntent reconnectPendingIntent = PendingIntent.getService(context, 2, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT);
+ PendingIntent reconnectPendingIntent = PendingIntentUtils.getService(context, 2, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT, false);
builder.addAction(R.drawable.ic_notification, context.getString(R.string.controlcenter_connect), reconnectPendingIntent);
}
@@ -480,8 +481,8 @@ public class GB {
Intent notificationIntent = new Intent(context, ControlCenterv2.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
- notificationIntent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getActivity(context, 0,
+ notificationIntent, 0, false);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID_TRANSFER)
.setTicker((title == null) ? context.getString(R.string.app_name) : title)
@@ -515,7 +516,7 @@ public class GB {
public static void createGpsNotification(Context context, int numDevices) {
Intent notificationIntent = new Intent(context, ControlCenterv2.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getActivity(context, 0, notificationIntent, 0, false);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID_GPS)
.setTicker(context.getString(R.string.notification_gps_title))
@@ -538,8 +539,8 @@ public class GB {
Intent notificationIntent = new Intent(context, ControlCenterv2.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
- notificationIntent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getActivity(context, 0,
+ notificationIntent, 0, false);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle(context.getString(R.string.app_name))
@@ -568,8 +569,8 @@ public class GB {
Intent notificationIntent = new Intent(context, ControlCenterv2.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
- notificationIntent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getActivity(context, 0,
+ notificationIntent, 0, false);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID_LOW_BATTERY)
.setContentTitle(context.getString(R.string.notif_battery_low_title))
@@ -602,8 +603,8 @@ public class GB {
Intent notificationIntent = new Intent(context, SettingsActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
- notificationIntent, 0);
+ PendingIntent pendingIntent = PendingIntentUtils.getActivity(context, 0,
+ notificationIntent, 0, false);
NotificationCompat.Builder nb = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle(context.getString(R.string.notif_export_failed_title))
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/PendingIntentUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/PendingIntentUtils.java
new file mode 100644
index 000000000..eaedfd0d9
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/PendingIntentUtils.java
@@ -0,0 +1,61 @@
+package nodomain.freeyourgadget.gadgetbridge.util;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+
+public class PendingIntentUtils {
+
+ public static PendingIntent getBroadcast(Context context,
+ int requestCode,
+ Intent intent,
+ int flags,
+ boolean makeMutable) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (makeMutable) {
+ flags |= PendingIntent.FLAG_MUTABLE;
+ } else {
+ flags |= PendingIntent.FLAG_IMMUTABLE;
+ }
+ return PendingIntent.getBroadcast(context, requestCode, intent, flags);
+ }
+
+ return PendingIntent.getBroadcast(context, requestCode, intent, flags);
+ }
+
+ public static PendingIntent getActivity(Context context,
+ int requestCode,
+ Intent intent,
+ int flags,
+ boolean makeMutable) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (makeMutable) {
+ flags |= PendingIntent.FLAG_MUTABLE;
+ } else {
+ flags |= PendingIntent.FLAG_IMMUTABLE;
+ }
+ return PendingIntent.getActivity(context, requestCode, intent, flags);
+ }
+
+ return PendingIntent.getActivity(context, requestCode, intent, flags);
+ }
+
+ public static PendingIntent getService(Context context,
+ int requestCode,
+ Intent intent,
+ int flags,
+ boolean makeMutable) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (makeMutable) {
+ flags |= PendingIntent.FLAG_MUTABLE;
+ } else {
+ flags |= PendingIntent.FLAG_IMMUTABLE;
+ }
+ return PendingIntent.getService(context, requestCode, intent, flags);
+ }
+
+ return PendingIntent.getService(context, requestCode, intent, flags);
+ }
+
+}