mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-04 01:09:47 +01:00
Bangle.js: Bump flavor targetSdkVersion to 31
This also touches parts of the app not only used for bangle.js. E.g. pending intents gets new flags from SDK 23 inclusive. Bluetooth permissions are updated to work on SDK 31. Permission handling is updated to the new way for doing it with introduction of a new function. This is called for newer sdk versions. bump Bangle.js flavor targetSdkVersion to 31 update comments re SDK 31 set the 'exported=true' I introduced to false instead - except for three places add uses-permission for handling bluetooth in order to work on api >30 add if-blocks adding FLAG_IMMUTABLE to PendingIntents on api >30 add link to bluetooth documentation Add comment to banglejs manifest. Add requirement annotation to ControlCenterv bump compileSdkVersion to 31 add "OpenAppSettings" permission popup while working out individual permission popups on android 13 if SDK < 31 do permissions one by one, else send user to app info page to switch permissions manually working solution, but needs cleaning do some cleaning, not done though remove some logging remove import Log tweak and remove toasts in new permissions handling Change conditions `> Build.VERSION_CODES.Q` to `>= Build.VERSION_CODES.R` matching the style used everywhere else Revert "Change conditions `> Build.VERSION_CODES.Q` to `>= Build.VERSION_CODES.R` matching the style used everywhere else" This reverts commit 2929629ff43fbb685eb3d15e42459f321f68fa11. Revert "add if-blocks adding FLAG_IMMUTABLE to PendingIntents on api >30" This reverts commit ed8e1df7bb8b71fee745fbf9d10747d47c8f6cb8. Pending intents gets `PendingIntent.FLAG_IMMUTABLE` if `(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)`. Bangle.js: undo `@RequiresApi` code R ... to remove error in Android Studio where declared required api was higher then minSDK version. Use FLAG_MUTABLE for reply to test notification This should fix Gadgetbridge crashing when replying to the test notification from the debug activity. As reported here: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/2924#issuecomment-917282 Change to use FLAG_IMMUTABLE/_MUTABLE from SDK 23 ... as suggested by Android Studio. This is supposed to make the app more secure by not allowing certain changes to pending intents where they are not expected. If I understood correctly. Add PendingIntentUtils class to manage mutability
This commit is contained in:
parent
514f983299
commit
7d1de4a5e8
@ -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'
|
||||
|
@ -12,4 +12,34 @@
|
||||
-->
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||
|
||||
<!-- https://developer.android.com/guide/topics/connectivity/bluetooth/permissions -->
|
||||
<!-- Request legacy Bluetooth permissions on older devices. -->
|
||||
<!-- We do this in the main Android Manifest already, but without android:maxSdkVersion="30".
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
|
||||
android:maxSdkVersion="30" />
|
||||
-->
|
||||
|
||||
|
||||
<!-- Needed only if your app looks for Bluetooth devices.
|
||||
If your app doesn't use Bluetooth scan results to derive physical
|
||||
location information, you can strongly assert that your app
|
||||
doesn't derive physical location.
|
||||
|
||||
We need to ask the user for this permission, if it's not granted the app crashes when
|
||||
clicking the plus-button. -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
|
||||
<!-- Needed only if your app makes the device discoverable to Bluetooth
|
||||
devices. -->
|
||||
<!-- <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> -->
|
||||
|
||||
<!-- Needed only if your app communicates with already-paired Bluetooth
|
||||
devices. -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
|
||||
<!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
|
||||
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> -->
|
||||
|
||||
</manifest>
|
||||
|
@ -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">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
@ -134,7 +135,8 @@
|
||||
<activity
|
||||
android:name=".activities.FwAppInstallerActivity"
|
||||
android:label="@string/title_activity_fw_app_insaller"
|
||||
android:parentActivityName=".activities.ControlCenterv2">
|
||||
android:parentActivityName=".activities.ControlCenterv2"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
@ -355,7 +357,8 @@
|
||||
<service
|
||||
android:name=".externalevents.NotificationListener"
|
||||
android:label="@string/app_name"
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
</intent-filter>
|
||||
@ -368,7 +371,8 @@
|
||||
|
||||
<receiver
|
||||
android:name=".externalevents.GenericWeatherReceiver"
|
||||
android:enabled="true">
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="nodomain.freeyourgadget.gadgetbridge.ACTION_GENERIC_WEATHER" />
|
||||
</intent-filter>
|
||||
@ -376,13 +380,15 @@
|
||||
|
||||
<receiver
|
||||
android:name=".externalevents.WeatherNotificationReceiver"
|
||||
android:enabled="true">
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="ru.gelin.android.weather.notification.ACTION_WEATHER_UPDATE_2" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity android:name=".externalevents.WeatherNotificationConfig">
|
||||
<activity android:name=".externalevents.WeatherNotificationConfig"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="ru.gelin.android.weather.notification.ACTION_WEATHER_SKIN_PREFERENCES" />
|
||||
</intent-filter>
|
||||
@ -390,7 +396,8 @@
|
||||
|
||||
<receiver
|
||||
android:name=".externalevents.AutoStartReceiver"
|
||||
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
|
||||
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@ -583,7 +590,8 @@
|
||||
|
||||
<receiver
|
||||
android:name=".SleepAlarmWidget"
|
||||
android:label="@string/appwidget_sleep_alarm_widget_label">
|
||||
android:label="@string/appwidget_sleep_alarm_widget_label"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
<action android:name="nodomain.freeyourgadget.gadgetbridge.SLEEP_ALARM_WIDGET_CLICK" />
|
||||
@ -595,7 +603,8 @@
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".Widget"
|
||||
android:label="@string/widget_listing_label">
|
||||
android:label="@string/widget_listing_label"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
|
||||
@ -614,13 +623,15 @@
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog" />
|
||||
|
||||
<activity android:name=".activities.WidgetConfigurationActivity">
|
||||
<activity android:name=".activities.WidgetConfigurationActivity"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".activities.SleepAlarmWidgetConfigurationActivity">
|
||||
<activity android:name=".activities.SleepAlarmWidgetConfigurationActivity"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||
</intent-filter>
|
||||
@ -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">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="nodomain.freeyourgadget.gadgetbridge.activities.ControlCenterv2" />
|
||||
@ -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">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,16 +535,23 @@ 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);
|
||||
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...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
@ -530,6 +560,7 @@ public class ControlCenterv2 extends AppCompatActivity
|
||||
telephonyManager.listen(fakeStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setLanguage(Locale language, boolean invalidateLanguage) {
|
||||
if (invalidateLanguage) {
|
||||
@ -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<String[]> 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user