Create an alert that wakes up the app from time to time; if there's stuff to do, the backend acquires a wake loke then. Additionally, if the app is just dismissed, we keep another wakelock for some minutes to catch messages the user just expects in that moment.

This commit is contained in:
B. Petersen
2017-03-27 22:16:26 +02:00
parent 590841d139
commit 8a5f05fe2e
13 changed files with 95 additions and 134 deletions
+2 -1
View File
@@ -216,7 +216,6 @@
<receiver android:name=".BootCompletedReceiver" android:enabled="true">
<intent-filter>
<action android:name="com.b44t.start" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
@@ -228,6 +227,8 @@
<receiver android:name=".ShareBroadcastReceiver" android:enabled="true"/>
-->
<receiver android:name=".TimerReceiver" android:enabled="true"/>
<receiver android:name=".NotificationDismissReceiver" android:exported="false"/>
<provider android:name=".AttachmentsContentProvider" android:authorities="${applicationId}.attachments" android:exported="true" />
@@ -40,6 +40,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Log;
import com.b44t.ui.Components.ForegroundDetector;
@@ -48,29 +49,21 @@ import com.b44t.ui.SettingsAdvActivity;
import java.io.File;
public class ApplicationLoader extends Application {
private static PendingIntent pendingIntent;
private static Drawable cachedWallpaper;
private static int selectedColor;
private static boolean isCustomTheme;
private static final Object sync = new Object();
public static volatile Context applicationContext;
public static volatile Handler applicationHandler;
private static volatile boolean applicationInited = false;
public static volatile boolean isScreenOn = false;
public static volatile boolean mainInterfacePaused = true;
public static boolean isCustomTheme() {
return isCustomTheme;
}
public static PowerManager.WakeLock backendWakeLock = null;
public static PowerManager.WakeLock wakeupWakeLock = null;
private static PowerManager.WakeLock stayAwakeWakeLock = null;
public static int getSelectedColor() {
return selectedColor;
}
private static PowerManager.WakeLock wakeLock = null;
public static int fontSize;
@@ -149,20 +142,51 @@ public class ApplicationLoader extends Application {
return new File("/data/data/com.b44t.messenger/files");
}
public static void postInitApplication() {
if (applicationInited) {
Log.i("DeltaChat", "*** Already inited."); // this is quite normal as the function is called in different activities and situations
return;
@Override
public void onCreate() {
Log.i("DeltaChat", "*************** ApplicationLoader.onCreate() ***************");
super.onCreate();
applicationContext = getApplicationContext();
System.loadLibrary("messenger.1");
new ForegroundDetector(this);
applicationHandler = new Handler(applicationContext.getMainLooper());
// create wake locks
try {
PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
backendWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "backendWakeLock" /*any name*/);
// bakendWakeLock _is_ reference counted by the backend (every acquire() has a release())
wakeupWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "wakeupWakeLock" /*any name*/);
wakeupWakeLock.setReferenceCounted(false);
stayAwakeWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "stayAwakeWakeLock" /*any name*/);
stayAwakeWakeLock.setReferenceCounted(false);
} catch (Exception e) {
Log.e("DeltaChat", "Cannot acquire wakeLock");
}
applicationInited = true;
// create a MrMailbox object; as android stops the App by just killing it, we do never call MrMailboxUnref()
// however, we may want to to have a look at onPause() eg. of activities (eg. for flushing data, if needed)
MrMailbox.MrCallback(0, 0, 0); // do not remove this call; this makes sure, the function is not removed from build or warnings are printed!
MrMailbox.init();
// start keep-alive service that restarts the app as soon it is terminated
// (this is done by just marking the service as START_STICKY which recreates the service as
// it goes away which also inititialized the app indirectly by calling this function)
applicationContext.startService(new Intent(applicationContext, KeepAliveService.class));
// init locale
try {
LocaleController.getInstance();
} catch (Exception e) {
e.printStackTrace();
}
// track screen on/ff
try {
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
@@ -181,22 +205,25 @@ public class ApplicationLoader extends Application {
}
UserConfig.loadConfig();
SharedPreferences notificationPreferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
// create and acquire wakeLock
try {
PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "lock");
wakeLock.setReferenceCounted(false);
if (notificationPreferences.getBoolean("keepAlive", true)) {
wakeLock.acquire();
}
// 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);
} catch (Exception e) {
Log.e("DeltaChat", "Cannot acquire wakeLock");
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.");
}
// make sure, the notifications for the "deaddrop" dialog are muted by default
SharedPreferences notificationPreferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
if( notificationPreferences.getInt("notify2_"+MrChat.MR_CHAT_ID_DEADDROP, 666)==666 ) {
SharedPreferences.Editor editor = notificationPreferences.edit();
editor.putInt("notify2_"+MrChat.MR_CHAT_ID_DEADDROP, 2);
@@ -217,51 +244,6 @@ public class ApplicationLoader extends Application {
MediaController.getInstance();
}
@Override
public void onCreate() {
Log.i("DeltaChat", "************ Primary-init ************");
super.onCreate();
applicationContext = getApplicationContext();
System.loadLibrary("messenger.1");
new ForegroundDetector(this);
// create a MrMailbox object; as android stops the App by just killing it, we do never call MrMailboxUnref()
// however, we may want to to have a look at onPause() eg. of activities (eg. for flushing data, if needed)
MrMailbox.MrCallback(0, 0, 0); // do not remove this call; this makes sure, the function is not removed from build or warnings are printed!
MrMailbox.init();
applicationHandler = new Handler(applicationContext.getMainLooper());
startKeepAliveService();
}
public static void startKeepAliveService() {
SharedPreferences preferences = applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE);
if (preferences.getBoolean("keepAlive", true)) {
AlarmManager am = (AlarmManager) applicationContext.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(applicationContext, ApplicationLoader.class);
pendingIntent = PendingIntent.getBroadcast(applicationContext, 0, i, 0);
am.cancel(pendingIntent);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 60000, pendingIntent);
applicationContext.startService(new Intent(applicationContext, KeepAliveService.class));
} else {
stopKeepAliveService();
}
}
public static void stopKeepAliveService() {
applicationContext.stopService(new Intent(applicationContext, KeepAliveService.class));
PendingIntent pintent = PendingIntent.getService(applicationContext, 0, new Intent(applicationContext, KeepAliveService.class), 0);
AlarmManager alarm = (AlarmManager)applicationContext.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pintent);
alarm.cancel(pendingIntent);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -291,4 +273,8 @@ public class ApplicationLoader extends Application {
return false;
}
public static void stayAwakeForAMoment()
{
stayAwakeWakeLock.acquire(2*60*1000); // 1 Minute, TODO: we should use about 10 Minutes here
}
}
@@ -33,9 +33,6 @@ public class AutoMessageHeardReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("DeltaChat", "*** Post-init via AutoMessageHeardReceiver.onReceive()");
ApplicationLoader.postInitApplication();
long dialog_id = intent.getLongExtra("dialog_id", 0);
int max_id = intent.getIntExtra("max_id", 0);
if (dialog_id == 0 || max_id == 0) {
@@ -35,9 +35,6 @@ public class AutoMessageReplyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("DeltaChat", "*** Post-init via AutoMessageReplyReceiver.onReceive()");
ApplicationLoader.postInitApplication();
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput == null) {
return;
@@ -31,11 +31,7 @@ import android.util.Log;
public class BootCompletedReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.i("DeltaChat", "*** BootCompletedReceiver.onReceive()");
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
ApplicationLoader.startKeepAliveService();
}
});
// there's nothing more to do here as all initialisation stuff is already done in
// ApplicationLoader.onCreate() which is called before this broadcast is sended.
}
}
@@ -24,7 +24,6 @@ package com.b44t.messenger;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;
@@ -33,14 +32,17 @@ public class KeepAliveService extends Service {
@Override
public void onCreate() {
Log.i("DeltaChat", "*** Post-init via KeepAliveService.onCreate()");
ApplicationLoader.postInitApplication();
Log.i("DeltaChat", "*** KeepAliveService.onCreate()");
// there's nothing more to do here as all initialisation stuff is already done in
// ApplicationLoader.onCreate() which is called before this broadcast is sended.
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// START_STICKY ensured, the service is recreated as soon it is terminted for any reasons.
// as ApplicationLoader.onCreate() is called before a service starts, there is no more to do here,
// the app is just running fine.
Log.i("DeltaChat", "*** KeepAliveService.onStartCommand()");
return START_STICKY;
}
@@ -50,13 +52,7 @@ public class KeepAliveService extends Service {
}
public void onDestroy() {
Log.i("DeltaChat", "*** KeepAliveService will be destroyed, restarting");
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", MODE_PRIVATE);
if( preferences.getBoolean("keepAlive", true) )
{
Intent intent = new Intent("com.b44t.start");
sendBroadcast(intent);
}
Log.i("DeltaChat", "*** KeepAliveService.onDestroy()");
// the service will be restarted due to START_STICKY automatically, there's nothing more to do.
}
}
@@ -33,6 +33,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
@@ -187,6 +188,7 @@ public class MrMailbox {
public final static int MR_EVENT_GET_STRING = 2091;
public final static int MR_EVENT_GET_QUANTITIY_STRING = 2092;
public final static int MR_EVENT_HTTP_GET = 2100;
public final static int MR_EVENT_WAKE_LOCK = 2110;
public static final Object m_lastErrorLock = new Object();
@@ -342,6 +344,18 @@ public class MrMailbox {
}
catch(Exception e) {}
return String2CPtr(httpContent);
case MR_EVENT_WAKE_LOCK:
if( data1 != 0 ) {
ApplicationLoader.backendWakeLock.acquire();
}
else {
if( !ApplicationLoader.wakeupWakeLock.isHeld()) {
ApplicationLoader.wakeupWakeLock.acquire(1 * 1000); /* make sure, subsequent release/acquires do not make the CPU sleep */
}
ApplicationLoader.backendWakeLock.release();
}
return 0;
}
return 0;
}
@@ -123,7 +123,7 @@ public class NotificationsController {
try {
PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE);
notificationDelayWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "lock");
notificationDelayWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "notificationDelayWakelock" /*any name*/);
notificationDelayWakelock.setReferenceCounted(false);
} catch (Exception e) {
FileLog.e("messenger", e);
@@ -35,9 +35,6 @@ public class WearReplyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("DeltaChat", "*** Post-init via WearReplyReceiver.onReceive()");
ApplicationLoader.postInitApplication();
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput == null) {
return;
@@ -122,9 +122,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("DeltaChat", "*** Post-init via LaunchActivity.onCreate()");
ApplicationLoader.postInitApplication();
if( MrMailbox.isConfigured()==0 ) {
Intent intent = getIntent();
if (intent != null && !intent.getBooleanExtra("fromIntro", false)) {
@@ -1320,9 +1317,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
if (PhotoViewer.getInstance().isVisible()) {
PhotoViewer.getInstance().onPause();
}
ApplicationLoader.stayAwakeForAMoment();
}
@Override
/*@Override
protected void onStart() {
Log.i("DeltaChat", "*** LaunchActivity.onStart()");
super.onStart();
@@ -1332,7 +1330,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
protected void onStop() {
Log.i("DeltaChat", "*** LaunchActivity.onStop()");
super.onStop();
}
}*/
@Override
protected void onDestroy() {
@@ -64,9 +64,6 @@ public class ManageSpaceActivity extends Activity implements ActionBarLayout.Act
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("DeltaChat", "*** Post-init via ManageSpaceActivity.onCreate()");
ApplicationLoader.postInitApplication();
requestWindowFeature(Window.FEATURE_NO_TITLE);
setTheme(R.style.Theme_MessengerProj);
getWindow().setBackgroundDrawableResource(R.drawable.transparent);
@@ -64,8 +64,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
private ListView listView;
private int notificationsServiceRow;
//private int notificationsServiceConnectionRow;
private int messageSectionRow;
private int messageAlertRow;
private int messagePreviewRow;
@@ -134,8 +132,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
messagePreviewRow = rowCount++;
badgeNumberRow = rowCount++;
repeatRow = rowCount++;
notificationsServiceRow = rowCount++;
//notificationsServiceConnectionRow = rowCount++;
resetNotificationsRow = rowCount++;
NotificationCenter.getInstance().addObserver(this, NotificationCenter.notificationsSettingsUpdated);
@@ -293,16 +289,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
editor.putBoolean("badgeNumber", !enabled);
editor.apply();
NotificationsController.getInstance().setBadgeEnabled(!enabled);
}
else if (i == notificationsServiceRow) {
// keep-alive service option
final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
final SharedPreferences.Editor editor = preferences.edit();
enabled = preferences.getBoolean("keepAlive", true);
editor.putBoolean("keepAlive", !enabled);
editor.apply();
ApplicationLoader.stopKeepAliveService();
ApplicationLoader.startKeepAliveService();
} else if (i == messageLedRow || i == groupLedRow) {
if (getParentActivity() == null) {
return;
@@ -592,10 +578,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
checkCell.setTextAndCheck(LocaleController.getString("Vibrate", R.string.Vibrate), preferences.getBoolean("EnableInAppVibrate", true), true);
/*} else if (i == inappPreviewRow) {
checkCell.setTextAndCheck(LocaleController.getString("MessagePreview", R.string.MessagePreview), preferences.getBoolean("EnableInAppPreview", true), true);*/
} else if (i == notificationsServiceRow) {
checkCell.setTextAndValueAndCheck(LocaleController.getString("NotificationsService", R.string.NotificationsService), LocaleController.getString("NotificationsServiceInfo", R.string.NotificationsServiceInfo), preferences.getBoolean("keepAlive", true), true, true);
/*} else if (i == notificationsServiceConnectionRow) {
checkCell.setTextAndValueAndCheck(LocaleController.getString("NotificationsServiceConnection", R.string.NotificationsServiceConnection), LocaleController.getString("NotificationsServiceConnectionInfo", R.string.NotificationsServiceConnectionInfo), preferences.getBoolean("pushConnection", true), true, true);*/
} else if (i == badgeNumberRow) {
checkCell.setTextAndCheck(LocaleController.getString("BadgeNumber", R.string.BadgeNumber), preferences.getBoolean("badgeNumber", true), true);
} else if (i == inchatSoundRow) {
@@ -704,8 +686,8 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
} else if (i == messageAlertRow || i == messagePreviewRow || i == groupAlertRow ||
/*i == groupPreviewRow ||*/ i == inappSoundRow || i == inappVibrateRow ||
/*i == inappPreviewRow ||*/
i == notificationsServiceRow || i == badgeNumberRow ||
i == inchatSoundRow /*|| i == notificationsServiceConnectionRow*/) {
i == badgeNumberRow ||
i == inchatSoundRow ) {
return TYPE_CHECK_CELL;
} else if (i == messageLedRow || i == groupLedRow) {
return TYPE_COLOR_CELL;
@@ -274,9 +274,6 @@ public class SettingsActivity extends BaseFragment {
else if (i == advRow) {
textCell.setText(ApplicationLoader.applicationContext.getString(R.string.AdvancedSettings), false);
}
else if (i == aboutRow) {
textCell.setText(ApplicationLoader.applicationContext.getString(R.string.AboutThisProgram), false);
}
}
else if (type == ROWTYPE_HEADER) {
if (view == null) {
@@ -317,6 +314,9 @@ public class SettingsActivity extends BaseFragment {
}
textCell.setTextAndValue(LocaleController.getString("MyName", R.string.MyName), subtitle, true);
}
else if (i == aboutRow) {
textCell.setTextAndValue(ApplicationLoader.applicationContext.getString(R.string.AboutThisProgram), "v" + getVersion(), false);
}
}
return view;
}
@@ -326,7 +326,7 @@ public class SettingsActivity extends BaseFragment {
if (i == accountShadowRow || i == settingsShadowRow || i == aboutShadowRow ) {
return ROWTYPE_SHADOW;
}
else if ( i == accountSettingsRow || i == usernameRow) {
else if ( i == accountSettingsRow || i == usernameRow || i==aboutRow ) {
return ROWTYPE_DETAIL_SETTINGS;
}
else if (i == settingsHeaderRow || i == aboutHeaderRow || i == accountHeaderRow) {