如何在特定时间调用 android 中的 SyncAdapter
How to call SyncAdapter in android on a particular time
每当我在我的应用程序中的 Sq-lite 数据库中插入任何联系人值时,我都想调用我的同步适配器
每当我在“设置”的“帐户和同步”部分手动执行时,它都可以正常工作,但我想在任何联系人添加到我的应用程序的 Sq lite 数据库时自动执行。
我也遵循此 link Android SyncAdapter Automatically Initialize Syncing 请求同步,但它在我的情况下不起作用。
这是我的同步适配器的代码:
package com.example.phonebook;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import com.example.phonebook.Database.DatabaseHelper;
import com.example.phonebook.Model.Contact;
import android.R.string;
import android.accounts.Account;
import android.accounts.OperationCanceledException;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContacts.Data;
import android.provider.ContactsContract.RawContacts.Entity;
import android.util.Log;
/**
* @author sam
*
*/
public class ContactsSyncAdapterService extends Service {
private static final String TAG = "ContactsSyncAdapterService";
private static SyncAdapterImpl sSyncAdapter = null;
private static ContentResolver mContentResolver = null;
private static String UsernameColumn = ContactsContract.RawContacts.SYNC1;
private static String PhotoTimestampColumn = ContactsContract.RawContacts.SYNC2;
static DatabaseHelper databaseHelper;
public ContactsSyncAdapterService() {
super();
databaseHelper=new DatabaseHelper(this);
}
public static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
private Context mContext;
public SyncAdapterImpl(Context context) {
super(context, true);
mContext = context;
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
try {
ContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
} catch (OperationCanceledException e) {
}
}
}
@Override
public IBinder onBind(Intent intent) {
IBinder ret = null;
ret = getSyncAdapter().getSyncAdapterBinder();
return ret;
}
public SyncAdapterImpl getSyncAdapter() {
if (sSyncAdapter == null)
sSyncAdapter = new SyncAdapterImpl(this);
return sSyncAdapter;
}
private static void addContact(Account account, String name, String username) {
Log.i(TAG, "Adding contact: " + name);
Log.v("name", name);
Log.v("phonenumber", username);
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
builder.withValue(RawContacts.ACCOUNT_NAME, account.name);
builder.withValue(RawContacts.ACCOUNT_TYPE, account.type);
builder.withValue(RawContacts.SYNC1, username);
operationList.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
//builder.withValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, username);
operationList.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.example.PhoneBook");
//builder.withValue(ContactsContract.Data.DATA1, username);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
builder.withValue(Phone.NUMBER, username);
operationList.add(builder.build());
try {
mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void updateContactStatus(ArrayList<ContentProviderOperation> operationList, long rawContactId, String status) {
Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
Cursor c = mContentResolver.query(entityUri, new String[] { RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1 }, null, null, null);
try {
while (c.moveToNext()) {
if (!c.isNull(1)) {
String mimeType = c.getString(2);
if (mimeType.equals("vnd.android.cursor.item/vnd.com.example.PhoneBook")) {
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.StatusUpdates.CONTENT_URI);
builder.withValue(ContactsContract.StatusUpdates.DATA_ID, c.getLong(1));
builder.withValue(ContactsContract.StatusUpdates.STATUS, status);
builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE, "com.example.PhoneBook");
builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name);
builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.ic_launcher);
builder.withValue(ContactsContract.StatusUpdates.STATUS_TIMESTAMP, System.currentTimeMillis());
operationList.add(builder.build());
//Only change the text of our custom entry to the status message pre-Honeycomb, as the newer contacts app shows
//statuses elsewhere
if(Integer.decode(Build.VERSION.SDK) < 11) {
builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
builder.withSelection(BaseColumns._ID + " = '" + c.getLong(1) + "'", null);
builder.withValue(ContactsContract.Data.DATA3, status);
operationList.add(builder.build());
}
}
}
}
} finally {
c.close();
}
}
private static void updateContactPhoto(ArrayList<ContentProviderOperation> operationList, long rawContactId, byte[] photo) {
ContentProviderOperation.Builder builder = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI);
builder.withSelection(ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'", null);
operationList.add(builder.build());
try {
if(photo != null) {
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValue(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID, rawContactId);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo);
operationList.add(builder.build());
builder = ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI);
builder.withSelection(ContactsContract.RawContacts.CONTACT_ID + " = '" + rawContactId + "'", null);
builder.withValue(PhotoTimestampColumn, String.valueOf(System.currentTimeMillis()));
operationList.add(builder.build());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static class SyncEntry {
public Long raw_id = 0L;
public Long photo_timestamp = null;
}
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
throws OperationCanceledException {
HashMap<String, SyncEntry> localContacts = new HashMap<String, SyncEntry>();
mContentResolver = context.getContentResolver();
Log.i(TAG, "performSync: " + account.toString());
// Load the local contacts
Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name).appendQueryParameter(
RawContacts.ACCOUNT_TYPE, account.type).build();
Cursor c1 = mContentResolver.query(rawContactUri, new String[] { BaseColumns._ID, UsernameColumn, PhotoTimestampColumn }, null, null, null);
while (c1.moveToNext()) {
SyncEntry entry = new SyncEntry();
entry.raw_id = c1.getLong(c1.getColumnIndex(BaseColumns._ID));
entry.photo_timestamp = c1.getLong(c1.getColumnIndex(PhotoTimestampColumn));
localContacts.put(c1.getString(1), entry);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
try {
// If we don't have any contacts, create one. Otherwise, set a
// status message
ArrayList<Contact> contacts=ContactsSyncAdapterService.databaseHelper.getAllContacts();
Log.v("size of contacts", ""+contacts.size());
for (int i = 0; i < contacts.size(); i++) {
String name=contacts.get(i).getName();
String phone=contacts.get(i).getPhone();
Log.v("contactName", name);
Log.v("phone", phone);
Log.v("image", ""+contacts.get(i).getImage());
Log.v("size of local contacts", ""+localContacts.size());
Log.v("size of local23 contacts", ""+localContacts.get(phone));
if (localContacts.get(phone) == null) {
addContact(account, name, phone);
} else {
System.out.println(localContacts.size());
Log.v("phonenumber",""+ localContacts.get(phone));
if (localContacts.get((phone)).photo_timestamp == null || System.currentTimeMillis() > (localContacts.get(phone).photo_timestamp + 604800000L)) {
//You would probably download an image file and just pass the bytes, but this sample doesn't use network so we'll decode and re-compress the icon resource to get the bytes
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap icon = BitmapFactory.decodeResource(context.getResources(), R.drawable.logo);
icon.compress(CompressFormat.PNG, 0, stream);
updateContactPhoto(operationList, localContacts.get(phone).raw_id, stream.toByteArray());
}
updateContactStatus(operationList, localContacts.get(phone).raw_id, "hunting wabbits");
}
}
if (operationList.size() > 0)
mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
ContactsSyncAdapterService.databaseHelper.closeDB();
} catch (Exception e1) {
// TODO Auto-generated catch block
//ContactsSyncAdapterService.databaseHelper.closeDB();;
e1.printStackTrace();
}
}
}</p>
请帮我短路this.If任何人都可以
如果您想避免服务不断检查您的数据库中的新记录,您可以使用广播消息来告知某些内容已更改。即在您的数据库中存储信息的函数中,您可以发送消息。
sendBroadcast(new Intent(Utils.REFRESH_DATA_INTENT));
最后,在您的 class 中,您会在内部 class 中收到消息。
private class DataUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Utils.REFRESH_DATA_INTENT)) {
//Do whatever you need!!
}
}
}
每当我在我的应用程序中的 Sq-lite 数据库中插入任何联系人值时,我都想调用我的同步适配器
每当我在“设置”的“帐户和同步”部分手动执行时,它都可以正常工作,但我想在任何联系人添加到我的应用程序的 Sq lite 数据库时自动执行。 我也遵循此 link Android SyncAdapter Automatically Initialize Syncing 请求同步,但它在我的情况下不起作用。 这是我的同步适配器的代码:package com.example.phonebook;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import com.example.phonebook.Database.DatabaseHelper;
import com.example.phonebook.Model.Contact;
import android.R.string;
import android.accounts.Account;
import android.accounts.OperationCanceledException;
import android.app.Service;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContacts.Data;
import android.provider.ContactsContract.RawContacts.Entity;
import android.util.Log;
/**
* @author sam
*
*/
public class ContactsSyncAdapterService extends Service {
private static final String TAG = "ContactsSyncAdapterService";
private static SyncAdapterImpl sSyncAdapter = null;
private static ContentResolver mContentResolver = null;
private static String UsernameColumn = ContactsContract.RawContacts.SYNC1;
private static String PhotoTimestampColumn = ContactsContract.RawContacts.SYNC2;
static DatabaseHelper databaseHelper;
public ContactsSyncAdapterService() {
super();
databaseHelper=new DatabaseHelper(this);
}
public static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
private Context mContext;
public SyncAdapterImpl(Context context) {
super(context, true);
mContext = context;
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
try {
ContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
} catch (OperationCanceledException e) {
}
}
}
@Override
public IBinder onBind(Intent intent) {
IBinder ret = null;
ret = getSyncAdapter().getSyncAdapterBinder();
return ret;
}
public SyncAdapterImpl getSyncAdapter() {
if (sSyncAdapter == null)
sSyncAdapter = new SyncAdapterImpl(this);
return sSyncAdapter;
}
private static void addContact(Account account, String name, String username) {
Log.i(TAG, "Adding contact: " + name);
Log.v("name", name);
Log.v("phonenumber", username);
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
builder.withValue(RawContacts.ACCOUNT_NAME, account.name);
builder.withValue(RawContacts.ACCOUNT_TYPE, account.type);
builder.withValue(RawContacts.SYNC1, username);
operationList.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
//builder.withValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, username);
operationList.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.example.PhoneBook");
//builder.withValue(ContactsContract.Data.DATA1, username);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
builder.withValue(Phone.NUMBER, username);
operationList.add(builder.build());
try {
mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void updateContactStatus(ArrayList<ContentProviderOperation> operationList, long rawContactId, String status) {
Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
Cursor c = mContentResolver.query(entityUri, new String[] { RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1 }, null, null, null);
try {
while (c.moveToNext()) {
if (!c.isNull(1)) {
String mimeType = c.getString(2);
if (mimeType.equals("vnd.android.cursor.item/vnd.com.example.PhoneBook")) {
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.StatusUpdates.CONTENT_URI);
builder.withValue(ContactsContract.StatusUpdates.DATA_ID, c.getLong(1));
builder.withValue(ContactsContract.StatusUpdates.STATUS, status);
builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE, "com.example.PhoneBook");
builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name);
builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.ic_launcher);
builder.withValue(ContactsContract.StatusUpdates.STATUS_TIMESTAMP, System.currentTimeMillis());
operationList.add(builder.build());
//Only change the text of our custom entry to the status message pre-Honeycomb, as the newer contacts app shows
//statuses elsewhere
if(Integer.decode(Build.VERSION.SDK) < 11) {
builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
builder.withSelection(BaseColumns._ID + " = '" + c.getLong(1) + "'", null);
builder.withValue(ContactsContract.Data.DATA3, status);
operationList.add(builder.build());
}
}
}
}
} finally {
c.close();
}
}
private static void updateContactPhoto(ArrayList<ContentProviderOperation> operationList, long rawContactId, byte[] photo) {
ContentProviderOperation.Builder builder = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI);
builder.withSelection(ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'", null);
operationList.add(builder.build());
try {
if(photo != null) {
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValue(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID, rawContactId);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo);
operationList.add(builder.build());
builder = ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI);
builder.withSelection(ContactsContract.RawContacts.CONTACT_ID + " = '" + rawContactId + "'", null);
builder.withValue(PhotoTimestampColumn, String.valueOf(System.currentTimeMillis()));
operationList.add(builder.build());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static class SyncEntry {
public Long raw_id = 0L;
public Long photo_timestamp = null;
}
private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
throws OperationCanceledException {
HashMap<String, SyncEntry> localContacts = new HashMap<String, SyncEntry>();
mContentResolver = context.getContentResolver();
Log.i(TAG, "performSync: " + account.toString());
// Load the local contacts
Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name).appendQueryParameter(
RawContacts.ACCOUNT_TYPE, account.type).build();
Cursor c1 = mContentResolver.query(rawContactUri, new String[] { BaseColumns._ID, UsernameColumn, PhotoTimestampColumn }, null, null, null);
while (c1.moveToNext()) {
SyncEntry entry = new SyncEntry();
entry.raw_id = c1.getLong(c1.getColumnIndex(BaseColumns._ID));
entry.photo_timestamp = c1.getLong(c1.getColumnIndex(PhotoTimestampColumn));
localContacts.put(c1.getString(1), entry);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
try {
// If we don't have any contacts, create one. Otherwise, set a
// status message
ArrayList<Contact> contacts=ContactsSyncAdapterService.databaseHelper.getAllContacts();
Log.v("size of contacts", ""+contacts.size());
for (int i = 0; i < contacts.size(); i++) {
String name=contacts.get(i).getName();
String phone=contacts.get(i).getPhone();
Log.v("contactName", name);
Log.v("phone", phone);
Log.v("image", ""+contacts.get(i).getImage());
Log.v("size of local contacts", ""+localContacts.size());
Log.v("size of local23 contacts", ""+localContacts.get(phone));
if (localContacts.get(phone) == null) {
addContact(account, name, phone);
} else {
System.out.println(localContacts.size());
Log.v("phonenumber",""+ localContacts.get(phone));
if (localContacts.get((phone)).photo_timestamp == null || System.currentTimeMillis() > (localContacts.get(phone).photo_timestamp + 604800000L)) {
//You would probably download an image file and just pass the bytes, but this sample doesn't use network so we'll decode and re-compress the icon resource to get the bytes
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap icon = BitmapFactory.decodeResource(context.getResources(), R.drawable.logo);
icon.compress(CompressFormat.PNG, 0, stream);
updateContactPhoto(operationList, localContacts.get(phone).raw_id, stream.toByteArray());
}
updateContactStatus(operationList, localContacts.get(phone).raw_id, "hunting wabbits");
}
}
if (operationList.size() > 0)
mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
ContactsSyncAdapterService.databaseHelper.closeDB();
} catch (Exception e1) {
// TODO Auto-generated catch block
//ContactsSyncAdapterService.databaseHelper.closeDB();;
e1.printStackTrace();
}
}
}</p>
请帮我短路this.If任何人都可以
如果您想避免服务不断检查您的数据库中的新记录,您可以使用广播消息来告知某些内容已更改。即在您的数据库中存储信息的函数中,您可以发送消息。
sendBroadcast(new Intent(Utils.REFRESH_DATA_INTENT));
最后,在您的 class 中,您会在内部 class 中收到消息。
private class DataUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Utils.REFRESH_DATA_INTENT)) {
//Do whatever you need!!
}
}
}