Skip to content

Commit f513a8f

Browse files
committed
Rare Registration and location fields fixes, and open callback improvements
* Fixed rare but were device would not register with OneSignal due to intermittent connection issues or GMS aar file version mismatches. * Fixes around NotificationOpenedHandler with the back button for Corona and Cordova. - Added new removeNotificationOpenedHandler method which will be called by the Corona/Cordova wrapper when its run time shutsdown. * Fixed issues with location fields.
1 parent 8d9dce0 commit f513a8f

File tree

11 files changed

+214
-71
lines changed

11 files changed

+214
-71
lines changed

OneSignalSDK/app/build.gradle

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ android {
1818
buildTypes {
1919
debug {
2020
// Test with proguard enabled to make sure our consumer rules are correct in the SDK.
21+
// minify does not work with GMS 7.0.0 with the current settings. Use 8.4.0 to test.
2122
minifyEnabled true
2223
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
2324
}
@@ -51,10 +52,12 @@ dependencies {
5152

5253
// Test with 7.0.0 to make sure there are no breaking changes in Google's libraries.
5354
// This insure that the SDK will work if an app developer is using an older version of GMS.
54-
compile "com.google.android.gms:play-services-gcm:7.0.0"
55-
compile "com.google.android.gms:play-services-analytics:7.0.0"
56-
compile "com.google.android.gms:play-services-location:7.0.0"
57-
// compile 'com.android.support:support-v4:23.0.0'
55+
compile "com.google.android.gms:play-services-gcm:8.4.0"
56+
57+
// play-services-analytics is required for AdvertisingIdClient when using GMS 8.1.0 or lower.
58+
// 8.3.0 it is included in 'basement' which is required by 'base'.
59+
//compile "com.google.android.gms:play-services-analytics:7.0.0"
60+
compile "com.google.android.gms:play-services-location:8.4.0"
5861

5962
// testCompile 'junit:junit:4.12'
6063
// testCompile 'org.robolectric:shadows-support-v4:3.0'

OneSignalSDK/app/src/test/java/com/onesignal/OneSignalPackagePrivateHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import static org.robolectric.Shadows.shadowOf;
1010

1111
public class OneSignalPackagePrivateHelper {
12-
public static void runAllNetworkRunnable() {
12+
public static void runAllNetworkRunnables() {
1313
for (Map.Entry<Integer, OneSignalStateSynchronizer.NetworkHandlerThread> handlerThread : OneSignalStateSynchronizer.networkHandlerThreads.entrySet()) {
1414
Scheduler scheduler = shadowOf(handlerThread.getValue().getLooper()).getScheduler();
1515
while (scheduler.advanceToNextPostedRunnable()) {}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2015 OneSignal
5+
*
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+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
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+
32+
import org.robolectric.annotation.Implements;
33+
34+
@Implements(LocationGMS.class)
35+
public class ShadowLocationGMS {
36+
37+
public static Double lat = 1.0, log = 2.0;
38+
public static Float accuracy = 3.0f;
39+
public static Integer type = 0;
40+
41+
static void getLocation(Context context, boolean promptLocation, LocationGMS.LocationHandler handler) {
42+
handler.complete(lat, log, accuracy, type);
43+
}
44+
}

OneSignalSDK/app/src/test/java/com/test/onesignal/CustomRobolectricTestRunner.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import org.junit.runners.model.InitializationError;
3131
import org.robolectric.RobolectricGradleTestRunner;
32+
import org.robolectric.annotation.Config;
3233
import org.robolectric.internal.bytecode.InstrumentationConfiguration;
3334

3435
public class CustomRobolectricTestRunner extends RobolectricGradleTestRunner {
@@ -37,7 +38,7 @@ public CustomRobolectricTestRunner(Class<?> klass) throws InitializationError {
3738
}
3839

3940
@Override
40-
public InstrumentationConfiguration createClassLoaderConfig() {
41+
public InstrumentationConfiguration createClassLoaderConfig(Config config) {
4142
return InstrumentationConfiguration.newBuilder().addInstrumentedPackage("com.onesignal").build();
4243
}
4344
}

OneSignalSDK/app/src/test/java/com/test/onesignal/MainOneSignalClassRunner.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.onesignal.BuildConfig;
3737
import com.onesignal.NotificationBundleProcessor;
3838
import com.onesignal.OneSignal;
39+
import com.onesignal.ShadowLocationGMS;
3940
import com.onesignal.ShadowOSUtils;
4041
import com.onesignal.ShadowOneSignalRestClient;
4142
import com.onesignal.OneSignalPackagePrivateHelper;
@@ -66,7 +67,7 @@
6667

6768
@Config(packageName = "com.onesignal.example",
6869
constants = BuildConfig.class,
69-
shadows = {ShadowOneSignalRestClient.class, ShadowPushRegistratorGPS.class, ShadowPushRegistratorADM.class, ShadowOSUtils.class},
70+
shadows = {ShadowOneSignalRestClient.class, ShadowPushRegistratorGPS.class, ShadowPushRegistratorADM.class, ShadowOSUtils.class, ShadowLocationGMS.class},
7071
sdk = 21)
7172

7273
@RunWith(CustomRobolectricTestRunner.class)
@@ -155,6 +156,25 @@ public void notificationOpened(String message, JSONObject additionalData, boolea
155156
Assert.assertEquals("Robo test message", notificationOpenedMessage);
156157
}
157158

159+
@Test
160+
public void shouldCorrectlyRemoveOpenedHandlerAndFireMissedOnesWhenAddedBack() throws Exception {
161+
OneSignal.NotificationOpenedHandler notifHandler = new OneSignal.NotificationOpenedHandler() {
162+
@Override
163+
public void notificationOpened(String message, JSONObject additionalData, boolean isActive) {
164+
notificationOpenedMessage = message;
165+
}
166+
};
167+
OneSignal.init(blankActivity, "123456789", ONESIGNAL_APP_ID, notifHandler);
168+
threadAndTaskWait();
169+
170+
OneSignal.removeNotificationOpenedHandler();
171+
OneSignal.handleNotificationOpened(blankActivity, new JSONArray("[{ \"alert\": \"Robo test message\", \"custom\": { \"i\": \"UUID\" } }]"), false);
172+
Assert.assertNull(notificationOpenedMessage);
173+
174+
OneSignal.init(blankActivity, "123456789", ONESIGNAL_APP_ID, notifHandler);
175+
Assert.assertEquals("Robo test message", notificationOpenedMessage);
176+
}
177+
158178
@Test
159179
public void shouldNotFireNotificationOpenAgainAfterAppRestart() throws Exception {
160180
OneSignal.init(blankActivity, "123456789", ONESIGNAL_APP_ID, new OneSignal.NotificationOpenedHandler() {
@@ -619,6 +639,29 @@ public void shouldNotDoubleCountFocusTime() throws Exception {
619639
}
620640
*/
621641

642+
// ####### Unit Test Location ########
643+
644+
@Test
645+
public void shouldUpdateAllLocationFieldsWhenAnyFieldsChange() throws Exception {
646+
OneSignalInit();
647+
threadAndTaskWait();
648+
Assert.assertEquals(1.0, ShadowOneSignalRestClient.lastPost.getDouble("lat"));
649+
Assert.assertEquals(2.0, ShadowOneSignalRestClient.lastPost.getDouble("long"));
650+
Assert.assertEquals(3.0, ShadowOneSignalRestClient.lastPost.getDouble("loc_acc"));
651+
Assert.assertEquals(0.0, ShadowOneSignalRestClient.lastPost.getDouble("loc_type"));
652+
653+
ShadowOneSignalRestClient.lastPost = null;
654+
StaticResetHelper.restSetStaticFields();
655+
ShadowLocationGMS.lat = 30.0;
656+
ShadowLocationGMS.accuracy = 5.0f;
657+
658+
OneSignalInit();
659+
threadAndTaskWait();
660+
Assert.assertEquals(30.0, ShadowOneSignalRestClient.lastPost.getDouble("lat"));
661+
Assert.assertEquals(2.0, ShadowOneSignalRestClient.lastPost.getDouble("long"));
662+
Assert.assertEquals(5.0, ShadowOneSignalRestClient.lastPost.getDouble("loc_acc"));
663+
Assert.assertEquals(0.0, ShadowOneSignalRestClient.lastPost.getDouble("loc_type"));
664+
}
622665

623666
// ####### Unit test helper methods ########
624667

@@ -628,7 +671,7 @@ private static void threadWait() {
628671

629672
private void threadAndTaskWait() {
630673
try {Thread.sleep(300);} catch (Throwable t) {}
631-
OneSignalPackagePrivateHelper.runAllNetworkRunnable();
674+
OneSignalPackagePrivateHelper.runAllNetworkRunnables();
632675
OneSignalPackagePrivateHelper.runFocusRunnables();
633676

634677
Robolectric.getForegroundThreadScheduler().runOneTask();

OneSignalSDK/onesignal/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ dependencies {
2626
provided fileTree(dir: 'libs', include: ['*.jar'])
2727

2828
compile 'com.google.android.gms:play-services-gcm:8.4.0'
29-
compile 'com.google.android.gms:play-services-analytics:8.4.0'
3029
compile 'com.google.android.gms:play-services-location:8.4.0'
3130
}
3231

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ static void onActivityPaused(Activity activity) {
8484
}
8585

8686
static void onActivityStopped(Activity activity) {
87+
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "onActivityStopped: " + activity.getClass().getName());
88+
8789
if (activity == curActivity) {
8890
curActivity = null;
8991
handleLostFocus();
@@ -93,6 +95,8 @@ static void onActivityStopped(Activity activity) {
9395
}
9496

9597
static void onActivityDestroyed(Activity activity) {
98+
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "onActivityDestroyed: " + activity.getClass().getName());
99+
96100
if (activity == curActivity) {
97101
curActivity = null;
98102
handleLostFocus();

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public void onPaused(Activity activity) {
6868

6969
while (true) {
7070
// Wait for new activity events, does not fire for pauses through.
71+
// waitForActivity should also return for onStop and onDestroy according to android/app/Instrumentation.java but this is not happening on a real device.
7172
Activity currentActivity = allActivitiesMonitor.waitForActivity();
7273

7374
if (!currentActivity.isFinishing()) {

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

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import android.location.Location;
3636
import android.os.Build;
3737
import android.os.Bundle;
38+
import android.os.SystemClock;
3839

3940
import com.google.android.gms.common.ConnectionResult;
4041
import com.google.android.gms.common.api.GoogleApiClient;
@@ -49,25 +50,29 @@ class LocationGMS {
4950
private static GoogleApiClientCompatProxy mGoogleApiClient;
5051
static String requestPermission;
5152

52-
private static ActivityLifecycleHandler.ActivityAvailableListener activityAvailableListener;
53-
5453
interface LocationHandler {
55-
void complete(Double lat, Double log);
54+
void complete(Double lat, Double log, Float accuracy, Integer type);
5655
}
5756

5857
private static LocationHandler locationHandler;
5958

59+
private static Thread fallbackFailThread;
60+
61+
private static boolean locationCoarse;
62+
6063
static void getLocation(Context context, boolean promptLocation, LocationHandler handler) {
6164
locationHandler = handler;
6265
int locationCoarsePermission = PackageManager.PERMISSION_DENIED;
6366

6467
int locationFinePermission = ContextCompat.checkSelfPermission(context, "android.permission.ACCESS_FINE_LOCATION");
65-
if (locationFinePermission == PackageManager.PERMISSION_DENIED)
68+
if (locationFinePermission == PackageManager.PERMISSION_DENIED) {
6669
locationCoarsePermission = ContextCompat.checkSelfPermission(context, "android.permission.ACCESS_COARSE_LOCATION");
70+
locationCoarse = true;
71+
}
6772

6873
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
6974
if (locationFinePermission != PackageManager.PERMISSION_GRANTED && locationCoarsePermission != PackageManager.PERMISSION_GRANTED) {
70-
handler.complete(null, null);
75+
handler.complete(null, null, null, null);
7176
return;
7277
}
7378

@@ -102,6 +107,15 @@ else if (locationCoarsePermission == PackageManager.PERMISSION_GRANTED)
102107

103108
static void startGetLocation() {
104109
try {
110+
fallbackFailThread = new Thread(new Runnable() {
111+
public void run() {
112+
SystemClock.sleep(30000);
113+
OneSignal.Log(OneSignal.LOG_LEVEL.WARN, "Location permission exists but GoogleApiClient timedout. Maybe related to mismatch google-play aar versions.");
114+
fireFailedComplete();
115+
}
116+
});
117+
fallbackFailThread.start();
118+
105119
GoogleApiClientListener googleApiClientListener = new GoogleApiClientListener();
106120
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(OneSignal.appContext)
107121
.addApi(LocationServices.API)
@@ -120,22 +134,33 @@ static void startGetLocation() {
120134
static void fireFailedComplete() {
121135
PermissionsActivity.answered = false;
122136

123-
locationHandler.complete(null, null);
137+
fireComplete(null, null, null, null);
124138
if (mGoogleApiClient != null)
125139
mGoogleApiClient.disconnect();
126140
}
127141

142+
private static void fireComplete(Double lat, Double log, Float accuracy, Integer type) {
143+
locationHandler.complete(lat, log, accuracy, type);
144+
if (fallbackFailThread != null && !Thread.currentThread().equals(fallbackFailThread))
145+
fallbackFailThread.interrupt();
146+
}
147+
128148
private static class GoogleApiClientListener implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
129149
@Override
130150
public void onConnected(Bundle bundle) {
131151
PermissionsActivity.answered = false;
132152

133153
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient.realInstance());
154+
134155
// Coarse always gives out 14 digits and has an accuracy 2000. Always rounding to 7 as this is what fine returns.
135-
if (location != null)
136-
locationHandler.complete(new BigDecimal(location.getLatitude()).setScale(7, RoundingMode.HALF_UP).doubleValue(), new BigDecimal(location.getLongitude()).setScale(7, RoundingMode.HALF_UP).doubleValue());
156+
if (location != null) {
157+
location.getAccuracy();
158+
Double lat = new BigDecimal(location.getLatitude()).setScale(7, RoundingMode.HALF_UP).doubleValue();
159+
Double log = new BigDecimal(location.getLongitude()).setScale(7, RoundingMode.HALF_UP).doubleValue();
160+
fireComplete(lat, log, location.getAccuracy(), locationCoarse ? 0 : 1);
161+
}
137162
else
138-
locationHandler.complete(null, null);
163+
fireComplete(null, null, null, null);
139164

140165
mGoogleApiClient.disconnect();
141166
}

0 commit comments

Comments
 (0)