Страница 1 из 1

Запись данных с сенсоров в базу данных.

Добавлено: 15 май 2013, 11:14
Mill666
Здравствуйте.
Разрабатываю приложение, которое будет сохранять данные с сенсоров (акселерометра, гироскопа и датчика магнитных полей) в базу данных.
Решил действовать по такой схеме:
В активити запускаю сервис, который снимает данные с сенсоров и отправляет их в активити в текстовые поля, и в контент провайдер, который сохраняет эти данные в базу.
Проблема заключается в том, что активити зависает при старте сервиса. При чем если в контент провайдер данные не отправлять, но все работает прекрасно.
Было, да собственно и остается, предположение что забивается главный поток, пытался использовать intentService, ситуация та же...

Подскажите, может быть мой подход в корне не верен?

MainActivity

Код: Выделить всё

public class MainActivity extends Activity {
	
	final String LOG_TAG = "myLogs";
	
	String timeValue,accelValue, gyroValue,compassValue;
	public final static String BROADCAST_ACTION = "ru.sibnia.develop.intentservice";
	TextView tv1,tv2,tv3,tv4;
	BroadcastReceiver br;
	public Intent intent;
	
	public final static String VAL1 = "val1";
	public final static String VAL2 = "val2";
	public final static String VAL3 = "val3";
	public final static String VAL4 = "val4";
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		tv1 = (TextView) findViewById (R.id.tv1);
		tv2 = (TextView) findViewById (R.id.tv2);
		tv3 = (TextView) findViewById (R.id.tv3);
		tv4 = (TextView) findViewById (R.id.tv4);
		
		br = new BroadcastReceiver(){

			@Override
			public void onReceive(Context context, Intent intent) {
				String accel = intent.getStringExtra(VAL1);
				tv1.setText(accel);
				String gyro = intent.getStringExtra(VAL2);
				tv2.setText(gyro);
				String compass = intent.getStringExtra(VAL3);
				tv3.setText(compass);
				String time = intent.getStringExtra(VAL4);
				tv4.setText(time);
			}
		};
		IntentFilter intFilt = new IntentFilter(BROADCAST_ACTION);
		registerReceiver(br, intFilt);
	}
    
    public void onClickStart(View v) {
    	startService(new Intent(this, IntService.class));
    }
    
    public void onClickStop(View v) {
      stopService(new Intent(this, IntService.class));
    }
}
Сервис

Код: Выделить всё

public class IntService extends IntentService implements SensorEventListener {
	final String LOG_TAG = "myLogs";
	SensorManager mgr;
	
	Intent intent;

	Calendar c;
	int mHour, mMinute, mSecond,mlSecond;
	String timeValue,accelValue, gyroValue,compassValue;
	
	private float[] accelData;          
    private float[] compassData;
    private float[] gyroData;
    
    final String DATA_TIME = "time";
	final String DATA_ACCEL = "accel";
	final String DATA_GYRO = "gyro";
	final String DATA_COMPASS = "compass";
    
    final Uri DATA_URI = Uri.parse("content://ru.sibnia.provider.IntProvider/data");
	

	public IntService() {
		super("intentService");
	}

