android ContentProvider

ContentProvider 与Activity、Service、BroadcastReceiver并称四大组件,一个应用程序通过ContentProvoder向外界暴露其数据操作方法,不管其应用程序是否启动,其他应用程序皆可操作程序的内部数据,增删改查。

开发ContentProvider的步骤。

1:定义自己的ContentProvider,该类需要继承安卓提供的ContentProvider基类。

2:需要在配置文件AndroidManifest.xml中配置此ContentProvider

<provider 
    android:name=”MyContentProvider”
    android:authorities=”com.wissen.MyContentProvider” //android:authorities 类似为此Provider的域名
  
android:exported="true"/> //为能否被外部访问,默认为true

当我们通过上面的配置的文件配置完,那么其他应用程序就可以访问Url来访问暴露的数据。使用暴露数据需要在ContentProvider复写CRUD操作

代码示例:

(一)ContentProvider 应用程序

public class DictProvider extends ContentProvider
{
    private static UriMatcher matcher 
        = new UriMatcher(UriMatcher.NO_MATCH);
    private static final int WORDS = 1;
    private static final int WORD = 2;
    private MyDatabaseHelper dbOpenHelper;
    static
    {
        // 为UriMatcher注册两个Uri
        matcher.addURI(Words.AUTHORITY, "words", WORDS);
        matcher.addURI(Words.AUTHORITY, "word/#", WORD);
    }

    // 第一次调用该DictProvider时,系统先创建DictProvider对象,并回调该方法
    @Override
    public boolean onCreate()
    {
        dbOpenHelper = new MyDatabaseHelper(this.getContext(),
            "myDict.db3", 1);
        return true;
    }
    
    // 返回指定Uri参数对应的数据的MIME类型
    @Override
    public String getType(Uri uri)
    {
        switch (matcher.match(uri))
        {
            // 如果操作的数据是多项记录
            case WORDS:
                return "vnd.android.cursor.dir/org.crazyit.dict";
            // 如果操作的数据是单项记录
            case WORD:
                return "vnd.android.cursor.item/org.crazyit.dict";
            default:
                throw new IllegalArgumentException("未知Uri:" + uri);
        }
    }

    // 查询数据的方法
    @Override
    public Cursor query(Uri uri, String[] projection, String where,
        String[] whereArgs, String sortOrder)
    {
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        switch (matcher.match(uri))
        {
            // 如果Uri参数代表操作全部数据项
            case WORDS:
                // 执行查询
                return db.query("dict", projection, where,
                    whereArgs, null, null, sortOrder);
            // 如果Uri参数代表操作指定数据项
            case WORD:
                // 解析出想查询的记录ID
                long id = ContentUris.parseId(uri);
                String whereClause = Words.Word._ID + "=" + id;
                // 如果原来的where子句存在,拼接where子句
                if (where != null && !"".equals(where))
                {
                    whereClause = whereClause + " and " + where;
                }
                return db.query("dict", projection, whereClause, whereArgs,
                    null, null, sortOrder);
            default:
                throw new IllegalArgumentException("未知Uri:" + uri);
        }
    }
    
    // 插入数据方法
    @Override
    public Uri insert(Uri uri, ContentValues values)
    {
        // 获得数据库实例
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        switch (matcher.match(uri))
        {
            // 如果Uri参数代表操作全部数据项
            case WORDS:
                // 插入数据,返回插入记录的ID
                long rowId = db.insert("dict", Words.Word._ID, values);
                // 如果插入成功返回uri
                if (rowId > 0)
                {
                    // 在已有的 Uri的后面追加ID
                    Uri wordUri = ContentUris.withAppendedId(uri, rowId);
                    // 通知数据已经改变
                    getContext().getContentResolver().notifyChange(wordUri, null);
                    return wordUri;
                }
                break;
            default :
                throw new IllegalArgumentException("未知Uri:" + uri);
        }
        return null;
    }
    
    // 修改数据的方法
    @Override
    public int update(Uri uri, ContentValues values, String where,
        String[] whereArgs)
    {
        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
        // 记录所修改的记录数
        int num = 0;
        switch (matcher.match(uri))
        {
            // 如果Uri参数代表操作全部数据项
            case WORDS:
                num = db.update("dict", values, where, whereArgs);
                break;
            // 如果Uri参数代表操作指定数据项    
            case WORD:
                // 解析出想修改的记录ID
                long id = ContentUris.parseId(uri);
                String whereClause = Words.Word._ID + "=" + id;
                // 如果原来的where子句存在,拼接where子句
                if (where != null && !where.equals(""))
                {
                    whereClause = whereClause + " and " + where;
                }
                num = db.update("dict", values, whereClause, whereArgs);
                break;
            default:
                throw new IllegalArgumentException("未知Uri:" + uri);
        }
        // 通知数据已经改变
        getContext().getContentResolver().notifyChange(uri, null);
        return num;
    }
    
