Skip to content

Commit

Permalink
Database error race condition and SyncService fixes
Browse files Browse the repository at this point in the history
* Fixed issue database race condition issues and removed last database close statement.
  - The following errors should be fixed
  - "Cannot perform this operation because the connection pool has been closed."
  - "attempt to re-open an already-closed object"
* Fixed issue with SyncService staying in memory.
  - START_NOT_STICKY is used when service is started outside of an Activity.
  • Loading branch information
jkasten2 committed Aug 18, 2016
1 parent 6ac10b2 commit 2deafee
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,17 @@ public static void restore(Context context) {
try {
NotificationBundleProcessor.deleteOldNotifications(writableDb);
writableDb.setTransactionSuccessful();
} catch (Exception e) {
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Error deleting old notification records! ", e);
} catch (Throwable t) {
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Error deleting old notification records! ", t);
} finally {
writableDb.endTransaction();
}

String[] retColumn = { NotificationTable.COLUMN_NAME_ANDROID_NOTIFICATION_ID,
NotificationTable.COLUMN_NAME_FULL_DATA };

Cursor cursor = writableDb.query(
SQLiteDatabase readableDb = dbHelper.getReadableDatabase();
Cursor cursor = readableDb.query(
NotificationTable.TABLE_NAME,
retColumn,
// 1 Week back.
Expand All @@ -83,27 +84,32 @@ public static void restore(Context context) {
NotificationTable._ID + " ASC" // sort order, old to new
);

if (cursor.moveToFirst()) {
boolean useExtender = (NotificationExtenderService.getIntent(context) != null);
try {
if (cursor.moveToFirst()) {
boolean useExtender = (NotificationExtenderService.getIntent(context) != null);

do {
int existingId = cursor.getInt(cursor.getColumnIndex(NotificationTable.COLUMN_NAME_ANDROID_NOTIFICATION_ID));
String fullData = cursor.getString(cursor.getColumnIndex(NotificationTable.COLUMN_NAME_FULL_DATA));
do {
int existingId = cursor.getInt(cursor.getColumnIndex(NotificationTable.COLUMN_NAME_ANDROID_NOTIFICATION_ID));
String fullData = cursor.getString(cursor.getColumnIndex(NotificationTable.COLUMN_NAME_FULL_DATA));

Intent serviceIntent;
Intent serviceIntent;

if (useExtender)
serviceIntent = NotificationExtenderService.getIntent(context);
else
serviceIntent = new Intent().setComponent(new ComponentName(context.getPackageName(), GcmIntentService.class.getName()));
if (useExtender)
serviceIntent = NotificationExtenderService.getIntent(context);
else
serviceIntent = new Intent().setComponent(new ComponentName(context.getPackageName(), GcmIntentService.class.getName()));

serviceIntent.putExtra("json_payload", fullData);
serviceIntent.putExtra("android_notif_id", existingId);
serviceIntent.putExtra("restoring", true);
context.startService(serviceIntent);
} while (cursor.moveToNext());
serviceIntent.putExtra("json_payload", fullData);
serviceIntent.putExtra("android_notif_id", existingId);
serviceIntent.putExtra("restoring", true);
context.startService(serviceIntent);
} while (cursor.moveToNext());
}
} catch (Throwable t) {
OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "Error restoring notification records! ", t);
} finally {
if (cursor != null && !cursor.isClosed())
cursor.close();
}

cursor.close();
}
}
14 changes: 11 additions & 3 deletions OneSignalSDK/onesignal/src/main/java/com/onesignal/OneSignal.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public void init() {
private static TrackGooglePurchase trackGooglePurchase;
private static TrackAmazonPurchase trackAmazonPurchase;

public static final String VERSION = "030003";
public static final String VERSION = "030004";

private static AdvertisingIdentifierProvider mainAdIdProvider = new AdvertisingIdProviderGPS();

Expand Down Expand Up @@ -252,14 +252,14 @@ public static void init(Context context, String googleProjectNumber, String oneS
if (contextIsActivity) {
ActivityLifecycleHandler.curActivity = (Activity) context;
NotificationRestorer.asyncRestore(appContext);
startSyncService();
}
else
ActivityLifecycleHandler.nextResumeIsFirstActivity = true;

lastTrackedFocusTime = SystemClock.elapsedRealtime();

OneSignalStateSynchronizer.initUserState(appContext);
appContext.startService(new Intent(appContext, SyncService.class));

if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR2)
((Application)appContext).registerActivityLifecycleCallbacks(new ActivityLifecycleListener());
Expand Down Expand Up @@ -535,6 +535,7 @@ void onSuccess(String response) {
}

static void onAppFocus() {
startSyncService();
foreground = true;
lastTrackedFocusTime = SystemClock.elapsedRealtime();

Expand Down Expand Up @@ -1309,7 +1310,6 @@ static boolean isDuplicateNotification(String id, Context context) {

boolean exists = cursor.moveToFirst();
cursor.close();
readableDb.close();

if (exists) {
Log(LOG_LEVEL.DEBUG, "Duplicate GCM message received, skip processing of " + id);
Expand Down Expand Up @@ -1371,4 +1371,12 @@ static void updateOnSessionDependents() {
private static boolean isPastOnSessionTime() {
return (System.currentTimeMillis() - getLastSessionTime(appContext)) / 1000 >= MIN_ON_SESSION_TIME;
}

static boolean startedSyncService;
private static void startSyncService() {
if (startedSyncService)
return;
startedSyncService = true;
appContext.startService(new Intent(appContext, SyncService.class));
}
}
37 changes: 18 additions & 19 deletions OneSignalSDK/onesignal/src/main/java/com/onesignal/SyncService.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,32 @@ private void checkOnFocusSync() {

@Override
public void onCreate() {
// If service was started from outside the app.
if (OneSignal.appContext == null) {
OneSignal.appContext = this.getApplicationContext();
if (OneSignal.startedSyncService)
return;

new Thread(new Runnable() {
@Override
public void run() {
if (OneSignal.getUserId() == null) {
stopSelf();
return;
}
OneSignal.appContext = this.getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
if (OneSignal.getUserId() == null) {
stopSelf();
return;
}

OneSignal.appId = OneSignal.getSavedAppId();
OneSignal.appId = OneSignal.getSavedAppId();

OneSignalStateSynchronizer.initUserState(OneSignal.appContext);
OneSignalStateSynchronizer.syncUserState(true);
checkOnFocusSync();
OneSignalStateSynchronizer.initUserState(OneSignal.appContext);
OneSignalStateSynchronizer.syncUserState(true);
checkOnFocusSync();

stopSelf();
}
}).start();
}
stopSelf();
}
}).start();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
return OneSignal.startedSyncService ? START_STICKY : START_NOT_STICKY;
}

// This Service does not support bindings.
Expand Down

0 comments on commit 2deafee

Please sign in to comment.