文档章节

Android自定义Content Provider及使用

Freewheel
 Freewheel
发布于 2015/05/28 11:19
字数 1093
阅读 57
收藏 0

先看看官网API的介绍:

Content providers are one of the primary building blocks of Android applications, providing content to applications. 

Content providers是Android app的基石之一。

They encapsulate data and provide it to applications through the single ContentResolver interface.

它们封装了数据,提供了唯一一个ContentResolver接口。

 A content provider is only required if you need to share data between multiple applications. For example, the contacts data is used by multiple applications and must be stored in a content provider.

只有当你需要在不同的APP之间分享数据,你才有必要创建一个的 content provider。比如,系统的联系人数据经常被许多APP所使用,所以必须存放在 content provider里。

 If you don't need to share data amongst multiple applications you can use a database directly via SQLiteDatabase.
如果你不需要在不同的APP之间分享数据,你可以直接使用SQLite数据库。

When a request is made via a ContentResolver the system inspects the authority of the given URI and passes the request to the content provider registered with the authority. 

当APP通过ContentResolver发起一个对content provider的数据请求时,系统会根据请求里的URI的身份标识将请求递交给对应的content provider

The content provider can interpret the rest of the URI however it wants. The UriMatcher class is helpful for parsing URIs.
收到请求的content provider可以自行翻译URI的剩余内容,UriMatcher类对此大有帮助。

The primary methods that need to be implemented are:
如果继承了ContentProvider类,需要实现以下方法。

onCreate() which is called to initialize the provider 初始化
query(Uri, String[], String, String[], String) which returns data to the caller 返回请求的数据
insert(Uri, ContentValues) which inserts new data into the content provider 插入新数据
update(Uri, ContentValues, String, String[]) which updates existing data in the content provider 修改数据
delete(Uri, String, String[]) which deletes data from the content provider 删除数据
getType(Uri) which returns the MIME type of data in the content provider 返回数据类型



自定义一个java类并继承自ContentProvider类:

public class BookProvider extends ContentProvider {

    public static final String PROVIDER_NAME = "com.hong.app.contentproviderexample.Books";

    public static final String PROVIDER_CONTENT_STRING = "content://" + PROVIDER_NAME + "/books";
    public static final Uri CONTENT_URI = Uri.parse(PROVIDER_CONTENT_STRING);
    static final String _ID = "_id";
    static final String TITLE = "title";
    static final String ISBN = "isbn";

    static final int BOOKS = 1;
    static final int BOOK_ID = 2;

