Showing
3 changed files
with
357 additions
and
142 deletions
... | @@ -258,8 +258,8 @@ | ... | @@ -258,8 +258,8 @@ |
258 | <!-- </intent-filter>--> | 258 | <!-- </intent-filter>--> |
259 | <!-- </receiver>--> | 259 | <!-- </receiver>--> |
260 | 260 | ||
261 | - <!-- <provider--> | 261 | + <provider |
262 | - <!-- android:name=".utils.WarplyProvider"--> | 262 | + android:name=".utils.WarplyProvider" |
263 | - <!-- android:authorities="ly.warp.sdk.utils.WarplyProvider" />--> | 263 | + android:authorities="ly.warp.sdk.utils.WarplyProvider" /> |
264 | </application> | 264 | </application> |
265 | </manifest> | 265 | </manifest> |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -26,6 +26,11 @@ import java.io.FileNotFoundException; | ... | @@ -26,6 +26,11 @@ import java.io.FileNotFoundException; |
26 | import java.io.IOException; | 26 | import java.io.IOException; |
27 | import java.util.ArrayList; | 27 | import java.util.ArrayList; |
28 | import java.util.List; | 28 | import java.util.List; |
29 | +import java.util.concurrent.ExecutorService; | ||
30 | +import java.util.concurrent.Executors; | ||
31 | +import java.util.concurrent.Future; | ||
32 | +import java.util.concurrent.TimeUnit; | ||
33 | +import java.util.concurrent.TimeoutException; | ||
29 | 34 | ||
30 | import ly.warp.sdk.utils.constants.WarpConstants; | 35 | import ly.warp.sdk.utils.constants.WarpConstants; |
31 | 36 | ||
... | @@ -40,9 +45,13 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -40,9 +45,13 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
40 | } | 45 | } |
41 | 46 | ||
42 | private static final String DB_NAME = "warply.db"; | 47 | private static final String DB_NAME = "warply.db"; |
43 | - private static final int DB_VERSION = 12; | 48 | + private static final int DB_VERSION = 13; |
44 | private static final String KEY_CIPHER = "tn#mpOl3v3Dy1pr@W"; | 49 | private static final String KEY_CIPHER = "tn#mpOl3v3Dy1pr@W"; |
45 | 50 | ||
51 | + // Timeout constants | ||
52 | + private static final int CONNECTION_TIMEOUT_MS = 5000; // 5 seconds for database connection | ||
53 | + private static final int OPERATION_TIMEOUT_MS = 5000; // 5 seconds for database operations | ||
54 | + | ||
46 | //------------------------------ Fields -----------------------------// | 55 | //------------------------------ Fields -----------------------------// |
47 | private static String TABLE_REQUESTS = "requests"; | 56 | private static String TABLE_REQUESTS = "requests"; |
48 | private static String TABLE_PUSH_REQUESTS = "push_requests"; | 57 | private static String TABLE_PUSH_REQUESTS = "push_requests"; |
... | @@ -119,6 +128,9 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -119,6 +128,9 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
119 | private SQLiteDatabase mDb; | 128 | private SQLiteDatabase mDb; |
120 | private static WarplyDBHelper mDBHelperInstance; | 129 | private static WarplyDBHelper mDBHelperInstance; |
121 | 130 | ||
131 | + // Single-threaded executor for database operations | ||
132 | + private final ExecutorService dbExecutor = Executors.newSingleThreadExecutor(); | ||
133 | + | ||
122 | // =========================================================== | 134 | // =========================================================== |
123 | // Constructors | 135 | // Constructors |
124 | // =========================================================== | 136 | // =========================================================== |
... | @@ -145,21 +157,65 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -145,21 +157,65 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
145 | } | 157 | } |
146 | 158 | ||
147 | /** | 159 | /** |
148 | - * If database connection already initialized, return the db. Else create a | 160 | + * Gets a writable database connection on a background thread with timeout. |
149 | - * new one | 161 | + * This prevents ANR issues by ensuring database operations don't block the main thread. |
150 | */ | 162 | */ |
151 | private SQLiteDatabase getDb() { | 163 | private SQLiteDatabase getDb() { |
152 | - if (mDb == null) | 164 | + if (mDb == null || !mDb.isOpen()) { |
153 | - mDb = getWritableDatabase(KEY_CIPHER); | 165 | + try { |
166 | + // Submit task to executor and get future | ||
167 | + Future<SQLiteDatabase> future = dbExecutor.submit(() -> getWritableDatabase(KEY_CIPHER)); | ||
168 | + | ||
169 | + // Wait for result with timeout | ||
170 | + mDb = future.get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS); | ||
171 | + | ||
172 | + // Set busy timeout on the database connection | ||
173 | + if (mDb != null && mDb.isOpen()) { | ||
174 | + mDb.rawExecSQL("PRAGMA busy_timeout = " + CONNECTION_TIMEOUT_MS); | ||
175 | + } | ||
176 | + } catch (TimeoutException e) { | ||
177 | + Log.e("WarplyDBHelper", "Timeout getting writable database connection", e); | ||
178 | + // Return null or handle timeout as appropriate | ||
179 | + } catch (Exception e) { | ||
180 | + Log.e("WarplyDBHelper", "Error getting writable database connection", e); | ||
181 | + // Handle other exceptions | ||
182 | + } | ||
183 | + } | ||
154 | return mDb; | 184 | return mDb; |
155 | } | 185 | } |
156 | 186 | ||
187 | + /** | ||
188 | + * Gets a readable database connection on a background thread with timeout. | ||
189 | + * This prevents ANR issues by ensuring database operations don't block the main thread. | ||
190 | + */ | ||
157 | private SQLiteDatabase getReadableDb() { | 191 | private SQLiteDatabase getReadableDb() { |
158 | - if (mDb == null) | 192 | + if (mDb == null || !mDb.isOpen()) { |
159 | - mDb = getReadableDatabase(KEY_CIPHER); | 193 | + try { |
194 | + // Submit task to executor and get future | ||
195 | + Future<SQLiteDatabase> future = dbExecutor.submit(() -> getReadableDatabase(KEY_CIPHER)); | ||
196 | + | ||
197 | + // Wait for result with timeout | ||
198 | + mDb = future.get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS); | ||
199 | + | ||
200 | + // Set busy timeout on the database connection | ||
201 | + if (mDb != null && mDb.isOpen()) { | ||
202 | + mDb.rawExecSQL("PRAGMA busy_timeout = " + CONNECTION_TIMEOUT_MS); | ||
203 | + } | ||
204 | + } catch (TimeoutException e) { | ||
205 | + Log.e("WarplyDBHelper", "Timeout getting readable database connection", e); | ||
206 | + // Return null or handle timeout as appropriate | ||
207 | + } catch (Exception e) { | ||
208 | + Log.e("WarplyDBHelper", "Error getting readable database connection", e); | ||
209 | + // Handle other exceptions | ||
210 | + } | ||
211 | + } | ||
160 | return mDb; | 212 | return mDb; |
161 | } | 213 | } |
162 | 214 | ||
215 | + /** | ||
216 | + * Close database connection - should only be called when app is being destroyed | ||
217 | + * or when database won't be used for a long time | ||
218 | + */ | ||
163 | private void closeDb() { | 219 | private void closeDb() { |
164 | if (mDb != null && mDb.isOpen()) { | 220 | if (mDb != null && mDb.isOpen()) { |
165 | mDb.close(); | 221 | mDb.close(); |
... | @@ -167,8 +223,53 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -167,8 +223,53 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
167 | } | 223 | } |
168 | } | 224 | } |
169 | 225 | ||
226 | + /** | ||
227 | + * Initialize database connection on a background thread. | ||
228 | + * Call this during app startup to prevent ANR issues. | ||
229 | + */ | ||
230 | + public void initialize() { | ||
231 | + if (mDb == null || !mDb.isOpen()) { | ||
232 | + try { | ||
233 | + // Submit task to executor and get future | ||
234 | + Future<SQLiteDatabase> future = dbExecutor.submit(() -> getWritableDatabase(KEY_CIPHER)); | ||
235 | + | ||
236 | + // Wait for result with timeout | ||
237 | + mDb = future.get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS); | ||
238 | + | ||
239 | + // Set busy timeout on the database connection | ||
240 | + if (mDb != null && mDb.isOpen()) { | ||
241 | + mDb.rawExecSQL("PRAGMA busy_timeout = " + CONNECTION_TIMEOUT_MS); | ||
242 | + } | ||
243 | + } catch (TimeoutException e) { | ||
244 | + Log.e("WarplyDBHelper", "Timeout initializing database connection", e); | ||
245 | + } catch (Exception e) { | ||
246 | + Log.e("WarplyDBHelper", "Error initializing database connection", e); | ||
247 | + } | ||
248 | + } | ||
249 | + } | ||
250 | + | ||
251 | + /** | ||
252 | + * Shutdown database connection and executor service. | ||
253 | + * Call this when app is being destroyed. | ||
254 | + */ | ||
255 | + public void shutdown() { | ||
256 | + closeDb(); | ||
257 | + | ||
258 | + // Shutdown executor service | ||
259 | + dbExecutor.shutdown(); | ||
260 | + try { | ||
261 | + if (!dbExecutor.awaitTermination(5, TimeUnit.SECONDS)) { | ||
262 | + dbExecutor.shutdownNow(); | ||
263 | + } | ||
264 | + } catch (InterruptedException e) { | ||
265 | + dbExecutor.shutdownNow(); | ||
266 | + Thread.currentThread().interrupt(); | ||
267 | + } | ||
268 | + } | ||
269 | + | ||
170 | @Override | 270 | @Override |
171 | public void onCreate(SQLiteDatabase db) { | 271 | public void onCreate(SQLiteDatabase db) { |
272 | + // Create tables | ||
172 | db.execSQL(CREATE_TABLE_REQUESTS); | 273 | db.execSQL(CREATE_TABLE_REQUESTS); |
173 | db.execSQL(CREATE_TABLE_TAGS); | 274 | db.execSQL(CREATE_TABLE_TAGS); |
174 | db.execSQL(CREATE_TABLE_PUSH_REQUESTS); | 275 | db.execSQL(CREATE_TABLE_PUSH_REQUESTS); |
... | @@ -176,6 +277,14 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -176,6 +277,14 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
176 | db.execSQL(CREATE_TABLE_CLIENT); | 277 | db.execSQL(CREATE_TABLE_CLIENT); |
177 | db.execSQL(CREATE_TABLE_AUTH); | 278 | db.execSQL(CREATE_TABLE_AUTH); |
178 | db.execSQL(CREATE_TABLE_TELEMATICS); | 279 | db.execSQL(CREATE_TABLE_TELEMATICS); |
280 | + | ||
281 | + // Create indexes for frequently queried columns to improve performance | ||
282 | + db.execSQL("CREATE INDEX IF NOT EXISTS idx_requests_force ON " + TABLE_REQUESTS + "(" + KEY_REQUESTS_FORCE + ")"); | ||
283 | + db.execSQL("CREATE INDEX IF NOT EXISTS idx_requests_date ON " + TABLE_REQUESTS + "(" + KEY_REQUESTS_DATE_ADDED + ")"); | ||
284 | + db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_requests_force ON " + TABLE_PUSH_REQUESTS + "(" + KEY_REQUESTS_FORCE + ")"); | ||
285 | + db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_requests_date ON " + TABLE_PUSH_REQUESTS + "(" + KEY_REQUESTS_DATE_ADDED + ")"); | ||
286 | + db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_ack_requests_force ON " + TABLE_PUSH_ACK_REQUESTS + "(" + KEY_REQUESTS_FORCE + ")"); | ||
287 | + db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_ack_requests_date ON " + TABLE_PUSH_ACK_REQUESTS + "(" + KEY_REQUESTS_DATE_ADDED + ")"); | ||
179 | } | 288 | } |
180 | 289 | ||
181 | @Override | 290 | @Override |
... | @@ -228,36 +337,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -228,36 +337,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
228 | public synchronized void clearTable(String tableName) { | 337 | public synchronized void clearTable(String tableName) { |
229 | SQLiteDatabase db = getDb(); | 338 | SQLiteDatabase db = getDb(); |
230 | db.delete(tableName, null, null); | 339 | db.delete(tableName, null, null); |
231 | - | 340 | + // Don't close the database here to improve performance |
232 | - closeDb(); | ||
233 | } | 341 | } |
234 | 342 | ||
235 | public synchronized void insert(String tableName, ContentValues values) { | 343 | public synchronized void insert(String tableName, ContentValues values) { |
236 | SQLiteDatabase db = getDb(); | 344 | SQLiteDatabase db = getDb(); |
237 | db.insert(tableName, null, values); | 345 | db.insert(tableName, null, values); |
238 | - | 346 | + // Don't close the database here to improve performance |
239 | - closeDb(); | ||
240 | } | 347 | } |
241 | 348 | ||
242 | public synchronized void update(String tableName, ContentValues values) { | 349 | public synchronized void update(String tableName, ContentValues values) { |
243 | SQLiteDatabase db = getDb(); | 350 | SQLiteDatabase db = getDb(); |
244 | db.update(tableName, values, null, null); | 351 | db.update(tableName, values, null, null); |
245 | - | 352 | + // Don't close the database here to improve performance |
246 | - closeDb(); | ||
247 | } | 353 | } |
248 | 354 | ||
249 | public synchronized boolean isTableNotEmpty(String tableName) { | 355 | public synchronized boolean isTableNotEmpty(String tableName) { |
250 | - Cursor cursor = getReadableDb().rawQuery("SELECT COUNT(*) FROM " + tableName, | 356 | + boolean isNotEmpty = false; |
251 | - null); | 357 | + Cursor cursor = null; |
252 | - if (cursor != null && cursor.moveToFirst()) { | 358 | + try { |
253 | - boolean isNotEmpty = cursor.getInt(0) > 0; | 359 | + cursor = getReadableDb().rawQuery("SELECT COUNT(*) FROM " + tableName, null); |
254 | - cursor.close(); | 360 | + if (cursor != null && cursor.moveToFirst()) { |
255 | - closeDb(); | 361 | + isNotEmpty = cursor.getInt(0) > 0; |
256 | - return isNotEmpty; | 362 | + } |
257 | - } else { | 363 | + } finally { |
258 | - closeDb(); | 364 | + if (cursor != null) { |
259 | - return false; | 365 | + cursor.close(); |
366 | + } | ||
367 | + // Don't close the database here to improve performance | ||
260 | } | 368 | } |
369 | + return isNotEmpty; | ||
261 | } | 370 | } |
262 | 371 | ||
263 | //------------------------------ Auth -----------------------------// | 372 | //------------------------------ Auth -----------------------------// |
... | @@ -288,30 +397,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -288,30 +397,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
288 | @Nullable | 397 | @Nullable |
289 | public synchronized String getAuthValue(String columnName) { | 398 | public synchronized String getAuthValue(String columnName) { |
290 | String columnValue = ""; | 399 | String columnValue = ""; |
291 | - Cursor cursor = getReadableDb().query(TABLE_AUTH, new String[]{columnName}, null, null, null, null, null); | 400 | + Cursor cursor = null; |
292 | - if (cursor != null && cursor.moveToFirst()) { | 401 | + try { |
293 | - cursor.moveToFirst(); | 402 | + cursor = getReadableDb().query(TABLE_AUTH, new String[]{columnName}, null, null, null, null, null); |
294 | - columnValue = cursor.getString(cursor.getColumnIndex(columnName)); | 403 | + if (cursor != null && cursor.moveToFirst()) { |
295 | - cursor.close(); | 404 | + columnValue = cursor.getString(cursor.getColumnIndex(columnName)); |
405 | + } | ||
406 | + } finally { | ||
407 | + if (cursor != null) { | ||
408 | + cursor.close(); | ||
409 | + } | ||
410 | + // Don't close the database here to improve performance | ||
296 | } | 411 | } |
297 | - | ||
298 | - closeDb(); | ||
299 | - | ||
300 | return columnValue; | 412 | return columnValue; |
301 | } | 413 | } |
302 | 414 | ||
303 | @Nullable | 415 | @Nullable |
304 | public synchronized String getClientValue(String columnName) { | 416 | public synchronized String getClientValue(String columnName) { |
305 | String columnValue = ""; | 417 | String columnValue = ""; |
306 | - Cursor cursor = getReadableDb().query(TABLE_CLIENT, new String[]{columnName}, null, null, null, null, null); | 418 | + Cursor cursor = null; |
307 | - if (cursor != null && cursor.moveToFirst()) { | 419 | + try { |
308 | - cursor.moveToFirst(); | 420 | + cursor = getReadableDb().query(TABLE_CLIENT, new String[]{columnName}, null, null, null, null, null); |
309 | - columnValue = cursor.getString(cursor.getColumnIndex(columnName)); | 421 | + if (cursor != null && cursor.moveToFirst()) { |
310 | - cursor.close(); | 422 | + columnValue = cursor.getString(cursor.getColumnIndex(columnName)); |
423 | + } | ||
424 | + } finally { | ||
425 | + if (cursor != null) { | ||
426 | + cursor.close(); | ||
427 | + } | ||
428 | + // Don't close the database here to improve performance | ||
311 | } | 429 | } |
312 | - | ||
313 | - closeDb(); | ||
314 | - | ||
315 | return columnValue; | 430 | return columnValue; |
316 | } | 431 | } |
317 | 432 | ||
... | @@ -324,21 +439,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -324,21 +439,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
324 | } | 439 | } |
325 | 440 | ||
326 | //------------------------------ Api requests -----------------------------// | 441 | //------------------------------ Api requests -----------------------------// |
442 | + /** | ||
443 | + * Gets all requests from the database. | ||
444 | + * NOTE: The caller is responsible for closing the returned Cursor when done with it. | ||
445 | + */ | ||
327 | public synchronized Cursor getAllRequests() { | 446 | public synchronized Cursor getAllRequests() { |
447 | + // We don't close the database here because the cursor needs it to remain open | ||
328 | return getReadableDb().query(TABLE_REQUESTS, | 448 | return getReadableDb().query(TABLE_REQUESTS, |
329 | new String[]{KEY_REQUESTS_ID, | 449 | new String[]{KEY_REQUESTS_ID, |
330 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, | 450 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, |
331 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); | 451 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); |
332 | } | 452 | } |
333 | 453 | ||
454 | + /** | ||
455 | + * Gets all push requests from the database. | ||
456 | + * NOTE: The caller is responsible for closing the returned Cursor when done with it. | ||
457 | + */ | ||
334 | public synchronized Cursor getAllPushRequests() { | 458 | public synchronized Cursor getAllPushRequests() { |
459 | + // We don't close the database here because the cursor needs it to remain open | ||
335 | return getReadableDb().query(TABLE_PUSH_REQUESTS, | 460 | return getReadableDb().query(TABLE_PUSH_REQUESTS, |
336 | new String[]{KEY_REQUESTS_ID, | 461 | new String[]{KEY_REQUESTS_ID, |
337 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, | 462 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, |
338 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); | 463 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); |
339 | } | 464 | } |
340 | 465 | ||
466 | + /** | ||
467 | + * Gets all push acknowledgment requests from the database. | ||
468 | + * NOTE: The caller is responsible for closing the returned Cursor when done with it. | ||
469 | + */ | ||
341 | public synchronized Cursor getAllPushAckRequests() { | 470 | public synchronized Cursor getAllPushAckRequests() { |
471 | + // We don't close the database here because the cursor needs it to remain open | ||
342 | return getReadableDb().query(TABLE_PUSH_ACK_REQUESTS, | 472 | return getReadableDb().query(TABLE_PUSH_ACK_REQUESTS, |
343 | new String[]{KEY_REQUESTS_ID, | 473 | new String[]{KEY_REQUESTS_ID, |
344 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, | 474 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, |
... | @@ -388,163 +518,225 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -388,163 +518,225 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
388 | } | 518 | } |
389 | 519 | ||
390 | public synchronized long getRequestsInQueueCount() { | 520 | public synchronized long getRequestsInQueueCount() { |
391 | - return DatabaseUtils.queryNumEntries(getReadableDb(), TABLE_REQUESTS); | 521 | + SQLiteDatabase db = getReadableDb(); |
522 | + long count = DatabaseUtils.queryNumEntries(db, TABLE_REQUESTS); | ||
523 | + // Don't close the database here to improve performance | ||
524 | + return count; | ||
392 | } | 525 | } |
393 | 526 | ||
394 | public synchronized long getPushRequestsInQueueCount() { | 527 | public synchronized long getPushRequestsInQueueCount() { |
395 | - return DatabaseUtils.queryNumEntries(getReadableDb(), TABLE_PUSH_REQUESTS); | 528 | + SQLiteDatabase db = getReadableDb(); |
529 | + long count = DatabaseUtils.queryNumEntries(db, TABLE_PUSH_REQUESTS); | ||
530 | + // Don't close the database here to improve performance | ||
531 | + return count; | ||
396 | } | 532 | } |
397 | 533 | ||
398 | public synchronized long getPushAckRequestsInQueueCount() { | 534 | public synchronized long getPushAckRequestsInQueueCount() { |
399 | - return DatabaseUtils.queryNumEntries(getReadableDb(), TABLE_PUSH_ACK_REQUESTS); | 535 | + SQLiteDatabase db = getReadableDb(); |
536 | + long count = DatabaseUtils.queryNumEntries(db, TABLE_PUSH_ACK_REQUESTS); | ||
537 | + // Don't close the database here to improve performance | ||
538 | + return count; | ||
400 | } | 539 | } |
401 | 540 | ||
402 | public synchronized void deleteRequests(Long... ids) { | 541 | public synchronized void deleteRequests(Long... ids) { |
403 | - StringBuilder strFilter = new StringBuilder(); | 542 | + if (ids.length == 0) return; |
404 | - for (int i = 0; i < ids.length; i++) { | 543 | + |
405 | - if (i > 0) { | 544 | + SQLiteDatabase db = getDb(); |
406 | - strFilter.append(" OR "); | 545 | + try { |
546 | + db.beginTransaction(); | ||
547 | + StringBuilder strFilter = new StringBuilder(); | ||
548 | + for (int i = 0; i < ids.length; i++) { | ||
549 | + if (i > 0) { | ||
550 | + strFilter.append(" OR "); | ||
551 | + } | ||
552 | + strFilter.append(KEY_REQUESTS_ID); | ||
553 | + strFilter.append("="); | ||
554 | + strFilter.append(ids[i]); | ||
407 | } | 555 | } |
408 | - strFilter.append(KEY_REQUESTS_ID); | 556 | + db.delete(TABLE_REQUESTS, strFilter.toString(), null); |
409 | - strFilter.append("="); | 557 | + db.setTransactionSuccessful(); |
410 | - strFilter.append(ids[i]); | 558 | + } finally { |
559 | + db.endTransaction(); | ||
560 | + // Don't close the database here to improve performance | ||
411 | } | 561 | } |
412 | - getDb().delete(TABLE_REQUESTS, strFilter.toString(), null); | ||
413 | - | ||
414 | - closeDb(); | ||
415 | } | 562 | } |
416 | 563 | ||
417 | public synchronized void deletePushRequests(Long... ids) { | 564 | public synchronized void deletePushRequests(Long... ids) { |
418 | - StringBuilder strFilter = new StringBuilder(); | 565 | + if (ids.length == 0) return; |
419 | - for (int i = 0; i < ids.length; i++) { | 566 | + |
420 | - if (i > 0) { | 567 | + SQLiteDatabase db = getDb(); |
421 | - strFilter.append(" OR "); | 568 | + try { |
569 | + db.beginTransaction(); | ||
570 | + StringBuilder strFilter = new StringBuilder(); | ||
571 | + for (int i = 0; i < ids.length; i++) { | ||
572 | + if (i > 0) { | ||
573 | + strFilter.append(" OR "); | ||
574 | + } | ||
575 | + strFilter.append(KEY_REQUESTS_ID); | ||
576 | + strFilter.append("="); | ||
577 | + strFilter.append(ids[i]); | ||
422 | } | 578 | } |
423 | - strFilter.append(KEY_REQUESTS_ID); | 579 | + db.delete(TABLE_PUSH_REQUESTS, strFilter.toString(), null); |
424 | - strFilter.append("="); | 580 | + db.setTransactionSuccessful(); |
425 | - strFilter.append(ids[i]); | 581 | + } finally { |
582 | + db.endTransaction(); | ||
583 | + // Don't close the database here to improve performance | ||
426 | } | 584 | } |
427 | - getDb().delete(TABLE_PUSH_REQUESTS, strFilter.toString(), null); | ||
428 | - | ||
429 | - closeDb(); | ||
430 | } | 585 | } |
431 | 586 | ||
432 | public synchronized void deletePushAckRequests(Long... ids) { | 587 | public synchronized void deletePushAckRequests(Long... ids) { |
433 | - StringBuilder strFilter = new StringBuilder(); | 588 | + if (ids.length == 0) return; |
434 | - for (int i = 0; i < ids.length; i++) { | 589 | + |
435 | - if (i > 0) { | 590 | + SQLiteDatabase db = getDb(); |
436 | - strFilter.append(" OR "); | 591 | + try { |
592 | + db.beginTransaction(); | ||
593 | + StringBuilder strFilter = new StringBuilder(); | ||
594 | + for (int i = 0; i < ids.length; i++) { | ||
595 | + if (i > 0) { | ||
596 | + strFilter.append(" OR "); | ||
597 | + } | ||
598 | + strFilter.append(KEY_REQUESTS_ID); | ||
599 | + strFilter.append("="); | ||
600 | + strFilter.append(ids[i]); | ||
437 | } | 601 | } |
438 | - strFilter.append(KEY_REQUESTS_ID); | 602 | + db.delete(TABLE_PUSH_ACK_REQUESTS, strFilter.toString(), null); |
439 | - strFilter.append("="); | 603 | + db.setTransactionSuccessful(); |
440 | - strFilter.append(ids[i]); | 604 | + } finally { |
605 | + db.endTransaction(); | ||
606 | + // Don't close the database here to improve performance | ||
441 | } | 607 | } |
442 | - getDb().delete(TABLE_PUSH_ACK_REQUESTS, strFilter.toString(), null); | ||
443 | - | ||
444 | - closeDb(); | ||
445 | } | 608 | } |
446 | 609 | ||
447 | public synchronized boolean isForceRequestsExist() { | 610 | public synchronized boolean isForceRequestsExist() { |
448 | - Cursor cursor = getReadableDb().query(TABLE_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", | ||
449 | - null, null, null, null); | ||
450 | boolean result = false; | 611 | boolean result = false; |
451 | - if (cursor != null) { | 612 | + Cursor cursor = null; |
452 | - result = cursor.getCount() > 0; | 613 | + try { |
453 | - cursor.close(); | 614 | + cursor = getReadableDb().query(TABLE_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", |
615 | + null, null, null, null); | ||
616 | + if (cursor != null) { | ||
617 | + result = cursor.getCount() > 0; | ||
618 | + } | ||
619 | + } finally { | ||
620 | + if (cursor != null) { | ||
621 | + cursor.close(); | ||
622 | + } | ||
623 | + // Don't close the database here to improve performance | ||
454 | } | 624 | } |
455 | - | ||
456 | - closeDb(); | ||
457 | - | ||
458 | return result; | 625 | return result; |
459 | } | 626 | } |
460 | 627 | ||
461 | public synchronized boolean isForcePushRequestsExist() { | 628 | public synchronized boolean isForcePushRequestsExist() { |
462 | - Cursor cursor = getReadableDb().query(TABLE_PUSH_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", | ||
463 | - null, null, null, null); | ||
464 | boolean result = false; | 629 | boolean result = false; |
465 | - if (cursor != null) { | 630 | + Cursor cursor = null; |
466 | - result = cursor.getCount() > 0; | 631 | + try { |
467 | - cursor.close(); | 632 | + cursor = getReadableDb().query(TABLE_PUSH_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", |
633 | + null, null, null, null); | ||
634 | + if (cursor != null) { | ||
635 | + result = cursor.getCount() > 0; | ||
636 | + } | ||
637 | + } finally { | ||
638 | + if (cursor != null) { | ||
639 | + cursor.close(); | ||
640 | + } | ||
641 | + // Don't close the database here to improve performance | ||
468 | } | 642 | } |
469 | - | ||
470 | - closeDb(); | ||
471 | - | ||
472 | return result; | 643 | return result; |
473 | } | 644 | } |
474 | 645 | ||
475 | public synchronized boolean isForcePushAckRequestsExist() { | 646 | public synchronized boolean isForcePushAckRequestsExist() { |
476 | - Cursor cursor = getReadableDb().query(TABLE_PUSH_ACK_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", | ||
477 | - null, null, null, null); | ||
478 | boolean result = false; | 647 | boolean result = false; |
479 | - if (cursor != null) { | 648 | + Cursor cursor = null; |
480 | - result = cursor.getCount() > 0; | 649 | + try { |
481 | - cursor.close(); | 650 | + cursor = getReadableDb().query(TABLE_PUSH_ACK_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", |
651 | + null, null, null, null); | ||
652 | + if (cursor != null) { | ||
653 | + result = cursor.getCount() > 0; | ||
654 | + } | ||
655 | + } finally { | ||
656 | + if (cursor != null) { | ||
657 | + cursor.close(); | ||
658 | + } | ||
659 | + // Don't close the database here to improve performance | ||
482 | } | 660 | } |
483 | - | ||
484 | - closeDb(); | ||
485 | - | ||
486 | return result; | 661 | return result; |
487 | } | 662 | } |
488 | 663 | ||
489 | //------------------------------ Tags -----------------------------// | 664 | //------------------------------ Tags -----------------------------// |
490 | public synchronized void saveTags(String[] tags) { | 665 | public synchronized void saveTags(String[] tags) { |
491 | if (tags != null && tags.length > 0) { | 666 | if (tags != null && tags.length > 0) { |
667 | + SQLiteDatabase db = getDb(); | ||
492 | try { | 668 | try { |
493 | - getDb().beginTransaction(); | 669 | + db.beginTransaction(); |
494 | ContentValues values = new ContentValues(); | 670 | ContentValues values = new ContentValues(); |
495 | for (String tag : tags) { | 671 | for (String tag : tags) { |
672 | + values.clear(); | ||
496 | values.put(KEY_TAG, tag); | 673 | values.put(KEY_TAG, tag); |
497 | values.put(KEY_TAG_LAST_ADD_DATE, System.currentTimeMillis()); | 674 | values.put(KEY_TAG_LAST_ADD_DATE, System.currentTimeMillis()); |
498 | - insert(TABLE_TAGS, values); | 675 | + db.insert(TABLE_TAGS, null, values); |
499 | } | 676 | } |
500 | - getDb().setTransactionSuccessful(); | 677 | + db.setTransactionSuccessful(); |
501 | - | ||
502 | } catch (SQLException e) { | 678 | } catch (SQLException e) { |
503 | - closeDb(); | ||
504 | if (WarpConstants.DEBUG) { | 679 | if (WarpConstants.DEBUG) { |
505 | e.printStackTrace(); | 680 | e.printStackTrace(); |
506 | } | 681 | } |
507 | } finally { | 682 | } finally { |
508 | - getDb().endTransaction(); | 683 | + db.endTransaction(); |
509 | - | 684 | + // Don't close the database here to improve performance |
510 | - closeDb(); | ||
511 | } | 685 | } |
512 | } | 686 | } |
513 | } | 687 | } |
514 | 688 | ||
515 | public synchronized void saveTelematics(JSONArray jsonArray) { | 689 | public synchronized void saveTelematics(JSONArray jsonArray) { |
516 | if (jsonArray != null && jsonArray.length() > 0) { | 690 | if (jsonArray != null && jsonArray.length() > 0) { |
517 | - ContentValues values = new ContentValues(); | 691 | + SQLiteDatabase db = getDb(); |
518 | - for (int i = 0; i < jsonArray.length(); i++) { | 692 | + try { |
519 | - JSONObject jsonobject = jsonArray.optJSONObject(i); | 693 | + db.beginTransaction(); |
520 | - if (jsonobject != null) { | 694 | + ContentValues values = new ContentValues(); |
521 | - String timestamp = jsonobject.keys().next(); | 695 | + for (int i = 0; i < jsonArray.length(); i++) { |
522 | - values.put(KEY_TIMESTAMP, timestamp); | 696 | + JSONObject jsonobject = jsonArray.optJSONObject(i); |
523 | - JSONObject jobjData = jsonobject.optJSONObject(timestamp); | 697 | + if (jsonobject != null) { |
524 | - if (jobjData != null) { | 698 | + values.clear(); |
525 | - values.put(KEY_ACCELERATION, jobjData.optDouble(KEY_ACCELERATION)); | 699 | + String timestamp = jsonobject.keys().next(); |
526 | - values.put(KEY_SPEED, jobjData.optDouble(KEY_SPEED)); | 700 | + values.put(KEY_TIMESTAMP, timestamp); |
701 | + JSONObject jobjData = jsonobject.optJSONObject(timestamp); | ||
702 | + if (jobjData != null) { | ||
703 | + values.put(KEY_ACCELERATION, jobjData.optDouble(KEY_ACCELERATION)); | ||
704 | + values.put(KEY_SPEED, jobjData.optDouble(KEY_SPEED)); | ||
705 | + } | ||
706 | + db.insert(TABLE_TELEMATICS, null, values); | ||
527 | } | 707 | } |
528 | - insert(TABLE_TELEMATICS, values); | ||
529 | } | 708 | } |
709 | + db.setTransactionSuccessful(); | ||
710 | + } finally { | ||
711 | + db.endTransaction(); | ||
712 | + // Don't close the database here to improve performance | ||
530 | } | 713 | } |
531 | } | 714 | } |
532 | } | 715 | } |
533 | 716 | ||
534 | public synchronized void removeTags(String[] tags) { | 717 | public synchronized void removeTags(String[] tags) { |
535 | - StringBuilder strFilter = new StringBuilder(); | 718 | + if (tags.length == 0) return; |
536 | - for (int i = 0; i < tags.length; i++) { | 719 | + |
537 | - if (i > 0) { | 720 | + SQLiteDatabase db = getDb(); |
538 | - strFilter.append(" OR "); | 721 | + try { |
722 | + db.beginTransaction(); | ||
723 | + StringBuilder strFilter = new StringBuilder(); | ||
724 | + for (int i = 0; i < tags.length; i++) { | ||
725 | + if (i > 0) { | ||
726 | + strFilter.append(" OR "); | ||
727 | + } | ||
728 | + strFilter.append(KEY_TAG); | ||
729 | + strFilter.append("="); | ||
730 | + strFilter.append("'"); | ||
731 | + strFilter.append(tags[i]); | ||
732 | + strFilter.append("'"); | ||
539 | } | 733 | } |
540 | - strFilter.append(KEY_TAG); | 734 | + db.delete(TABLE_TAGS, strFilter.toString(), null); |
541 | - strFilter.append("="); | 735 | + db.setTransactionSuccessful(); |
542 | - strFilter.append("'"); | 736 | + } finally { |
543 | - strFilter.append(tags[i]); | 737 | + db.endTransaction(); |
544 | - strFilter.append("'"); | 738 | + // Don't close the database here to improve performance |
545 | } | 739 | } |
546 | - getDb().delete(TABLE_TAGS, strFilter.toString(), null); | ||
547 | - closeDb(); | ||
548 | } | 740 | } |
549 | 741 | ||
550 | public synchronized void removeAllTags() { | 742 | public synchronized void removeAllTags() { |
... | @@ -553,21 +745,22 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -553,21 +745,22 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
553 | 745 | ||
554 | @Nullable | 746 | @Nullable |
555 | public synchronized String[] getTags() { | 747 | public synchronized String[] getTags() { |
556 | - | ||
557 | List<String> tags = null; | 748 | List<String> tags = null; |
558 | - Cursor cursor = getReadableDb().query(TABLE_TAGS, null, null, null, null, null, null); | 749 | + Cursor cursor = null; |
559 | - if (cursor != null) { | 750 | + try { |
560 | - | 751 | + cursor = getReadableDb().query(TABLE_TAGS, null, null, null, null, null, null); |
561 | - tags = new ArrayList<>(cursor.getCount()); | 752 | + if (cursor != null) { |
562 | - while (cursor.moveToNext()) { | 753 | + tags = new ArrayList<>(cursor.getCount()); |
563 | - tags.add(cursor.getString(cursor | 754 | + while (cursor.moveToNext()) { |
564 | - .getColumnIndex(KEY_TAG))); | 755 | + tags.add(cursor.getString(cursor.getColumnIndex(KEY_TAG))); |
756 | + } | ||
757 | + } | ||
758 | + } finally { | ||
759 | + if (cursor != null) { | ||
760 | + cursor.close(); | ||
565 | } | 761 | } |
566 | - cursor.close(); | 762 | + // Don't close the database here to improve performance |
567 | } | 763 | } |
568 | - | ||
569 | - closeDb(); | ||
570 | - | ||
571 | return tags != null ? tags.toArray(new String[tags.size()]) : null; | 764 | return tags != null ? tags.toArray(new String[tags.size()]) : null; |
572 | } | 765 | } |
573 | 766 | ... | ... |
... | @@ -2,6 +2,7 @@ package ly.warp.sdk.utils; | ... | @@ -2,6 +2,7 @@ package ly.warp.sdk.utils; |
2 | 2 | ||
3 | import android.content.ContentProvider; | 3 | import android.content.ContentProvider; |
4 | import android.content.ContentValues; | 4 | import android.content.ContentValues; |
5 | +import android.content.Context; | ||
5 | import android.database.Cursor; | 6 | import android.database.Cursor; |
6 | import android.net.Uri; | 7 | import android.net.Uri; |
7 | 8 | ||
... | @@ -9,6 +10,8 @@ import androidx.annotation.NonNull; | ... | @@ -9,6 +10,8 @@ import androidx.annotation.NonNull; |
9 | import androidx.annotation.Nullable; | 10 | import androidx.annotation.Nullable; |
10 | import androidx.appcompat.app.AppCompatDelegate; | 11 | import androidx.appcompat.app.AppCompatDelegate; |
11 | 12 | ||
13 | +import ly.warp.sdk.db.WarplyDBHelper; | ||
14 | + | ||
12 | /** | 15 | /** |
13 | * Created by Panagiotis Triantafyllou on 05/Αυγ/2022. | 16 | * Created by Panagiotis Triantafyllou on 05/Αυγ/2022. |
14 | */ | 17 | */ |
... | @@ -16,7 +19,14 @@ public class WarplyProvider extends ContentProvider { | ... | @@ -16,7 +19,14 @@ public class WarplyProvider extends ContentProvider { |
16 | 19 | ||
17 | @Override | 20 | @Override |
18 | public boolean onCreate() { | 21 | public boolean onCreate() { |
19 | - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); | 22 | +// AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); |
23 | + | ||
24 | + // Initialize the database helper | ||
25 | + Context context = getContext(); | ||
26 | + if (context != null) { | ||
27 | + WarplyDBHelper dbHelper = WarplyDBHelper.getInstance(context); | ||
28 | + dbHelper.initialize(); // This will initialize the database connection on a background thread | ||
29 | + } | ||
20 | // ViewPump.init(ViewPump.builder() | 30 | // ViewPump.init(ViewPump.builder() |
21 | // .addInterceptor(new CalligraphyInterceptor( | 31 | // .addInterceptor(new CalligraphyInterceptor( |
22 | // new CalligraphyConfig.Builder() | 32 | // new CalligraphyConfig.Builder() |
... | @@ -34,6 +44,18 @@ public class WarplyProvider extends ContentProvider { | ... | @@ -34,6 +44,18 @@ public class WarplyProvider extends ContentProvider { |
34 | return true; | 44 | return true; |
35 | } | 45 | } |
36 | 46 | ||
47 | + @Override | ||
48 | + public void shutdown() { | ||
49 | + // Get the database helper instance and shut it down | ||
50 | + Context context = getContext(); | ||
51 | + if (context != null) { | ||
52 | + WarplyDBHelper dbHelper = WarplyDBHelper.getInstance(context); | ||
53 | + dbHelper.shutdown(); | ||
54 | + } | ||
55 | + | ||
56 | + super.shutdown(); | ||
57 | + } | ||
58 | + | ||
37 | @Nullable | 59 | @Nullable |
38 | @Override | 60 | @Override |
39 | public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) { | 61 | public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) { | ... | ... |
-
Please register or login to post a comment