Как обратиться к базе данных из сервиса?

SQLite, Preferences, файлы, SD, Content Provider, XML, JSON
Ответить
Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Как обратиться к базе данных из сервиса?

Сообщение powercat » 04 сен 2012, 16:25

Собственно вопрос...база есть, сервис работает. Как получить курсор из базы? Можно ли пример, а то без него непонятно, как DBOpenHelper использовать

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Как обратиться к базе данных из сервиса?

Сообщение rezak90 » 04 сен 2012, 16:29

просто описать метод в хелпере который возвращает курсор:

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

public Cursor getAllCursor() {
		SQLiteDatabase db = this.getReadableDatabase();
		return db.query(AppData.TABLE_NAME, null, null, null, null, null, null);
	}
ну и потом в самой активити:

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

Cursor cursor = db.getAllCursor();
R.id.team
Политика на форуме запрещена

Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Re: Как обратиться к базе данных из сервиса?

Сообщение powercat » 04 сен 2012, 17:04

Наверное я не умею объяснять ((((
База есть, создана из АКТИВИТИ. После этого приложение закрывается и стартует СЕРВИС. Он умеет обращаться к базе и получать курсор из нее, используя вот такой коТТ:

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

package com.example.baseservice;

public class MyService extends Service {

	SQLiteDatabase db;
	String pathToDB;
	
	public void onCreate(){
		super.onCreate();
	}
	
	public int onStartCommand(Intent intent,int flags,int startId){
		pathToDB=intent.getStringExtra("pathToDB");
		db=SQLiteDatabase.openOrCreateDatabase(pathToDB, null);
		Cursor cursor=db.query(GlobalData.DATABASETABLE_NAME, null, null, null, null, null, null);
		if (cursor.moveToFirst()){
			...................;
		}
		db.close();
		stopSelf();
		return super.onStartCommand(intent, flags, startId);
	}
	
	public void onDestroy(){
		super.onDestroy();
	}
	
	public IBinder onBind(Intent arg0) {
		return null;
	}
}
Все работает, ..............выполняется отлично.
Когда же я хочу вместо этого:

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

db=SQLiteDatabase.openOrCreateDatabase(pathToDB, null);
использовать SQLiteOpenHelper, используя следующий коТТ:

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

public class MyService extends Service {

	DBH dbHelper;
	SQLiteDatabase db;
	String pathToDB;
	
	public void onCreate(){
		super.onCreate();
	}
	
	public int onStartCommand(Intent intent,int flags,int startId){
		pathToDB=intent.getStringExtra("pathToDB");
		dbHelper=new DBH(this);
		dbHelper.getWritableDatabase();
		Cursor cursor=db.query(GlobalData.DATABASETABLE_NAME, null, null, null, null, null, null);
		if (cursor.moveToFirst()){
			....................................;
		}
		dbHelper.close();
		stopSelf();
		return super.onStartCommand(intent, flags, startId);
	}
	
	public void onDestroy(){
		super.onDestroy();
	}
	
	public IBinder onBind(Intent arg0) {
		return null;
	}
	
	public class DBH extends SQLiteOpenHelper {

		public DBH(Context context) {
			super(context, pathToDB, null, 1);
		}

		public void onCreate(SQLiteDatabase db) {
			try{
				db.execSQL(GlobalData.CREATE_TABLE);
			}catch (Exception e) {
				e.printStackTrace();
			}
		}

		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			
		}
	}
}
то приложение при пуске сервиса аварийно закрывается с вот такими логами:

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

08-31 01:05:57.495: D/myLogs(15447): onCreate
08-31 01:05:57.554: D/AndroidRuntime(15447): Shutting down VM
08-31 01:05:57.554: W/dalvikvm(15447): threadid=1: thread exiting with uncaught exception (group=0x40015560)
08-31 01:05:57.577: E/AndroidRuntime(15447): FATAL EXCEPTION: main
08-31 01:05:57.577: E/AndroidRuntime(15447): java.lang.RuntimeException: Unable to start service com.example.baseservice.MyService@40517b30 with Intent { act=com.qqq.findservice (has extras) }: java.lang.NullPointerException
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2052)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at android.app.ActivityThread.access$2800(ActivityThread.java:117)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:994)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at android.os.Handler.dispatchMessage(Handler.java:99)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at android.os.Looper.loop(Looper.java:123)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at android.app.ActivityThread.main(ActivityThread.java:3683)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at java.lang.reflect.Method.invokeNative(Native Method)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at java.lang.reflect.Method.invoke(Method.java:507)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at dalvik.system.NativeStart.main(Native Method)
08-31 01:05:57.577: E/AndroidRuntime(15447): Caused by: java.lang.NullPointerException
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at com.example.baseservice.MyService.onStartCommand(MyService.java:34)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2039)
08-31 01:05:57.577: E/AndroidRuntime(15447): 	... 10 more
В начале onCreate - это кусочек моего лога...т.е. сервис создается, но не стартует...Подозреваю, что косяк где-то в ОпенХелпере в контексте, но я пока до конца не въехал, что за зверь контекст, поэтому жду, когда укажете на ашипку )))

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Как обратиться к базе данных из сервиса?