    private static final UriMatcher uriMatcher;

    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(PROVIDER_NAME, "books", BOOKS);
        uriMatcher.addURI(PROVIDER_NAME, "book/#", BOOK_ID);
    }

    //--FOR DATABASE USE
    SQLiteDatabase booksDB;
    static final String DATABASE_NAME = "Books";
    static final String DATABASE_TABLE = "titles";
    static final int DATABASE_VERSION = 1;
    static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + "(_id integer primary key autoincrement, title text not null,isbn text not null);";

    private static class DatabaseHelper extends SQLiteOpenHelper {

        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS titles");
            onCreate(db);
        }
    }

    @Override
    public boolean onCreate() {
        Context context = getContext();
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        booksDB = databaseHelper.getWritableDatabase();
        return (booksDB == null) ? false : true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        queryBuilder.setTables(DATABASE_TABLE);

        if (uriMatcher.match(uri) == BOOK_ID) {
            queryBuilder.appendWhere(_ID + " = " + uri.getPathSegments().get(1));
        }

        if (sortOrder == null || sortOrder == "") {
            sortOrder = TITLE;
        }

        Cursor cursor = queryBuilder.query(
                booksDB,
                projection,
                selection,
                selectionArgs,
                null,
                null,
                sortOrder
        );

        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

    @Override
    public String getType(Uri uri) {
        switch (uriMatcher.match(uri)) {
            case BOOKS:
                return "vnd.android.cursor.dir/vnd.example.administrator.books";

            case BOOK_ID:
                return "vnd.android.cursor.item/vnd.example.administrator.books";

            default:
                throw new IllegalArgumentException("Unsupported URI : " + uri);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        long rowID = booksDB.insert(DATABASE_TABLE, "", values);

        if (rowID > 0) {
            Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
            getContext().getContentResolver().notifyChange(_uri, null);
            return _uri;
        } else {
            // throw new SQLException("Failed to insert row into " + uri);
            return null;
        }

    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int count = 0;
        switch (uriMatcher.match(uri)) {
            case BOOKS:
                count = booksDB.delete(DATABASE_TABLE, selection, selectionArgs);
                break;

            case BOOK_ID:
                String id = uri.getPathSegments().get(1);
                count = booksDB.delete(DATABASE_TABLE, _ID + "=" + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
                break;
            default:
                throw new IllegalArgumentException("UnKnown URI : " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);

        return count;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        int count = 0;
        switch (uriMatcher.match(uri)) {
            case BOOKS:
                count = booksDB.update(DATABASE_TABLE, values, selection, selectionArgs);
                break;
            case BOOK_ID:
                count = booksDB.update(DATABASE_TABLE, values, _ID + "=" + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
                break;
            default:
                throw new IllegalArgumentException("UnKnown URI : " + uri);
        }

        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }
}


主要用到的类:  UriMatcher SQLiteDatabase SQLiteOpenHelper
主要用到的方法:重写了ContentProvider类的6个方法—— update,delete,onCreate,query,getType,insert; uriMatcher . match ( uri ) getContext () getContentResolver () notifyChange ( uri , null ) getPathSegments ()
关键:以上自定义的content provider 用SQLite的方式保存数据,用    UriMatcher 类来核对传入的uri进而进行对应的操作。



使用自定义的content provider:

private void addContent() {
        ContentValues values = new ContentValues();
        values.put(
                BookProvider.TITLE,
                titleEditText.getText().toString()
        );
        values.put(
                BookProvider.ISBN,
                ISBNEditText.getText().toString()
        );
        Uri uri = getContentResolver().insert(BookProvider.CONTENT_URI, values);
        Toast.makeText(getBaseContext(), "Add book: \n" + uri.toString(), Toast.LENGTH_LONG).show();
    }


    private void retrieveAll() {

        Uri allTitles = Uri.parse(BookProvider.PROVIDER_CONTENT_STRING);
        Cursor cursor;

        CursorLoader cursorLoader = new CursorLoader(
                getBaseContext(),
                allTitles,
                null,
                null,
                null,
                "title desc"
        );
        cursor = cursorLoader.loadInBackground();

        StringBuilder builder = new StringBuilder();
        if (cursor!=null) {
            if (cursor.moveToFirst()) {
                do {
                    builder.append(cursor.getString(BookProvider.BOOK_ID) + ","
                            + cursor.getString(cursor.getColumnIndex(BookProvider.TITLE)) + ","
                            + cursor.getString(cursor.getColumnIndex(BookProvider.ISBN)) + "\n");
                } while (cursor.moveToNext());

                String content = builder.toString();

                new AlertDialog.Builder(this)
                        .setTitle("Books")
                        .setMessage("All books:\n" + content)
                        .show();

            }
        }
    }





注意事项:


  1. 记得在 AndroidManifest.xml中声明provider。并且android:exported值设为true


<provider
        android:exported="true"
        android:name=".BookProvider"
        android:authorities="com.hong.app.contentproviderexample.Books">
    </provider>




    2.声明权限


<uses-permission android:name="com.hong.app.contentproviderexample.Books" />






源码:https://github.com/freewheel70/ContentProviderExample





© 著作权归作者所有

Freewheel
粉丝 10
博文 83
码字总数 48265
作品 0
普陀
程序员
私信 提问
ContentProvider学习

当一个应用程序需要把自己的数据暴露给其他程序使用时,该就用程序就可通过提供ContentProvider来实现;其他应用程序就可通过ContentResolver来操作ContentProvider暴露的数据。 一旦某个应用...

天下杰论
2012/09/19
0
0
Android中创建自己的ContentProvider

Android是如何实现应用程序之间数据共享的?我们以前谈到外界的程序可以 通过ContentResolver接口访问ContentProvider提供的数据,今天我们来谈下如何创建自己的ContentProvider来实现应用程...

鉴客
2011/12/21
1K
0
android Content Provider 详解

Android中的Contentprovider机制可支持在多个应用中存储和读取数据。这也是跨应用共享数据的唯一方式。在android系统中,没有一个公共的内存区域,供多个应用共享存储数据。 Android提供了一...

鉴客
2011/12/21
39.2K
5
Activity.startManagingCursor方法

总结一下Activity.startManagingCursor方法: 转 我们将获得的Cursor对象交与Activity 来管理,这样Cursor对象的生命周期便能与当前的Activity自动同步,省去了自己管理Cursor。 1.这个方法使...

AlexZhuang
2012/06/21
0
1
Android 自定义权限详解

一、自定义权限与使用 在用户app中,自定义权限往往设定在 四大组件上Activity,Service,BroadcastReceiver,ContentProvider,作为app的一部分,如果不允许组件被其他调用,设置权限也是一种保...

IamOkay
2014/11/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

计算机网络

计算机网络体系结构 OSI 其中表示层和会话层用途如下: 表示层 :数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。 会话层 :建立及管理会话。 五层...

一只小青蛙
51分钟前
2
0
0.01-Win10安装linux子系统

一、安装Debian子系统 -1、控制面板设置: -1.1、打开“控制面板” —— “程序” —— “启用或关闭Windows功能” —— 勾选 “适用于Linux的Windows子系统” -2、设置: -2.1、打开“设置”...

静以修身2025
昨天
2
0
init 0-6 (启动级别:init 0,1,2,3,4,5,6)

启动级别: init 0,1,2,3,4,5,6 这是个很久的知识点了,只是自己一直都迷迷糊糊的,今天在翻出来好好理解下。。 0: 停机 1:单用户形式,只root进行维护 2:多用户,不能使用net file system...

圣洁之子
昨天
2
0
Android Camera HAL浅析

1、Camera成像原理介绍 Camera工作流程图 Camera的成像原理可以简单概括如下: 景物(SCENE)通过镜头(LENS)生成的光学图像投射到图像传感器(Sensor)表面上,然后转为电信号,经过A/D(模数转...

天王盖地虎626
昨天
2
0
聊聊Elasticsearch的ProcessProbe

序 本文主要研究一下Elasticsearch的ProcessProbe ProcessProbe elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/monitor/process/ProcessProbe.java public class ProcessProb......

go4it
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部