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

来源:互联网 发布:ubuntu16更新软件源 编辑:程序博客网 时间:2024/04/30 04:58

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


我们的思路是这样,一个程序使用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);

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










0 0
原创粉丝点击