From c6d6f418bddca4b5543fe833cd162af0fefb5b46 Mon Sep 17 00:00:00 2001 From: dani Date: Wed, 15 Mar 2017 14:57:40 +0900 Subject: [PATCH 01/33] Add crashlytics to StepSensorLib This will be removed once we know what's going on with the crashes --- build.gradle | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build.gradle b/build.gradle index db0b2c0..69d746d 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,10 @@ android { } } +repositories { + maven { url 'https://maven.fabric.io/public' } +} + dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { @@ -29,4 +33,7 @@ dependencies { }) compile 'com.android.support:appcompat-v7:23.1.1' testCompile 'junit:junit:4.12' + compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') { + transitive = true; + } } From e412bac71a78abcf2e079415827af1dbe6e246ff Mon Sep 17 00:00:00 2001 From: dani Date: Wed, 15 Mar 2017 17:41:58 +0900 Subject: [PATCH 02/33] Catches crashes and logs to Crashlytics Catches the crashes reported in crashlytics and logs more information like process id, process name, thread id, etc --- .../sukesan1984/stepsensorlib/Database.java | 89 +++++++++++++++---- .../stepsensorlib/util/Logger.java | 38 ++++++++ 2 files changed, 108 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index f328a93..22ad176 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -4,9 +4,12 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabaseLockedException; import android.database.sqlite.SQLiteOpenHelper; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import com.crashlytics.android.Crashlytics; import com.sukesan1984.stepsensorlib.model.ChunkStepCount; import com.sukesan1984.stepsensorlib.util.DateUtils; import com.sukesan1984.stepsensorlib.util.Logger; @@ -26,26 +29,34 @@ public class Database extends SQLiteOpenHelper { private final static String COLUMN_IS_RECORDED_ON_SERVER = "is_recorded_on_server"; private final static String COLUMN_LAST_UPDATED = "last_updated"; private final static int DB_VERSION = 1; - - private static Database instance; + private final static String LOG_TAG = "Database"; private static final AtomicInteger openCounter = new AtomicInteger(); + private static Database instance; + private final Context context; private Database(final Context context) { super(context, TABLE_NAME, null, DB_VERSION); + this.context = context; } public static synchronized Database getInstance(final Context c) { if (instance == null) { instance = new Database(c.getApplicationContext()); } - openCounter.incrementAndGet(); + + Crashlytics.log("----------Opening connection----------"); + Crashlytics.log("openCounter: " + openCounter); + Logger.logInCrashlytics(c); return instance; } @Override public void close() { + Crashlytics.log("----------Closing connection----------"); + Crashlytics.log("openCounter: " + openCounter); + Logger.logInCrashlytics(context); if (openCounter.decrementAndGet() == 0) { super.close(); } @@ -92,23 +103,45 @@ public Cursor query(final String[] columns, final String selection, .query(TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy, limit); } + @Override + public SQLiteDatabase getWritableDatabase() { + Crashlytics.log("------Writing in database------"); + Logger.logInCrashlytics(context); + return super.getWritableDatabase(); + } + + @Override + public SQLiteDatabase getReadableDatabase() { + Crashlytics.log("------Reading from database------"); + Logger.logInCrashlytics(context); + return super.getReadableDatabase(); + } + /** * @param dateAndHour the dateAndHour in ms since 1970 * @param stepsSinceBoot the steps since boot */ public void updateOrInsert(long dateAndHour, int stepsSinceBoot) { - SQLiteDatabase db = getWritableDatabase(); - db.beginTransaction(); try { - updateOrInsertWithoutTransaction(db, dateAndHour, stepsSinceBoot); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); + SQLiteDatabase db = getWritableDatabase(); + db.beginTransaction(); + try { + updateOrInsertWithoutTransaction(db, dateAndHour, stepsSinceBoot); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } catch (SQLiteDatabaseLockedException | IllegalStateException e) { + Crashlytics.logException(e); } } private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHour, int stepsSinceBoot) { Cursor c = getByDateAndHour(dateAndHour); + //FIXME Remove this check once we know what is blocking the database. + if (c == null) { + return; + } initializeLastUpdatedSteps(db, stepsSinceBoot); int lastUpdatedSteps = getLastUpdatedSteps(); if (lastUpdatedSteps > stepsSinceBoot) { @@ -135,6 +168,10 @@ private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHou public void insertOrReplaceSteps(final long dateAndHour, final int steps) { SQLiteDatabase db = getWritableDatabase(); Cursor c = getByDateAndHour(dateAndHour); + //FIXME Remove this check once we know what is blocking the database. + if (c == null) { + return; + } db.beginTransaction(); try { if (c.getCount() == 0) { @@ -187,10 +224,16 @@ private void insertNewDateAndHour(SQLiteDatabase db, final long dateAndHour, fin } } + @Nullable private Cursor getByDateAndHour(long dateAndHour) { - return getReadableDatabase().query(TABLE_NAME, new String[]{COLUMN_STEPS}, - COLUMN_DATE_AND_HOUR + " = ?", - new String[]{String.valueOf(dateAndHour)}, null, null, null); + try { + return getReadableDatabase().query(TABLE_NAME, new String[]{COLUMN_STEPS}, + COLUMN_DATE_AND_HOUR + " = ?", + new String[]{String.valueOf(dateAndHour)}, null, null, null); + } catch (SQLiteDatabaseLockedException | IllegalStateException e) { + Crashlytics.logException(e); + return null; + } } private void addToLastEntry(SQLiteDatabase db, int steps) { @@ -220,7 +263,10 @@ public void logState() { public int getSteps(final long dateAndHour) { Logger.log("getStep dateAndHour" + dateAndHour); Cursor c = getByDateAndHour(dateAndHour); - + //FIXME Remove this check once we know what is blocking the database. + if (c == null) { + return Integer.MIN_VALUE; + } c.moveToFirst(); int steps; if (c.getCount() == 0) { @@ -321,12 +367,17 @@ public int getTodayStep() { @NonNull public List getNotRecordedChunkedStepCounts() { - Cursor c = getReadableDatabase() - .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, - COLUMN_DATE_AND_HOUR + " != ? and " + - COLUMN_IS_RECORDED_ON_SERVER + " = ?", new String[]{"-1", "0"}, null, null, null); - Logger.log("Not recoreded Chunk Size: " + c.getCount()); - return createChunkedStepCounts(c); + try { + Cursor c = getReadableDatabase() + .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, + COLUMN_DATE_AND_HOUR + " != ? and " + + COLUMN_IS_RECORDED_ON_SERVER + " = ?", new String[]{"-1", "0"}, null, null, null); + Logger.log("Not recoreded Chunk Size: " + c.getCount()); + return createChunkedStepCounts(c); + } catch (SQLiteDatabaseLockedException | IllegalStateException e) { + Crashlytics.logException(e); + return new ArrayList<>(); + } } private List createChunkedStepCounts(Cursor c) { diff --git a/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java b/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java index 4da95ad..67c9ef6 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java @@ -15,11 +15,15 @@ */ package com.sukesan1984.stepsensorlib.util; +import android.app.ActivityManager; +import android.content.Context; import android.database.Cursor; +import com.crashlytics.android.Crashlytics; import com.sukesan1984.stepsensorlib.BuildConfig; import java.util.Date; +import java.util.List; public abstract class Logger { @@ -33,6 +37,40 @@ public static void log(Throwable ex) { } } + + private static String stackToString(StackTraceElement[] stackTrace) { + String stack = "Finc-log Stacktrace:"; + for (StackTraceElement stackTraceElement : stackTrace) { + stack += ",at " + (stackTraceElement.toString()); + } + return stack; + } + + public static void logInCrashlytics(Context context){ + Crashlytics.log("Thread id: " + Thread.currentThread().getId()); + Crashlytics.log("Process id: " + android.os.Process.myPid()); + Crashlytics.log("Process name: " + getProcessName(context)); + if (BuildConfig.DEBUG) { + Crashlytics.log("Stack: " + stackToString(Thread.currentThread().getStackTrace())); + } + } + + + private static String getProcessName(Context context) { + int pid = android.os.Process.myPid(); + ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List infos = manager.getRunningAppProcesses(); + if (infos != null) { + for (ActivityManager.RunningAppProcessInfo processInfo : infos) { + if (processInfo.pid == pid) { + return processInfo.processName; + } + } + } + + return null; + } + public static void log(final Cursor c) { if (!BuildConfig.DEBUG) return; c.moveToFirst(); From 11b73dd42c30fc9caec44b80c03e873b3fb1cb17 Mon Sep 17 00:00:00 2001 From: dani Date: Thu, 16 Mar 2017 10:37:19 +0900 Subject: [PATCH 03/33] Closes some cursors missing --- src/main/java/com/sukesan1984/stepsensorlib/Database.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 22ad176..093ff13 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -157,6 +157,7 @@ private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHou addToLastEntry(db, addedSteps); } saveLastUpdatedSteps(db, stepsSinceBoot); + c.close(); } /** @@ -196,6 +197,7 @@ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { } finally { db.endTransaction(); } + c.close(); } From 6e097cc698e251d36f6b636a5a0227e58d5581a4 Mon Sep 17 00:00:00 2001 From: beylerian Date: Tue, 18 Apr 2017 22:58:49 +0900 Subject: [PATCH 04/33] temporary fix for database crash --- .../sukesan1984/stepsensorlib/Database.java | 219 +++++++++--------- 1 file changed, 109 insertions(+), 110 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 093ff13..8b366a4 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -4,12 +4,9 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabaseLockedException; import android.database.sqlite.SQLiteOpenHelper; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import com.crashlytics.android.Crashlytics; import com.sukesan1984.stepsensorlib.model.ChunkStepCount; import com.sukesan1984.stepsensorlib.util.DateUtils; import com.sukesan1984.stepsensorlib.util.Logger; @@ -29,34 +26,26 @@ public class Database extends SQLiteOpenHelper { private final static String COLUMN_IS_RECORDED_ON_SERVER = "is_recorded_on_server"; private final static String COLUMN_LAST_UPDATED = "last_updated"; private final static int DB_VERSION = 1; - private final static String LOG_TAG = "Database"; - private static final AtomicInteger openCounter = new AtomicInteger(); + private static Database instance; - private final Context context; + private static final AtomicInteger openCounter = new AtomicInteger(); private Database(final Context context) { super(context, TABLE_NAME, null, DB_VERSION); - this.context = context; } public static synchronized Database getInstance(final Context c) { if (instance == null) { instance = new Database(c.getApplicationContext()); } - openCounter.incrementAndGet(); + openCounter.incrementAndGet(); - Crashlytics.log("----------Opening connection----------"); - Crashlytics.log("openCounter: " + openCounter); - Logger.logInCrashlytics(c); return instance; } @Override public void close() { - Crashlytics.log("----------Closing connection----------"); - Crashlytics.log("openCounter: " + openCounter); - Logger.logInCrashlytics(context); if (openCounter.decrementAndGet() == 0) { super.close(); } @@ -75,9 +64,13 @@ public void onCreate(SQLiteDatabase db) { * delete all */ public void deleteAll() { - SQLiteDatabase db = getWritableDatabase(); - db.delete(TABLE_NAME, "", new String[]{}); - db.close(); + try { + SQLiteDatabase db = getWritableDatabase(); + db.delete(TABLE_NAME, "", new String[]{}); + db.close(); + } catch (Exception e) { + e.printStackTrace(); + } } @Override @@ -99,22 +92,13 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public Cursor query(final String[] columns, final String selection, final String[] selectionArgs, final String groupBy, final String having, final String orderBy, final String limit) { - return getReadableDatabase() - .query(TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy, limit); - } - - @Override - public SQLiteDatabase getWritableDatabase() { - Crashlytics.log("------Writing in database------"); - Logger.logInCrashlytics(context); - return super.getWritableDatabase(); - } - - @Override - public SQLiteDatabase getReadableDatabase() { - Crashlytics.log("------Reading from database------"); - Logger.logInCrashlytics(context); - return super.getReadableDatabase(); + try { + return getReadableDatabase() + .query(TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy, limit); + } catch (Exception e) { + e.printStackTrace(); + return null; + } } /** @@ -125,20 +109,16 @@ public void updateOrInsert(long dateAndHour, int stepsSinceBoot) { try { SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); - try { - updateOrInsertWithoutTransaction(db, dateAndHour, stepsSinceBoot); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } catch (SQLiteDatabaseLockedException | IllegalStateException e) { - Crashlytics.logException(e); + updateOrInsertWithoutTransaction(db, dateAndHour, stepsSinceBoot); + db.setTransactionSuccessful(); + db.endTransaction(); + } catch (Exception e) { + e.printStackTrace(); } } private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHour, int stepsSinceBoot) { Cursor c = getByDateAndHour(dateAndHour); - //FIXME Remove this check once we know what is blocking the database. if (c == null) { return; } @@ -167,14 +147,11 @@ private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHou * @param steps */ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { - SQLiteDatabase db = getWritableDatabase(); - Cursor c = getByDateAndHour(dateAndHour); - //FIXME Remove this check once we know what is blocking the database. - if (c == null) { - return; - } - db.beginTransaction(); try { + SQLiteDatabase db = getWritableDatabase(); + Cursor c = getByDateAndHour(dateAndHour); + db.beginTransaction(); + if (c.getCount() == 0) { if (steps > 0) { insertNewDateAndHour(db, dateAndHour, steps); @@ -194,10 +171,10 @@ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { new String[]{String.valueOf(dateAndHour)}); } db.setTransactionSuccessful(); - } finally { db.endTransaction(); + } catch (Exception e) { + e.printStackTrace(); } - c.close(); } @@ -226,16 +203,16 @@ private void insertNewDateAndHour(SQLiteDatabase db, final long dateAndHour, fin } } - @Nullable private Cursor getByDateAndHour(long dateAndHour) { try { return getReadableDatabase().query(TABLE_NAME, new String[]{COLUMN_STEPS}, COLUMN_DATE_AND_HOUR + " = ?", new String[]{String.valueOf(dateAndHour)}, null, null, null); - } catch (SQLiteDatabaseLockedException | IllegalStateException e) { - Crashlytics.logException(e); + } catch (Exception e) { + e.printStackTrace(); return null; } + } private void addToLastEntry(SQLiteDatabase db, int steps) { @@ -265,43 +242,54 @@ public void logState() { public int getSteps(final long dateAndHour) { Logger.log("getStep dateAndHour" + dateAndHour); Cursor c = getByDateAndHour(dateAndHour); - //FIXME Remove this check once we know what is blocking the database. - if (c == null) { - return Integer.MIN_VALUE; - } - c.moveToFirst(); - int steps; - if (c.getCount() == 0) { - steps = Integer.MIN_VALUE; + + if (c != null) { + c.moveToFirst(); + int steps; + if (c.getCount() == 0) { + steps = Integer.MIN_VALUE; + } else { + steps = c.getInt(0); + } + c.close(); + return steps; } else { - steps = c.getInt(0); + return c.getInt(0); } - c.close(); - return steps; } public int getSteps(final long start, final long end) { - Cursor c = getReadableDatabase() - .query(TABLE_NAME, new String[]{"SUM(" + COLUMN_STEPS + ")"}, - COLUMN_DATE_AND_HOUR + " >= ? AND " + - COLUMN_DATE_AND_HOUR + " <= ?", - new String[]{String.valueOf(start), String.valueOf(end)}, null, null, null); - int sumSteps; - if (c.getCount() == 0) { - sumSteps = 0; - } else { - c.moveToFirst(); - sumSteps = c.getInt(0); + try { + Cursor c = getReadableDatabase() + .query(TABLE_NAME, new String[]{"SUM(" + COLUMN_STEPS + ")"}, + COLUMN_DATE_AND_HOUR + " >= ? AND " + + COLUMN_DATE_AND_HOUR + " <= ?", + new String[]{String.valueOf(start), String.valueOf(end)}, null, null, null); + int sumSteps; + if (c.getCount() == 0) { + sumSteps = 0; + } else { + c.moveToFirst(); + sumSteps = c.getInt(0); + } + c.close(); + return sumSteps; + } catch (Exception e) { + e.printStackTrace(); + return 0; } - c.close(); - return sumSteps; } public List getChunkStepsFrom(final long start) { - Cursor c = getReadableDatabase() - .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, - COLUMN_DATE_AND_HOUR + " >= ?", new String[]{String.valueOf(start)}, null, null, null); - return createChunkedStepCounts(c); + try { + Cursor c = getReadableDatabase() + .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, + COLUMN_DATE_AND_HOUR + " >= ?", new String[]{String.valueOf(start)}, null, null, null); + return createChunkedStepCounts(c); + } catch (Exception e) { + e.printStackTrace(); + return null; + } } /** @@ -311,7 +299,11 @@ public List getChunkStepsFrom(final long start) { * day as the current offset is likely to be negative. */ void removeNegativeEntries() { - getWritableDatabase().delete(TABLE_NAME, COLUMN_STEPS + " < ?", new String[]{"0"}); + try { + getWritableDatabase().delete(TABLE_NAME, COLUMN_STEPS + " < ?", new String[]{"0"}); + } catch (Exception e) { + e.printStackTrace(); + } } /** @@ -319,21 +311,27 @@ void removeNegativeEntries() { * Currently, an invalid input is such with steps >= 200,000 */ public void removeInvalidEntries() { - getWritableDatabase().delete(TABLE_NAME, COLUMN_STEPS + " >= ?", new String[]{"200000"}); + try { + getWritableDatabase().delete(TABLE_NAME, COLUMN_STEPS + " >= ?", new String[]{"200000"}); + } catch (Exception e) { + e.printStackTrace(); + } } /** * @param stepsSinceBoot steps after boot. */ public void resetLastUpdatedSteps(final int stepsSinceBoot) { - SQLiteDatabase db = getWritableDatabase(); - db.beginTransaction(); try { + SQLiteDatabase db = getWritableDatabase(); + db.beginTransaction(); + updateOrInsertWithoutTransaction(db, DateUtils.getCurrentDateAndHour(), stepsSinceBoot); saveLastUpdatedSteps(db, 0); db.setTransactionSuccessful(); - } finally { db.endTransaction(); + } catch (Exception e) { + e.printStackTrace(); } } @@ -376,9 +374,9 @@ public List getNotRecordedChunkedStepCounts() { COLUMN_IS_RECORDED_ON_SERVER + " = ?", new String[]{"-1", "0"}, null, null, null); Logger.log("Not recoreded Chunk Size: " + c.getCount()); return createChunkedStepCounts(c); - } catch (SQLiteDatabaseLockedException | IllegalStateException e) { - Crashlytics.logException(e); - return new ArrayList<>(); + } catch (Exception e) { + e.printStackTrace(); + return null; } } @@ -396,32 +394,33 @@ private List createChunkedStepCounts(Cursor c) { } public void updateToRecorded(long[] dateAndHours) { - ContentValues values = new ContentValues(); - values.put(COLUMN_IS_RECORDED_ON_SERVER, "1"); - int length = dateAndHours.length; - String args = ""; - String[] dateAndHoursString = new String[length]; - for (int i = 0; i < length; i++) { - if (i == 0) { - args = "?"; - } else { - args += ", ?"; - } - dateAndHoursString[i] = String.valueOf(dateAndHours[i]); - } - SQLiteDatabase db = getWritableDatabase(); - db.beginTransaction(); try { + ContentValues values = new ContentValues(); + values.put(COLUMN_IS_RECORDED_ON_SERVER, "1"); + int length = dateAndHours.length; + String args = ""; + String[] dateAndHoursString = new String[length]; + for (int i = 0; i < length; i++) { + if (i == 0) { + args = "?"; + } else { + args += ", ?"; + } + dateAndHoursString[i] = String.valueOf(dateAndHours[i]); + } + + SQLiteDatabase db = getWritableDatabase(); + db.beginTransaction(); + int rows = db.update(TABLE_NAME, values, String.format(COLUMN_DATE_AND_HOUR + " in (%s)", args), dateAndHoursString); Logger.log("updated number: " + rows); logState(); db.setTransactionSuccessful(); - } finally { db.endTransaction(); + Logger.log("update to Recorded: " + dateAndHoursString.toString()); + db.close(); + } catch (Exception e) { + e.printStackTrace(); } - - Logger.log("update to Recorded: " + dateAndHoursString.toString()); - db.close(); - return; } } From fd2f89d091bb499d3562770d97294ca790adaddc Mon Sep 17 00:00:00 2001 From: beylerian Date: Tue, 18 Apr 2017 23:01:31 +0900 Subject: [PATCH 05/33] missing null check --- src/main/java/com/sukesan1984/stepsensorlib/Database.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 8b366a4..30ca88e 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -151,7 +151,9 @@ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { SQLiteDatabase db = getWritableDatabase(); Cursor c = getByDateAndHour(dateAndHour); db.beginTransaction(); - + if (c == null) { + return; + } if (c.getCount() == 0) { if (steps > 0) { insertNewDateAndHour(db, dateAndHour, steps); From 63c6b1b55270855ad61a8cf59ebbf8ae8a291d62 Mon Sep 17 00:00:00 2001 From: beylerian Date: Mon, 24 Apr 2017 14:33:28 +0900 Subject: [PATCH 06/33] null checks --- .../sukesan1984/stepsensorlib/Database.java | 105 ++++++++++++++---- 1 file changed, 85 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 30ca88e..9de828e 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -53,6 +53,9 @@ public void close() { @Override public void onCreate(SQLiteDatabase db) { + if (db == null) { + return; + } db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + COLUMN_DATE_AND_HOUR + " INTEGER UNIQUE, " + COLUMN_STEPS + " INTEGER, " + @@ -64,12 +67,16 @@ public void onCreate(SQLiteDatabase db) { * delete all */ public void deleteAll() { + SQLiteDatabase db = null; try { - SQLiteDatabase db = getWritableDatabase(); + db = getWritableDatabase(); db.delete(TABLE_NAME, "", new String[]{}); - db.close(); } catch (Exception e) { e.printStackTrace(); + } finally { + if (db != null) { + db.close(); + } } } @@ -106,18 +113,27 @@ public Cursor query(final String[] columns, final String selection, * @param stepsSinceBoot the steps since boot */ public void updateOrInsert(long dateAndHour, int stepsSinceBoot) { + SQLiteDatabase db = null; try { - SQLiteDatabase db = getWritableDatabase(); + db = getWritableDatabase(); db.beginTransaction(); updateOrInsertWithoutTransaction(db, dateAndHour, stepsSinceBoot); db.setTransactionSuccessful(); - db.endTransaction(); + } catch (Exception e) { e.printStackTrace(); + } finally { + if (db != null) { + db.endTransaction(); + db.close(); + } } } private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHour, int stepsSinceBoot) { + if (db == null) { + return; + } Cursor c = getByDateAndHour(dateAndHour); if (c == null) { return; @@ -129,7 +145,6 @@ private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHou return; } - int addedSteps = stepsSinceBoot - lastUpdatedSteps; if (c.getCount() == 0 && stepsSinceBoot >= 0) { insertNewDateAndHour(db, dateAndHour, addedSteps); @@ -147,11 +162,15 @@ private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHou * @param steps */ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { + SQLiteDatabase db = null; + Cursor c = null; try { - SQLiteDatabase db = getWritableDatabase(); - Cursor c = getByDateAndHour(dateAndHour); + db = getWritableDatabase(); + c = getByDateAndHour(dateAndHour); db.beginTransaction(); if (c == null) { + db.endTransaction(); + db.close(); return; } if (c.getCount() == 0) { @@ -173,9 +192,17 @@ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { new String[]{String.valueOf(dateAndHour)}); } db.setTransactionSuccessful(); - db.endTransaction(); + } catch (Exception e) { e.printStackTrace(); + } finally { + if (c != null) { + c.close(); + } + if (db != null) { + db.endTransaction(); + db.close(); + } } } @@ -232,8 +259,10 @@ public void logState() { if (BuildConfig.DEBUG) { Cursor c = getReadableDatabase() .query(TABLE_NAME, null, null, null, null, null, COLUMN_DATE_AND_HOUR + " DESC", null); - Logger.log(c); - c.close(); + if (c != null) { + Logger.log(c); + c.close(); + } } } @@ -256,7 +285,7 @@ public int getSteps(final long dateAndHour) { c.close(); return steps; } else { - return c.getInt(0); + return Integer.MIN_VALUE; } } @@ -267,6 +296,9 @@ public int getSteps(final long start, final long end) { COLUMN_DATE_AND_HOUR + " >= ? AND " + COLUMN_DATE_AND_HOUR + " <= ?", new String[]{String.valueOf(start), String.valueOf(end)}, null, null, null); + if (c == null) { + return 0; + } int sumSteps; if (c.getCount() == 0) { sumSteps = 0; @@ -278,15 +310,24 @@ public int getSteps(final long start, final long end) { return sumSteps; } catch (Exception e) { e.printStackTrace(); + if (c != null) { + c.close(); + } return 0; } } public List getChunkStepsFrom(final long start) { + Cursor c = null; try { - Cursor c = getReadableDatabase() + c = getReadableDatabase() .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, COLUMN_DATE_AND_HOUR + " >= ?", new String[]{String.valueOf(start)}, null, null, null); + + if (c == null) { + return null; + } + return createChunkedStepCounts(c); } catch (Exception e) { e.printStackTrace(); @@ -324,20 +365,27 @@ public void removeInvalidEntries() { * @param stepsSinceBoot steps after boot. */ public void resetLastUpdatedSteps(final int stepsSinceBoot) { + SQLiteDatabase db = null; try { - SQLiteDatabase db = getWritableDatabase(); + db = getWritableDatabase(); db.beginTransaction(); - updateOrInsertWithoutTransaction(db, DateUtils.getCurrentDateAndHour(), stepsSinceBoot); saveLastUpdatedSteps(db, 0); db.setTransactionSuccessful(); - db.endTransaction(); } catch (Exception e) { e.printStackTrace(); + } finally { + if (db != null) { + db.endTransaction(); + db.close(); + } } } private void initializeLastUpdatedSteps(SQLiteDatabase db, final int stepsSinceBoot) { + if (db == null) { + return; + } // initialize if there is no date if (getSteps(-1) == Integer.MIN_VALUE) { saveLastUpdatedSteps(db, stepsSinceBoot); @@ -345,6 +393,9 @@ private void initializeLastUpdatedSteps(SQLiteDatabase db, final int stepsSinceB } private void saveLastUpdatedSteps(SQLiteDatabase db, final int steps) { + if (db == null) { + return; + } ContentValues values = new ContentValues(); values.put(COLUMN_STEPS, steps); if (db.update(TABLE_NAME, values, COLUMN_DATE_AND_HOUR + " = -1", null) == 0) { @@ -369,20 +420,31 @@ public int getTodayStep() { @NonNull public List getNotRecordedChunkedStepCounts() { + Cursor c = null; try { - Cursor c = getReadableDatabase() + c = getReadableDatabase() .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, COLUMN_DATE_AND_HOUR + " != ? and " + COLUMN_IS_RECORDED_ON_SERVER + " = ?", new String[]{"-1", "0"}, null, null, null); Logger.log("Not recoreded Chunk Size: " + c.getCount()); + if (c == null) { + return null; + } + // cursor close is in method return createChunkedStepCounts(c); } catch (Exception e) { e.printStackTrace(); + if (c != null) { + c.close(); + } return null; } } private List createChunkedStepCounts(Cursor c) { + if (c == null) { + return null; + } List lists = new ArrayList<>(); if (c.getCount() == 0) { @@ -396,6 +458,7 @@ private List createChunkedStepCounts(Cursor c) { } public void updateToRecorded(long[] dateAndHours) { + SQLiteDatabase db = null; try { ContentValues values = new ContentValues(); values.put(COLUMN_IS_RECORDED_ON_SERVER, "1"); @@ -411,18 +474,20 @@ public void updateToRecorded(long[] dateAndHours) { dateAndHoursString[i] = String.valueOf(dateAndHours[i]); } - SQLiteDatabase db = getWritableDatabase(); + db = getWritableDatabase(); db.beginTransaction(); - int rows = db.update(TABLE_NAME, values, String.format(COLUMN_DATE_AND_HOUR + " in (%s)", args), dateAndHoursString); Logger.log("updated number: " + rows); logState(); db.setTransactionSuccessful(); - db.endTransaction(); Logger.log("update to Recorded: " + dateAndHoursString.toString()); - db.close(); } catch (Exception e) { e.printStackTrace(); + } finally { + if (db != null) { + db.endTransaction(); + db.close(); + } } } } From ccd401ca627fdd76bec1754ed8ef547ef99163ec Mon Sep 17 00:00:00 2001 From: beylerian Date: Thu, 11 May 2017 23:17:53 +0900 Subject: [PATCH 07/33] bug fix for variable scope --- src/main/java/com/sukesan1984/stepsensorlib/Database.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 9de828e..af006fe 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -290,8 +290,9 @@ public int getSteps(final long dateAndHour) { } public int getSteps(final long start, final long end) { + Cursor c = null; try { - Cursor c = getReadableDatabase() + c = getReadableDatabase() .query(TABLE_NAME, new String[]{"SUM(" + COLUMN_STEPS + ")"}, COLUMN_DATE_AND_HOUR + " >= ? AND " + COLUMN_DATE_AND_HOUR + " <= ?", From b0fd5038608e14f958808d035b1b718c9996db19 Mon Sep 17 00:00:00 2001 From: beylerian Date: Thu, 18 May 2017 02:08:58 +0900 Subject: [PATCH 08/33] added null check --- .../java/com/sukesan1984/stepsensorlib/Database.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index af006fe..3bf1b27 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -292,14 +292,14 @@ public int getSteps(final long dateAndHour) { public int getSteps(final long start, final long end) { Cursor c = null; try { - c = getReadableDatabase() - .query(TABLE_NAME, new String[]{"SUM(" + COLUMN_STEPS + ")"}, - COLUMN_DATE_AND_HOUR + " >= ? AND " + - COLUMN_DATE_AND_HOUR + " <= ?", - new String[]{String.valueOf(start), String.valueOf(end)}, null, null, null); + c = getReadableDatabase(); if (c == null) { return 0; } + c.query(TABLE_NAME, new String[]{"SUM(" + COLUMN_STEPS + ")"}, + COLUMN_DATE_AND_HOUR + " >= ? AND " + + COLUMN_DATE_AND_HOUR + " <= ?", + new String[]{String.valueOf(start), String.valueOf(end)}, null, null, null); int sumSteps; if (c.getCount() == 0) { sumSteps = 0; From 853528da176ad4e906831b79a41cf211eef33039 Mon Sep 17 00:00:00 2001 From: neonankiti Date: Mon, 22 May 2017 16:05:29 +0900 Subject: [PATCH 09/33] fix compile error --- .../java/com/sukesan1984/stepsensorlib/Database.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 3bf1b27..af006fe 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -292,14 +292,14 @@ public int getSteps(final long dateAndHour) { public int getSteps(final long start, final long end) { Cursor c = null; try { - c = getReadableDatabase(); - if (c == null) { - return 0; - } - c.query(TABLE_NAME, new String[]{"SUM(" + COLUMN_STEPS + ")"}, + c = getReadableDatabase() + .query(TABLE_NAME, new String[]{"SUM(" + COLUMN_STEPS + ")"}, COLUMN_DATE_AND_HOUR + " >= ? AND " + COLUMN_DATE_AND_HOUR + " <= ?", new String[]{String.valueOf(start), String.valueOf(end)}, null, null, null); + if (c == null) { + return 0; + } int sumSteps; if (c.getCount() == 0) { sumSteps = 0; From e502e4dc924b0a9f2e4ef015fe9f8f379953ff31 Mon Sep 17 00:00:00 2001 From: neonankiti Date: Thu, 25 May 2017 23:15:10 +0900 Subject: [PATCH 10/33] adjust the step sensor --- .../sukesan1984/stepsensorlib/util/Logger.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java b/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java index 4da95ad..0a03158 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/util/Logger.java @@ -37,13 +37,24 @@ public static void log(final Cursor c) { if (!BuildConfig.DEBUG) return; c.moveToFirst(); String title = ""; - for (int i = 0; i < c.getColumnCount(); i++) + for (int i = 0; i < c.getColumnCount(); i++) { title += c.getColumnName(i) + "\t| "; + } log(title); while (!c.isAfterLast()) { title = ""; - for (int i = 0; i < c.getColumnCount(); i++) - title += c.getString(i) + "\t| "; + for (int i = 0; i < c.getColumnCount(); i++) { + final int columnTitleLength = c.getColumnName(i).length(); + int columnValueLength = c.getString(i).length(); + int diffLength = columnTitleLength - columnValueLength > 0 + ? columnTitleLength - columnValueLength + : 0; + String diff = ""; + for (int diffCount = 0; diffCount < diffLength; diffCount++) { + diff += " "; + } + title += c.getString(i) + diff + "\t| "; + } log(title); c.moveToNext(); } From 749a4e86853dbd3cb618ae9d528ff330423cac97 Mon Sep 17 00:00:00 2001 From: neonankiti Date: Fri, 26 May 2017 00:45:42 +0900 Subject: [PATCH 11/33] add new log type --- .../sukesan1984/stepsensorlib/util/SensorListener.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java index a468176..2122d5f 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java @@ -5,7 +5,6 @@ import android.app.Service; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; @@ -13,7 +12,6 @@ import android.os.IBinder; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.util.Log; import com.sukesan1984.stepsensorlib.BuildConfig; import com.sukesan1984.stepsensorlib.Database; @@ -48,13 +46,14 @@ public void onAccuracyChanged(Sensor sensor, int accuracy) { @Override public void onSensorChanged(SensorEvent event) { + Logger.log("################################## onSensorChanged called ####################################"); if (event.values[0] > Integer.MAX_VALUE) { if (BuildConfig.DEBUG) { Logger.log("probably not a real value: " + event.values[0]); - return; } } else { steps = (int) event.values[0]; + Logger.log("sensor returned steps is " + steps + " and WAIT_FOR_VALID_STEPS is " + WAIT_FOR_VALID_STEPS); if (WAIT_FOR_VALID_STEPS && steps > 0) { Logger.log("periodically save"); WAIT_FOR_VALID_STEPS = false; @@ -78,7 +77,7 @@ public IBinder onBind(Intent intent) { @Override public int onStartCommand(Intent intent, int flags, int startId) { - Log.d("Hoge", "################################## onStartCommand"); + Logger.log("################################## onStartCommand called ####################################"); if (intent != null && ACTION_PAUSE.equals(intent.getStringExtra("action"))) { if (BuildConfig.DEBUG) { Logger.log("onStartCommand action: " + intent.getStringExtra("action")); @@ -88,7 +87,6 @@ public int onStartCommand(Intent intent, int flags, int startId) { steps = db.getLastUpdatedSteps(); db.close(); } - SharedPreferences prefs = getSharedPreferences("pedometer", Context.MODE_PRIVATE); ((AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE)) .cancel(PendingIntent.getService(getApplicationContext(), 2, new Intent(this, SensorListener.class), From f24442960df58d69bc046cd825b18ff7361e6fb4 Mon Sep 17 00:00:00 2001 From: neonankiti Date: Fri, 26 May 2017 00:47:34 +0900 Subject: [PATCH 12/33] remove unnecessary blocks for checking debug it's including inside the method --- .../stepsensorlib/util/SensorListener.java | 58 +++++++------------ 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java index 2122d5f..fcbb2eb 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java @@ -39,18 +39,14 @@ public static Intent createIntent(@NonNull Context context) { public void onAccuracyChanged(Sensor sensor, int accuracy) { // nobody knows what happens here: step value might magically decrease // when this method is called... - if (BuildConfig.DEBUG) { - Logger.log(sensor.getName() + " accuracy changed: " + accuracy); - } + Logger.log(sensor.getName() + " accuracy changed: " + accuracy); } @Override public void onSensorChanged(SensorEvent event) { Logger.log("################################## onSensorChanged called ####################################"); if (event.values[0] > Integer.MAX_VALUE) { - if (BuildConfig.DEBUG) { - Logger.log("probably not a real value: " + event.values[0]); - } + Logger.log("probably not a real value: " + event.values[0]); } else { steps = (int) event.values[0]; Logger.log("sensor returned steps is " + steps + " and WAIT_FOR_VALID_STEPS is " + WAIT_FOR_VALID_STEPS); @@ -79,9 +75,7 @@ public IBinder onBind(Intent intent) { public int onStartCommand(Intent intent, int flags, int startId) { Logger.log("################################## onStartCommand called ####################################"); if (intent != null && ACTION_PAUSE.equals(intent.getStringExtra("action"))) { - if (BuildConfig.DEBUG) { - Logger.log("onStartCommand action: " + intent.getStringExtra("action")); - } + Logger.log("onStartCommand action: " + intent.getStringExtra("action")); if (steps == 0) { Database db = Database.getInstance(this); steps = db.getLastUpdatedSteps(); @@ -108,18 +102,14 @@ public int onStartCommand(Intent intent, int flags, int startId) { @Override public void onCreate() { super.onCreate(); - if (BuildConfig.DEBUG) { - Logger.log("SensorListener onCreate"); - } + Logger.log("SensorListener onCreate"); reRegisterSensor(); } @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); - if (BuildConfig.DEBUG) { - Logger.log("sensor service task removed"); - } + Logger.log("sensor service task removed"); ((AlarmManager) getSystemService(Context.ALARM_SERVICE)) .set(AlarmManager.RTC, System.currentTimeMillis() + 500, PendingIntent @@ -129,41 +119,33 @@ public void onTaskRemoved(Intent rootIntent) { @Override public void onDestroy() { super.onDestroy(); - if (BuildConfig.DEBUG) { - Logger.log("SensorListener onDestroy"); - try { - SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); - sm.unregisterListener(this); - } catch (Exception e) { - if (BuildConfig.DEBUG) { - Logger.log(e); - e.printStackTrace(); - } + Logger.log("SensorListener onDestroy"); + try { + SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); + sm.unregisterListener(this); + } catch (Exception e) { + if (BuildConfig.DEBUG) { + Logger.log(e); + e.printStackTrace(); } } } private void reRegisterSensor() { - if (BuildConfig.DEBUG) { - Logger.log("re-register sensor listener"); - } + Logger.log("re-register sensor listener"); SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); try { sm.unregisterListener(this); } catch (Exception e) { - if (BuildConfig.DEBUG) { - Logger.log(e); - e.printStackTrace(); - } + Logger.log(e); + e.printStackTrace(); } - if (BuildConfig.DEBUG) { - Logger.log("step sensors: " + sm.getSensorList(Sensor.TYPE_STEP_COUNTER).size()); - if (sm.getSensorList(Sensor.TYPE_STEP_COUNTER).size() < 1) { - return; - } - Logger.log("default: " + sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER).getName()); + Logger.log("step sensors: " + sm.getSensorList(Sensor.TYPE_STEP_COUNTER).size()); + if (sm.getSensorList(Sensor.TYPE_STEP_COUNTER).size() < 1) { + return; } + Logger.log("default: " + sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER).getName()); // enable batching with delay of max 5min if (StepSensorFacade.isValidStepSensorDevice(this)) { From c1d51d733e6307390f5759d200f29805d0f88b92 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Wed, 31 May 2017 02:38:52 +0900 Subject: [PATCH 13/33] Redesign interface and impl to fix unexpected behavior around step count --- src/main/AndroidManifest.xml | 2 +- .../stepsensorlib/BootReceiver.java | 27 -- .../sukesan1984/stepsensorlib/Database.java | 317 ++++-------------- .../stepsensorlib/PreferenceManager.java | 7 +- .../{util => }/SensorListener.java | 77 +---- .../stepsensorlib/ShutdownReceiver.java | 21 +- .../stepsensorlib/StepCountCoordinator.java | 69 ++++ .../stepsensorlib/StepSensorFacade.java | 44 +++ 8 files changed, 194 insertions(+), 370 deletions(-) rename src/main/java/com/sukesan1984/stepsensorlib/{util => }/SensorListener.java (56%) create mode 100644 src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index c90e544..20277a1 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -6,7 +6,7 @@ android:label="@string/app_name" android:supportsRtl="true"> diff --git a/src/main/java/com/sukesan1984/stepsensorlib/BootReceiver.java b/src/main/java/com/sukesan1984/stepsensorlib/BootReceiver.java index 162d9fd..6669256 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/BootReceiver.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/BootReceiver.java @@ -4,36 +4,9 @@ import android.content.Context; import android.content.Intent; -import com.sukesan1984.stepsensorlib.util.DateUtils; -import com.sukesan1984.stepsensorlib.util.Logger; -import com.sukesan1984.stepsensorlib.util.SensorListener; - -/** - * Created by kosuketakami on 2016/11/05. - */ - public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - Database db = Database.getInstance(context); - - if (!PreferenceManager.readCorrectShutDown(context, false)) { - if (BuildConfig.DEBUG) { - Logger.log("Incorrect shutdown"); - } - int steps = db.getLastUpdatedSteps(); - if (BuildConfig.DEBUG) { - Logger.log("Trying to recover " + steps + " steps"); - } - db.updateOrInsert(DateUtils.getCurrentDateAndHour(), steps); - } - // last entry might still have a negative step value, so remove that - // row if that's the case - db.removeNegativeEntries(); - db.close(); - - PreferenceManager.deleteCorrectShutDown(context); - PreferenceManager.deleteStepsSinceBoot(context); context.startService(new Intent(context, SensorListener.class)); } } diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index af006fe..7e3277a 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -15,17 +15,13 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -/** - * - */ - -public class Database extends SQLiteOpenHelper { +class Database extends SQLiteOpenHelper { private final static String TABLE_NAME = "steps"; private final static String COLUMN_DATE_AND_HOUR = "date_and_hour"; private final static String COLUMN_STEPS = "steps"; private final static String COLUMN_IS_RECORDED_ON_SERVER = "is_recorded_on_server"; private final static String COLUMN_LAST_UPDATED = "last_updated"; - private final static int DB_VERSION = 1; + private final static int DB_VERSION = 2; private static Database instance; private static final AtomicInteger openCounter = new AtomicInteger(); @@ -82,197 +78,60 @@ public void deleteAll() { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - // on upgrade - } - - /** - * Query the 'steps' table. Remember to close the cursor! - * - * @param columns the colums - * @param selection the selection - * @param selectionArgs the selction arguments - * @param groupBy the group by statement - * @param having the having statement - * @param orderBy the order by statement - * @return the cursor - */ - public Cursor query(final String[] columns, final String selection, - final String[] selectionArgs, final String groupBy, final String having, - final String orderBy, final String limit) { - try { - return getReadableDatabase() - .query(TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy, limit); - } catch (Exception e) { - e.printStackTrace(); - return null; + if (oldVersion < 2) { + db.delete("steps", "date_and_hour = ?", new String[]{"-1"}); } } /** - * @param dateAndHour the dateAndHour in ms since 1970 - * @param stepsSinceBoot the steps since boot - */ - public void updateOrInsert(long dateAndHour, int stepsSinceBoot) { - SQLiteDatabase db = null; - try { - db = getWritableDatabase(); - db.beginTransaction(); - updateOrInsertWithoutTransaction(db, dateAndHour, stepsSinceBoot); - db.setTransactionSuccessful(); - - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (db != null) { - db.endTransaction(); - db.close(); - } - } - } - - private void updateOrInsertWithoutTransaction(SQLiteDatabase db, long dateAndHour, int stepsSinceBoot) { - if (db == null) { - return; - } - Cursor c = getByDateAndHour(dateAndHour); - if (c == null) { - return; - } - initializeLastUpdatedSteps(db, stepsSinceBoot); - int lastUpdatedSteps = getLastUpdatedSteps(); - if (lastUpdatedSteps > stepsSinceBoot) { - saveLastUpdatedSteps(db, stepsSinceBoot); - return; - } - - int addedSteps = stepsSinceBoot - lastUpdatedSteps; - if (c.getCount() == 0 && stepsSinceBoot >= 0) { - insertNewDateAndHour(db, dateAndHour, addedSteps); - } else { - addToLastEntry(db, addedSteps); - } - saveLastUpdatedSteps(db, stepsSinceBoot); - c.close(); - } - - /** - * replace steps count if steps is larger than current databace value. + * Add step count in table. If no row matching to targetDateAndHour is exist, it will be created. * - * @param dateAndHour - * @param steps + * @param targetDateAndHour Key for table. + * @param stepsToAdd Count to be added. + * @throws IllegalArgumentException if stepsToAdd is negative value. */ - public void insertOrReplaceSteps(final long dateAndHour, final int steps) { + public boolean addSteps(long targetDateAndHour, int stepsToAdd) { + if (stepsToAdd < 0) throw new IllegalArgumentException("stepsToAdd should not be negative value."); SQLiteDatabase db = null; - Cursor c = null; try { db = getWritableDatabase(); - c = getByDateAndHour(dateAndHour); db.beginTransaction(); - if (c == null) { - db.endTransaction(); - db.close(); - return; - } - if (c.getCount() == 0) { - if (steps > 0) { - insertNewDateAndHour(db, dateAndHour, steps); - } else { - return; - } - } else if (c.moveToFirst() && c.getInt(0) < steps) { - Logger.log("#### update"); - Logger.log("#### data_and_hour: " + dateAndHour); - Logger.log("#### steps: " + steps); - ContentValues values = new ContentValues(); - values.put(COLUMN_DATE_AND_HOUR, dateAndHour); - values.put(COLUMN_STEPS, steps); - values.put(COLUMN_LAST_UPDATED, DateUtils.getCurrentTimeMllis()); - db.update(TABLE_NAME, values, - COLUMN_DATE_AND_HOUR + " = ?", - new String[]{String.valueOf(dateAndHour)}); - } + int currentSteps = getStepsImpl(db, targetDateAndHour); + insertOrReplaceStepRow(db, targetDateAndHour, currentSteps + stepsToAdd, true); db.setTransactionSuccessful(); - + return true; } catch (Exception e) { e.printStackTrace(); + return false; } finally { - if (c != null) { - c.close(); - } if (db != null) { db.endTransaction(); db.close(); } } - } - /** - * Inserts a new entry in the database, if there is no entry for the given - * dateAndHour yet. - *

