Browse Source

fix: compatibly with SDK API 21

main
Distopico Vegan 4 years ago
parent
commit
9005f7c69a
No known key found for this signature in database GPG Key ID: 98093A8072546BF3
7 changed files with 172 additions and 47 deletions
  1. +7
    -3
      app/src/main/java/org/dystopia/email/FragmentAbout.java
  2. +5
    -3
      app/src/main/java/org/dystopia/email/FragmentCompose.java
  3. +5
    -2
      app/src/main/java/org/dystopia/email/FragmentEx.java
  4. +9
    -2
      app/src/main/java/org/dystopia/email/FragmentSetup.java
  5. +4
    -1
      app/src/main/java/org/dystopia/email/JobDaily.java
  6. +38
    -36
      app/src/main/java/org/dystopia/email/ServiceSynchronize.java
  7. +104
    -0
      app/src/main/java/org/dystopia/email/util/CompatibilityUtils.java

+ 7
- 3
app/src/main/java/org/dystopia/email/FragmentAbout.java View File

@ -36,6 +36,9 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentTransaction;
import org.dystopia.email.util.CompatibilityUtils;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
@ -69,7 +72,9 @@ public class FragmentAbout extends FragmentEx {
btnLog = view.findViewById(R.id.btnLog);
btnDebugInfo = view.findViewById(R.id.btnDebugInfo);
tvVersion.setText(getString(R.string.title_version, BuildConfig.VERSION_NAME));
int version = R.string.title_version;
String versionName = getString(version, BuildConfig.VERSION_NAME);
tvVersion.setText(versionName);
btnLog.setOnClickListener(
new View.OnClickListener() {
@ -126,8 +131,7 @@ public class FragmentAbout extends FragmentEx {
sb.append(String.format(locale, "Id: %s\r\n", Build.ID));
sb.append("\r\n");
PowerManager pm = getContext().getSystemService(PowerManager.class);
boolean ignoring = pm.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID);
boolean ignoring = CompatibilityUtils.isIgnoringOptimizations(getContext());
sb.append(String.format(locale, "Battery optimizations: %b\r\n", !ignoring));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {


+ 5
- 3
app/src/main/java/org/dystopia/email/FragmentCompose.java View File

@ -100,6 +100,8 @@ import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.dystopia.email.util.CompatibilityUtils;
import org.openintents.openpgp.OpenPgpError;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
@ -483,9 +485,9 @@ public class FragmentCompose extends FragmentEx {
break;
case R.id.menu_link:
Uri uri = null;
ClipboardManager cbm = getContext().getSystemService(ClipboardManager.class);
if (cbm.hasPrimaryClip()) {
String link = cbm.getPrimaryClip().getItemAt(0).coerceToText(getContext()).toString();
ClipboardManager clipboardManager = CompatibilityUtils.getClipboardManager(getContext());
if (clipboardManager.hasPrimaryClip()) {
String link = clipboardManager.getPrimaryClip().getItemAt(0).coerceToText(getContext()).toString();
uri = Uri.parse(link);
if (uri.getScheme() == null) {
uri = null;


+ 5
- 2
app/src/main/java/org/dystopia/email/FragmentEx.java View File

@ -20,6 +20,7 @@ package org.dystopia.email;
Copyright 2018-2020, Distopico (dystopia project) <distopico@riseup.net> and contributors
*/
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
@ -32,6 +33,8 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import org.dystopia.email.util.CompatibilityUtils;
public class FragmentEx extends Fragment {
private String title = "";
private String subtitle = " ";
@ -113,10 +116,10 @@ public class FragmentEx extends Fragment {
public void onDetach() {
super.onDetach();
InputMethodManager im = getContext().getSystemService(InputMethodManager.class);
InputMethodManager inputMethodManager = CompatibilityUtils.getInputMethodManager(getContext());
View focused = getActivity().getCurrentFocus();
if (focused != null) {
im.hideSoftInputFromWindow(focused.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}


+ 9
- 2
app/src/main/java/org/dystopia/email/FragmentSetup.java View File

@ -67,6 +67,7 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import org.dystopia.email.util.CompatibilityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
@ -369,8 +370,14 @@ public class FragmentSetup extends FragmentEx {
public void onResume() {
super.onResume();
PowerManager pm = getContext().getSystemService(PowerManager.class);
boolean ignoring = pm.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID);
boolean ignoring = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
PackageManager packageManager = getContext().getPackageManager();
if (intent.resolveActivity(packageManager) != null) { // system whitelisted
ignoring = CompatibilityUtils.isIgnoringOptimizations(getContext());
}
}
btnDoze.setEnabled(!ignoring);
tvDozeDone.setText(ignoring ? R.string.title_setup_done : R.string.title_setup_to_do);
tvDozeDone.setCompoundDrawablesWithIntrinsicBounds(ignoring ? check : null, null, null, null);


+ 4
- 1
app/src/main/java/org/dystopia/email/JobDaily.java View File

@ -26,6 +26,9 @@ import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.util.Log;
import org.dystopia.email.util.CompatibilityUtils;
import java.io.File;
import java.util.Date;
import java.util.concurrent.ExecutorService;
@ -45,7 +48,7 @@ public class JobDaily extends JobService {
.setPeriodic(CLEANUP_INTERVAL)
.setRequiresDeviceIdle(true);
JobScheduler scheduler = context.getSystemService(JobScheduler.class);
JobScheduler scheduler = CompatibilityUtils.getJobScheduler(context);
scheduler.cancel(Helper.JOB_DAILY);
if (scheduler.schedule(job.build()) == JobScheduler.RESULT_SUCCESS) {
Log.i(Helper.TAG, "Scheduled daily job");


+ 38
- 36
app/src/main/java/org/dystopia/email/ServiceSynchronize.java View File

@ -114,6 +114,8 @@ import javax.mail.internet.MimeMessage;
import javax.mail.search.ComparisonTerm;
import javax.mail.search.ReceivedDateTerm;
import javax.net.ssl.SSLException;
import org.dystopia.email.util.CompatibilityUtils;
import org.json.JSONArray;
import org.json.JSONException;
@ -160,8 +162,8 @@ public class ServiceSynchronize extends LifecycleService {
db.account().liveStats().observe(this, new Observer<TupleAccountStats>() {
@Override
public void onChanged(@Nullable TupleAccountStats stats) {
NotificationManager nm = getSystemService(NotificationManager.class);
nm.notify(NOTIFICATION_SYNCHRONIZE, getNotificationService(stats).build());
NotificationManager notificationManager = CompatibilityUtils.getNotificationManger(getBaseContext());
notificationManager.notify(NOTIFICATION_SYNCHRONIZE, getNotificationService(stats).build());
}
});
@ -171,7 +173,7 @@ public class ServiceSynchronize extends LifecycleService {
@Override
public void onChanged(List<TupleNotification> messages) {
NotificationManager nm = getSystemService(NotificationManager.class);
NotificationManager notificationManager = CompatibilityUtils.getNotificationManger(getBaseContext());
LongSparseArray<List<TupleNotification>> messagesByAccount = new LongSparseArray<>();
LongSparseArray<List<Integer>> removed = notifying.clone();
@ -179,7 +181,7 @@ public class ServiceSynchronize extends LifecycleService {
setWidgetUnseen(messages);
if (messages.size() == 0) {
nm.cancelAll();
notificationManager.cancelAll();
return;
}
@ -232,7 +234,7 @@ public class ServiceSynchronize extends LifecycleService {
Integer id = (int) notification.extras.getLong("id", 0);
if ((id == 0 && added.size() > 0) || added.contains(id)) {
nm.notify(tag, id, notification);
notificationManager.notify(tag, id, notification);
}
}
@ -247,7 +249,7 @@ public class ServiceSynchronize extends LifecycleService {
String tag = "unseen-" + accountId;
for (Integer id : notifyRemove) {
nm.cancel(tag, id);
notificationManager.cancel(tag, id);
}
}
}
@ -267,8 +269,8 @@ public class ServiceSynchronize extends LifecycleService {
stopForeground(true);
NotificationManager nm = getSystemService(NotificationManager.class);
nm.cancel(NOTIFICATION_SYNCHRONIZE);
NotificationManager notificationManager = CompatibilityUtils.getNotificationManger(this);
notificationManager.cancel(NOTIFICATION_SYNCHRONIZE);
super.onDestroy();
}
@ -574,10 +576,10 @@ public class ServiceSynchronize extends LifecycleService {
PendingIntent piTrash = PendingIntent.getService(this, PI_TRASH, trash, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Action.Builder actionSeen = new Notification.Action.Builder(
Icon.createWithResource(this, R.drawable.baseline_visibility_24), getString(R.string.title_seen), piSeen);
R.drawable.baseline_visibility_24, getString(R.string.title_seen), piSeen);
Notification.Action.Builder actionTrash = new Notification.Action.Builder(
Icon.createWithResource(this, R.drawable.baseline_delete_24), getString(R.string.title_trash), piTrash);
R.drawable.baseline_delete_24, getString(R.string.title_trash), piTrash);
Notification.Builder mbuilder = Helper.getNotificationBuilder(this, channelId);
Notification.InboxStyle mstyle = new Notification.InboxStyle();
@ -652,8 +654,8 @@ public class ServiceSynchronize extends LifecycleService {
EntityLog.log(this, action + " " + Helper.formatThrowable(ex));
if (ex instanceof SendFailedException) {
NotificationManager nm = getSystemService(NotificationManager.class);
nm.notify(action, 1, getNotificationError(action, ex).build());
NotificationManager notificationManager = CompatibilityUtils.getNotificationManger(this);
notificationManager.notify(action, 1, getNotificationError(action, ex).build());
}
if (BuildConfig.DEBUG && !(ex instanceof SendFailedException) && !(ex instanceof MailConnectException)
@ -666,14 +668,14 @@ public class ServiceSynchronize extends LifecycleService {
&& !(ex instanceof MessagingException && ex.getCause() instanceof SocketTimeoutException)
&& !(ex instanceof MessagingException && ex.getCause() instanceof SSLException)
&& !(ex instanceof MessagingException && "connection failure".equals(ex.getMessage()))) {
NotificationManager nm = getSystemService(NotificationManager.class);
nm.notify(action, 1, getNotificationError(action, ex).build());
NotificationManager notificationManager = CompatibilityUtils.getNotificationManger(this);
notificationManager.notify(action, 1, getNotificationError(action, ex).build());
}
}
private void monitorAccount(final EntityAccount account, final ServiceState state) throws NoSuchProviderException {
final PowerManager pm = getSystemService(PowerManager.class);
final PowerManager.WakeLock wl0 = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
final PowerManager powerManager = CompatibilityUtils.getPowerManager(getBaseContext());
final PowerManager.WakeLock wl0 = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
BuildConfig.APPLICATION_ID + ":account." + account.id + ".monitor");
try {
wl0.acquire();
@ -702,7 +704,7 @@ public class ServiceSynchronize extends LifecycleService {
try {
// Listen for store events
istore.addStoreListener(new StoreListener() {
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
BuildConfig.APPLICATION_ID + ":account." + account.id + ".store");
@Override
@ -721,7 +723,7 @@ public class ServiceSynchronize extends LifecycleService {
// Listen for folder events
istore.addFolderListener(new FolderAdapter() {
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
BuildConfig.APPLICATION_ID + ":account." + account.id + ".folder");
@Override
@ -822,7 +824,7 @@ public class ServiceSynchronize extends LifecycleService {
// Synchronize folder
Thread sync = new Thread(new Runnable() {
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
BuildConfig.APPLICATION_ID + ":account." + account.id + ".sync");
@Override
@ -1033,7 +1035,7 @@ public class ServiceSynchronize extends LifecycleService {
@Override
public void onReceive(Context context, final Intent intent) {
executor.submit(new Runnable() {
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
BuildConfig.APPLICATION_ID + ":account." + account.id + ".process");
@Override
@ -1150,13 +1152,13 @@ public class ServiceSynchronize extends LifecycleService {
registerReceiver(alarm, new IntentFilter(id));
// Keep alive
AlarmManager am = getSystemService(AlarmManager.class);
AlarmManager alarmManager = CompatibilityUtils.getAlarmManager(this);
try {
while (state.running) {
// Schedule keep alive alarm
EntityLog.log(this, account.name + " wait=" + account.poll_interval);
am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + account.poll_interval * 60 * 1000L, pi);
CompatibilityUtils.setAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + account.poll_interval * 60 * 1000L, pi);
try {
wl0.release();
@ -1185,7 +1187,7 @@ public class ServiceSynchronize extends LifecycleService {
}
} finally {
// Cleanup
am.cancel(pi);
alarmManager.cancel(pi);
unregisterReceiver(alarm);
lbm.unregisterReceiver(processFolder);
}
@ -2027,8 +2029,8 @@ public class ServiceSynchronize extends LifecycleService {
List<EntityAttachment> attachments = db.attachment().getAttachments(message.id);
MessageHelper helper = new MessageHelper(imessage);
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
boolean metered = (cm == null || cm.isActiveNetworkMetered());
ConnectivityManager connectivityManager = CompatibilityUtils.getConnectivityManager(context);
boolean metered = (connectivityManager == null || connectivityManager.isActiveNetworkMetered());
boolean fetch = false;
if (!message.content) {
@ -2102,8 +2104,8 @@ public class ServiceSynchronize extends LifecycleService {
@Override
public void onAvailable(Network network) {
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
NetworkInfo ni = cm.getNetworkInfo(network);
ConnectivityManager connectivityManager = CompatibilityUtils.getConnectivityManager(ServiceSynchronize.this);
NetworkInfo ni = connectivityManager.getNetworkInfo(network);
EntityLog.log(ServiceSynchronize.this,
"Network available " + network + " running=" + running + " " + ni);
@ -2124,8 +2126,8 @@ public class ServiceSynchronize extends LifecycleService {
EntityLog.log(ServiceSynchronize.this, "Network lost " + network + " running=" + running);
if (running) {
ConnectivityManager cm = getSystemService(ConnectivityManager.class);
NetworkInfo ani = (network == null ? null : cm.getActiveNetworkInfo());
ConnectivityManager connectivityManager = CompatibilityUtils.getConnectivityManager(ServiceSynchronize.this);
NetworkInfo ani = (network == null ? null : connectivityManager.getActiveNetworkInfo());
EntityLog.log(ServiceSynchronize.this,
"Network active=" + (ani == null ? null : ani.toString()));
if (ani == null || !ani.isConnected()) {
@ -2151,9 +2153,9 @@ public class ServiceSynchronize extends LifecycleService {
@Override
public void run() {
PowerManager pm = getSystemService(PowerManager.class);
PowerManager powerManager = CompatibilityUtils.getPowerManager(ServiceSynchronize.this);
PowerManager.WakeLock wl =
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":start");
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":start");
try {
wl.acquire();
@ -2259,9 +2261,9 @@ public class ServiceSynchronize extends LifecycleService {
}
private void stop() {
PowerManager pm = getSystemService(PowerManager.class);
PowerManager powerManager = CompatibilityUtils.getPowerManager(ServiceSynchronize.this);
PowerManager.WakeLock wl =
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":stop");
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":stop");
try {
wl.acquire();
EntityLog.log(ServiceSynchronize.this, "Main stop");
@ -2324,8 +2326,8 @@ public class ServiceSynchronize extends LifecycleService {
executor.submit(new Runnable() {
@Override
public void run() {
PowerManager pm = getSystemService(PowerManager.class);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
PowerManager powerManager = CompatibilityUtils.getPowerManager(context);
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
BuildConfig.APPLICATION_ID + ":outbox");
try {


+ 104
- 0
app/src/main/java/org/dystopia/email/util/CompatibilityUtils.java View File

@ -0,0 +1,104 @@
package org.dystopia.email.util;
/*
This file is part of SimpleEmail.
SimpleEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
SimpleEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SimpleEmail. If not, see <http://www.gnu.org/licenses/>.
Copyright 2018-2020, Distopico (dystopia project) <distopico@riseup.net> and contributors
*/
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.job.JobScheduler;
import android.content.ClipboardManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.PowerManager;
import android.view.inputmethod.InputMethodManager;
import org.dystopia.email.BuildConfig;
public class CompatibilityUtils {
static public NotificationManager getNotificationManger(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return context.getSystemService(NotificationManager.class);
}
return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
static public PowerManager getPowerManager(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return context.getSystemService(PowerManager.class);
}
return (PowerManager) context.getSystemService(Context.POWER_SERVICE);
}
static public AlarmManager getAlarmManager(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return context.getSystemService(AlarmManager.class);
}
return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
static public ConnectivityManager getConnectivityManager(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return context.getSystemService(ConnectivityManager.class);
}
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
static public InputMethodManager getInputMethodManager(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return context.getSystemService(InputMethodManager.class);
}
return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
}
static public JobScheduler getJobScheduler(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return context.getSystemService(JobScheduler.class);
} else {
return (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
}
}
static public ClipboardManager getClipboardManager(Context context) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
return context.getSystemService(ClipboardManager.class);
}
return (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
}
static public Boolean isIgnoringOptimizations(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PowerManager powerManager = getPowerManager(context);
if (powerManager != null) {
return powerManager.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID);
}
}
return true;
}
static public void setAndAllowWhileIdle(AlarmManager alarmManager, int type, long triggerAtMillis, PendingIntent operation) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation);
return;
}
alarmManager.setExact(type, triggerAtMillis, operation);
}
}

Loading…
Cancel
Save