    // 删除数据的方法
    @Override
    public int delete(Uri uri, String where, String[] whereArgs)
    {
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        // 记录所删除的记录数
        int num = 0;
        // 对于uri进行匹配。
        switch (matcher.match(uri))
        {
            // 如果Uri参数代表操作全部数据项
            case WORDS:
                num = db.delete("dict", where, whereArgs);
                break;
            // 如果Uri参数代表操作指定数据项    
            case WORD:
                // 解析出所需要删除的记录ID
                long id = ContentUris.parseId(uri);
                String whereClause = Words.Word._ID + "=" + id;
                // 如果原来的where子句存在,拼接where子句
                if (where != null && !where.equals(""))
                {
                    whereClause = whereClause + " and " + where;
                }
                num = db.delete("dict", whereClause, whereArgs);
                break;
            default:
                throw new IllegalArgumentException("未知Uri:" + uri);
        }
        // 通知数据已经改变
        getContext().getContentResolver().notifyChange(uri, null);
        return num;
    }
}
//数据库操作类
public class MyDatabaseHelper extends SQLiteOpenHelper
{
    final String CREATE_TABLE_SQL =
        "create table dict(_id integer primary key autoincrement , word , detail)";
    /**
     * @param context
     * @param name
     * @param version
     */
    public MyDatabaseHelper(Context context, String name, int version)
    {
        super(context, name, null, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db)
    {
        // 第一个使用数据库时自动建表
        db.execSQL(CREATE_TABLE_SQL);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    {
        System.out.println("--------onUpdate Called--------"
            + oldVersion + "--->" + newVersion);
    }
}
//全局变量
public final class Words
{
    // 定义该ContentProvider的Authority
    public static final String AUTHORITY 
        = "org.crazyit.providers.dictprovider";

    // 定义一个静态内部类,定义该ContentProvider所包的数据列的列名
    public static final class Word implements BaseColumns
    {
        // 定义Content所允许操作的3个数据列
        public final static String _ID = "_id";
        public final static String WORD = "word";
        public final static String DETAIL = "detail";
        // 定义该Content提供服务的两个Uri
        public final static Uri DICT_CONTENT_URI = Uri
            .parse("content://" + AUTHORITY + "/words");
        public final static Uri WORD_CONTENT_URI = Uri
            .parse("content://"    + AUTHORITY + "/word");
    }
}

配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.crazyit.content"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />
    <application
        android:icon="@drawable/ic_launcher">
        <!-- 注册一个ContentProvider -->
        <provider
            android:exported="true"
            android:name=".DictProvider"
            android:authorities="org.crazyit.providers.dictprovider">
        </provider>
    </application>
</manifest>

 

(二)ContentResolver (Words类与上面一致)

public class DictResolverTest extends Activity
{
    ContentResolver contentResolver;
    Button insert = null;
    Button search = null;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取系统的ContentResolver对象
        contentResolver = getContentResolver();
        insert = (Button) findViewById(R.id.insert);
        search = (Button) findViewById(R.id.search);
        // 为insert按钮的单击事件绑定事件监听器
        insert.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View source)
            {
                // 获取用户输入
                String word = ((EditText) findViewById(R.id.word))
                    .getText().toString();
                String detail = ((EditText) findViewById(R.id.detail))
                    .getText().toString();
                // 插入生词记录
                ContentValues values = new ContentValues();
                values.put(Words.Word.WORD, word);
                values.put(Words.Word.DETAIL, detail);
                contentResolver.insert(
                    Words.Word.DICT_CONTENT_URI, values);
                // 显示提示信息
                Toast.makeText(DictResolverTest.this, "添加生词成功!"
                    , Toast.LENGTH_LONG).show();
            }
        });
        // 为search按钮的单击事件绑定事件监听器
        search.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View source)
            {
                // 获取用户输入
                String key = ((EditText) findViewById(R.id.key))
                    .getText().toString();
                // 执行查询
                Cursor cursor = contentResolver.query(
                    Words.Word.DICT_CONTENT_URI, null,
                    "word like ? or detail like ?", new String[] {
                        "%" + key + "%", "%" + key + "%" }, null);
                // 创建一个Bundle对象
                Bundle data = new Bundle();
                data.putSerializable("data", converCursorToList(cursor));
                // 创建一个Intent
                Intent intent = new Intent(DictResolverTest.this,
                    ResultActivity.class);
                intent.putExtras(data);
                // 启动Activity
                startActivity(intent);
            }
        });
    }

    private ArrayList<Map<String, String>> converCursorToList(Cursor cursor)
    {
        ArrayList<Map<String, String>> result 
            = new ArrayList<Map<String, String>>();
        // 遍历Cursor结果集
        while (cursor.moveToNext())
        {
            // 将结果集中的数据存入ArrayList中
            Map<String, String> map = new HashMap<String, String>();
            // 取出查询记录中第2列、第3列的值
            map.put(Words.Word.WORD, cursor.getString(1));
            map.put(Words.Word.DETAIL, cursor.getString(2));
            result.add(map);
        }
        return result;
    }
public class ResultActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.popup);
        ListView listView = (ListView) findViewById(R.id.show);
        Intent intent = getIntent();
        // 获取该intent所携带的数据
        Bundle data = intent.getExtras();
        // 从Bundle数据包中取出数据
        @SuppressWarnings("unchecked")
        List<Map<String, String>> list = (List<Map<String, String>>)
            data.getSerializable("data");
        // 将List封装成SimpleAdapter
        SimpleAdapter adapter = new SimpleAdapter(ResultActivity.this,
            list, R.layout.line
            , new String[] { Words.Word.WORD, Words.Word.DETAIL }
            , new int[] { R.id.word, R.id.detail });
        // 填充ListView
        listView.setAdapter(adapter);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.crazyit.resolver"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />
    <application android:icon="@drawable/ic_launcher" android:label="@string/app_name">
        <activity android:name=".DictResolverTest"
                android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".ResultActivity" 
            android:theme="@android:style/Theme.Dialog"
            android:label="找到的单词">
        </activity>
    </application>
</manifest> 

 

posted on 2014-11-19 16:37  弗不是佛  阅读(326)  评论(0编辑  收藏  举报

导航