Сообщение rezak90 » 04 сен 2012, 17:14

а просматривал ли ты, pathToDB передаётся или же там всё таки null?
R.id.team
Политика на форуме запрещена

Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Re: Как обратиться к базе данных из сервиса?

Сообщение powercat » 04 сен 2012, 19:20

Передается. В первом же случае, когда все работает - все передается...тут явно косяк с хелпером, но где...хрен знает...

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Как обратиться к базе данных из сервиса?

Сообщение rezak90 » 04 сен 2012, 19:34

кажется понял, было у меня такое из-за не внимательности... у тебя в сервисе объявлена переменная SQLiteDatabase db и в DBH ты используешь переменную db - это уже должна быть другая переменная, а у тебя получается что одна и та же. Переименуй какую то из них и будет праздник во дворе)))
R.id.team
Политика на форуме запрещена

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Как обратиться к базе данных из сервиса?

Сообщение AndreyI » 04 сен 2012, 19:39

А где хранится БД? Случайно не на внешнем носителе?

Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Re: Как обратиться к базе данных из сервиса?

Сообщение powercat » 04 сен 2012, 21:05

данкс, завтра попробую
да фиг знает, где хранится, кидаю в ту же папку, куда встает программа...но работа с картой разрешена в манифесте

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Как обратиться к базе данных из сервиса?

Сообщение AndreyI » 04 сен 2012, 21:33

При стандартной реализации хэлпера унаследованного от SQLiteOpenHelper нельзя использовать путь к файлу, используется только имя файла БД. База создается и открывается в специальной папке data/data/package_name/databases/ (ее не нужно нигде прописывать, система сама создает эту папку). Доступ к этой папке имеет только приложение её создавшее.
А вот openOrCreateDatabase позволяет в качестве имени файла задавать путь, тогда база будет создаваться в указанном месте, а если указать только имя файла, то база будет создаваться/открываться также в data/data/package_name/databases/.

В общем, если вы в переменной pathToDB передаете в конструктор хэлпера что-то вроде "/да_фиг_знает/DB_Name", то однозначно будет исключение.

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Как обратиться к базе данных из сервиса?

Сообщение rezak90 » 04 сен 2012, 21:43

правильно будет исключение, но думаю не NullPointerException, а что то вида "не могу найти бд по указанному пути", в общем как сказал тс завтра проверит =)
R.id.team
Политика на форуме запрещена

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Как обратиться к базе данных из сервиса?

Сообщение AndreyI » 04 сен 2012, 23:02

Еще непонятна строка 14
"dbHelper.getWritableDatabase();"

