Android 12 foreground restrictions

pull/206/head
M66B 3 years ago
parent 0903fb77ea
commit 244b6df87e

@ -19,7 +19,7 @@ android {
defaultConfig {
applicationId "eu.faircode.email"
minSdkVersion 21
targetSdkVersion 30
targetSdkVersion 31
versionCode getVersionCode()
versionName "1." + getVersionCode()
archivesBaseName = "FairEmail-v$versionName"

@ -44,7 +44,7 @@ public class AlarmManagerCompatEx {
AlarmManagerCompat.setAndAllowWhileIdle(am, type, trigger, pi);
}
static boolean hasExactAlarms(Context context){
static boolean hasExactAlarms(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean exact_alarms = prefs.getBoolean("exact_alarms", true);
return (exact_alarms && canScheduleExactAlarms(context));
@ -53,10 +53,13 @@ public class AlarmManagerCompatEx {
static boolean canScheduleExactAlarms(Context context) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R)
return true;
else {
try {
// https://developer.android.com/about/versions/12/behavior-changes-12#exact-alarm-permission
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
return am.canScheduleExactAlarms();
} catch (Throwable ex) {
Log.e(ex);
return false;
}
}
}

@ -196,8 +196,10 @@ public class ApplicationEx extends Application
DisconnectBlacklist.init(this);
ServiceSynchronize.watchdog(this);
ServiceSend.watchdog(this);
if (!Helper.isOptimizing12(this)) {
ServiceSynchronize.watchdog(this);
ServiceSend.watchdog(this);
}
ServiceSynchronize.scheduleWatchdog(this);
WorkManager.getInstance(this).cancelUniqueWork("WorkerWatchdog");
@ -519,6 +521,9 @@ public class ApplicationEx extends Application
} else if (version < 1721) {
if (!prefs.contains("discard_delete"))
editor.putBoolean("discard_delete", false);
} else if (version < 1732) {
if (Helper.isOptimizing12(context))
editor.remove("setup_reminder");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !BuildConfig.DEBUG)

@ -174,12 +174,7 @@ public class EntityAccount extends EntityOrder implements Serializable {
}
boolean isExempted(Context context) {
if (Helper.isTarget(context, Build.VERSION_CODES.R)) {
Boolean ignoring = Helper.isIgnoringOptimizations(context);
if (ignoring != null && !ignoring)
return false;
}
return this.poll_exempted;
return (!Helper.isOptimizing12(context) && this.poll_exempted);
}
String getProtocol() {

@ -49,7 +49,7 @@ public class FragmentDialogStill extends FragmentDialogBase {
View dview = LayoutInflater.from(context).inflate(R.layout.dialog_setup, null);
TextView tvDozeDevice = dview.findViewById(R.id.tvDozeDevice);
TextView tvDozeAndroid = dview.findViewById(R.id.tvDozeAndroid);
ImageButton ibInfo = dview.findViewById(R.id.ibInfo);
TextView tvInexact = dview.findViewById(R.id.tvInexact);
CheckBox cbNotAgain = dview.findViewById(R.id.cbNotAgain);
Group grp2 = dview.findViewById(R.id.grp2);
Group grp3 = dview.findViewById(R.id.grp3);
@ -62,13 +62,6 @@ public class FragmentDialogStill extends FragmentDialogBase {
}
});
ibInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Helper.view(v.getContext(), Uri.parse(Helper.DONTKILL_URI), true);
}
});
cbNotAgain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@ -80,11 +73,12 @@ public class FragmentDialogStill extends FragmentDialogBase {
boolean hasPermissions = Helper.hasPermission(context, Manifest.permission.READ_CONTACTS);
Boolean isIgnoring = Helper.isIgnoringOptimizations(context);
boolean isKilling = Helper.isKilling() && !(isIgnoring == null || isIgnoring);
boolean isRequired = Helper.isDozeRequired() && !(isIgnoring == null || isIgnoring);
boolean isOptimizing = Helper.isOptimizing12(context);
boolean canSchedule = AlarmManagerCompatEx.canScheduleExactAlarms(context);
tvDozeDevice.setVisibility(isKilling && !isRequired ? View.VISIBLE : View.GONE);
tvDozeAndroid.setVisibility(isRequired ? View.VISIBLE : View.GONE);
cbNotAgain.setVisibility(isRequired ? View.GONE : View.VISIBLE);
tvDozeDevice.setVisibility(isKilling && !isOptimizing ? View.VISIBLE : View.GONE);
tvDozeAndroid.setVisibility(isOptimizing ? View.VISIBLE : View.GONE);
tvInexact.setVisibility(canSchedule ? View.GONE : View.VISIBLE);
grp2.setVisibility(hasPermissions ? View.GONE : View.VISIBLE);
grp3.setVisibility(isIgnoring == null || isIgnoring ? View.GONE : View.VISIBLE);
@ -96,10 +90,8 @@ public class FragmentDialogStill extends FragmentDialogBase {
public void onClick(DialogInterface dialog, int which) {
sendResult(Activity.RESULT_OK);
}
});
if (!isRequired)
builder.setNegativeButton(android.R.string.cancel, null);
})
.setNegativeButton(android.R.string.cancel, null);
return builder.create();
}

