【原创】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[0]);  
            } else {  
                sb.append(", calling package is one of: [");  
                for (int i = 0; i < callerPackages.length; i++) {  
                    if (i != 0) {  
                        sb.append(", ");  
                    }  
                    sb.append(callerPackages[i]);  
                }  
                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[0])) {  
            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[newLength];  
            newSelectionArgs[0] = 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);  
    }  
  
}  
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值