firewings 发表于 2013-2-1 12:12:52

【原创】ContentProvider 示例

package com.firewings.smstools;    import java.util.HashMap;import java.util.LinkedHashMap;import java.util.List;    import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.Context;import android.content.UriMatcher;import android.content.pm.PackageManager;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteQueryBuilder;import android.database.sqlite.SQLiteTransactionListener;import android.net.Uri;import android.os.Binder;import android.provider.BaseColumns;import android.provider.ContactsContract;import android.provider.SyncStateContract;import android.provider.ContactsContract.Data;import android.provider.ContactsContract.Groups;import android.provider.ContactsContract.RawContacts;import android.util.Log;    public class SmsProvider extends ContentProvider implements SQLiteTransactionListener {      private static final String TAG = "SmsProvider";      private static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE);      private DbHelper mDbHelper;      private SQLiteDatabase mDb;      private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);      private static final int SMS = 1000;      private static final int SMS_ID = 1001;      public static final String SMS_ITEM_TYPE = "vnd.android.cursor.item/sms";      public static final String AUTHORITY = "com.firewings.smstools";      public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);      public static final HashMap<string, string=""> sCountProjectionMap;      public static final HashMap<string, string=""> smsProjectionMap;      static {            final UriMatcher matcher = sUriMatcher;          matcher.addURI(AUTHORITY, "sms", SMS);          matcher.addURI(AUTHORITY, "sms/#", SMS_ID);            sCountProjectionMap = new LinkedHashMap<string, string="">();          sCountProjectionMap.put(BaseColumns._COUNT, "COUNT(*)");            smsProjectionMap = new LinkedHashMap<string, string="">();          smsProjectionMap.put(DbHelper.SmsColumns._ID, DbHelper.SmsColumns._ID);          smsProjectionMap.put(DbHelper.SmsColumns.ADDRESS, DbHelper.SmsColumns.ADDRESS);          smsProjectionMap.put(DbHelper.SmsColumns.PERSON, DbHelper.SmsColumns.PERSON);          smsProjectionMap.put(DbHelper.SmsColumns.DATE, DbHelper.SmsColumns.DATE);          smsProjectionMap.put(DbHelper.SmsColumns.TYPE, DbHelper.SmsColumns.TYPE);          smsProjectionMap.put(DbHelper.SmsColumns.BODY, DbHelper.SmsColumns.BODY);          smsProjectionMap.put(DbHelper.SmsColumns.SEND, DbHelper.SmsColumns.SEND);      }      private final ThreadLocal<boolean> mApplyingBatch = new ThreadLocal<boolean>();      private volatile boolean mNotifyChange;      @Override      public int delete(Uri uri, String selection, String[] selectionArgs) {          int count = 0;          boolean applyingBatch = applyingBatch();          if (!applyingBatch) {            mDb = mDbHelper.getWritableDatabase();            mDb.beginTransactionWithListener(this);            try {                  count = deleteInTransaction(uri, selection, selectionArgs);                  if (count > 0) {                      mNotifyChange = true;                  }                  mDb.setTransactionSuccessful();            } finally {                  mDb.endTransaction();            }                onEndTransaction();          } else {            count = deleteInTransaction(uri, selection, selectionArgs);            if (count > 0) {                  mNotifyChange = true;            }          }          return count;      }      protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) {          if (VERBOSE_LOGGING) {            Log.v(TAG, "updateInTransaction: " + uri);          }            int count = 0;            final int match = sUriMatcher.match(uri);            switch (match) {            case SMS: {            count = mDb.delete(DbHelper.Tables.SMS, selection, selectionArgs);            break;          }            case SMS_ID: {            long smsId = ContentUris.parseId(uri);            if (selection != null) {                  selectionArgs = selectionArg(selectionArgs, String.valueOf(smsId));                  count = mDb.delete(DbHelper.Tables.SMS, RawContacts._ID + "=?" + " AND (" + selection + ")", selectionArgs);            } else {                  count = mDb.delete(DbHelper.Tables.SMS, RawContacts._ID + "=?", new String[] { String.valueOf(smsId) });            }            break;          }            default: {            throw new UnsupportedOperationException(exceptionMessage(uri));          }          }            return count;      }      @Override      public String getType(Uri uri) {          final int match = sUriMatcher.match(uri);          switch (match) {          case SMS:            return SMS_ITEM_TYPE;            default:            throw new IllegalArgumentException(exceptionMessage(uri));          }      }      /**      * Returns a detailed exception message for the supplied URI. It includes      * the calling user and calling package(s).      */      public String exceptionMessage(Uri uri) {          return exceptionMessage(null, uri);      }      /**      * Returns a detailed exception message for the supplied URI. It includes      * the calling user and calling package(s).      */      public String exceptionMessage(String message, Uri uri) {          StringBuilder sb = new StringBuilder();          if (message != null) {            sb.append(message).append("; ");          }          sb.append("URI: ").append(uri);          final PackageManager pm = getContext().getPackageManager();          int callingUid = Binder.getCallingUid();          sb.append(", calling user: ");          String userName = pm.getNameForUid(callingUid);          if (userName != null) {            sb.append(userName);          } else {            sb.append(callingUid);          }            final String[] callerPackages = pm.getPackagesForUid(callingUid);          if (callerPackages != null && callerPackages.length > 0) {            if (callerPackages.length == 1) {                  sb.append(", calling package:");                  sb.append(callerPackages);            } else {                  sb.append(", calling package is one of: [");                  for (int i = 0; i < callerPackages.length; i++) {                      if (i != 0) {                        sb.append(", ");                      }                      sb.append(callerPackages);                  }                  sb.append("]");            }          }            return sb.toString();      }      private boolean applyingBatch() {          return mApplyingBatch.get() != null && mApplyingBatch.get();      }      @Override      public Uri insert(Uri uri, ContentValues values) {          Uri result = null;          boolean applyingBatch = applyingBatch();          if (!applyingBatch) {            mDb = mDbHelper.getWritableDatabase();            mDb.beginTransactionWithListener(this);            try {                  result = insertInTransaction(uri, values);                  if (result != null) {                      mNotifyChange = true;                  }                  mDb.setTransactionSuccessful();            } finally {                  mDb.endTransaction();            }                onEndTransaction();          } else {            result = insertInTransaction(uri, values);            if (result != null) {                  mNotifyChange = true;            }          }          return result;      }      protected Uri insertInTransaction(Uri uri, ContentValues values) {          if (VERBOSE_LOGGING) {            Log.v(TAG, "insertInTransaction: " + uri + " " + values);          }            final int match = sUriMatcher.match(uri);          long id = 0;            switch (match) {            case SMS: {            values.putNull(DbHelper.SmsColumns._ID);            id = mDb.insert(DbHelper.Tables.SMS, DbHelper.SmsColumns._ID, values);            break;          }            default: {            throw new UnsupportedOperationException(exceptionMessage(uri));          }          }            if (id < 0) {            return null;          }            return ContentUris.withAppendedId(uri, id);      }      @Override      public boolean onCreate() {          try {            return initialize();          } catch (RuntimeException e) {            Log.e(TAG, "Cannot start provider", e);            return false;          }      }      @Override      public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {            if (VERBOSE_LOGGING) {            Log.v(TAG, "query: " + uri);          }            final SQLiteDatabase db = mDbHelper.getReadableDatabase();            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();          String groupBy = null;          String limit = getLimit(uri);            final int match = sUriMatcher.match(uri);            switch (match) {          case SMS: {            setTablesAndProjectionMapForSms(qb, uri);            break;          }          }            return query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy, limit);      }      private Cursor query(final SQLiteDatabase db, SQLiteQueryBuilder qb, String[] projection, String selection, String[] selectionArgs, String sortOrder, String groupBy, String limit) {          if (projection != null && projection.length == 1 && BaseColumns._COUNT.equals(projection)) {            qb.setProjectionMap(sCountProjectionMap);          }          final Cursor c = qb.query(db, projection, selection, selectionArgs, groupBy, null, sortOrder, limit);          if (c != null) {            c.setNotificationUri(getContext().getContentResolver(), AUTHORITY_URI);          }          return c;      }      private void setTablesAndProjectionMapForSms(SQLiteQueryBuilder qb, Uri uri) {          StringBuilder sb = new StringBuilder();          sb.append(DbHelper.Tables.SMS);          qb.setTables(sb.toString());          qb.setProjectionMap(smsProjectionMap);      }      @Override      public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {          int count = 0;          boolean applyingBatch = applyingBatch();          if (!applyingBatch) {            mDb = mDbHelper.getWritableDatabase();            mDb.beginTransactionWithListener(this);            try {                  count = updateInTransaction(uri, values, selection, selectionArgs);                  if (count > 0) {                      mNotifyChange = true;                  }                  mDb.setTransactionSuccessful();            } finally {                  mDb.endTransaction();            }                onEndTransaction();          } else {            count = updateInTransaction(uri, values, selection, selectionArgs);            if (count > 0) {                  mNotifyChange = true;            }          }            return count;      }      protected int updateInTransaction(Uri uri, ContentValues values, String selection, String[] selectionArgs) {          if (VERBOSE_LOGGING) {            Log.v(TAG, "updateInTransaction: " + uri);          }            int count = 0;            final int match = sUriMatcher.match(uri);            switch (match) {            case SMS: {            count = mDb.update(DbHelper.Tables.SMS, values, selection, selectionArgs);            break;          }            case SMS_ID: {            long smsId = ContentUris.parseId(uri);            if (selection != null) {                  selectionArgs = selectionArg(selectionArgs, String.valueOf(smsId));                  count = mDb.update(DbHelper.Tables.SMS, values, RawContacts._ID + "=?" + " AND (" + selection + ")", selectionArgs);            } else {                  count = mDb.update(DbHelper.Tables.SMS, values, RawContacts._ID + "=?", new String[] { String.valueOf(smsId) });            }            break;          }            default: {            throw new UnsupportedOperationException(exceptionMessage(uri));          }          }            return count;      }      /**      * Inserts an argument at the beginning of the selection arg list.      */      private String[] selectionArg(String[] selectionArgs, String arg) {          if (selectionArgs == null) {            return new String[] { arg };          } else {            int newLength = selectionArgs.length + 1;            String[] newSelectionArgs = new String;            newSelectionArgs = arg;            System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length);            return newSelectionArgs;          }      }      private boolean initialize() {          final Context context = getContext();          mDbHelper = (DbHelper) DbHelper.getInstance(context);          return true;      }      private String getLimit(Uri uri) {          String limitParam = getQueryParameter(uri, "limit");          if (limitParam == null) {            return null;          }          // make sure that the limit is a non-negative integer          try {            int l = Integer.parseInt(limitParam);            if (l < 0) {                  Log.w(TAG, "Invalid limit parameter: " + limitParam);                  return null;            }            return String.valueOf(l);          } catch (NumberFormatException ex) {            Log.w(TAG, "Invalid limit parameter: " + limitParam);            return null;          }      }      /* package */static String getQueryParameter(Uri uri, String parameter) {          String query = uri.getEncodedQuery();          if (query == null) {            return null;          }            int queryLength = query.length();          int parameterLength = parameter.length();            String value;          int index = 0;          while (true) {            index = query.indexOf(parameter, index);            if (index == -1) {                  return null;            }                index += parameterLength;                if (queryLength == index) {                  return null;            }                if (query.charAt(index) == '=') {                  index++;                  break;            }          }            int ampIndex = query.indexOf('&', index);          if (ampIndex == -1) {            value = query.substring(index);          } else {            value = query.substring(index, ampIndex);          }            return Uri.decode(value);      }      public void onBegin() {          // TODO Auto-generated method stub      }      public void onCommit() {          // TODO Auto-generated method stub      }      public void onRollback() {          // TODO Auto-generated method stub      }      protected void onEndTransaction() {          if (mNotifyChange) {            mNotifyChange = false;            notifyChange(true);          }      }      protected void notifyChange(boolean syncToNetwork) {          getContext().getContentResolver().notifyChange(AUTHORITY_URI, null, syncToNetwork);      }    }
页: [1]
查看完整版本: 【原创】ContentProvider 示例