@ -4189,15 +4189,21 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (viewType != AdapterMessage.ViewType.UNIFIED)
return false;
if (!Helper.isDozeRequired())
final Context context = getContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean setup_reminder = prefs.getBoolean("setup_reminder", true);
if (!setup_reminder)
return false;
final Context context = getContext();
Boolean isIgnoring = Helper.isIgnoringOptimizations(context);
if (isIgnoring == null || isIgnoring)
boolean isOptimizing = Helper.isOptimizing12(context);
boolean canSchedule = AlarmManagerCompatEx.canScheduleExactAlarms(context);
if (!isOptimizing && canSchedule)
return false;
final Snackbar snackbar = Snackbar.make(view, R.string.title_setup_doze, Snackbar.LENGTH_INDEFINITE)
final Snackbar snackbar = Snackbar.make(view,
canSchedule ? R.string.title_setup_doze_12 : R.string.title_setup_alarm_12,
Snackbar.LENGTH_INDEFINITE)
.setGestureInsetBottomIgnored(true);
snackbar.setAction(R.string.title_fix, new View.OnClickListener() {
@Override

@ -556,7 +556,8 @@ public class FragmentOptionsSynchronize extends FragmentBase implements SharedPr
}
private void bindTo(EntityAccount account) {
cbExempted.setEnabled(!account.ondemand && account.protocol == EntityAccount.TYPE_IMAP);
cbExempted.setEnabled(!Helper.isOptimizing12(context) &&
!account.ondemand && account.protocol == EntityAccount.TYPE_IMAP);
cbExempted.setChecked(account.poll_exempted);
cbExempted.setText(account.name);
}

@ -93,6 +93,7 @@ public class FragmentSetup extends FragmentBase {
private TextView tvDozeDone;
private Button btnDoze;
private TextView tvDoze12;
private Button btnInexactAlarms;
private Button btnBackgroundRestricted;
@ -158,6 +159,7 @@ public class FragmentSetup extends FragmentBase {
tvDozeDone = view.findViewById(R.id.tvDozeDone);
btnDoze = view.findViewById(R.id.btnDoze);
tvDoze12 = view.findViewById(R.id.tvDoze12);
btnInexactAlarms = view.findViewById(R.id.btnInexactAlarms);
btnBackgroundRestricted = view.findViewById(R.id.btnBackgroundRestricted);
@ -534,6 +536,7 @@ public class FragmentSetup extends FragmentBase {
tvDozeDone.setText(null);
tvDozeDone.setCompoundDrawables(null, null, null, null);
btnDoze.setEnabled(false);
tvDoze12.setVisibility(View.GONE);
btnInbox.setEnabled(false);
@ -660,9 +663,10 @@ public class FragmentSetup extends FragmentBase {
tvDozeDone.setTextColor(ignoring == null || ignoring ? textColorPrimary : colorWarning);
tvDozeDone.setTypeface(null, ignoring == null || ignoring ? Typeface.NORMAL : Typeface.BOLD);
tvDozeDone.setCompoundDrawablesWithIntrinsicBounds(ignoring == null || ignoring ? check : null, null, null, null);
tvDoze12.setVisibility(Helper.isOptimizing12(getContext()) ? View.VISIBLE : View.GONE);
grpInexactAlarms.setVisibility(
!AlarmManagerCompatEx.canScheduleExactAlarms(getContext())
!AlarmManagerCompatEx.canScheduleExactAlarms(getContext()) || BuildConfig.DEBUG
? View.VISIBLE : View.GONE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {

@ -433,20 +433,12 @@ public class Helper {
return pm.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID);
}
private static Integer targetSdk = null;
static boolean isTarget(Context context, int sdk) {
if (targetSdk == null)
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
targetSdk = ai.targetSdkVersion;
} catch (Throwable ex) {
Log.e(ex);
targetSdk = Build.VERSION.SDK_INT;
}
static boolean isOptimizing12(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S)
return false;
return (targetSdk >= sdk);
Boolean ignoring = Helper.isIgnoringOptimizations(context);
return (ignoring != null && !ignoring);
}
static Integer getBatteryLevel(Context context) {

@ -2721,11 +2721,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
}
static int getPollInterval(Context context) {
if (Helper.isTarget(context, Build.VERSION_CODES.R)) {
Boolean ignoring = Helper.isIgnoringOptimizations(context);
if (ignoring != null && !ignoring)
return 15;
}
if (Helper.isOptimizing12(context))
return (BuildConfig.DEBUG ? 2 : 15);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getInt("poll_interval", 0); // minutes

@ -89,7 +89,7 @@
android:id="@+id/tvDozeDevice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginTop="12dp"
android:drawableEnd="@drawable/twotone_open_in_new_12"
android:drawablePadding="6dp"
android:drawableTint="?attr/colorWarning"
@ -104,24 +104,25 @@
android:id="@+id/tvDozeAndroid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/title_setup_doze_android"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:layout_marginTop="12dp"
android:text="@string/title_setup_doze_12"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvDozeDevice" />
<ImageButton
android:id="@+id/ibInfo"
<eu.faircode.email.FixedTextView
android:id="@+id/tvInexact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:contentDescription="@string/title_info"
android:tooltipText="@string/title_info"
android:layout_marginTop="12dp"
android:text="@string/title_setup_alarm_12"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvDozeAndroid"
app:srcCompat="@drawable/twotone_info_24" />
app:layout_constraintTop_toBottomOf="@id/tvDozeAndroid" />
<CheckBox
android:id="@+id/cbNotAgain"
@ -131,7 +132,7 @@
android:text="@string/title_no_ask_again"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ibInfo" />
app:layout_constraintTop_toBottomOf="@id/tvInexact" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grp2"
@ -143,6 +144,6 @@
android:id="@+id/grp3"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="three,title3,tvDoze,ibInfo" />
app:constraint_referenced_ids="three,title3,tvDoze" />
</androidx.constraintlayout.widget.ConstraintLayout>
</eu.faircode.email.ScrollViewEx>

@ -703,17 +703,41 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnDoze" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvDoze12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_setup_doze_12"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvDozeHint" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvInexactAlarms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_setup_inexact"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvDozeHint" />
app:layout_constraintTop_toBottomOf="@id/tvDoze12" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvInexactAlarmsWarning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/title_setup_alarm_12"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvInexactAlarms" />
<Button
android:id="@+id/btnInexactAlarms"
@ -726,7 +750,7 @@
android:drawablePadding="6dp"
android:text="@string/title_setup_manage"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvInexactAlarms" />
app:layout_constraintTop_toBottomOf="@id/tvInexactAlarmsWarning" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvBackgroundRestricted"
@ -734,7 +758,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_setup_background"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
@ -759,7 +783,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_setup_data"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?attr/colorWarning"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
@ -825,7 +849,7 @@
android:id="@+id/grpInexactAlarms"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvInexactAlarms,btnInexactAlarms" />
app:constraint_referenced_ids="tvInexactAlarms,tvInexactAlarmsWarning,btnInexactAlarms" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpBackgroundRestricted"

@ -226,7 +226,8 @@
<string name="title_setup_doze_battery">High battery usage?</string>
<string name="title_setup_doze_stopped">Sync stopped?</string>
<string name="title_setup_doze_device">This is probably required for this device</string>
<string name="title_setup_doze_android">This is required for this Android version</string>
<string name="title_setup_doze_12">Push messages are disabled</string>
<string name="title_setup_alarm_12">The app won\'t work</string>
<string name="title_setup_inexact">Alarms &amp; reminders are disabled</string>
<string name="title_setup_background">Background restrictions are enabled</string>
<string name="title_setup_data">Data saver is enabled</string>

Loading…
Cancel
Save