- * - * @param dateAndHour the dateAndHour in ms since 1970 - * @param steps the current step value - */ - - private void insertNewDateAndHour(SQLiteDatabase db, final long dateAndHour, final int steps) { - Logger.log("insert new date and hour"); - Logger.log("date_and_hour: " + dateAndHour); - Logger.log("steps: " + steps); + private void insertOrReplaceStepRow(SQLiteDatabase db, long dateAndHour, int steps, boolean markNotRecorded) { ContentValues values = new ContentValues(); values.put(COLUMN_DATE_AND_HOUR, dateAndHour); - // use the negative steps as offset values.put(COLUMN_STEPS, steps); values.put(COLUMN_LAST_UPDATED, DateUtils.getCurrentTimeMllis()); - db.insert(TABLE_NAME, null, values); - if (BuildConfig.DEBUG) { - Logger.log("insertDayAndHour" + dateAndHour + " / " + steps); - logState(); - } - } - - private Cursor getByDateAndHour(long dateAndHour) { - try { - return getReadableDatabase().query(TABLE_NAME, new String[]{COLUMN_STEPS}, - COLUMN_DATE_AND_HOUR + " = ?", - new String[]{String.valueOf(dateAndHour)}, null, null, null); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - - } - - private void addToLastEntry(SQLiteDatabase db, int steps) { - if (steps > 0) { - db.execSQL("UPDATE " + TABLE_NAME + " SET " + COLUMN_STEPS + " = " + COLUMN_STEPS + " + " + steps - + ", " + COLUMN_IS_RECORDED_ON_SERVER + " = 0, " + COLUMN_LAST_UPDATED + " =" + DateUtils.getCurrentTimeMllis() + - " WHERE " + COLUMN_DATE_AND_HOUR + "= (SELECT MAX(" + COLUMN_DATE_AND_HOUR + ") FROM " + TABLE_NAME + ");"); - } - } - - /** - * Writes the current steps database to the log. - */ - public void logState() { - if (BuildConfig.DEBUG) { - Cursor c = getReadableDatabase() - .query(TABLE_NAME, null, null, null, null, null, COLUMN_DATE_AND_HOUR + " DESC", null); - if (c != null) { - Logger.log(c); - c.close(); - } + if (markNotRecorded) { + values.put(COLUMN_IS_RECORDED_ON_SERVER, 0); } + db.replaceOrThrow(TABLE_NAME, null, values); } - /** - * @param dateAndHour - * @return - */ public int getSteps(final long dateAndHour) { Logger.log("getStep dateAndHour" + dateAndHour); - Cursor c = getByDateAndHour(dateAndHour); + SQLiteDatabase db = getReadableDatabase(); + return getStepsImpl(db, dateAndHour); + } + + private int getStepsImpl(SQLiteDatabase db, long dateAndHour) { + Cursor c = db.query(TABLE_NAME, new String[]{COLUMN_STEPS}, + COLUMN_DATE_AND_HOUR + " = ?", + new String[]{String.valueOf(dateAndHour)}, null, null, null); if (c != null) { c.moveToFirst(); @@ -318,109 +177,32 @@ public int getSteps(final long start, final long end) { } } - public List getChunkStepsFrom(final long start) { - Cursor c = null; + @NonNull + public List getChunkStepsSince(final long start) { + Cursor c; try { c = getReadableDatabase() .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, COLUMN_DATE_AND_HOUR + " >= ?", new String[]{String.valueOf(start)}, null, null, null); if (c == null) { - return null; + return new ArrayList<>(); } return createChunkedStepCounts(c); } catch (Exception e) { e.printStackTrace(); - return null; - } - } - - /** - * Removes all entries with negative values. - *

- * Only call this directly after boot, otherwise it might remove the current - * day as the current offset is likely to be negative. - */ - void removeNegativeEntries() { - try { - getWritableDatabase().delete(TABLE_NAME, COLUMN_STEPS + " < ?", new String[]{"0"}); - } catch (Exception e) { - e.printStackTrace(); + return new ArrayList<>(); } } - /** - * Remove invalid entries from the database. - * Currently, an invalid input is such with steps >= 200,000 - */ - public void removeInvalidEntries() { - try { - getWritableDatabase().delete(TABLE_NAME, COLUMN_STEPS + " >= ?", new String[]{"200000"}); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * @param stepsSinceBoot steps after boot. - */ - public void resetLastUpdatedSteps(final int stepsSinceBoot) { - SQLiteDatabase db = null; - try { - db = getWritableDatabase(); - db.beginTransaction(); - updateOrInsertWithoutTransaction(db, DateUtils.getCurrentDateAndHour(), stepsSinceBoot); - saveLastUpdatedSteps(db, 0); - db.setTransactionSuccessful(); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (db != null) { - db.endTransaction(); - db.close(); - } - } - } - - private void initializeLastUpdatedSteps(SQLiteDatabase db, final int stepsSinceBoot) { - if (db == null) { - return; - } - // initialize if there is no date - if (getSteps(-1) == Integer.MIN_VALUE) { - saveLastUpdatedSteps(db, stepsSinceBoot); - } - } - - private void saveLastUpdatedSteps(SQLiteDatabase db, final int steps) { - if (db == null) { - return; - } - ContentValues values = new ContentValues(); - values.put(COLUMN_STEPS, steps); - if (db.update(TABLE_NAME, values, COLUMN_DATE_AND_HOUR + " = -1", null) == 0) { - values.put(COLUMN_DATE_AND_HOUR, -1); - values.put(COLUMN_LAST_UPDATED, DateUtils.getCurrentTimeMllis()); - db.insert(TABLE_NAME, null, values); - } - if (BuildConfig.DEBUG) { - Logger.log("saving steps in db: " + steps); - } - } - - public int getLastUpdatedSteps() { - int currentSteps = getSteps(-1); - return currentSteps == Integer.MIN_VALUE ? 0 : currentSteps; - } - public int getTodayStep() { Logger.log("getTodayStep"); return getSteps(DateUtils.getStartOfToday(), DateUtils.getCurrentTimeMllis()); } @NonNull - public List getNotRecordedChunkedStepCounts() { + public List getNotRecordedChunkStepCounts() { Cursor c = null; try { c = getReadableDatabase() @@ -429,7 +211,7 @@ public List getNotRecordedChunkedStepCounts() { COLUMN_IS_RECORDED_ON_SERVER + " = ?", new String[]{"-1", "0"}, null, null, null); Logger.log("Not recoreded Chunk Size: " + c.getCount()); if (c == null) { - return null; + return new ArrayList<>(); } // cursor close is in method return createChunkedStepCounts(c); @@ -438,7 +220,7 @@ public List getNotRecordedChunkedStepCounts() { if (c != null) { c.close(); } - return null; + return new ArrayList<>(); } } @@ -458,12 +240,12 @@ private List createChunkedStepCounts(Cursor c) { return lists; } - public void updateToRecorded(long[] dateAndHours) { + public void updateToRecorded(List dateAndHours) { SQLiteDatabase db = null; try { ContentValues values = new ContentValues(); values.put(COLUMN_IS_RECORDED_ON_SERVER, "1"); - int length = dateAndHours.length; + int length = dateAndHours.size(); String args = ""; String[] dateAndHoursString = new String[length]; for (int i = 0; i < length; i++) { @@ -472,14 +254,13 @@ public void updateToRecorded(long[] dateAndHours) { } else { args += ", ?"; } - dateAndHoursString[i] = String.valueOf(dateAndHours[i]); + dateAndHoursString[i] = String.valueOf(dateAndHours.get(i)); } db = getWritableDatabase(); db.beginTransaction(); int rows = db.update(TABLE_NAME, values, String.format(COLUMN_DATE_AND_HOUR + " in (%s)", args), dateAndHoursString); Logger.log("updated number: " + rows); - logState(); db.setTransactionSuccessful(); Logger.log("update to Recorded: " + dateAndHoursString.toString()); } catch (Exception e) { @@ -491,4 +272,28 @@ public void updateToRecorded(long[] dateAndHours) { } } } + + public void increaseByChunkStepCounts(List chunkStepCounts) { + SQLiteDatabase db = null; + try { + db = getWritableDatabase(); + db.beginTransaction(); + for (ChunkStepCount chunkStepCount : chunkStepCounts) { + increaseByChunkStepCount(db, chunkStepCount); + } + db.setTransactionSuccessful(); + } finally { + if (db != null) { + db.endTransaction(); + db.close(); + } + } + } + + private void increaseByChunkStepCount(SQLiteDatabase db, ChunkStepCount chunkStepCount) { + int currentSteps = getStepsImpl(db, chunkStepCount.unixTimeMillis); + if (chunkStepCount.steps > currentSteps) { + insertOrReplaceStepRow(db, chunkStepCount.unixTimeMillis, chunkStepCount.steps, false); + } + } } diff --git a/src/main/java/com/sukesan1984/stepsensorlib/PreferenceManager.java b/src/main/java/com/sukesan1984/stepsensorlib/PreferenceManager.java index a0d965e..b5c7b4f 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/PreferenceManager.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/PreferenceManager.java @@ -4,11 +4,8 @@ import android.content.SharedPreferences; import android.support.annotation.NonNull; -/** - * Created by kosuketakami on 2017/01/16. - */ - -public class PreferenceManager { +// TODO: use this for service restart +class PreferenceManager { private static String PEDOMETER = "pedometer"; private static String CORRECT_SHUTDOWN = "corretctShutdown"; private static String STEPS_SINCE_BOOT = "stepsSinceBoot"; diff --git a/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java similarity index 56% rename from src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java rename to src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java index fcbb2eb..bd04cc7 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/util/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java @@ -1,4 +1,4 @@ -package com.sukesan1984.stepsensorlib.util; +package com.sukesan1984.stepsensorlib; import android.app.AlarmManager; import android.app.PendingIntent; @@ -13,25 +13,16 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import com.sukesan1984.stepsensorlib.BuildConfig; -import com.sukesan1984.stepsensorlib.Database; -import com.sukesan1984.stepsensorlib.PreferenceManager; -import com.sukesan1984.stepsensorlib.StepSensorFacade; - -/** - * Created by kosuketakami on 2016/11/05. - */ +import com.sukesan1984.stepsensorlib.util.Logger; public class SensorListener extends Service implements SensorEventListener { - public final static String ACTION_PAUSE = "pause"; - private static int steps; - - private static boolean WAIT_FOR_VALID_STEPS = false; + private final static int MICROSECONDS_IN_ONE_MINUTE = 60 * 1000 * 1000; - private final static int MICROSECONDS_IN_ONE_MINUTE = 60000000; - - public static Intent createIntent(@NonNull Context context) { + /** + * Start service + */ + static Intent createIntent(@NonNull Context context) { return new Intent(context, SensorListener.class); } @@ -46,23 +37,11 @@ public void onAccuracyChanged(Sensor sensor, int accuracy) { public void onSensorChanged(SensorEvent event) { Logger.log("################################## onSensorChanged called ####################################"); if (event.values[0] > Integer.MAX_VALUE) { - Logger.log("probably not a real value: " + event.values[0]); - } else { - steps = (int) event.values[0]; - Logger.log("sensor returned steps is " + steps + " and WAIT_FOR_VALID_STEPS is " + WAIT_FOR_VALID_STEPS); - if (WAIT_FOR_VALID_STEPS && steps > 0) { - Logger.log("periodically save"); - WAIT_FOR_VALID_STEPS = false; - Database db = Database.getInstance(this); - db.updateOrInsert(DateUtils.getCurrentDateAndHour(), steps); - reRegisterSensor(); - int difference = steps - PreferenceManager.readStepsSinceBoot(this, steps); - if (difference > 0) { - PreferenceManager.writeStepsSinceBoot(this, steps); - } - db.close(); - } + Logger.log("probably not a real value: " + event.values[0]); return; } + + int stepsSinceBoot = (int) event.values[0]; + StepCountCoordinator.getInstance().onStepCounterEvent(this, stepsSinceBoot); } @Nullable @@ -74,28 +53,11 @@ public IBinder onBind(Intent intent) { @Override public int onStartCommand(Intent intent, int flags, int startId) { Logger.log("################################## onStartCommand called ####################################"); - if (intent != null && ACTION_PAUSE.equals(intent.getStringExtra("action"))) { - Logger.log("onStartCommand action: " + intent.getStringExtra("action")); - if (steps == 0) { - Database db = Database.getInstance(this); - steps = db.getLastUpdatedSteps(); - db.close(); - } - ((AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE)) - .cancel(PendingIntent.getService(getApplicationContext(), 2, - new Intent(this, SensorListener.class), - PendingIntent.FLAG_UPDATE_CURRENT)); - stopSelf(); - return START_NOT_STICKY; - } - // restart service every minutes get the current step count ((AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE)) .set(AlarmManager.RTC, System.currentTimeMillis() + 60 * 1000, - PendingIntent.getService(getApplicationContext(), 2, new Intent(this, SensorListener.class), - PendingIntent.FLAG_UPDATE_CURRENT)); - WAIT_FOR_VALID_STEPS = true; - + PendingIntent.getService(this, 2, createIntent(this), PendingIntent.FLAG_UPDATE_CURRENT)); + StepCountCoordinator.getInstance().saveSteps(this); return START_STICKY; } @@ -103,7 +65,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { public void onCreate() { super.onCreate(); Logger.log("SensorListener onCreate"); - reRegisterSensor(); + registerSensor(); } @Override @@ -131,16 +93,9 @@ public void onDestroy() { } } - private void reRegisterSensor() { - Logger.log("re-register sensor listener"); + private void registerSensor() { + Logger.log("register sensor listener"); SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); - try { - sm.unregisterListener(this); - } catch (Exception e) { - Logger.log(e); - e.printStackTrace(); - } - Logger.log("step sensors: " + sm.getSensorList(Sensor.TYPE_STEP_COUNTER).size()); if (sm.getSensorList(Sensor.TYPE_STEP_COUNTER).size() < 1) { return; diff --git a/src/main/java/com/sukesan1984/stepsensorlib/ShutdownReceiver.java b/src/main/java/com/sukesan1984/stepsensorlib/ShutdownReceiver.java index ba1c52d..16eb2c2 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/ShutdownReceiver.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/ShutdownReceiver.java @@ -5,30 +5,11 @@ import android.content.Intent; import com.sukesan1984.stepsensorlib.util.Logger; -import com.sukesan1984.stepsensorlib.util.SensorListener; - -/** - * Created by kosuketakami on 2016/11/05. - */ public class ShutdownReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (BuildConfig.DEBUG) Logger.log("shutting down"); - - context.startService(new Intent(context, SensorListener.class)); - - // if the user used a root script for shutdown, the DEVICE_SHUTDOWN - // broadcast might not be send. Thereforee, the app will check this - // setting on the next boot and displays an error message if it's not - // set to true - PreferenceManager.writeCorrectShutDown(context, true); - - Database db = Database.getInstance(context); - - db.resetLastUpdatedSteps(db.getLastUpdatedSteps()); - if (BuildConfig.DEBUG) db.logState(); - - db.close(); + StepCountCoordinator.getInstance().saveSteps(context); } } diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java new file mode 100644 index 0000000..c4a88c7 --- /dev/null +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -0,0 +1,69 @@ +package com.sukesan1984.stepsensorlib; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.Log; + +import com.sukesan1984.stepsensorlib.util.DateUtils; + +class StepCountCoordinator { + private static final String TAG = "StepCountCoordinator"; + private static volatile StepCountCoordinator singleton; + + @Nullable + private Long dateAndHourOfLastEvent; + private int stepsOffset; + private int unsavedSteps = 0; + + public static StepCountCoordinator getInstance() { + if (singleton == null) { + synchronized (StepCountCoordinator.class) { + if (singleton == null) { + singleton = new StepCountCoordinator(); + } + } + } + return singleton; + } + + private StepCountCoordinator() { + } + + public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) { + long dateAndHour = DateUtils.getCurrentDateAndHour(); + if (dateAndHourOfLastEvent == null) { + dateAndHourOfLastEvent = dateAndHour; + stepsOffset = stepsSinceBoot; + Log.v(TAG, "onStepSensorEvent: stepsOffset is set to " + unsavedSteps); + return; + } + + if (dateAndHour != dateAndHourOfLastEvent) { + saveSteps(context); + } + unsavedSteps = stepsSinceBoot - stepsOffset; + Log.v(TAG, "onStepSensorEvent: " + unsavedSteps); + dateAndHourOfLastEvent = dateAndHour; + } + + public synchronized void saveSteps(Context context) { + if (dateAndHourOfLastEvent == null) return; + Database database = Database.getInstance(context); + Log.v(TAG, "saveSteps: " + unsavedSteps); + if (database.addSteps(dateAndHourOfLastEvent, unsavedSteps)) { + unsavedSteps = 0; + } else { + Log.e(TAG, "Failed to save steps."); + } + database.close(); + } + + public synchronized int getTodaySteps(Context context) { + long dateAndHour = DateUtils.getCurrentDateAndHour(); + if (dateAndHourOfLastEvent != null && dateAndHour != dateAndHourOfLastEvent) { + // Save and flush step count before fetch. + saveSteps(context); + } + return Database.getInstance(context).getTodayStep() + unsavedSteps; + } +} diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java index 60c8202..a35b515 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java @@ -3,15 +3,59 @@ import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; +import android.support.annotation.NonNull; + +import com.sukesan1984.stepsensorlib.model.ChunkStepCount; + +import java.util.ArrayList; +import java.util.List; /** * Step Sensor Facade */ public class StepSensorFacade { + private StepSensorFacade() { + throw new AssertionError(); + } + public static boolean isValidStepSensorDevice(Context context) { // TODO: get from server side black list model. return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_COUNTER); } + + public static void startService(Context context) { + context.startService(SensorListener.createIntent(context)); + } + + public static int getTodaySteps(Context context) { + return StepCountCoordinator.getInstance().getTodaySteps(context); + } + + public static void clearAllData(Context context) { + Database.getInstance(context).deleteAll(); + } + + public static void increaseByChunkStepCounts(Context context, List chunkStepCounts) { + Database.getInstance(context).increaseByChunkStepCounts(chunkStepCounts); + } + + @NonNull + public static List getChunkStepsSince(Context context, long dateAndHour) { + return Database.getInstance(context).getChunkStepsSince(dateAndHour); + } + + @NonNull + public static List getNotRecordedChunkStepCounts(Context context) { + return Database.getInstance(context).getNotRecordedChunkStepCounts(); + } + + public static void markChunkStepCountsAsRecorded(Context context, List chunkStepCounts) { + List dateAndHours = new ArrayList<>(chunkStepCounts.size()); + for (ChunkStepCount chunkStepCount : chunkStepCounts) { + dateAndHours.add(chunkStepCount.unixTimeMillis); + } + Database.getInstance(context).updateToRecorded(dateAndHours); + } } From 6f1ff53ecf64b150ea2d81b7e0c5fd7fc23656e2 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Wed, 31 May 2017 03:33:31 +0900 Subject: [PATCH 14/33] Fix security issue of exporting internal service --- src/main/AndroidManifest.xml | 2 +- .../sukesan1984/stepsensorlib/Database.java | 44 ++++++++++--------- .../stepsensorlib/StepCountCoordinator.java | 12 ++--- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 20277a1..5fd4509 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ android:supportsRtl="true"> + android:exported="false" /> diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 7e3277a..5049732 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -6,6 +6,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import com.sukesan1984.stepsensorlib.model.ChunkStepCount; import com.sukesan1984.stepsensorlib.util.DateUtils; @@ -88,21 +89,23 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { * * @param targetDateAndHour Key for table. * @param stepsToAdd Count to be added. + * @return Total count after add, or negative value when failed. * @throws IllegalArgumentException if stepsToAdd is negative value. */ - public boolean addSteps(long targetDateAndHour, int stepsToAdd) { + public int addSteps(long targetDateAndHour, int stepsToAdd) { if (stepsToAdd < 0) throw new IllegalArgumentException("stepsToAdd should not be negative value."); SQLiteDatabase db = null; try { db = getWritableDatabase(); db.beginTransaction(); int currentSteps = getStepsImpl(db, targetDateAndHour); - insertOrReplaceStepRow(db, targetDateAndHour, currentSteps + stepsToAdd, true); + int newSteps = currentSteps + stepsToAdd; + insertOrReplaceStepRow(db, targetDateAndHour, newSteps, true); db.setTransactionSuccessful(); - return true; + return newSteps; } catch (Exception e) { e.printStackTrace(); - return false; + return -1; } finally { if (db != null) { db.endTransaction(); @@ -132,19 +135,17 @@ private int getStepsImpl(SQLiteDatabase db, long dateAndHour) { Cursor c = db.query(TABLE_NAME, new String[]{COLUMN_STEPS}, COLUMN_DATE_AND_HOUR + " = ?", new String[]{String.valueOf(dateAndHour)}, null, null, null); - - if (c != null) { + try { + if (c == null) { + return 0; + } c.moveToFirst(); - int steps; if (c.getCount() == 0) { - steps = Integer.MIN_VALUE; - } else { - steps = c.getInt(0); + return 0; } - c.close(); - return steps; - } else { - return Integer.MIN_VALUE; + return c.getInt(0); + } finally { + closeCursor(c); } } @@ -166,20 +167,18 @@ public int getSteps(final long start, final long end) { c.moveToFirst(); sumSteps = c.getInt(0); } - c.close(); return sumSteps; } catch (Exception e) { e.printStackTrace(); - if (c != null) { - c.close(); - } return 0; + } finally { + closeCursor(c); } } @NonNull public List getChunkStepsSince(final long start) { - Cursor c; + Cursor c = null; try { c = getReadableDatabase() .query(TABLE_NAME, new String[]{COLUMN_DATE_AND_HOUR, COLUMN_STEPS}, @@ -193,6 +192,8 @@ public List getChunkStepsSince(final long start) { } catch (Exception e) { e.printStackTrace(); return new ArrayList<>(); + } finally { + closeCursor(c); } } @@ -236,7 +237,6 @@ private List createChunkedStepCounts(Cursor c) { while (c.moveToNext()) { lists.add(new ChunkStepCount(c.getLong(0), c.getInt(1))); } - c.close(); return lists; } @@ -296,4 +296,8 @@ private void increaseByChunkStepCount(SQLiteDatabase db, ChunkStepCount chunkSte insertOrReplaceStepRow(db, chunkStepCount.unixTimeMillis, chunkStepCount.steps, false); } } + + private void closeCursor(@Nullable Cursor cursor) { + if (cursor != null) cursor.close(); + } } diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index c4a88c7..572910e 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -34,7 +34,7 @@ public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) if (dateAndHourOfLastEvent == null) { dateAndHourOfLastEvent = dateAndHour; stepsOffset = stepsSinceBoot; - Log.v(TAG, "onStepSensorEvent: stepsOffset is set to " + unsavedSteps); + Log.v(TAG, "onStepCounterEvent: stepsOffset is set to " + stepsOffset); return; } @@ -42,7 +42,7 @@ public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) saveSteps(context); } unsavedSteps = stepsSinceBoot - stepsOffset; - Log.v(TAG, "onStepSensorEvent: " + unsavedSteps); + Log.v(TAG, "onStepCounterEvent: " + unsavedSteps); dateAndHourOfLastEvent = dateAndHour; } @@ -50,10 +50,12 @@ public synchronized void saveSteps(Context context) { if (dateAndHourOfLastEvent == null) return; Database database = Database.getInstance(context); Log.v(TAG, "saveSteps: " + unsavedSteps); - if (database.addSteps(dateAndHourOfLastEvent, unsavedSteps)) { - unsavedSteps = 0; - } else { + int newSteps = database.addSteps(dateAndHourOfLastEvent, unsavedSteps); + if (newSteps < 0) { Log.e(TAG, "Failed to save steps."); + } else { + unsavedSteps = 0; + stepsOffset = newSteps; } database.close(); } From 726a006a4507913bc8aa5e7ea25e42ad63279f38 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Wed, 31 May 2017 14:34:08 +0900 Subject: [PATCH 15/33] Fix useless lazy singleton --- .../sukesan1984/stepsensorlib/StepCountCoordinator.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index 572910e..c34c271 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -8,7 +8,7 @@ class StepCountCoordinator { private static final String TAG = "StepCountCoordinator"; - private static volatile StepCountCoordinator singleton; + private static final StepCountCoordinator singleton = new StepCountCoordinator(); @Nullable private Long dateAndHourOfLastEvent; @@ -16,13 +16,6 @@ class StepCountCoordinator { private int unsavedSteps = 0; public static StepCountCoordinator getInstance() { - if (singleton == null) { - synchronized (StepCountCoordinator.class) { - if (singleton == null) { - singleton = new StepCountCoordinator(); - } - } - } return singleton; } From a11a0e0128a1e9d4d6a79f9d46880c635e67121d Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Wed, 31 May 2017 15:06:56 +0900 Subject: [PATCH 16/33] Fix stepsOffset set to too small value after hour is changed --- .../com/sukesan1984/stepsensorlib/StepCountCoordinator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index c34c271..36b36fd 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -47,8 +47,8 @@ public synchronized void saveSteps(Context context) { if (newSteps < 0) { Log.e(TAG, "Failed to save steps."); } else { + stepsOffset += unsavedSteps; unsavedSteps = 0; - stepsOffset = newSteps; } database.close(); } From 1786631c40664bb2dc684ddf789851eed6219d14 Mon Sep 17 00:00:00 2001 From: sukesan1984 Date: Thu, 8 Jun 2017 21:28:10 +0900 Subject: [PATCH 17/33] fix to not call db.close http://d.hatena.ne.jp/ukiki999/20100524/p1 --- .../java/com/sukesan1984/stepsensorlib/Database.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index af006fe..9015309 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -73,10 +73,6 @@ public void deleteAll() { db.delete(TABLE_NAME, "", new String[]{}); } catch (Exception e) { e.printStackTrace(); - } finally { - if (db != null) { - db.close(); - } } } @@ -125,7 +121,6 @@ public void updateOrInsert(long dateAndHour, int stepsSinceBoot) { } finally { if (db != null) { db.endTransaction(); - db.close(); } } } @@ -170,7 +165,6 @@ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { db.beginTransaction(); if (c == null) { db.endTransaction(); - db.close(); return; } if (c.getCount() == 0) { @@ -201,7 +195,6 @@ public void insertOrReplaceSteps(final long dateAndHour, final int steps) { } if (db != null) { db.endTransaction(); - db.close(); } } @@ -273,7 +266,6 @@ public void logState() { public int getSteps(final long dateAndHour) { Logger.log("getStep dateAndHour" + dateAndHour); Cursor c = getByDateAndHour(dateAndHour); - if (c != null) { c.moveToFirst(); int steps; @@ -378,7 +370,6 @@ public void resetLastUpdatedSteps(final int stepsSinceBoot) { } finally { if (db != null) { db.endTransaction(); - db.close(); } } } @@ -487,7 +478,6 @@ public void updateToRecorded(long[] dateAndHours) { } finally { if (db != null) { db.endTransaction(); - db.close(); } } } From e31cfa4b6c5f4b67796ebbc49ebcddf69fc48818 Mon Sep 17 00:00:00 2001 From: sukesan1984 Date: Fri, 9 Jun 2017 14:51:47 +0900 Subject: [PATCH 18/33] remove db.close http://d.hatena.ne.jp/ukiki999/20100524/p1 --- src/main/java/com/sukesan1984/stepsensorlib/Database.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 5049732..297e2f3 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -70,10 +70,6 @@ public void deleteAll() { db.delete(TABLE_NAME, "", new String[]{}); } catch (Exception e) { e.printStackTrace(); - } finally { - if (db != null) { - db.close(); - } } } @@ -109,7 +105,6 @@ public int addSteps(long targetDateAndHour, int stepsToAdd) { } finally { if (db != null) { db.endTransaction(); - db.close(); } } } @@ -268,7 +263,6 @@ public void updateToRecorded(List dateAndHours) { } finally { if (db != null) { db.endTransaction(); - db.close(); } } } @@ -285,7 +279,6 @@ public void increaseByChunkStepCounts(List chunkStepCounts) { } finally { if (db != null) { db.endTransaction(); - db.close(); } } } From c55381c436c33eaab972fe2cf44bc000950e2547 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Mon, 12 Jun 2017 16:56:02 +0900 Subject: [PATCH 19/33] Rename startService method --- .../java/com/sukesan1984/stepsensorlib/StepSensorFacade.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java index a35b515..cc4ccbc 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java @@ -25,7 +25,7 @@ public static boolean isValidStepSensorDevice(Context context) { && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_COUNTER); } - public static void startService(Context context) { + public static void startServiceAndSaveData(Context context) { context.startService(SensorListener.createIntent(context)); } From a49b6247346471a6d59c6a3d06dd5de4fcee7871 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Mon, 12 Jun 2017 16:57:00 +0900 Subject: [PATCH 20/33] Fix remaining data in StepCountCoordinator after clearAllData --- .../stepsensorlib/SensorListener.java | 20 ++++++++++++++++++- .../stepsensorlib/StepCountCoordinator.java | 6 ++++++ .../stepsensorlib/StepSensorFacade.java | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java index bd04cc7..b8a9274 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java @@ -18,14 +18,19 @@ public class SensorListener extends Service implements SensorEventListener { private final static int MICROSECONDS_IN_ONE_MINUTE = 60 * 1000 * 1000; + private final static String EXTRA_RESET_DATA = BuildConfig.APPLICATION_ID + ".ResetData"; /** - * Start service + * Start service, and write unsaved data to DB. */ static Intent createIntent(@NonNull Context context) { return new Intent(context, SensorListener.class); } + public static Intent createIntentForReset(Context context) { + return new Intent(context, SensorListener.class).putExtra(EXTRA_RESET_DATA, true); + } + @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // nobody knows what happens here: step value might magically decrease @@ -53,6 +58,15 @@ public IBinder onBind(Intent intent) { @Override public int onStartCommand(Intent intent, int flags, int startId) { Logger.log("################################## onStartCommand called ####################################"); + if (intent.getBooleanExtra(EXTRA_RESET_DATA, false)) { + Logger.log("Deleting all data and stopping service."); + unregisterSensor(); + StepCountCoordinator.getInstance().reset(); + Database.getInstance(this).deleteAll(); + stopSelf(); + return START_NOT_STICKY; + } + // restart service every minutes get the current step count ((AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE)) .set(AlarmManager.RTC, System.currentTimeMillis() + 60 * 1000, @@ -82,6 +96,10 @@ public void onTaskRemoved(Intent rootIntent) { public void onDestroy() { super.onDestroy(); Logger.log("SensorListener onDestroy"); + unregisterSensor(); + } + + private void unregisterSensor() { try { SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); sm.unregisterListener(this); diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index 36b36fd..04fa791 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -61,4 +61,10 @@ public synchronized int getTodaySteps(Context context) { } return Database.getInstance(context).getTodayStep() + unsavedSteps; } + + public synchronized void reset() { + dateAndHourOfLastEvent = null; + stepsOffset = 0; + unsavedSteps = 0; + } } diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java index cc4ccbc..0c01afb 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java @@ -34,7 +34,7 @@ public static int getTodaySteps(Context context) { } public static void clearAllData(Context context) { - Database.getInstance(context).deleteAll(); + context.startService(SensorListener.createIntentForReset(context)); } public static void increaseByChunkStepCounts(Context context, List chunkStepCounts) { From a3ff88f775061c3b08cd2c08081e1546146d67b8 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Mon, 12 Jun 2017 17:06:06 +0900 Subject: [PATCH 21/33] Skip DB access when unsavedSteps == 0 --- .../com/sukesan1984/stepsensorlib/StepCountCoordinator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index 04fa791..f0b406d 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -41,8 +41,9 @@ public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) public synchronized void saveSteps(Context context) { if (dateAndHourOfLastEvent == null) return; - Database database = Database.getInstance(context); Log.v(TAG, "saveSteps: " + unsavedSteps); + if (unsavedSteps == 0) return; + Database database = Database.getInstance(context); int newSteps = database.addSteps(dateAndHourOfLastEvent, unsavedSteps); if (newSteps < 0) { Log.e(TAG, "Failed to save steps."); From 9452dce96b05fbea818bb6eda7a7fca0e7c8741f Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Tue, 13 Jun 2017 19:52:50 +0900 Subject: [PATCH 22/33] Add limit for step count increment at once --- .../stepsensorlib/StepCountCoordinator.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index f0b406d..116a4ba 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -3,16 +3,18 @@ import android.content.Context; import android.support.annotation.Nullable; import android.util.Log; - import com.sukesan1984.stepsensorlib.util.DateUtils; class StepCountCoordinator { private static final String TAG = "StepCountCoordinator"; private static final StepCountCoordinator singleton = new StepCountCoordinator(); + // https://finc.slack.com/archives/C3552EVFV/p1497343956278850 + // https://finc.slack.com/archives/C2AFVMQ5V/p1495508346662505 + private static final long MAX_STEPS_PER_HOUR = 18000; @Nullable private Long dateAndHourOfLastEvent; - private int stepsOffset; + private int lastSteps; private int unsavedSteps = 0; public static StepCountCoordinator getInstance() { @@ -26,17 +28,27 @@ public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) long dateAndHour = DateUtils.getCurrentDateAndHour(); if (dateAndHourOfLastEvent == null) { dateAndHourOfLastEvent = dateAndHour; - stepsOffset = stepsSinceBoot; - Log.v(TAG, "onStepCounterEvent: stepsOffset is set to " + stepsOffset); + lastSteps = stepsSinceBoot; + Log.v(TAG, "onStepCounterEvent: lastSteps is set to " + lastSteps); return; } if (dateAndHour != dateAndHourOfLastEvent) { + Log.d(TAG, "Save by hour change."); saveSteps(context); } - unsavedSteps = stepsSinceBoot - stepsOffset; + + int increment = stepsSinceBoot - lastSteps; + if (increment > MAX_STEPS_PER_HOUR) { + Log.e(TAG, "onStepCounterEvent: Skipping steps " + increment + " exceeds limit of " + MAX_STEPS_PER_HOUR + "."); + lastSteps = stepsSinceBoot; + return; + } + + unsavedSteps += increment; Log.v(TAG, "onStepCounterEvent: " + unsavedSteps); dateAndHourOfLastEvent = dateAndHour; + lastSteps = stepsSinceBoot; } public synchronized void saveSteps(Context context) { @@ -48,7 +60,6 @@ public synchronized void saveSteps(Context context) { if (newSteps < 0) { Log.e(TAG, "Failed to save steps."); } else { - stepsOffset += unsavedSteps; unsavedSteps = 0; } database.close(); @@ -65,7 +76,7 @@ public synchronized int getTodaySteps(Context context) { public synchronized void reset() { dateAndHourOfLastEvent = null; - stepsOffset = 0; + lastSteps = 0; unsavedSteps = 0; } } From 7a0f914c85cb9b49df5fd34b53e8ab2208f4e099 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Tue, 13 Jun 2017 19:53:14 +0900 Subject: [PATCH 23/33] Remove remaining db close code --- .../com/sukesan1984/stepsensorlib/Database.java | 14 -------------- .../stepsensorlib/StepCountCoordinator.java | 1 - 2 files changed, 15 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index 297e2f3..f86f3cc 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -25,7 +25,6 @@ class Database extends SQLiteOpenHelper { private final static int DB_VERSION = 2; private static Database instance; - private static final AtomicInteger openCounter = new AtomicInteger(); private Database(final Context context) { super(context, TABLE_NAME, null, DB_VERSION); @@ -35,19 +34,9 @@ public static synchronized Database getInstance(final Context c) { if (instance == null) { instance = new Database(c.getApplicationContext()); } - - openCounter.incrementAndGet(); - return instance; } - @Override - public void close() { - if (openCounter.decrementAndGet() == 0) { - super.close(); - } - } - @Override public void onCreate(SQLiteDatabase db) { if (db == null) { @@ -206,9 +195,6 @@ public List getNotRecordedChunkStepCounts() { COLUMN_DATE_AND_HOUR + " != ? and " + COLUMN_IS_RECORDED_ON_SERVER + " = ?", new String[]{"-1", "0"}, null, null, null); Logger.log("Not recoreded Chunk Size: " + c.getCount()); - if (c == null) { - return new ArrayList<>(); - } // cursor close is in method return createChunkedStepCounts(c); } catch (Exception e) { diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index 116a4ba..23c26f3 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -62,7 +62,6 @@ public synchronized void saveSteps(Context context) { } else { unsavedSteps = 0; } - database.close(); } public synchronized int getTodaySteps(Context context) { From 0c788f2e7ab48491267e55f831d3d965923f2bdd Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Tue, 13 Jun 2017 19:53:44 +0900 Subject: [PATCH 24/33] Save in-memory steps before any db operation --- .../sukesan1984/stepsensorlib/StepSensorFacade.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java index 0c01afb..95fbd4d 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java @@ -25,10 +25,14 @@ public static boolean isValidStepSensorDevice(Context context) { && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_COUNTER); } - public static void startServiceAndSaveData(Context context) { + public static void startService(Context context) { context.startService(SensorListener.createIntent(context)); } + public static void saveNow(Context context) { + StepCountCoordinator.getInstance().saveSteps(context); + } + public static int getTodaySteps(Context context) { return StepCountCoordinator.getInstance().getTodaySteps(context); } @@ -38,20 +42,24 @@ public static void clearAllData(Context context) { } public static void increaseByChunkStepCounts(Context context, List chunkStepCounts) { + saveNow(context); Database.getInstance(context).increaseByChunkStepCounts(chunkStepCounts); } @NonNull public static List getChunkStepsSince(Context context, long dateAndHour) { + saveNow(context); return Database.getInstance(context).getChunkStepsSince(dateAndHour); } @NonNull public static List getNotRecordedChunkStepCounts(Context context) { + saveNow(context); return Database.getInstance(context).getNotRecordedChunkStepCounts(); } public static void markChunkStepCountsAsRecorded(Context context, List chunkStepCounts) { + saveNow(context); List dateAndHours = new ArrayList<>(chunkStepCounts.size()); for (ChunkStepCount chunkStepCount : chunkStepCounts) { dateAndHours.add(chunkStepCount.unixTimeMillis); From aa186cbc554f4675531128261b2548ab4ee0a316 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Tue, 13 Jun 2017 19:54:38 +0900 Subject: [PATCH 25/33] Shorten max report latency of step sensor --- .../sukesan1984/stepsensorlib/SensorListener.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java index b8a9274..a031c06 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java @@ -19,6 +19,7 @@ public class SensorListener extends Service implements SensorEventListener { private final static int MICROSECONDS_IN_ONE_MINUTE = 60 * 1000 * 1000; private final static String EXTRA_RESET_DATA = BuildConfig.APPLICATION_ID + ".ResetData"; + private static final int MAX_DELAY_MINUTES = 1; /** * Start service, and write unsaved data to DB. @@ -40,11 +41,6 @@ public void onAccuracyChanged(Sensor sensor, int accuracy) { @Override public void onSensorChanged(SensorEvent event) { - Logger.log("################################## onSensorChanged called ####################################"); - if (event.values[0] > Integer.MAX_VALUE) { - Logger.log("probably not a real value: " + event.values[0]); return; - } - int stepsSinceBoot = (int) event.values[0]; StepCountCoordinator.getInstance().onStepCounterEvent(this, stepsSinceBoot); } @@ -69,7 +65,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { // restart service every minutes get the current step count ((AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE)) - .set(AlarmManager.RTC, System.currentTimeMillis() + 60 * 1000, + .set(AlarmManager.RTC, System.currentTimeMillis() + MAX_DELAY_MINUTES * 60 * 1000, PendingIntent.getService(this, 2, createIntent(this), PendingIntent.FLAG_UPDATE_CURRENT)); StepCountCoordinator.getInstance().saveSteps(this); return START_STICKY; @@ -87,9 +83,10 @@ public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); Logger.log("sensor service task removed"); + // restart service ((AlarmManager) getSystemService(Context.ALARM_SERVICE)) .set(AlarmManager.RTC, System.currentTimeMillis() + 500, PendingIntent - .getService(this, 3, new Intent(this, SensorListener.class), 0)); + .getService(this, 3, createIntent(this), 0)); } @Override @@ -123,7 +120,7 @@ private void registerSensor() { // enable batching with delay of max 5min if (StepSensorFacade.isValidStepSensorDevice(this)) { sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_STEP_COUNTER), - SensorManager.SENSOR_DELAY_NORMAL, 5 * MICROSECONDS_IN_ONE_MINUTE); + SensorManager.SENSOR_DELAY_NORMAL, MAX_DELAY_MINUTES * MICROSECONDS_IN_ONE_MINUTE); } } } From fe7e8b6045cdaaf722d19135a0dd3b17ee298624 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Tue, 13 Jun 2017 20:03:33 +0900 Subject: [PATCH 26/33] Atomically mark as recorded to server on increasing step count --- .../sukesan1984/stepsensorlib/Database.java | 53 ++++--------------- .../stepsensorlib/StepSensorFacade.java | 13 +---- 2 files changed, 11 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/Database.java b/src/main/java/com/sukesan1984/stepsensorlib/Database.java index f86f3cc..fb2ef5f 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/Database.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/Database.java @@ -7,14 +7,11 @@ import android.database.sqlite.SQLiteOpenHelper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; - import com.sukesan1984.stepsensorlib.model.ChunkStepCount; import com.sukesan1984.stepsensorlib.util.DateUtils; import com.sukesan1984.stepsensorlib.util.Logger; - import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; class Database extends SQLiteOpenHelper { private final static String TABLE_NAME = "steps"; @@ -85,7 +82,7 @@ public int addSteps(long targetDateAndHour, int stepsToAdd) { db.beginTransaction(); int currentSteps = getStepsImpl(db, targetDateAndHour); int newSteps = currentSteps + stepsToAdd; - insertOrReplaceStepRow(db, targetDateAndHour, newSteps, true); + insertOrReplaceStepRow(db, targetDateAndHour, newSteps, false); db.setTransactionSuccessful(); return newSteps; } catch (Exception e) { @@ -98,13 +95,13 @@ public int addSteps(long targetDateAndHour, int stepsToAdd) { } } - private void insertOrReplaceStepRow(SQLiteDatabase db, long dateAndHour, int steps, boolean markNotRecorded) { + private void insertOrReplaceStepRow(SQLiteDatabase db, long dateAndHour, int steps, @Nullable Boolean markAsRecorded) { ContentValues values = new ContentValues(); values.put(COLUMN_DATE_AND_HOUR, dateAndHour); values.put(COLUMN_STEPS, steps); values.put(COLUMN_LAST_UPDATED, DateUtils.getCurrentTimeMllis()); - if (markNotRecorded) { - values.put(COLUMN_IS_RECORDED_ON_SERVER, 0); + if (markAsRecorded != null) { + values.put(COLUMN_IS_RECORDED_ON_SERVER, markAsRecorded ? 1 : 0); } db.replaceOrThrow(TABLE_NAME, null, values); } @@ -221,45 +218,13 @@ private List createChunkedStepCounts(Cursor c) { return lists; } - public void updateToRecorded(List dateAndHours) { - SQLiteDatabase db = null; - try { - ContentValues values = new ContentValues(); - values.put(COLUMN_IS_RECORDED_ON_SERVER, "1"); - int length = dateAndHours.size(); - String args = ""; - String[] dateAndHoursString = new String[length]; - for (int i = 0; i < length; i++) { - if (i == 0) { - args = "?"; - } else { - args += ", ?"; - } - dateAndHoursString[i] = String.valueOf(dateAndHours.get(i)); - } - - db = getWritableDatabase(); - db.beginTransaction(); - int rows = db.update(TABLE_NAME, values, String.format(COLUMN_DATE_AND_HOUR + " in (%s)", args), dateAndHoursString); - Logger.log("updated number: " + rows); - db.setTransactionSuccessful(); - Logger.log("update to Recorded: " + dateAndHoursString.toString()); - } catch (Exception e) { - e.printStackTrace(); - } finally { - if (db != null) { - db.endTransaction(); - } - } - } - - public void increaseByChunkStepCounts(List chunkStepCounts) { + public void increaseByServerChunkStepCounts(List chunkStepCounts) { SQLiteDatabase db = null; try { db = getWritableDatabase(); db.beginTransaction(); for (ChunkStepCount chunkStepCount : chunkStepCounts) { - increaseByChunkStepCount(db, chunkStepCount); + increaseBySeverChunkStepCount(db, chunkStepCount); } db.setTransactionSuccessful(); } finally { @@ -269,10 +234,10 @@ public void increaseByChunkStepCounts(List chunkStepCounts) { } } - private void increaseByChunkStepCount(SQLiteDatabase db, ChunkStepCount chunkStepCount) { + private void increaseBySeverChunkStepCount(SQLiteDatabase db, ChunkStepCount chunkStepCount) { int currentSteps = getStepsImpl(db, chunkStepCount.unixTimeMillis); - if (chunkStepCount.steps > currentSteps) { - insertOrReplaceStepRow(db, chunkStepCount.unixTimeMillis, chunkStepCount.steps, false); + if (chunkStepCount.steps >= currentSteps) { + insertOrReplaceStepRow(db, chunkStepCount.unixTimeMillis, chunkStepCount.steps, true); } } diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java index 95fbd4d..7e995ae 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepSensorFacade.java @@ -41,9 +41,9 @@ public static void clearAllData(Context context) { context.startService(SensorListener.createIntentForReset(context)); } - public static void increaseByChunkStepCounts(Context context, List chunkStepCounts) { + public static void increaseByServerChunkStepCounts(Context context, List chunkStepCounts) { saveNow(context); - Database.getInstance(context).increaseByChunkStepCounts(chunkStepCounts); + Database.getInstance(context).increaseByServerChunkStepCounts(chunkStepCounts); } @NonNull @@ -57,13 +57,4 @@ public static List getNotRecordedChunkStepCounts(Context context saveNow(context); return Database.getInstance(context).getNotRecordedChunkStepCounts(); } - - public static void markChunkStepCountsAsRecorded(Context context, List chunkStepCounts) { - saveNow(context); - List dateAndHours = new ArrayList<>(chunkStepCounts.size()); - for (ChunkStepCount chunkStepCount : chunkStepCounts) { - dateAndHours.add(chunkStepCount.unixTimeMillis); - } - Database.getInstance(context).updateToRecorded(dateAndHours); - } } From 8974b25d9c585f6ecdb1e064b5b998a7c65d9e77 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Tue, 13 Jun 2017 22:37:31 +0900 Subject: [PATCH 27/33] Fix NPE on service restart --- .../java/com/sukesan1984/stepsensorlib/SensorListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java index a031c06..0990e6f 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java @@ -52,9 +52,9 @@ public IBinder onBind(Intent intent) { } @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@Nullable Intent intent, int flags, int startId) { Logger.log("################################## onStartCommand called ####################################"); - if (intent.getBooleanExtra(EXTRA_RESET_DATA, false)) { + if (intent != null && intent.getBooleanExtra(EXTRA_RESET_DATA, false)) { Logger.log("Deleting all data and stopping service."); unregisterSensor(); StepCountCoordinator.getInstance().reset(); From cc04408c4a0883af2c2ee8c75cbaa8d74ee4f765 Mon Sep 17 00:00:00 2001 From: beylerian Date: Tue, 27 Jun 2017 16:28:49 +0900 Subject: [PATCH 28/33] fixed target SDK version temporarily to work with centralized versioning --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 69d746d..7b84b19 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ android { defaultConfig { minSdkVersion 15 - targetSdkVersion project.appTargetSdkVersion + targetSdkVersion 25 versionCode 1 versionName "1.0" From 5d97a09dd1e27953c44203c279a32a6ca296a86b Mon Sep 17 00:00:00 2001 From: beylerian Date: Tue, 27 Jun 2017 16:41:13 +0900 Subject: [PATCH 29/33] typo fix --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7b84b19..e5922c1 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ android { defaultConfig { minSdkVersion 15 - targetSdkVersion 25 + targetSdkVersion 23 versionCode 1 versionName "1.0" From 98494e3c4a3fa2e265bd0dd343eb08d0d95c6a73 Mon Sep 17 00:00:00 2001 From: neonankiti Date: Wed, 28 Jun 2017 10:59:09 +0900 Subject: [PATCH 30/33] fix lint error --- build.gradle | 6 +++--- .../java/com/sukesan1984/stepsensorlib/SensorListener.java | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index e5922c1..369f7f5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,8 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 24 - buildToolsVersion "25.0.0" + compileSdkVersion project.appCompileSdkVersion + buildToolsVersion project.appBuildToolVersion publishNonDefault true defaultConfig { @@ -31,7 +31,7 @@ dependencies { androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) - compile 'com.android.support:appcompat-v7:23.1.1' + compile "com.android.support:appcompat-v7:${project.supportLibVersion}" testCompile 'junit:junit:4.12' compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') { transitive = true; diff --git a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java index 0990e6f..29d1f50 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java @@ -1,5 +1,6 @@ package com.sukesan1984.stepsensorlib; +import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; @@ -108,6 +109,7 @@ private void unregisterSensor() { } } + @SuppressLint("NewApi") private void registerSensor() { Logger.log("register sensor listener"); SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); From 1fafe39247fb6a624e788ef4d18c6a7b71877035 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Thu, 6 Jul 2017 11:52:47 +0900 Subject: [PATCH 31/33] Use TargetApi instead of harmful SuppressLint --- .../java/com/sukesan1984/stepsensorlib/SensorListener.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java index 29d1f50..3e7cc12 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/SensorListener.java @@ -1,6 +1,6 @@ package com.sukesan1984.stepsensorlib; -import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; @@ -10,6 +10,7 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.os.Build; import android.os.IBinder; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -109,7 +110,7 @@ private void unregisterSensor() { } } - @SuppressLint("NewApi") + @TargetApi(Build.VERSION_CODES.KITKAT) private void registerSensor() { Logger.log("register sensor listener"); SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); From 029218839d36ab57a47d512e35fd11275789cd9f Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Thu, 6 Jul 2017 12:09:15 +0900 Subject: [PATCH 32/33] Fix crash with negative increment of step counts --- .../stepsensorlib/StepCountCoordinator.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index 23c26f3..e3acad3 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -25,6 +25,11 @@ private StepCountCoordinator() { } public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) { + if (stepsSinceBoot < 0) { + Log.e(TAG, "onStepCounterEvent: Oops... stepsSinceBoot is negative... This SHOULD NOT happen..."); + return; + } + long dateAndHour = DateUtils.getCurrentDateAndHour(); if (dateAndHourOfLastEvent == null) { dateAndHourOfLastEvent = dateAndHour; @@ -40,7 +45,17 @@ public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) int increment = stepsSinceBoot - lastSteps; if (increment > MAX_STEPS_PER_HOUR) { - Log.e(TAG, "onStepCounterEvent: Skipping steps " + increment + " exceeds limit of " + MAX_STEPS_PER_HOUR + "."); + Log.e(TAG, "onStepCounterEvent: Skipping steps, increment " + increment + " exceeds limit of " + MAX_STEPS_PER_HOUR + "."); + lastSteps = stepsSinceBoot; + return; + } + if (increment < 0) { + Log.e(TAG, "onStepCounterEvent: Discarding steps event, negative increment " + + increment + " happened! (stepsSinceBoot: " + stepsSinceBoot + ")"); + // XXX: Resetting can cause extra steps to be added if the problem is order of event is randomized. + // But it can be sudden decrease of internal counter of sensor, then no step recorded + // until restarting the app or counter reaches lastSteps value. Counting extra steps is + // far more better than no steps, so I choose to reset here! lastSteps = stepsSinceBoot; return; } From 3bef5dbc5f54a15c57d1590f3a4c6084665d38f6 Mon Sep 17 00:00:00 2001 From: Yuya Tanaka Date: Thu, 6 Jul 2017 13:50:24 +0900 Subject: [PATCH 33/33] Reduce verboseness of log --- .../com/sukesan1984/stepsensorlib/StepCountCoordinator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java index e3acad3..6e73916 100644 --- a/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java +++ b/src/main/java/com/sukesan1984/stepsensorlib/StepCountCoordinator.java @@ -26,7 +26,7 @@ private StepCountCoordinator() { public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) { if (stepsSinceBoot < 0) { - Log.e(TAG, "onStepCounterEvent: Oops... stepsSinceBoot is negative... This SHOULD NOT happen..."); + Log.d(TAG, "onStepCounterEvent: Oops... stepsSinceBoot is negative... This SHOULD NOT happen..."); return; } @@ -45,12 +45,12 @@ public synchronized void onStepCounterEvent(Context context, int stepsSinceBoot) int increment = stepsSinceBoot - lastSteps; if (increment > MAX_STEPS_PER_HOUR) { - Log.e(TAG, "onStepCounterEvent: Skipping steps, increment " + increment + " exceeds limit of " + MAX_STEPS_PER_HOUR + "."); + Log.d(TAG, "onStepCounterEvent: Skipping steps, increment " + increment + " exceeds limit of " + MAX_STEPS_PER_HOUR + "."); lastSteps = stepsSinceBoot; return; } if (increment < 0) { - Log.e(TAG, "onStepCounterEvent: Discarding steps event, negative increment " + Log.d(TAG, "onStepCounterEvent: Discarding steps event, negative increment " + increment + " happened! (stepsSinceBoot: " + stepsSinceBoot + ")"); // XXX: Resetting can cause extra steps to be added if the problem is order of event is randomized. // But it can be sudden decrease of internal counter of sensor, then no step recorded