Skip to content

Commit 4b394e2

Browse files
authored
Replace FocusDelaySyncJobService by Worker (#1515)
* On focus delay service is replaced by a Worker * JobService is not stopped by the system after completed
1 parent 0e18977 commit 4b394e2

13 files changed

+159
-258
lines changed

OneSignalSDK/onesignal/src/main/AndroidManifest.xml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,11 @@
9090
android:permission="android.permission.BIND_JOB_SERVICE"
9191
android:exported="false" />
9292

93-
<service
94-
android:name="com.onesignal.FocusDelaySyncService"
95-
android:stopWithTask="true"
96-
android:exported="false"/>
97-
<service
98-
android:name="com.onesignal.FocusDelaySyncJobService"
99-
android:permission="android.permission.BIND_JOB_SERVICE"
100-
android:exported="false" />
101-
10293
<service
10394
android:name="com.onesignal.SyncService"
10495
android:stopWithTask="true"
10596
android:exported="false" />
97+
10698
<service
10799
android:name="com.onesignal.SyncJobService"
108100
android:permission="android.permission.BIND_JOB_SERVICE"

OneSignalSDK/onesignal/src/main/java/com/onesignal/ActivityLifecycleHandler.java

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
import android.annotation.SuppressLint;
3131
import android.app.Activity;
32-
import android.content.Context;
3332
import android.content.pm.ActivityInfo;
3433
import android.content.res.Configuration;
3534
import android.os.Build;
@@ -56,17 +55,24 @@ void lostFocus() {
5655
}
5756
}
5857

59-
private static final Object SYNC_LOCK = new Object();
60-
private static final String FOCUS_LOST_WORKER_TAG = "FOCUS_LOST_WORKER_TAG";
6158
private static final Map<String, ActivityAvailableListener> sActivityAvailableListeners = new ConcurrentHashMap<>();
6259
private static final Map<String, OSSystemConditionController.OSSystemConditionObserver> sSystemConditionObservers = new ConcurrentHashMap<>();
6360
private static final Map<String, KeyboardListener> sKeyboardListeners = new ConcurrentHashMap<>();
6461

65-
private static AppFocusRunnable appFocusRunnable;
62+
private static final String FOCUS_LOST_WORKER_TAG = "FOCUS_LOST_WORKER_TAG";
63+
// We want to perform a on_focus sync as soon as the session is done to report the time
64+
private static final int SYNC_AFTER_BG_DELAY_MS = 2000;
65+
66+
private final OSFocusHandler focusHandler;
67+
6668
@SuppressLint("StaticFieldLeak")
6769
private Activity curActivity = null;
6870
private boolean nextResumeIsFirstActivity = false;
6971

72+
public ActivityLifecycleHandler(OSFocusHandler focusHandler) {
73+
this.focusHandler = focusHandler;
74+
}
75+
7076
void onConfigurationChanged(Configuration newConfig, Activity activity) {
7177
// If Activity contains the configChanges orientation flag, re-create the view this way
7278
if (curActivity != null && OSUtils.hasConfigChangeFlag(curActivity, ActivityInfo.CONFIG_ORIENTATION)) {
@@ -166,23 +172,23 @@ private void onOrientationChanged(Activity activity) {
166172

167173
private void handleLostFocus() {
168174
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler Handling lost focus");
169-
if (appFocusRunnable != null && appFocusRunnable.backgrounded && !appFocusRunnable.completed)
175+
if (focusHandler == null || focusHandler.hasBackgrounded() && !focusHandler.hasCompleted())
170176
return;
171177

172178
OneSignal.getFocusTimeController().appStopped();
173-
OSFocusDelaySync.getInstance().scheduleSyncTask(OneSignal.appContext);
179+
focusHandler.startOnLostFocusWorker(FOCUS_LOST_WORKER_TAG, SYNC_AFTER_BG_DELAY_MS, OneSignal.appContext);
174180
}
175181

176182
private void handleFocus() {
177-
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler handleFocus, with runnable: " + appFocusRunnable + " nextResumeIsFirstActivity: " + nextResumeIsFirstActivity);
178-
if (hasBackgrounded() || nextResumeIsFirstActivity) {
183+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler handleFocus, nextResumeIsFirstActivity: " + nextResumeIsFirstActivity);
184+
if (focusHandler.hasBackgrounded() || nextResumeIsFirstActivity) {
179185
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler reset background state, call app focus");
180186
nextResumeIsFirstActivity = false;
181-
resetBackgroundState();
187+
focusHandler.resetBackgroundState();
182188
OneSignal.onAppFocus();
183189
} else {
184-
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler cancel background lost focus sync task");
185-
OSFocusDelaySync.getInstance().cancelBackgroundSyncTask(OneSignal.appContext);
190+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler cancel background lost focus worker");
191+
focusHandler.cancelOnLostFocusWorker(FOCUS_LOST_WORKER_TAG, OneSignal.appContext);
186192
}
187193
}
188194

@@ -249,46 +255,6 @@ void setNextResumeIsFirstActivity(boolean nextResumeIsFirstActivity) {
249255
this.nextResumeIsFirstActivity = nextResumeIsFirstActivity;
250256
}
251257

252-
void resetBackgroundState() {
253-
if (appFocusRunnable != null)
254-
appFocusRunnable.backgrounded = false;
255-
}
256-
257-
boolean hasBackgrounded() {
258-
return appFocusRunnable != null && appFocusRunnable.backgrounded;
259-
}
260-
261-
static void runLostFocusLogic(Context context) {
262-
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler runLostFocusLogic");
263-
ActivityLifecycleHandler activityLifecycleHandler = ActivityLifecycleListener.getActivityLifecycleHandler();
264-
if (activityLifecycleHandler == null || activityLifecycleHandler.curActivity == null)
265-
OneSignal.setInForeground(false);
266-
appFocusRunnable = new AppFocusRunnable();
267-
OSFocusDelaySync.getInstance().doBackgroundSync(
268-
context,
269-
appFocusRunnable
270-
);
271-
}
272-
273-
static class AppFocusRunnable implements Runnable {
274-
private boolean backgrounded, completed;
275-
276-
public void run() {
277-
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "ActivityLifecycleHandler running AppFocusRunnable");
278-
backgrounded = true;
279-
OneSignal.onAppLostFocus();
280-
completed = true;
281-
}
282-
283-
@Override
284-
public String toString() {
285-
return "AppFocusRunnable{" +
286-
"backgrounded=" + backgrounded +
287-
", completed=" + completed +
288-
'}';
289-
}
290-
}
291-
292258
static class KeyboardListener implements ViewTreeObserver.OnGlobalLayoutListener {
293259

294260
private final OSSystemConditionController.OSSystemConditionObserver observer;

OneSignalSDK/onesignal/src/main/java/com/onesignal/ActivityLifecycleListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static void registerActivityLifecycleCallbacks(@NonNull final Application applic
5353
}
5454

5555
if (activityLifecycleHandler == null) {
56-
activityLifecycleHandler = new ActivityLifecycleHandler();
56+
activityLifecycleHandler = new ActivityLifecycleHandler(new OSFocusHandler());
5757
}
5858

5959
// Configuration change listener setup

OneSignalSDK/onesignal/src/main/java/com/onesignal/FocusDelaySyncJobService.java

Lines changed: 0 additions & 51 deletions
This file was deleted.

OneSignalSDK/onesignal/src/main/java/com/onesignal/OSFocusDelaySync.java

Lines changed: 0 additions & 78 deletions
This file was deleted.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* Modified MIT License
3+
* <p>
4+
* Copyright 2022 OneSignal
5+
* <p>
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
* <p>
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
* <p>
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
* <p>
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
package com.onesignal
29+
30+
import android.content.Context
31+
import androidx.work.*
32+
import java.util.concurrent.TimeUnit
33+
34+
class OSFocusHandler {
35+
36+
fun hasBackgrounded() = backgrounded
37+
38+
fun hasCompleted() = completed
39+
40+
fun resetBackgroundState() {
41+
backgrounded = false
42+
}
43+
44+
fun startOnLostFocusWorker(tag: String, delay: Long, context: Context) {
45+
val constraints = buildConstraints()
46+
val workRequest = OneTimeWorkRequest.Builder(OnLostFocusWorker::class.java)
47+
.setConstraints(constraints)
48+
.setInitialDelay(delay, TimeUnit.MILLISECONDS)
49+
.addTag(tag)
50+
.build()
51+
WorkManager.getInstance(context)
52+
.enqueueUniqueWork(
53+
tag,
54+
ExistingWorkPolicy.KEEP,
55+
workRequest
56+
)
57+
}
58+
59+
fun cancelOnLostFocusWorker(tag: String, context: Context) {
60+
WorkManager.getInstance(context).cancelAllWorkByTag(tag)
61+
}
62+
63+
private fun buildConstraints(): Constraints {
64+
return Constraints.Builder()
65+
.setRequiredNetworkType(NetworkType.CONNECTED)
66+
.build()
67+
}
68+
69+
class OnLostFocusWorker(context: Context, workerParams: WorkerParameters) :
70+
Worker(context, workerParams) {
71+
override fun doWork(): Result {
72+
onLostFocusDoWork()
73+
return Result.success()
74+
}
75+
}
76+
77+
companion object {
78+
private var backgrounded = false
79+
private var completed = false
80+
81+
fun onLostFocusDoWork() {
82+
val activityLifecycleHandler = ActivityLifecycleListener.getActivityLifecycleHandler()
83+
if (activityLifecycleHandler == null || activityLifecycleHandler.curActivity == null) {
84+
OneSignal.setInForeground(false)
85+
}
86+
OneSignal.onesignalLog(
87+
OneSignal.LOG_LEVEL.DEBUG,
88+
"OSFocusHandler running onAppLostFocus"
89+
)
90+
backgrounded = true
91+
OneSignal.onAppLostFocus()
92+
completed = true
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)