Я очень новичок в мире Android. Вот что я пытаюсь выполнить. Поэтому я хочу сделать простой сеанс калибровки для датчика акселерометра, который просто собирает данные акселерометра и вставляет их в базу данных в течение 3 минут. Вот мои коды:Android SQLite Транзакция с базой данных заблокирована
Калибровка Активность
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() продолжает вызываться, и на данном этапе ошибки не возникает. Тем не менее, я не думаю, что данные записываются в базу данных вообще, потому что я не вижу никаких данных, генерируемых в представлении DDMS на Eclipse. Затем, после завершения кода, я попытался снова нажать кнопку. Но теперь я получаю сообщение об ошибке "(5) база данных заблокирована". Я так растерялся. Есть предположения?
Спасибо!
Поскольку в вашем приложении есть async-задача, он попытается получить доступ к db, пока идет один процесс с db. Таким образом, это может привести к ошибке, например, блокировка db, поскольку она занята каким-то процессом. –