	public void onCreate() {
		super.onCreate();
		Log.d(LOG_TAG, "onCreate");
		
		accelData = new float[3];
        compassData = new float[3];
        gyroData = new float[3];
        
		mgr = (SensorManager) this.getSystemService(SENSOR_SERVICE);
		mgr.registerListener(this, mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
		mgr.registerListener(this, mgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_UI);
		mgr.registerListener(this, mgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		
		// Чтоб сервис работал пока его не закроют в MainActivity
		
		for (int i=1; i>0;i++){	
		}
	}

	// копирование данных сенсоров в массивы
	private void loadSensorData (SensorEvent event){
		c = Calendar.getInstance();
		switch (event.sensor.getType()){
		case Sensor.TYPE_ACCELEROMETER:
			for (int i=0; i<3; i++)
				accelData[i] = event.values[i];
			break;
		case Sensor.TYPE_MAGNETIC_FIELD:
			for (int i=0; i<3; i++)
				compassData[i] = event.values[i];
			break;
		case Sensor.TYPE_GYROSCOPE:
			for (int i=0; i<3; i++)
				gyroData[i] = event.values[i];
			break;
		}
	}
	
	// перевод массивов данных с сенсоров в строку
	private String getValues(float[] sensorData){		
		String msg = String.format(
                "X: %8.4f Y: %8.4f Z: %8.4f\n",
                sensorData[0], sensorData[1], sensorData[2]);
		return msg;
	}
	
	//получение времени (идет в месте с данными в базу)
	private String updateDisplay() {
		mHour = c.get(Calendar.HOUR);
	    mMinute = c.get(Calendar.MINUTE);
	    mSecond = c.get(Calendar.SECOND);
	    mlSecond = c.get(Calendar.MILLISECOND);
		StringBuilder sb = 
	        new StringBuilder()
	                .append(pad(mHour)).append(":")
	                .append(pad(mMinute)).append(":")
	                .append(pad(mSecond)).append(":")
	                .append(pad(mlSecond));
		String time = sb.toString();
		return time;
	}
	private static String pad(int c) {
	    if (c >= 10)
	        return String.valueOf(c);
	    else
	        return "0" + String.valueOf(c);
	}
	
	
	//Отправка данных в активити и в провайдер
	public void writeData(String timeValue,String accelValue,String gyroValue,String compassValue ) {
		
		Intent intent = new Intent(MainActivity.BROADCAST_ACTION);
		intent.putExtra(MainActivity.VAL1, timeValue);
		intent.putExtra(MainActivity.VAL2, accelValue);
		intent.putExtra(MainActivity.VAL3, gyroValue);
		intent.putExtra(MainActivity.VAL4, compassValue);
		sendBroadcast(intent);
		
		
		// Проблемное место!!!
		/*
		ContentValues cv = new ContentValues();
		cv.put(DATA_TIME, timeValue);
		cv.put(DATA_ACCEL, accelValue);
		cv.put(DATA_GYRO, gyroValue);
		cv.put(DATA_COMPASS, compassValue);
		getContentResolver().insert(DATA_URI, cv);
		*/
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		Log.d(LOG_TAG, "onSensorChanged");
		loadSensorData (event);
		timeValue  = updateDisplay();
		accelValue = getValues(accelData);
		gyroValue = getValues(gyroData);
		compassValue = getValues(compassData);
		writeData(timeValue, accelValue, gyroValue, compassValue);

	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
	}
	
	public void onDestroy() {
		super.onDestroy();
		mgr.unregisterListener(this);
		Log.d(LOG_TAG, "onDestroy");
	}
}
провайдер

Код: Выделить всё

public class IntProvider extends ContentProvider {

	private class DBHelper extends SQLiteOpenHelper {

		public DBHelper(Context context) {
			super(context, DB_NAME, null, DB_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(DB_CREATE);
			Log.d(LOG_TAG, "База создана!");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		}

	}

	final String LOG_TAG = "myLogs";

	static final String DB_NAME = "mydb";
	static final int DB_VERSION = 1;
	static final String DATA_TABLE = "data";

	static final String DATA_ID = "_id";
	static final String DATA_TIME = "time";
	static final String DATA_ACCEL = "accel";
	static final String DATA_GYRO = "gyro";
	static final String DATA_COMPASS = "compass";

	static final String DB_CREATE = "create table " + DATA_TABLE + "(" + 
			DATA_ID + " integer primary key autoincrement, " + 
			DATA_TIME + " text, " + 
			DATA_ACCEL + " text, " + 
			DATA_GYRO + " text, " + 
			DATA_COMPASS + " text" + ");";

	static final String AUTHORITY = "ru.sibnia.provider.IntProvider";
	static final String DATA_PATH = "data";
	public static final Uri DATA_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + DATA_PATH);

	static final String DATA_CONTENT_TYPE = "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + DATA_PATH;

	// одна строка
	static final String DATA_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd." + AUTHORITY + "." + DATA_PATH;

	// // UriMatcher
	// общий Uri
	static final int URI_DATA = 1;

	// Uri с указанным ID
	static final int URI_DATA_ID = 2;

	// описание и создание UriMatcher
	private static final UriMatcher uriMatcher;
	static {
		uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		uriMatcher.addURI(AUTHORITY, DATA_PATH, URI_DATA);
		uriMatcher.addURI(AUTHORITY, DATA_PATH + "/#", URI_DATA_ID);
	}

	DBHelper dbHelper;
	SQLiteDatabase db;
	
	@Override
	public boolean onCreate() {
		dbHelper = new DBHelper(getContext());
		Log.d(LOG_TAG, "Провайдер открыт!");
		return true;
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		
		if (uriMatcher.match(uri) != URI_DATA)
			throw new IllegalArgumentException("Wrong URI: " + uri);

		db = dbHelper.getWritableDatabase();
		long rowID = db.insert(DATA_TABLE, null, values);
		Uri resultUri = ContentUris.withAppendedId(DATA_CONTENT_URI, rowID);
		// уведомляем ContentResolver, что данные по адресу resultUri изменились
		getContext().getContentResolver().notifyChange(resultUri, null);
		Log.d(LOG_TAG, "Вставлена запись №: "+rowID);
		return resultUri;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		switch (uriMatcher.match(uri)) {
		case URI_DATA:
			break;
		case URI_DATA_ID:
			String id = uri.getLastPathSegment();
			Log.d(LOG_TAG, "URI_CONTACTS_ID, " + id);
			if (TextUtils.isEmpty(selection)) {
				selection = DATA_ID + " = " + id;
			} else {
				selection = selection + " AND " + DATA_ID + " = " + id;
			}
			break;
		default:
			throw new IllegalArgumentException("Wrong URI: " + uri);
		}
		db = dbHelper.getWritableDatabase();
		int cnt = db.delete(DATA_TABLE, null, null);
		getContext().getContentResolver().notifyChange(uri, null);
		return cnt;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// проверяем Uri
		switch (uriMatcher.match(uri)) {
		case URI_DATA: 
			// если сортировка не указана, ставим свою - по имени
			if (TextUtils.isEmpty(sortOrder)) {
				sortOrder = DATA_TIME + " ASC";
			}
			break;
		case URI_DATA_ID: // Uri с ID
			String id = uri.getLastPathSegment();
			Log.d(LOG_TAG, "URI_DATA_ID, " + id);
			// добавляем ID к условию выборки
			if (TextUtils.isEmpty(selection)) {
				selection = DATA_ID + " = " + id;
			} else {
				selection = selection + " AND " + DATA_ID + " = " + id;
			}
			break;
		default:
			throw new IllegalArgumentException("Wrong URI: " + uri);
		}
		db = dbHelper.getWritableDatabase();
		Cursor cursor = db.query(DATA_TABLE, projection, selection,
				selectionArgs, null, null, sortOrder);
		// просим ContentResolver уведомлять этот курсор
		// об изменениях данных в CONTACT_CONTENT_URI
		cursor.setNotificationUri(getContext().getContentResolver(),
				DATA_CONTENT_URI);
		return cursor;

	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		Log.d(LOG_TAG, "update, " + uri.toString());
		switch (uriMatcher.match(uri)) {
		case URI_DATA:
			Log.d(LOG_TAG, "URI_CONTACTS");

			break;
		case URI_DATA_ID:
			String id = uri.getLastPathSegment();
			Log.d(LOG_TAG, "URI_CONTACTS_ID, " + id);
			if (TextUtils.isEmpty(selection)) {
				selection = DATA_ID + " = " + id;
			} else {
				selection = selection + " AND " + DATA_ID + " = " + id;
			}
			break;
		default:
			throw new IllegalArgumentException("Wrong URI: " + uri);
		}
		db = dbHelper.getWritableDatabase();
		int cnt = db.update(DATA_TABLE, values, selection, selectionArgs);
		getContext().getContentResolver().notifyChange(uri, null);
		return cnt;
	}

	@Override
	public String getType(Uri uri) {
		Log.d(LOG_TAG, "getType, " + uri.toString());
		switch (uriMatcher.match(uri)) {
		case URI_DATA:
			return DATA_CONTENT_TYPE;
		case URI_DATA_ID:
			return DATA_CONTENT_ITEM_TYPE;
		}
		return null;
	}
}
манифест

Код: Выделить всё

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ru.sibnia.develop.intentservice"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="ru.sibnia.develop.intentservice.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name="IntService" >
        </service>

        <provider
            android:name="IntProvider"
            android:authorities="ru.sibnia.provider.IntProvider" >
        </provider>
    </application>

</manifest>

Re: Запись данных с сенсоров в базу данных.

Добавлено: 20 май 2013, 07:51
Mill666
Задача решена при помощи обычного сервиса и выделения в нем записи в базу в отдельный поток.

Re: Запись данных с сенсоров в базу данных.

Добавлено: 06 июн 2013, 09:50
didima7777
А можно чуть более подробно, если можно пример кода?