1

私はアンドロイドの世界にとても慣れていません。これが私が達成しようとしていることです。そこで、加速度センサーの簡単なキャリブレーション セッションを作成したいと思います。これは、加速度センサーのデータを収集し、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)データベースがロックされています」というエラーが表示されます。私はとても混乱しています。何かご意見は?

ありがとうございました!

4

1 に答える 1

3

これは私には疑わしいようです:

mDb.beginTransaction();
if (mTransactionStatus){
    try{
        mDb.setTransactionSuccessful()
    }
    finally{
        mDb.endTransaction();
        stopSelf();
    }
}

mTransactionStatus が true でない限り、トランザクションを閉じたようには見えません。

于 2013-02-17T05:35:35.580 に答える