[update] Removes the foreground service requirement for the timer service.
This commit is contained in:
parent
6507a6de49
commit
5fb7ca4180
4 changed files with 110 additions and 17 deletions
|
|
@ -10,8 +10,6 @@
|
|||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
|
||||
<application
|
||||
android:name=".PFAktivpause"
|
||||
|
|
@ -120,8 +118,7 @@
|
|||
<service
|
||||
android:name="org.secuso.aktivpause.service.TimerService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="specialUse"/>
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".backup.PFABackupService"
|
||||
android:enabled="true"
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ package org.secuso.aktivpause.activities;
|
|||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
|
@ -12,6 +14,7 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager;
|
||||
|
|
@ -117,14 +120,39 @@ public class ExerciseActivity extends AppCompatActivity implements LoaderManager
|
|||
private SharedPreferences pref;
|
||||
private Handler mHandler;
|
||||
|
||||
private TimerService timerService = null;
|
||||
private boolean serviceBound = false;
|
||||
|
||||
/**
|
||||
* Defines callbacks for service binding, passed to bindService()
|
||||
* Performs an initial GUI update when connection is established.
|
||||
**/
|
||||
private final ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
TimerService.TimerServiceBinder binder = (TimerService.TimerServiceBinder) service;
|
||||
timerService = binder.getService();
|
||||
serviceBound = true;
|
||||
|
||||
timerService.setIsAppInBackground(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0) {
|
||||
serviceBound = false;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_exercise);
|
||||
|
||||
Intent stopTimer = new Intent(this, TimerService.class);
|
||||
stopTimer.setAction(ACTION_STOP_TIMER);
|
||||
startService(stopTimer);
|
||||
bindService(stopTimer, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||
// stopTimer.setAction(ACTION_STOP_TIMER);
|
||||
// startService(stopTimer);
|
||||
|
||||
mHandler = new Handler();
|
||||
|
||||
|
|
@ -327,6 +355,10 @@ public class ExerciseActivity extends AppCompatActivity implements LoaderManager
|
|||
super.onResume();
|
||||
isActivityVisible = true;
|
||||
|
||||
if (timerService != null) {
|
||||
timerService.setIsAppInBackground(false);
|
||||
}
|
||||
|
||||
if (isBreakFinished) {
|
||||
showEndDialog(this);
|
||||
}
|
||||
|
|
@ -341,6 +373,10 @@ public class ExerciseActivity extends AppCompatActivity implements LoaderManager
|
|||
super.onPause();
|
||||
isActivityVisible = false;
|
||||
|
||||
if (timerService != null) {
|
||||
timerService.setIsAppInBackground(true);
|
||||
}
|
||||
|
||||
if(isBreakFinished) {
|
||||
// TODO: Either start a short Timer to see if the user comes back - or start the next work time rand finish this activity
|
||||
// TODO: for now we just finish
|
||||
|
|
@ -350,6 +386,28 @@ public class ExerciseActivity extends AppCompatActivity implements LoaderManager
|
|||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the notification when activity is destroyed
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (timerService != null) {
|
||||
timerService.workoutClosed();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
// Unbind from the service
|
||||
if (serviceBound) {
|
||||
unbindService(serviceConnection);
|
||||
serviceBound = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<ExerciseSet> loader, ExerciseSet set) {
|
||||
if (set != null) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import android.os.Build;
|
|||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.AlarmManagerCompat;
|
||||
import androidx.legacy.content.WakefulBroadcastReceiver;
|
||||
|
||||
import org.secuso.aktivpause.service.TimerService;
|
||||
|
|
@ -79,7 +80,7 @@ public class TimerSchedulerReceiver extends WakefulBroadcastReceiver {
|
|||
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
Intent automaticTimerIntent = new Intent(context, TimerSchedulerReceiver.class);
|
||||
PendingIntent automaticTimerPending = PendingIntent.getBroadcast(context, 0, automaticTimerIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
PendingIntent automaticTimerPending = PendingIntent.getBroadcast(context, 0, automaticTimerIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTimeInMillis(timestamp);
|
||||
|
|
@ -143,12 +144,8 @@ public class TimerSchedulerReceiver extends WakefulBroadcastReceiver {
|
|||
}
|
||||
}
|
||||
|
||||
if(done || !scheduleExerciseDaysEnabled) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), automaticTimerPending);
|
||||
} else {
|
||||
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), automaticTimerPending);
|
||||
}
|
||||
if((done || !scheduleExerciseDaysEnabled)) {
|
||||
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), automaticTimerPending);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import android.content.SharedPreferences;
|
|||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Binder;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
|
|
@ -56,6 +57,9 @@ public class TimerService extends Service {
|
|||
|
||||
private static final int UPDATE_INTERVAL = 125;
|
||||
public static final int NOTIFICATION_ID = 31337;
|
||||
private NotificationCompat.Builder notiBuilder = null;
|
||||
private NotificationManager notiManager = null;
|
||||
private boolean isAppInBackground = false;
|
||||
|
||||
private TimerServiceBinder mBinder = new TimerServiceBinder();
|
||||
private CountDownTimer mTimer;
|
||||
|
|
@ -366,13 +370,50 @@ public class TimerService extends Service {
|
|||
}
|
||||
|
||||
private void updateNotification() {
|
||||
if(isRunning() || isPaused()) {
|
||||
ServiceCompat.startForeground(this, NOTIFICATION_ID, buildNotification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
|
||||
} else {
|
||||
stopForeground(true);
|
||||
if(isAppInBackground) {
|
||||
Notification notification = buildNotification();
|
||||
notiManager.notify(NOTIFICATION_ID, notification);
|
||||
}
|
||||
else if(notiManager != null) {
|
||||
notiManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the app is in the background.
|
||||
* If so, start a notification showing the current timer.
|
||||
*
|
||||
* @param isInBackground Sets global flag to determine whether the app is in the background
|
||||
*/
|
||||
public void setIsAppInBackground(boolean isInBackground){
|
||||
this.isAppInBackground = isInBackground;
|
||||
|
||||
//Execute after short delay to prevent short notification popup if workoutActivity is closed
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateNotification();
|
||||
}
|
||||
}, 700);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the notification when workout activity is destroyed
|
||||
*/
|
||||
public void workoutClosed(){
|
||||
this.isAppInBackground = false;
|
||||
notiManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
|
||||
// private void updateNotification() {
|
||||
// if(isRunning() || isPaused()) {
|
||||
// ServiceCompat.startForeground(this, NOTIFICATION_ID, buildNotification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
|
||||
// } else {
|
||||
// stopForeground(true);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue