Skip to content

Commit a7a9976

Browse files
committed
Add multiple prompt handling
1 parent 3be69a5 commit a7a9976

File tree

9 files changed

+213
-82
lines changed

9 files changed

+213
-82
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,8 @@ public void run() {
441441
* IAM has been fully dismissed, remove all views and call the onMessageWasDismissed callback
442442
*/
443443
private void cleanupViewsAfterDismiss() {
444-
removeAllViews();
444+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "InAppMessageView cleanupViewsAfterDismiss");
445+
removeAllViews();
445446
if (messageController != null)
446447
messageController.onMessageWasDismissed();
447448
}

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

Lines changed: 90 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,14 @@
4747

4848
import java.math.BigDecimal;
4949
import java.math.RoundingMode;
50+
import java.util.ArrayList;
5051
import java.util.Arrays;
5152
import java.util.HashMap;
5253
import java.util.List;
5354
import java.util.concurrent.ConcurrentHashMap;
5455

5556
class LocationGMS {
56-
57+
5758
static class LocationPoint {
5859
Double lat;
5960
Double log;
@@ -62,74 +63,122 @@ static class LocationPoint {
6263
Boolean bg;
6364
Long timeStamp;
6465
}
65-
66+
6667
private static final long TIME_FOREGROUND_SEC = 5 * 60;
6768
private static final long TIME_BACKGROUND_SEC = 10 * 60;
6869
private static final long FOREGROUND_UPDATE_TIME_MS = (TIME_FOREGROUND_SEC - 30) * 1_000;
6970
private static final long BACKGROUND_UPDATE_TIME_MS = (TIME_BACKGROUND_SEC - 30) * 1_000;
70-
71+
7172
private static GoogleApiClientCompatProxy mGoogleApiClient;
7273
private static Location mLastLocation;
7374
static String requestPermission;
7475
private static Context classContext;
75-
76+
7677
private static LocationHandlerThread locationHandlerThread;
7778

7879
protected static final Object syncLock = new Object() {};
7980

80-
enum CALLBACK_TYPE {
81+
enum PermissionType {
8182
STARTUP, PROMPT_LOCATION, SYNC_SERVICE
8283
}
8384
interface LocationHandler {
84-
CALLBACK_TYPE getType();
85+
PermissionType getType();
8586
void complete(LocationPoint point);
8687
}
8788

88-
private static ConcurrentHashMap<CALLBACK_TYPE, LocationHandler> locationHandlers = new ConcurrentHashMap<>();
89+
abstract static class LocationPromptCompletionHandler implements LocationHandler {
90+
void onAnswered(boolean accepted) {}
91+
}
92+
93+
private static ConcurrentHashMap<PermissionType, LocationHandler> locationHandlers = new ConcurrentHashMap<>();
94+
private static final List<LocationPromptCompletionHandler> promptHandlers = new ArrayList<>();
8995

9096
private static Thread fallbackFailThread;
9197

9298
private static boolean locationCoarse;
93-
99+
94100
static boolean scheduleUpdate(Context context) {
95101
if (!hasLocationPermission(context) || !OneSignal.shareLocation)
96102
return false;
97-
103+
98104
long lastTime = System.currentTimeMillis() - getLastLocationTime();
99105
long minTime = 1_000 * (OneSignal.isForeground() ? TIME_FOREGROUND_SEC : TIME_BACKGROUND_SEC);
100106
long scheduleTime = minTime - lastTime;
101-
107+
102108
OneSignalSyncServiceUtils.scheduleLocationUpdateTask(context, scheduleTime);
103109
return true;
104110
}
105-
111+
106112
private static void setLastLocationTime(long time) {
107113
OneSignalPrefs.saveLong(OneSignalPrefs.PREFS_ONESIGNAL,
108114
OneSignalPrefs.PREFS_OS_LAST_LOCATION_TIME,time);
109115
}
110-
116+
111117
private static long getLastLocationTime() {
112118
return OneSignalPrefs.getLong(
113119
OneSignalPrefs.PREFS_ONESIGNAL,
114120
OneSignalPrefs.PREFS_OS_LAST_LOCATION_TIME,
115121
TIME_BACKGROUND_SEC * -1_000
116122
);
117123
}
118-
124+
119125
private static boolean hasLocationPermission(Context context) {
120126
return ContextCompat.checkSelfPermission(context, "android.permission.ACCESS_FINE_LOCATION") == PackageManager.PERMISSION_GRANTED
121127
|| ContextCompat.checkSelfPermission(context, "android.permission.ACCESS_COARSE_LOCATION") == PackageManager.PERMISSION_GRANTED;
122128
}
123129

130+
static void addPromptHandlerIfAvailable(LocationHandler handler) {
131+
if (handler instanceof LocationPromptCompletionHandler) {
132+
synchronized (promptHandlers) {
133+
promptHandlers.add((LocationPromptCompletionHandler) handler);
134+
}
135+
}
136+
}
137+
138+
static void sendAndClearPromptHandlers(boolean promptLocation, boolean accepted) {
139+
if (!promptLocation) {
140+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "LocationGMS sendAndClearPromptHandlers from non prompt flow");
141+
return;
142+
}
143+
144+
synchronized (promptHandlers) {
145+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "LocationGMS calling prompt handlers");
146+
for (LocationPromptCompletionHandler promptHandler : promptHandlers) {
147+
promptHandler.onAnswered(accepted);
148+
}
149+
// We only call the prompt handlers once
150+
promptHandlers.clear();
151+
}
152+
}
153+
154+
/**
155+
* This method handle location and permission location flows and border cases.
156+
* For each flow we need to trigger location prompts listener,
157+
* in that way all listener will now that location request completed, even if its showing a prompt
158+
*
159+
* Cases managed:
160+
* - If app doesn't have location sharing activated, then location will not attributed
161+
* - For API less than 23, prompt permission aren't needed
162+
* - For API greater or equal than 23
163+
* - Ask for permission if needed, this will prompt PermissionActivity
164+
* - If permission granted, then trigger location attribution
165+
* - If permission denied, then trigger fail flow
166+
* - If location service is disable, then trigger fail flow
167+
* - If the user approved for location and has disable location this will continue triggering fails flows
168+
*
169+
* For all cases we are calling prompt listeners.
170+
*/
124171
static void getLocation(Context context, boolean promptLocation, LocationHandler handler) {
172+
addPromptHandlerIfAvailable(handler);
125173
classContext = context;
126174
locationHandlers.put(handler.getType(), handler);
127-
175+
128176
if (!OneSignal.shareLocation) {
177+
sendAndClearPromptHandlers(promptLocation, false);
129178
fireFailedComplete();
130179
return;
131180
}
132-
181+
133182
int locationCoarsePermission = PackageManager.PERMISSION_DENIED;
134183

135184
int locationFinePermission = ContextCompat.checkSelfPermission(context, "android.permission.ACCESS_FINE_LOCATION");
@@ -140,10 +189,11 @@ static void getLocation(Context context, boolean promptLocation, LocationHandler
140189

141190
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
142191
if (locationFinePermission != PackageManager.PERMISSION_GRANTED && locationCoarsePermission != PackageManager.PERMISSION_GRANTED) {
192+
sendAndClearPromptHandlers(promptLocation,false);
143193
handler.complete(null);
144194
return;
145195
}
146-
196+
sendAndClearPromptHandlers(promptLocation, true);
147197
startGetLocation();
148198
}
149199
else { // Android 6.0+
@@ -158,18 +208,24 @@ else if (permissionList.contains("android.permission.ACCESS_COARSE_LOCATION")) {
158208
requestPermission = "android.permission.ACCESS_COARSE_LOCATION";
159209
}
160210

161-
if (requestPermission != null && promptLocation)
211+
if (requestPermission != null && promptLocation) {
162212
PermissionsActivity.startPrompt();
163-
else if (locationCoarsePermission == PackageManager.PERMISSION_GRANTED)
213+
} else if (locationCoarsePermission == PackageManager.PERMISSION_GRANTED) {
214+
sendAndClearPromptHandlers(promptLocation, true);
164215
startGetLocation();
165-
else
216+
} else {
217+
sendAndClearPromptHandlers(promptLocation, false);
166218
fireFailedComplete();
219+
}
167220
} catch (PackageManager.NameNotFoundException e) {
221+
sendAndClearPromptHandlers(promptLocation, false);
168222
e.printStackTrace();
169223
}
170224
}
171-
else
225+
else {
226+
sendAndClearPromptHandlers(promptLocation, true);
172227
startGetLocation();
228+
}
173229
}
174230
}
175231

@@ -231,17 +287,16 @@ static void fireFailedComplete() {
231287
PermissionsActivity.answered = false;
232288

233289
synchronized (syncLock) {
234-
if(mGoogleApiClient != null)
290+
if (mGoogleApiClient != null)
235291
mGoogleApiClient.disconnect();
236292
mGoogleApiClient = null;
237293
}
238-
239294
fireComplete(null);
240295
}
241296

242297
private static void fireComplete(LocationPoint point) {
243298
// create local copies of fields in thread-safe way
244-
HashMap<CALLBACK_TYPE, LocationHandler> _locationHandlers = new HashMap<>();
299+
HashMap<PermissionType, LocationHandler> _locationHandlers = new HashMap<>();
245300
Thread _fallbackFailThread;
246301
synchronized (LocationGMS.class) {
247302
_locationHandlers.putAll(LocationGMS.locationHandlers);
@@ -250,7 +305,7 @@ private static void fireComplete(LocationPoint point) {
250305
}
251306

252307
// execute race-independent logic
253-
for(CALLBACK_TYPE type : _locationHandlers.keySet())
308+
for(PermissionType type : _locationHandlers.keySet())
254309
_locationHandlers.get(type).complete(point);
255310
if (_fallbackFailThread != null && !Thread.currentThread().equals(_fallbackFailThread))
256311
_fallbackFailThread.interrupt();
@@ -265,15 +320,15 @@ private static void fireComplete(LocationPoint point) {
265320
// Save last time so even if a failure we trigger the same schedule update
266321
setLastLocationTime(System.currentTimeMillis());
267322
}
268-
323+
269324
private static void fireCompleteForLocation(Location location) {
270325
LocationPoint point = new LocationPoint();
271-
326+
272327
point.accuracy = location.getAccuracy();
273328
point.bg = !OneSignal.isForeground();
274329
point.type = locationCoarse ? 0 : 1;
275330
point.timeStamp = location.getTime();
276-
331+
277332
// Coarse always gives out 14 digits and has an accuracy 2000.
278333
// Always rounding to 7 as this is what fine returns.
279334
if (locationCoarse) {
@@ -304,7 +359,7 @@ static void onFocusChange() {
304359
}
305360

306361
static LocationUpdateListener locationUpdateListener;
307-
362+
308363
private static class GoogleApiClientListener implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
309364
@Override
310365
public void onConnected(Bundle bundle) {
@@ -336,7 +391,7 @@ public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
336391
}
337392

338393
static class LocationUpdateListener implements LocationListener {
339-
394+
340395
private GoogleApiClient mGoogleApiClient;
341396

342397
// this initializer method is already synchronized from LocationGMS with respect to the GoogleApiClient lock
@@ -352,17 +407,17 @@ static class LocationUpdateListener implements LocationListener {
352407
.setInterval(updateInterval)
353408
.setMaxWaitTime((long)(updateInterval * 1.5))
354409
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
355-
410+
356411
FusedLocationApiWrapper.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
357412
}
358-
413+
359414
@Override
360415
public void onLocationChanged(Location location) {
361416
mLastLocation = location;
362417
OneSignal.Log(OneSignal.LOG_LEVEL.INFO, "Location Change Detected");
363418
}
364419
}
365-
420+
366421
static class FusedLocationApiWrapper {
367422
@SuppressWarnings("MissingPermission")
368423
static void requestLocationUpdates(GoogleApiClient googleApiClient, LocationRequest locationRequest, LocationListener locationListener) {
@@ -375,7 +430,7 @@ static void requestLocationUpdates(GoogleApiClient googleApiClient, LocationRequ
375430
OneSignal.Log(OneSignal.LOG_LEVEL.WARN, "FusedLocationApi.requestLocationUpdates failed!", t);
376431
}
377432
}
378-
433+
379434
@SuppressWarnings("MissingPermission")
380435
static Location getLastLocation(GoogleApiClient googleApiClient) {
381436
synchronized(LocationGMS.syncLock) {
@@ -385,10 +440,10 @@ static Location getLastLocation(GoogleApiClient googleApiClient) {
385440
return null;
386441
}
387442
}
388-
443+
389444
private static class LocationHandlerThread extends HandlerThread {
390445
Handler mHandler;
391-
446+
392447
LocationHandlerThread() {
393448
super("OSH_LocationHandlerThread");
394449
start();

0 commit comments

Comments
 (0)