通过ContentProvider完成不同应用程序之间的数据提取

由于牵涉到两个应用程序,布局文件等等等等的东西太多,每个项目还不一样。我这里就拉出重点的思路,详细讲解一下。


我们的思路是这样,一个程序使用ContentProvider连接数据库的查询接口。另一个程序使用ContentResolver,连接ContentProvider的查询接口,思路很简单,接下来我们先来看看ContentProvider。

ContentProvider的使用还是很方便的,只需要继承该类,实现抽象方法就可以了,之后会详细说,我先把我代码中的类写出来,方便之后讲解

public class SQLiteProvider extends ContentProvider

首先还是看权限,如果在完全分离的不同应用程序下,需要允许外部应用接入我们应用下的Provider,就需要在AndroidManifest里去注册这个Provider,就和注册Activity一样

        <provider
            android:authorities="com.ty.messagedb_provider_demo1.util.SQLite.Provider.SQLiteProvider"
            android:name=".util.SQLite.Provider.SQLiteProvider"
            android:exported="true">

        </provider>
注册的语句一共有三条

第一条authoritiess,应该填的是需要注册的Provider的全名(我是理解成,这个名字是给外部应用调用的时候匹配的)

第二条name,就是指定继承了ContentProvider这个类的所属位置(这个应该是内部定位)

第三条exported就是权限的设置,true是允许外部接入,false反之


好了  准备工作做完,我们看如何实现ContentProvider这个类

按照我们的思路,我们是需要通过provider去访问数据库的

我这里已经创建好了,SQLiteOpenHelper 和 SQLiteDAO并实现了query查询方法,和insert插入方法,之前有专门博客讲解,我这里就直接跳过了

当继承了ContentProvider这个类之后,需要实现他的几个方法,其实我感觉就是一层接口,看了就明白了,我先把他们列出来,一会再实现

public boolean onCreate()
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
public String getType(Uri uri)
public Uri insert(Uri uri, ContentValues values)
public int delete(Uri uri, String selection, String[] selectionArgs)
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

方法列出来了,那我们还需要操作数据库啊,那就还需要DB

SQLiteDatabase db;
我们所需要的元素都集齐了,接下来就来看方法吧

onCreate这个方法已经太常见了,那Provider的OnCreate什么时候被调用呢

我给activity的oncreate  onStrat  onResume打上了Log

02-22 08:30:48.393 21046-21046/com.ty.messagedb_provider_demo1 D/Provider: OnCreate
02-22 08:30:48.613 21046-21046/com.ty.messagedb_provider_demo1 D/Provider: Activity OnCreate
02-22 08:30:48.613 21046-21046/com.ty.messagedb_provider_demo1 D/Provider: Activity onStart
02-22 08:30:48.613 21046-21046/com.ty.messagedb_provider_demo1 D/Provider: Activity onResume

结果是这样的,说明他与activity其实是没有关系的,在程序编译阶段,或者之后一点点,他就会创建

下面是完整的OnCreate方法

    public boolean onCreate() {
        SQLiteHelper sqLiteHelper = new SQLiteHelper(getContext());
        db = sqLiteHelper.getReadableDatabase();
        Log.d("Provider", "OnCreate");
        return true;
    }
注意返回值

true if the provider was successfully loaded, false otherwise


接下来就是query方法了,他返回一个游标Cursor

直接看代码可能好理解一点

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor cursor = db.query(SQLiteHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
        return cursor;
    }
我这里要附上一段英文的解释,很详细,虽然我还么i仔细看,但是我一定会看的,如果我看完以后,我会在中间插入中文的解释

/**
 * Implement this to handle query requests from clients.
 * This method can be called from multiple threads, as described in
 * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
 * and Threads</a>.
 * <p>
 * Example client call:<p>
 * <pre>// Request a specific record.
 * Cursor managedCursor = managedQuery(
            ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2),
            projection,    // Which columns to return.
            null,          // WHERE clause.
            null,          // WHERE clause value substitution
            People.NAME + " ASC");   // Sort order.</pre>
 * Example implementation:<p>
 * <pre>// SQLiteQueryBuilder is a helper class that creates the
    // proper SQL syntax for us.
    SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();

    // Set the table we're querying.
    qBuilder.setTables(DATABASE_TABLE_NAME);

    // If the query ends in a specific record number, we're
    // being asked for a specific record, so set the
    // WHERE clause in our query.
    if((URI_MATCHER.match(uri)) == SPECIFIC_MESSAGE){
        qBuilder.appendWhere("_id=" + uri.getPathLeafId());
    }

    // Make the query.
    Cursor c = qBuilder.query(mDb,
            projection,
            selection,
            selectionArgs,
            groupBy,
            having,
            sortOrder);
    c.setNotificationUri(getContext().getContentResolver(), uri);
    return c;</pre>
 *
 * @param uri The URI to query. This will be the full URI sent by the client;
 *      if the client is requesting a specific record, the URI will end in a record number
 *      that the implementation should parse and add to a WHERE or HAVING clause, specifying
 *      that _id value.
 * @param projection The list of columns to put into the cursor. If
 *      {@code null} all columns are included.
 * @param selection A selection criteria to apply when filtering rows.
 *      If {@code null} then all rows are included.
 * @param selectionArgs You may include ?s in selection, which will be replaced by
 *      the values from selectionArgs, in order that they appear in the selection.
 *      The values will be bound as Strings.
 * @param sortOrder How the rows in the cursor should be sorted.
 *      If {@code null} then the provider is free to define the sort order.
 * @return a Cursor or {@code null}.
 */

好了,因为只需要提供给外部应用查询,我就只实现了这两个接口,接下来就是Solver的时间了,因为之前已经写过一篇了,我这里就快速点

定义需要的变量

    ListView listView;
    ListBaseAdapter adapter;
    ArrayList<MessageData> dataList;
    ContentResolver resolver;
实现

        listView = (ListView) findViewById(R.id.LV_Main_ListView);
        dataList = new ArrayList<>();
        resolver = getContentResolver();
接下来就是唯一的新内容

        Cursor cursor = resolver.query(Uri.parse("content://com.ty.messagedb_provider_demo1.util.SQLite.Provider.SQLiteProvider"), new String[]{"message", "type", "time"},
                null, null, null);

        if (cursor != null) {
            while (cursor.moveToNext()) {
                dataList.add(new MessageData(cursor.getString(cursor.getColumnIndex("message")),
                        cursor.getInt(cursor.getColumnIndex("type")),
                        cursor.getLong(cursor.getColumnIndex("time"))));
            }
            cursor.close();
        }
注意resolber.query的第一个参数 他需要的是一个Uri,并且这个获取的格式是固定的,后面的内容其实就是我们在Provider的AndroidManifest的注册的第一条authoritiess,

然后就能通过Resolver的query去调用Provider的query最后去调用我们SQLite的query,就是这个逻辑

好了,之后就是一下数据设置,大家看看就可以了

        adapter = new ListBaseAdapter(this, dataList);
        listView.setAdapter(adapter);

这样内容就讲完了,梳理一遍,自己的记忆也更清晰哈










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值