mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Request the user to ignore the battery optimizations which avoid running Delta Chat properly.
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<String> 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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user