我对android的世界很新。这是我想要完成的。所以我想为加速度计传感器做一个简单的校准会话,它只需收集加速度计数据并在3分钟内将它们插入数据库。 这是我的代码:
校准活动
package com.example.calibration;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.calibration.AccelsService.LocalBinder;
public class CalibrationActivity extends Activity{
private final String DEBUG_TAG = CalibrationActivity.class.getSimpleName();
private TextView mCountdownTv;
private Button mStartButton;
private final int countdownPeriod = 10; //3 Minutes
private AccelsService mService;
private boolean mBound;
private Intent mIntent;
private class myCountdown extends CountDownTimer{
public myCountdown(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
public void onTick(long millisUntilFinished) {
int minutes = (int) millisUntilFinished / (60*1000);
int seconds = (int) (millisUntilFinished - minutes*60*1000)/1000;
if (seconds >= 10){
mCountdownTv.setText(minutes+":" + seconds);
}
else{
mCountdownTv.setText(minutes+":0" + seconds);
}
}
public void onFinish() {
mCountdownTv.setText("Done!");
mCountdown = null;
Log.d(DEBUG_TAG,"Done Calibrating! With mBound = "+mBound);
if (mBound){
mService.setTransactionStatus(true);
unbindService(mConnection);
mBound = false;
}
mStartButton.setEnabled(true);
}
}
private CountDownTimer mCountdown;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder iservice) {
LocalBinder binder = (LocalBinder) iservice;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName className) {
mBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calibration);
mCountdownTv = (TextView) findViewById(R.id.countdown_timer);
mStartButton = (Button) findViewById(R.id.start_button);
}
@Override
protected void onStart(){
super.onStart();
mStartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mIntent = new Intent(CalibrationActivity.this, AccelsService.class);
bindService(mIntent,mConnection,Context.BIND_AUTO_CREATE);
//Start to countdown 3 minutes and stop the service
if (mCountdown==null){
mCountdown = new myCountdown(1000*countdownPeriod, 1000);
mCountdown.start();
}
//Disable the button after it's clicked
mStartButton.setEnabled(false);
}
});
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
Log.d(DEBUG_TAG,"ONSTOP! mBound is "+mBound);
if (mBound) {
mService.setTransactionStatus(false);
unbindService(mConnection);
mBound = false;
}
}
@Override
protected void onRestart(){
super.onRestart();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_calibration, menu);
return true;
}
}
AccelsService:
package com.example.calibration;
import android.app.Service;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class AccelsService extends Service implements SensorEventListener{
private final String DEBUG_TAG = AccelsService.class.getSimpleName();
private boolean mTransactionStatus = false;//Indicate if the service should commit the database changes
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder{
AccelsService getService() {
// Return this instance of AccelsService so clients can call public methods
return AccelsService.this;
}
};
private SensorManager mSensorManager;
private Sensor mSensor;
private AccelsDbHelper mDbHelper;
private SQLiteDatabase mDb;
@Override
public void onCreate(){
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(DEBUG_TAG, "onStartCommand!" );
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
startCalibration();
return mBinder;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onDestroy(){
super.onDestroy();
mSensorManager.unregisterListener(AccelsService.this);
Log.d(DEBUG_TAG, "AccelService got Destroyed!" );
mDbHelper.close();
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.d(DEBUG_TAG, "onSensorChanged" );
new AccelTask().execute(event);
}
private class AccelTask extends AsyncTask<SensorEvent,Void,Void> {
protected Void doInBackground(SensorEvent... events){
mDb.execSQL("INSERT INTO "+ AccelsDbHelper.ACCELS_TABLE_NAME +" VALUES ( "+ events[0].values[0]
+", "+ events[0].values[1] + ", " + events[0].values[2] + ", " + System.currentTimeMillis() + " );");
return null;
}
}
private void startCalibration(){
/*Register the Sensor Listener */
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = (Sensor) mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this,mSensor,SensorManager.SENSOR_DELAY_NORMAL);
Toast.makeText(this, "AccelService starting...", Toast.LENGTH_SHORT).show();
mDbHelper = new AccelsDbHelper(this);
mDb = mDbHelper.getWritableDatabase();
mDb.beginTransaction();
if (mTransactionStatus){
try{
mDb.setTransactionSuccessful();
}
finally{
mDb.endTransaction();
stopSelf();
}
}
}
public void setTransactionStatus(boolean isSuccessful){
mTransactionStatus = isSuccessful;
}
}
我省略了SQLiteOpenHelper类,因为它非常普通。因此,在单击按钮后,OnSensorChanged()事件将继续被调用,并且此阶段不会发生错误。尽管如此,我认为数据根本不会写入数据库,因为我无法在Eclipse上看到从DDMS视图生成的任何数据。然后,在代码完成后,我尝试再次单击该按钮。但现在我收到错误“(5)数据库被锁定”。我感到很困惑。有什么想法吗?
谢谢!
答案 0 :(得分:2)
这看起来很可疑:
mDb.beginTransaction();
if (mTransactionStatus){
try{
mDb.setTransactionSuccessful()
}
finally{
mDb.endTransaction();
stopSelf();
}
}
除非mTransactionStatus为true,否则看起来不会关闭事务。