Я бы предложил небольшую модификацию, которая, вероятно, позволит вам более эффективно использовать данные.
То есть вместо использования
db.execSQL("CREATE TABLE IF NOT EXISTS STEPS_TABLE(steps INTEGER);");
.........
db.execSQL("INSERT INTO STEPS_TABLE VALUES('"+tv_steps.getText()+"');");
используйте
db.execSQL("CREATE TABLE IF NOT EXISTS STEPS_TABLE(steps INTEGER, timestamp TEXT DEFAULT CURRENT_TIMESTAMP);");
.........
db.execSQL("INSERT INTO STEPS_TABLE (steps) VALUES('"+tv_steps.getText()+"');");
также меняется: -
Таким образом, вместо того, чтобы иметь такие данные, как: -
![enter image description here](https://i.stack.imgur.com/XqvpG.jpg)
Вы бы (безлюбая дополнительная работа, кроме двух изменений), получить такие данные, как: -
![enter image description here](https://i.stack.imgur.com/DL396.jpg)
- Обратите внимание, что вышеуказанные данные для обоих были сгенерированы случайным образом, но болеекороткий промежуток времени, поэтому даты и время совпадают.
Это, например, позволит вам очень легко извлекать, скажем, количество шагов в день.
В отношении передачи информацииВ другом упражнении нет необходимости, поскольку в основном таблицы содержат все, поэтому просто запросите таблицу в новом упражнении.
Рабочий пример
Следующий пример основан на вашем коде.Для моего удобства я добавил кнопку и метод для имитации смены датчика, который будет добавлять случайное количество шагов при нажатии кнопки.
Комментарии в коде, надеюсь, объяснят код.
TrackWalk **
public class TrackWalk extends AppCompatActivity implements SensorEventListener {
//<<<<<<<<<< Use single source (constants) for DB related names
public static final String DBNAME = "STEPSTAKEN";
public static final String TB_STEPSTAKEN = "stepstaken";
public static final String COL_STEPSTAKEN_STEPS = "steps";
public static final String COl_STEPSTAKEN_TIMESTAMP = "timestamp";
SensorManager sensorManager;
TextView tv_steps;
boolean running = false;
SQLiteDatabase db;
Button button, sensor; //<<<< Added another button to mimic sensor change
Random rnd; //<<<<< For creating random number of steps
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rnd = new Random();
//<<<<<<<<<< Note changes to use constants
db=openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE, null); //
db.execSQL(
"CREATE TABLE IF NOT EXISTS " +
TB_STEPSTAKEN +
"(" +
COL_STEPSTAKEN_STEPS + " INTEGER, " +
COl_STEPSTAKEN_TIMESTAMP + " TEXT DEFAULT CURRENT_TIMESTAMP" +
")"
);
tv_steps = (TextView) findViewById(R.id.steps);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//<<<<<<<<<< Added to mimic sensor change at button click
sensor = this.findViewById(R.id.sensor);
sensor.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
noSensor(); //<<<< Mimic sensor change
}
});
button = findViewById(R.id.trackWalk);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Reset counter and Populate Total Value in "Walk History"
Intent i = new Intent(getBaseContext(),WalkHistory.class); //<<<< ready to start activity
startActivity(i); // start the WalkHistory Activity
}
});
}
@Override
protected void onResume() {
super.onResume();
running=true;
Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if(countSensor != null) {
sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI);
}
else {
Toast.makeText(this, "Please enable Sensor!", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onPause() {
super.onPause();
running = false;
// Unregistering will stop steps
// sensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if(running) {
tv_steps.setText(String.valueOf(event.values[0]));
db.execSQL("INSERT INTO STEPS_TABLE VALUES('"+tv_steps.getText()+"');");
}
}
//<<<<<<<<<< MIMIC SENSOR for testing >>>>>>>>>>
public void noSensor() {
db.execSQL("INSERT INTO " + TB_STEPSTAKEN +
"(" + COL_STEPSTAKEN_STEPS + ")" +
"VALUES("+String.valueOf(rnd.nextInt(10000-1 + 1)+1) +");");
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
activity_walk_history.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".WalkHistory"
tools:showIn="@layout/activity_walk_history">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total Steps "
/>
<TextView
android:id="@+id/totalsteps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ListView
android:id="@+id/walkhistorylist"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
WalkHistory
public class WalkHistory extends AppCompatActivity {
Cursor mCsr;
SQLiteDatabase mDB;
SimpleCursorAdapter mSCA;
ListView mLV;
TextView mTotalSteps;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walk_history);
mLV = this.findViewById(R.id.walkhistorylist);
mTotalSteps = this.findViewById(R.id.totalsteps);
String total_steps_column_name = "total_steps";
// As Cursor Adpaters need _id column grab an alias of thr rowid as _id
String[] columns = new String[]{"rowid AS " + BaseColumns._ID + ",*"};
// Get the database
mDB = this.openOrCreateDatabase(TrackWalk.DBNAME, MODE_PRIVATE,null);
// Extract Data (all) into a Cursor)
mCsr = mDB.query(
TrackWalk.TB_STEPSTAKEN,
columns,
null,
null,
null,
null,
TrackWalk.COl_STEPSTAKEN_TIMESTAMP + " DESC"
);
// Setup the Adapter for the ListView
mSCA = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_2,mCsr,
new String[]{"timestamp","steps"},
new int[]{android.R.id.text1, android.R.id.text2},
0
);
// Tie the Adapter to the Listview
mLV.setAdapter(mSCA);
// Get the sum of the Steps (note would use the same WHERE clause as the ListView Cursor)
Cursor csr = mDB.query(
TrackWalk.TB_STEPSTAKEN,
new String[]{
"sum(steps) AS " + total_steps_column_name
},
null,
null,
null,
null,
null
);
// Apply the sum of the steps to the TextView
if (csr.moveToFirst()) {
mTotalSteps.setText(csr.getString(csr.getColumnIndex(total_steps_column_name)));
}
}
}
Результат
Ниже приведен пример результатанажмите кнопку, чтобы перейти к действию WalkHistory (после добавления некоторых данных).Записи перечислены.Списоку предшествует общее количество шагов.
![enter image description here](https://i.stack.imgur.com/sRELG.jpg)
Как видно, нет необходимости передавать какую-либо информацию из действия TrackWalk вУпражнение WalkHistory.
Дополнительные многократные прогулки / счетчик сброса (вроде)
Если вы хотите сохранить историческую запись, а кнопка «История» была кнопкой «Завершить прогулку».Тогда может быть достаточно следующего (по крайней мере, возможно, в качестве отправной точки).По сути, это работает с концепцией «Текущего обхода», запускает приложение, а «Текущий обход» предполагается и считается завершенным при нажатии кнопки «История», когда отображаются только эти шаги для этого обхода вместе с итогом для этого обхода.
При возврате (кнопка назад) предполагается новая прогулка и т. Д.
Используется вторая таблица для прогулок с 3 столбцами, идентификатором дата / время, когда дата начала / время, когда закончилось, НОВАЖНО не заполнено до конца.
К первой таблице добавлен еще один столбец, столбец прогулки, который является идентификатором соответствующей прогулки.
Когда приложение запускается или возобновляется (возврат из действия WalkHistory)если есть какие-либо прогулки (должно быть только 1), у которых нет даты / времени в столбце с прогулкой, то эта прогулка считается текущей прогулкой.В противном случае вставляется текущая строка ходьбы (с пустым столбцом).В обоих случаях переменная mCurrentWalk установлена на соответствующий id .
Каждая запись включает в себя владелец walkid.При нажатии кнопки «История» отправляется значение mCurrentlWalk через дополнительное намерение к действию WalkHistory.Действие WalkHistory получает это и соответственно устанавливает аналогичную именованную переменную и использует ее для выбора соответствующих строк, показанных в списке, а также при определении итога.new - это вызов, который обновляет строку прогулки с текущей датой и временем, таким образом, эффективно помечая строку (иначе прогулку) как завершенную.
Итак, вот измененная TrackWalk активность ": -
public class TrackWalk extends AppCompatActivity implements SensorEventListener {
//<<<<<<<<<< Use single source (constants) for DB related names
public static final String DBNAME = "STEPSTAKEN";
public static final String TB_STEPSTAKEN = "stepstaken";
public static final String COL_STEPSTAKEN_STEPS = "steps";
public static final String COl_STEPSTAKEN_TIMESTAMP = "timestamp";
public static final String COL_STEPSTAKEN_WALK = "walk";
public static final String TB_WALKS = "walks";
public static final String COL_WALKID = "walkid";
public static final String COL_WALKSTARTED = "walkstarted";
public static final String COL_WALKENDED = "walkended";
// used for passing data
public static final String INTENTEXTRA_WALKID = "ie_walkid";
SensorManager sensorManager;
TextView tv_steps;
boolean running = false;
SQLiteDatabase db;
Button button, sensor; //<<<< Added another button to mimic sensor change
Random rnd; //<<<<< For creating random number of steps
long mCurrentWalk;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rnd = new Random();
//<<<<<<<<<< Note changes to use constants
db=openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE, null); //
db.execSQL(
"CREATE TABLE IF NOT EXISTS " +
TB_STEPSTAKEN +
"(" +
COL_STEPSTAKEN_STEPS + " INTEGER, " +
COl_STEPSTAKEN_TIMESTAMP + " TEXT DEFAULT CURRENT_TIMESTAMP," +
COL_STEPSTAKEN_WALK + " INTEGER " + //<<<< ADDED FOR multiple walks
")"
);
// Create a Walks table
String crt_walks_table = "CREATE TABLE IF NOT EXISTS " +
TB_WALKS +
"(" +
COL_WALKID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COL_WALKSTARTED + " TEXT DEFAULT CURRENT_TIMESTAMP, " +
COL_WALKENDED + " TEXT DEFAULT ''" +
")";
db.execSQL(crt_walks_table);
tv_steps = (TextView) findViewById(R.id.steps);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//<<<<<<<<<< Added to mimic sensor change at button click
sensor = this.findViewById(R.id.sensor);
sensor.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
noSensor(); //<<<< Mimic sensor change
}
});
button = findViewById(R.id.trackWalk);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Reset counter and Populate Total Value in "Walk History"
Intent i = new Intent(getBaseContext(),WalkHistory.class); //<<<< ready to start activity
i.putExtra(INTENTEXTRA_WALKID,mCurrentWalk);
startActivity(i); // start the WalkHistory Activity
}
});
setCurrentWalk(); //<<<< Set the current walk (utilises last if not ended)
}
@Override
protected void onResume() {
super.onResume();
running=true;
Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if(countSensor != null) {
sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI);
}
else {
Toast.makeText(this, "Please enable Sensor!", Toast.LENGTH_SHORT).show();
}
setCurrentWalk();
}
@Override
protected void onPause() {
super.onPause();
running = false;
// Unregistering will stop steps
// sensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if(running) {
tv_steps.setText(String.valueOf(event.values[0]));
db.execSQL("INSERT INTO STEPS_TABLE VALUES('"+tv_steps.getText()+"');");
}
}
//<<<<<<<<<< MIMIC SENSOR for testing >>>>>>>>>>
public void noSensor() {
db.execSQL("INSERT INTO " + TB_STEPSTAKEN +
"(" +
COL_STEPSTAKEN_STEPS +
"," +
COL_STEPSTAKEN_WALK +
")" +
"VALUES(" +
String.valueOf(rnd.nextInt(10000-1 + 1)+1)
+
"," +
String.valueOf(mCurrentWalk) +
");");
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void setCurrentWalk() {
mCurrentWalk = -1;
String whereclause = "length(" + COL_WALKENDED + ") < 1"; // Only walks that haven't been ended
// Is there an unfished walk?? if so use that
Cursor csr = db.query(TB_WALKS,null,whereclause,null,null,null,COL_WALKID + " DESC");
if (csr.moveToFirst()) {
mCurrentWalk = csr.getLong(csr.getColumnIndex(COL_WALKID)); //<<<< use incomplete walk
}
csr.close();
// If there is no unfinished walk then create a new walk
if (mCurrentWalk < 1) {
String insrtsql = "INSERT INTO " + TB_WALKS +
" (" +
COL_WALKID +
") VALUES(null)";
db.execSQL(insrtsql);
mCurrentWalk = DatabaseUtils.longForQuery(db,"SELECT last_insert_rowid()",null);
}
}
}
И вот измененная WalkHistory Активность: -
public class WalkHistory extends AppCompatActivity {
Cursor mCsr;
SQLiteDatabase mDB;
SimpleCursorAdapter mSCA;
ListView mLV;
TextView mTotalSteps;
long mCurrentWalk;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walk_history);
// Get the current walk id
mCurrentWalk = this.getIntent().getLongExtra(TrackWalk.INTENTEXTRA_WALKID,-1);
mLV = this.findViewById(R.id.walkhistorylist);
mTotalSteps = this.findViewById(R.id.totalsteps);
String total_steps_column_name = "total_steps";
// As Cursor Adpaters need _id column grab an alias of thr rowid as _id
String[] columns = new String[]{"rowid AS " + BaseColumns._ID + ",*"};
// Get the database
mDB = this.openOrCreateDatabase(TrackWalk.DBNAME, MODE_PRIVATE,null);
// Set the current walk as ended
setCurrentWalkEnded();
String whereclause = TrackWalk.COL_STEPSTAKEN_WALK + "=?";
String[] whereargs = new String[]{String.valueOf(mCurrentWalk)};
// Extract Data for this walk
mCsr = mDB.query(
TrackWalk.TB_STEPSTAKEN,
columns,
whereclause,
whereargs,
null,
null,
TrackWalk.COl_STEPSTAKEN_TIMESTAMP + " DESC"
);
// Setup the Adapter for the ListView
mSCA = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_2,mCsr,
new String[]{"timestamp","steps"},
new int[]{android.R.id.text1, android.R.id.text2},
0
);
// Tie the Adapter to the Listview
mLV.setAdapter(mSCA);
// Get the sum of the Steps (note would use the same WHERE clause as the ListView Cursor)
Cursor csr = mDB.query(
TrackWalk.TB_STEPSTAKEN,
new String[]{
"sum(steps) AS " + total_steps_column_name
},
whereclause,
whereargs,
null,
null,
null
);
// Apply the sum of the steps to the TextView
if (csr.moveToFirst()) {
mTotalSteps.setText(csr.getString(csr.getColumnIndex(total_steps_column_name)));
}
}
/**
* Set the current walk as ended, but only if some records exist
*/
private void setCurrentWalkEnded() {
String whereclause1 = TrackWalk.COL_STEPSTAKEN_WALK + "=?";
String[] whereargs = new String[]{String.valueOf(mCurrentWalk)};
Cursor csr = mDB.query(TrackWalk.TB_STEPSTAKEN,null,whereclause1,whereargs,null,null,null);
String whereclause2 = TrackWalk.COL_WALKID + "=?";
if (csr.getCount() > 0 ) {
String updtsql = "UPDATE " + TrackWalk.TB_WALKS + " SET " + TrackWalk.COL_WALKENDED + " = datetime('now') WHERE " + whereclause2;
mDB.execSQL(updtsql, whereargs);
}
csr.close();
}
}
- Примечание это не было тщательно протестировано и является довольно элементарным.