я так понимаю должно быть db=dbHelper.getWritableDatabase(); Вот здесь походу и выскакивает NullPointerException потому что следом вы пытаетесь получить курсор из несуществующей db

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Как обратиться к базе данных из сервиса?

Сообщение rezak90 » 04 сен 2012, 23:42

AndreyI кстати да всё верно. А я погорячился, так как поля объявлены как private и не могут быть видны в inner классе.
R.id.team
Политика на форуме запрещена

Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Re: Как обратиться к базе данных из сервиса?

Сообщение powercat » 05 сен 2012, 11:29

AndreyI - смотри...ты говоришь, что нельзя передать путь...но именно таким способом база и заполнятеся - я передаю из приложения составной путь Хелперу (он в отдельном файле) и все работает отлично - база заполняется, редактируется, записи удаляются. Правда этот хелпер относится к приложению, а не к сервису...Может твой случай только для сервисного хелпера подходит? Но при этом, если хелперу, который работает в сервисе, давать только имя базы - то как он узнает путь к ней?

А что с 14-й строкой? там нет кавычек

Резак - не...изменение имени не помогло ((

Я попробовал сделать базу по умолчанию, а в сервисном хелпере открыть ее...но как я понял, все траблы именно из-за этого...сервис не представляет, в каком приложении девайса искать эту базу...А когда через SQLiteDatabase.openOrCreateDatabase - действительно - полный путь к базе...Наверное, проблема в этом...
Вывод таков - в сервисе надо каким-то образом дать понять, к какой базе обращаться, если хочешь юзать хелпер.

Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Re: Как обратиться к базе данных из сервиса?

Сообщение powercat » 05 сен 2012, 14:11

и остается вопрос - если в сервисе юзать SQLiteDatabase.openOrCreateDatabase, то как быть с обновлениями базы? Я их еще не учился делать, но говорили, что это можно только с помощью хелпера делать...

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Как обратиться к базе данных из сервиса?

Сообщение rezak90 » 05 сен 2012, 14:27

так ты поменял 14 строку dbHelper.getWritableDatabase(); на db = dbHelper.getWritableDatabase(); - не работает и так?
R.id.team
Политика на форуме запрещена

Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Re: Как обратиться к базе данных из сервиса?

Сообщение powercat » 05 сен 2012, 16:24

Резак...данкс....это ппц я ТУПЛЮ...жесть...это не одна ошибка...я пытался еще в курсор вместо имени таблицы - путь к базе запихнуть ))))
Все заработало, всем данкс...

Вывод новый - AndreyI - можно передавать составной путь в хелпер, все нормально. У меня в обоих хелперах отработало на ура.

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Как обратиться к базе данных из сервиса?

Сообщение AndreyI » 05 сен 2012, 17:11

powercat писал(а): Вывод новый - AndreyI - можно передавать составной путь в хелпер, все нормально. У меня в обоих хелперах отработало на ура.
На скольких платформах Андроид и устройствах вы это тестировали?
Не стоит делать поспешных выводов, эта проблема давно известна, и регулярно поднимается в Инете, даже на данном форуме обсуждалась

Аватара пользователя
powercat
Сообщения: 508
Зарегистрирован: 20 июл 2012, 11:31

Re: Как обратиться к базе данных из сервиса?

Сообщение powercat » 05 сен 2012, 20:14

AndreyI писал(а):
powercat писал(а): Вывод новый - AndreyI - можно передавать составной путь в хелпер, все нормально. У меня в обоих хелперах отработало на ура.
На скольких платформах Андроид и устройствах вы это тестировали?
Не стоит делать поспешных выводов, эта проблема давно известна, и регулярно поднимается в Инете, даже на данном форуме обсуждалась
Под сколькими? Под ADV 233 ))))) еще не настала пора под реальные тестить ))) Но посмотрим, может полезет что-нить...вернее - наверняка полезет...

Ответить