diff --git a/MessengerProj/build.gradle b/MessengerProj/build.gradle
index 3bccad1f1..2616a47aa 100644
--- a/MessengerProj/build.gradle
+++ b/MessengerProj/build.gradle
@@ -76,7 +76,7 @@ android {
}
}
- defaultConfig.versionCode = 24
+ defaultConfig.versionCode = 26
sourceSets.main {
jniLibs.srcDir 'libs'
@@ -117,6 +117,6 @@ android {
defaultConfig {
minSdkVersion 14 // 14: Android 4.0 Ice Cream Sandwich 2011 (Telegram default), 21: Android 5.0 Lollipop 2014 (recommended for InstantRun)
targetSdkVersion 25 // 25: Nougat. CAVE: Do NOT target "Andoid O" without checking the background tasks carefully, see https://developer.android.com/preview/behavior-changes.html#back-all . As long as we target "Nougat", everything works as expected even for "Andoid O" or later
- versionName "0.1.25" // do NOT forget to increase defaultConfig.versionCode!
+ versionName "0.1.26" // do NOT forget to increase defaultConfig.versionCode!
}
}
diff --git a/MessengerProj/src/main/AndroidManifest.xml b/MessengerProj/src/main/AndroidManifest.xml
index 91352d3d0..84d6f686a 100644
--- a/MessengerProj/src/main/AndroidManifest.xml
+++ b/MessengerProj/src/main/AndroidManifest.xml
@@ -40,6 +40,7 @@
+
diff --git a/MessengerProj/src/main/java/com/b44t/messenger/ApplicationLoader.java b/MessengerProj/src/main/java/com/b44t/messenger/ApplicationLoader.java
index 300a59ded..381869df5 100644
--- a/MessengerProj/src/main/java/com/b44t/messenger/ApplicationLoader.java
+++ b/MessengerProj/src/main/java/com/b44t/messenger/ApplicationLoader.java
@@ -203,20 +203,7 @@ public class ApplicationLoader extends Application {
UserConfig.loadConfig();
// create a timer that wakes up the CPU from time to time
- try
- {
- Intent intent = new Intent(applicationContext, TimerReceiver.class);
- PendingIntent alarmIntent = PendingIntent.getBroadcast(applicationContext, 0, intent, 0);
-
- AlarmManager alarmManager = (AlarmManager)applicationContext.getSystemService(Activity.ALARM_SERVICE);
- alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime()+60*1000,
- 60*1000,
- alarmIntent);
- }
- catch( Exception e) {
- Log.e("DeltaChat", "Cannot create alarm.");
- }
+ TimerReceiver.scheduleNextAlarm();
// make sure, the notifications for the "deaddrop" dialog are muted by default
SharedPreferences notificationPreferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
@@ -273,6 +260,6 @@ public class ApplicationLoader extends Application {
public static void stayAwakeForAMoment()
{
- stayAwakeWakeLock.acquire(10*60*1000); // 10 Minutes to wait for "after chat" messages, after that, we sleep most time, see wakeupWakeLock
+ stayAwakeWakeLock.acquire(1*60*1000); // 1 Minute to wait for "after chat" messages, after that, we sleep most time, see wakeupWakeLock
}
}
diff --git a/MessengerProj/src/main/java/com/b44t/messenger/TimerReceiver.java b/MessengerProj/src/main/java/com/b44t/messenger/TimerReceiver.java
index 36e93bf89..7d4c7cd5a 100644
--- a/MessengerProj/src/main/java/com/b44t/messenger/TimerReceiver.java
+++ b/MessengerProj/src/main/java/com/b44t/messenger/TimerReceiver.java
@@ -22,18 +22,49 @@
package com.b44t.messenger;
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import android.util.Log;
public class TimerReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
+
+ // acquire for 3 seconds, this should wake up the threads,
+ // _if_ there is more to do, the backend acquires an additional wakelock using MR_EVENT_WAKE_LOCK
+ ApplicationLoader.wakeupWakeLock.acquire(3*1000); // do this first!
Log.i("DeltaChat", "*** TimerReceiver.onReceive()");
- // acquire for 5 seconds, this should wake un the threads,
- // _if_ there is more to do, the backend acquires an additional wakelock using MR_EVENT_WAKE_LOCK
- ApplicationLoader.wakeupWakeLock.acquire(5*1000);
+ // we assume, the IMAP thread is alive. I cannot imagine, the thread was killed with the App being running.
+ // (if the whole App was killed, the IMAP thread is already started by MrMailbox.connect() if we're here)
+ // (the thread itself will reconnect to the IMAP server as needed)
+
+ // create the next alarm in about a minute
+ scheduleNextAlarm();
+ }
+
+ public static void scheduleNextAlarm()
+ {
+ try {
+ Intent intent = new Intent(ApplicationLoader.applicationContext, TimerReceiver.class);
+ PendingIntent alarmIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, intent, 0);
+
+ long triggerAtMillis = System.currentTimeMillis() + 60 * 1000;
+
+ AlarmManager alarmManager = (AlarmManager) ApplicationLoader.applicationContext.getSystemService(Activity.ALARM_SERVICE);
+ if( Build.VERSION.SDK_INT >= 23 ) {
+ // a simple AlarmManager.set() is no longer send in the new DOZE mode
+ alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, alarmIntent);
+ }
+ else {
+ alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAtMillis, alarmIntent);
+ }
+ }
+ catch(Exception e) { Log.e("DeltaChat", "Cannot create alarm.", e); }
}
}
diff --git a/MessengerProj/src/main/java/com/b44t/ui/ActionBar/BaseFragment.java b/MessengerProj/src/main/java/com/b44t/ui/ActionBar/BaseFragment.java
index 0151eaeda..a76e7ad6b 100644
--- a/MessengerProj/src/main/java/com/b44t/ui/ActionBar/BaseFragment.java
+++ b/MessengerProj/src/main/java/com/b44t/ui/ActionBar/BaseFragment.java
@@ -60,7 +60,8 @@ public class BaseFragment {
RC13_AVATAR_IMAGE_CAPTURE = 13,
RC14_AVATAR_GET_CONTENT = 14,
RC21_CHAT_PICK_WO_COMPR = 21,
- RC500_PHOTO_VIEW = 500;
+ RC500_PHOTO_VIEW = 500,
+ RC600_BATTERY_REQUEST_DONE = 600;
public BaseFragment() {
classGuid = ApplicationLoader.generateClassGuid();
diff --git a/MessengerProj/src/main/java/com/b44t/ui/DialogsActivity.java b/MessengerProj/src/main/java/com/b44t/ui/DialogsActivity.java
index a3f527a57..bbb563f59 100644
--- a/MessengerProj/src/main/java/com/b44t/ui/DialogsActivity.java
+++ b/MessengerProj/src/main/java/com/b44t/ui/DialogsActivity.java
@@ -32,11 +32,16 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Outline;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -53,6 +58,7 @@ import android.widget.TextView;
import com.b44t.messenger.AndroidUtilities;
import com.b44t.messenger.ApplicationLoader;
+import com.b44t.messenger.FileLog;
import com.b44t.messenger.ImageLoader;
import com.b44t.messenger.LocaleController;
import com.b44t.messenger.MrChat;
@@ -516,30 +522,107 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
dialogsSearchAdapter.notifyDataSetChanged();
}
if (checkPermission && !onlySelect && Build.VERSION.SDK_INT >= 23) {
- Activity activity = getParentActivity();
- if (activity != null) {
- checkPermission = false;
- if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED || activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- askForPermissons();
+ checkPermission = false;
+ askForIgnoreBatteryOptimization(); // after that, requestForOtherPermissions() is called
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ private void askForIgnoreBatteryOptimization() {
+ boolean requestIgnoreActivityStarted = false;
+
+ try {
+ String packageName = ApplicationLoader.applicationContext.getPackageName();
+ PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
+ if (!pm.isIgnoringBatteryOptimizations(packageName)) {
+
+ // As FCM (was: GCM) does not support IMAP servers and there are other server involved,
+ // the only possibility for us to get notified about new messages, is to keep the connection to the server alive.
+ // This is done by ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS.
+ //
+ // This is an "Acceptable Use Cases for Whitelisting", see
+ // https://developer.android.com/training/monitoring-device-state/doze-standby.html#whitelisting-cases
+ // "Instant messaging, chat, or calling app; enterprise VOIP apps |
+ // No, can't use FCM because of technical dependency on another messaging service or Doze and App Standby break the core function of the app |
+ // Acceptable"
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
+ intent.setData(Uri.parse("package:" + packageName));
+ getParentActivity().startActivityForResult(intent, BaseFragment.RC600_BATTERY_REQUEST_DONE);
+ requestIgnoreActivityStarted = true;
+ }
+ } catch (Exception e) {
+ Log.e("DeltaChat", "cannot ignore battery optimizations.", e);
+ }
+
+ if( !requestIgnoreActivityStarted ) {
+ askForOtherPermissons(); // otherwise, it gets started on RC600_BATTERY_REQUEST_DONE
+ }
+ }
+
+ @Override
+ public void onActivityResultFragment(int requestCode, int resultCode, Intent data) {
+ if (requestCode == BaseFragment.RC600_BATTERY_REQUEST_DONE) {
+ boolean requestIgnoreActivityMaybeRestarted = false;
+
+ if( Build.VERSION.SDK_INT >= 23 ) {
+ PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
+ if (!pm.isIgnoringBatteryOptimizations(ApplicationLoader.applicationContext.getPackageName())) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
+ builder.setMessage(AndroidUtilities.replaceTags(ApplicationLoader.applicationContext.getString(R.string.PermissionBattery)));
+ builder.setPositiveButton(ApplicationLoader.applicationContext.getString(R.string.OK), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ askForIgnoreBatteryOptimization();
+ }
+ });
+ builder.setCancelable(false);
+ builder.setNegativeButton(ApplicationLoader.applicationContext.getString(R.string.Cancel), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ askForOtherPermissons();
+ }
+ });
+ builder.show();
+ requestIgnoreActivityMaybeRestarted = true;
+
+ /*-- this is an alternative implementation to the alert above
+ IF we use this, we should handle the situation, ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS cannot be started due to a missing REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission
+ checkPermission = true;
+ getParentActivity().finish();
+ return;
+ */
}
}
+
+ if( !requestIgnoreActivityMaybeRestarted ) {
+ askForOtherPermissons();
+ }
}
}
@TargetApi(Build.VERSION_CODES.M)
- private void askForPermissons() {
+ private void askForOtherPermissons() {
Activity activity = getParentActivity();
if (activity == null) {
return;
}
+
+ if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
+ && activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
+ return; // everything is fine
+ }
+
ArrayList permissons = new ArrayList<>();
if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
permissons.add(Manifest.permission.READ_CONTACTS);
}
+
if (activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissons.add(Manifest.permission.READ_EXTERNAL_STORAGE);
permissons.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
+
String[] items = permissons.toArray(new String[permissons.size()]);
activity.requestPermissions(items, LaunchActivity.REQ_CONTACT_N_STORAGE_PERMISON_ID);
}
diff --git a/MessengerProj/src/main/java/com/b44t/ui/SettingsActivity.java b/MessengerProj/src/main/java/com/b44t/ui/SettingsActivity.java
index cf08fa4ee..c83b95ea3 100644
--- a/MessengerProj/src/main/java/com/b44t/ui/SettingsActivity.java
+++ b/MessengerProj/src/main/java/com/b44t/ui/SettingsActivity.java
@@ -31,6 +31,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageInfo;
import android.os.Build;
+import android.os.PowerManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -177,7 +178,7 @@ public class SettingsActivity extends BaseFragment {
private String getAndroidInfo()
{
String abi = "ErrAbi";
- int versionCode = 0;
+ int versionCode = 0, ignoreBatteryOptimizations = -1;
try {
PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0);
versionCode = pInfo.versionCode;
@@ -195,6 +196,10 @@ public class SettingsActivity extends BaseFragment {
abi = "universal";
break;
}
+ if( Build.VERSION.SDK_INT >= 23 ) {
+ PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
+ ignoreBatteryOptimizations = pm.isIgnoringBatteryOptimizations(ApplicationLoader.applicationContext.getPackageName())? 1 : 0;
+ }
} catch (Exception e) {}
return "SDK_INT=" + Build.VERSION.SDK_INT
@@ -202,6 +207,7 @@ public class SettingsActivity extends BaseFragment {
+ "\nMODEL=" + Build.MODEL
+ "\nDEBUG_VERSION=" + BuildVars.DEBUG_VERSION
+ "\nABI=" + abi // ABI = Application Binary Interface
+ + "\nignoreBatteryOptimizations=" + ignoreBatteryOptimizations
+ "\nversionCode=" + versionCode;
}
diff --git a/MessengerProj/src/main/res/values-de/strings.xml b/MessengerProj/src/main/res/values-de/strings.xml
index e716e3d4c..6ce822397 100644
--- a/MessengerProj/src/main/res/values-de/strings.xml
+++ b/MessengerProj/src/main/res/values-de/strings.xml
@@ -260,7 +260,8 @@
Für eine einfache Kontaktaufnahme, benötigt Delta Chat Zugriff auf die Kontakte. Die Daten werden dabei nur lokal verarbeitet und zu keinem Server oder Dienst übertragen.
Um Bilder, Videos, Musik und Dateien senden und speichern zu können, benötigt Delta Chat Zugriff auf den Speicher.
Um Sprachnachrichten versenden zu können, benötigt Delta Chat Zugriff auf das Mikrofon.
- Einstellungen
+ Um Nachrichten von Ihrem Server empfangen zu können, muss Delta Chat im Hintergrund ausgeführt werden.\n\nDiese normale und batteriesparende Vorgehensweise wird von den Akku-Optimierungen unterbunden.\n\nEinstellungen anpassen?
+ Einstellungen anpassen
Delta Chat
Der Messenger mit der größten Reichweite]]> der Welt.Kostenlos]]> und sicher]]>.
diff --git a/MessengerProj/src/main/res/values/strings.xml b/MessengerProj/src/main/res/values/strings.xml
index f8c3b78d4..742a6869d 100644
--- a/MessengerProj/src/main/res/values/strings.xml
+++ b/MessengerProj/src/main/res/values/strings.xml
@@ -260,7 +260,13 @@
Delta Chat needs access to your contacts so that you can connect with your friends across all your devices.
Delta Chat needs access to your storage so that you can send and save photos, videos, music and other media.
Delta Chat needs access to your microphone so that you can send voice messages.
- Settings
+
+
+ Delta Chat needs to stay connected in the background for receiving messages from your server.\n\nThis is a normal, battery-saving and very usual behaviour, which, however, is blocked by the battery optimizations.\n\nAdapt settings?
+
+ Adapt settings
Delta Chat
The messenger with the largest range]]> in the world.Free]]> and save]]>.