问题
I'm trying to use a Content Observer to update a Service when any changes happen to the sqlite database in my app.
I'm confused as to what to do, so I put together some code below. Usually, Content Observers are used with contacts or mediaplayer with a background service. In my research I read that it can be used with the sqlite database on the phone.
Questions:
1. Since Sqlite database does not have a uri, what info do I replace People.CONTENT_URI
in
this.getContentResolver().registerContentObserver (People.CONTENT_URI, true, contentObserver);
2. In my research I didn't find any code that would go into the database class that would alert the ContentObserver. Does all the code for the Content Observer work within the service class?
Note that this question is similar to Android SQLite DB notifications and how to listen for changes in Contact Database Both questions do not explicitly answer my question. If you have code that explains this, that would be very helpful.
Here is my semi-pusedo code below. It does not work. I'm using it to learn about how to update a service when the database info changes.
package com.example.com.test.content.observer;
import java.sql.Date;
import java.util.Calendar;
import java.util.List;
import com.google.android.gcm.demo.app.Alerts.AlarmsService;
import com.google.android.gcm.demo.app.Alerts.Alerts;
import com.google.android.gcm.demo.app.sqllite.DatabaseSqlite;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.provider.Contacts.People;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.database.ContentObserver;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import android.support.v4.app.NavUtils;
public class AlarmService extends Service
{
Handler mHandler = new Handler();
DatabaseSqlite db = new DatabaseSqlite(this);
List<Alerts> listAlerts;
PendingIntent pendingIntent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getApplicationContext()
.getContentResolver()
.registerContentObserver(?????, true,
contentObserver);
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TAG", "started onstart command Created from Alerts service .");
return super.onStartCommand(intent, flags, startId);// START_STICKY;
}
@Override
public void onStart(final Intent intent, int startId) {
super.onStart(intent, startId);
runThread();
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private class MyContentObserver extends ContentObserver {
@SuppressLint("ParserError")
public MyContentObserver(Handler mHandler) {
super(mHandler);
}
@Override
public void onChange(boolean selfChange) {
runThread();
super.onChange(selfChange);
}
public void runThread(){
Thread thread = new Thread() {
@Override
public void run() {
Boolean x = true;
while (x) {
db.open();
listAlerts = db.getAlarmsForService();
db.close();
int alerts=listAlerts.size();
for (int i = 0; i < alerts; i++) {
Alerts item = listAlerts.get(i);
item.getRowId();
item.getRemoteServerId();
String alertInMills = item.getAlertDateInMills();
String alertDuration = item.getAlertDurationInMinutes();
String eventName = item.getEventName();
long longAlertInMills = Long.parseLong(alertInMills);
pendingIntent = PendingIntent.getService(AlarmsService.this, 0,intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
// go to data base for time in mills
calendar.setTimeInMillis(longAlertInMills);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pendingIntent);
//
System.out.println(calendar.toString());
}
//
System.out.println("thread");
x = false;
}
}
};
thread.start();
}
}
MyContentObserver contentObserver = new MyContentObserver(mHandler);
this.getContentResolver().registerContentObserver (People.CONTENT_URI, true, contentObserver);
}
回答1:
In general, there are two parts to handling this: you have the ContentObserver which needs to register to receive changes, as you've pointed out, and the SQLiteDatabase which has to notify the registered observers of any changes. If this is a database you own, you can create the URI that you can use to listen for.
(1) First define your URI, typically in your Database definition file.
public static final Uri CONTENT_URI = Uri.parse("mycontent://packagename/something");
(2) for your database Content Provider:
Each db function (insert, update, delete) should call through to notifyChange()
after completing the operation in order to inform the observers that changes have happened.
rowId = db.insert(tableName, null, cv);
...
getContext().getContentResolver().notifyChange(newUri, null);
(3) Create and register your ContentObserver in the Service, as described in the same link you provided above (remember to override the deliverSelfNotifications()
to return true)
public class MyService extends Service {
private MyContentObserver mObserver;
@Override
public void onStartCommand(Intent intent, int flags, int startId) {
...
mObserver = new MyContentObserver();
getContentResolver().registerContentObserver(Dbfile.CONTENT_URI, null, mObserver);
}
@Override
public void onDestroy() {
...
if (mObserver != null) {
getContentResolver().unregisterContentObserver(mObserver);
mObserver = null;
}
}
// define MyContentObserver here
}
(4) In your ContentObserver.onChange()
, you can post something to the Service or handle the change right there if possible.
Also, if it helps your cause, you can customize the URI definition to handle different types of data that you are observing, register your observer for each URI, and then override ContentObserver.onChange(boolean, Uri) instead.
Hope this helps!
来源:https://stackoverflow.com/questions/11944378/sqlite-database-updates-triggers-service-to-update-via-content-observer