美文网首页
内容提供器

内容提供器

作者: C_G__ | 来源:发表于2019-04-26 15:35 被阅读0次

Content Provider

主要用于在不同App间共享数据。

权限申请

App中某些功能的执行需要申请Android系统权限,如打电话等。
AndroidManifest.xml中可以申请权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bl.blandroidpro">
    <uses-permission android:name="android.permission.CALL_PHONE" />
</manifest>

Android权限机制

Android 6.0之前安装app时,提示app需要获取某些权限,其中包括一些个人隐私相关,如地理位置等,但是这些app日常粘度很高,还不能不安,所以用户只能被迫同意安装。
Android开发团队也意识到了这个问题,于是Android 6.0开始引入了运行时权限。但是安卓的权限很多,有上百个,如果让用户一个个授权也很繁琐,所以Android团队将权限分成两部分:普通权限危险权限。只有危险权限才需要用户授权。

危险权限

Android的危险权限 一共9组 24个。每个权限属于一个权限组,同意其中一个权限就同意了同组中的所有权限。

  • CALENDAR
    READ_CALENDAR
    WRITE_CALENDAR
  • CAMERA
  • CONTACTS
    READ_CONTACTS
    WRITE_CONTACTS
    GET_ACCOUNTS
  • LOCATION
    ACCESS_FINE_LOCATION
    ACCESS_COARSE_LOCATION
  • MICROPHONE
    RECORD_AUTIO
  • PHONE
    READ_PHONE_STATE
    CALL_PHONE
    READ_CALL_LOG
    WRITE_CALL_LOG
    ADD_VOICEMAIL
    USE_SIP
    PROCESS_OUTGOING_CALLS
  • SENSORS
    BODY_SENSORS
  • SMS
    SEND_SMS
    RECEIVE_SMS
    READ_SMS
    RECEIVE_WAP_PUSH
    RECEIVE_MMS
  • STORAGE
    READ_EXTERNAL_STORAGE
    WRITE_EXTERNAL_STORAGE

运行时权限

运行时权限就是app在安装时不需要授权,在运行时具体用到某些功能时,再由用户决定是否授权,程序不可以擅自做主。

// 校验是否获取某权限
if (ContextCompat.checkSelfPermission(this,
    Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
    // 没有获取则请求权限
    ActivityCompat.requestPermissions(this,
        new String[]{Manifest.permission.READ_CONTACTS}, 1);
} else {
    // 已经获取权限则做相应业务
    readContacts();
}

@Override
public void onRequestPermissionsResult(int requestCode,
                   @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case 1:
            // 同意授权
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                readContacts();

            // 不同意授权
            } else {
                Toast.makeText(this,
                            "You denied the permission", Toast.LENGTH_LONG).show();
            }
            break;
        default:
            break;
    }
}

访问其他app的数据

ContentResolver 通过该类访问其它app的数据。该类提供了CRUD操作的相关方法。以Uri作为参数。

  • insert() 插入数据
  • update() 修改数据
  • delete() 删除数据
  • query() 查询数据

Uri参数格式及组成结构
path结尾表示访问该表所有数据
id结尾表示仅访问此条数据
'*':匹配任意长度字符
'#':匹配任意长度数字

  • scheme 协议
  • authority 区分应用程序,以包名命名。
  • path 对同一应用不同表做区分。
  • id 对同一表下的记录做区分
// path结尾
Uri uri = Uri.parse("content://com.example.app.provider/table1");
// id结尾
Uri uri = Uri.parse("content://com.example.app.provider/table2/1");
// path *
"content://com.example.app.provider/*";
// id #
"content://com.example.app.provider/table2/#";
// 查询是通过query方法返回的游标,逐行按字段获取想要的信息
// 获取联系人列表
private void readContacts() {
        Cursor cursor = null;
        try {
            // 查询
            cursor = getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null, null, null, null);
            if (cursor != null) {
                // 移动到下一条
                while (cursor.moveToNext()) {
                    // 获取联系人名
                    String disName = cursor.getString(cursor.getColumnIndex(
                            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
                    ));
                    // 获取联系人号码
                    String number = cursor.getString(cursor.getColumnIndex(
                            ContactsContract.CommonDataKinds.Phone.NUMBER
                    ));
                    contactList.add(disName + "\n" + number);
                }
                // 刷新列表
                adapter.notifyDataSetChanged();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                // 关闭游标
                cursor.close();
            }
        }
}

自定义内容提供器

需要继承ContentProvider类,重写其中6个方法

  • onCreate()
  • query()
  • insert()
  • update()
  • delete()
  • getType() 获取MIME类型
    MIME类型由3部分组成
  • 必须以vnd开头
  • 以path结尾,后接 android.cursor.dir/, 以id结尾android.cursor.item/
  • 最后接上vnd.'authority'.'path'
// path结尾
vnd.android.cursor.dir/vnd.com.exxample.app.provider.table1
// id结尾
vnd.android.cursor.item/vnd.com.exxample.app.provider.table2

示例代码


MyContentProvider.java

public class MyContentProvider extends ContentProvider {

    public static final int BOOK_DIR = 0;
    public static final int BOOK_ITEM = 1;
    public static final int CATEGORY_DIR = 2;
    public static final int CATEGORY_ITEM = 3;

    public static String URI_BOOK;
    public static String URI_CATEGORY;

    private static final String AUTHORITY = "com.bl.blandroidpro.provider";
    private static final String DB_NAME = "BookStore.db";
    private static final String PREFIX_CONTENT = "content://";
    private static final String SURFIX_BOOK = "book";
    private static final String SURFIX_BOOK_ID = "book/#";
    private static final String SURFIX_BOOK_TABLE = "Book";
    private static final String SURFIX_CATEGORY = "category";
    private static final String SURFIX_CATEGORY_ID = "category/#";
    private static final String SURFIX_CATEGORY_TABLE = "Category";

    private static final String VND_BOOK_DIR =
            "vnd.android.cursor.dir/vnd.com.bl.blandroidpro.provider.book";
    private static final String VND_BOOK_ITEM =
            "vnd.android.cursor.item/vnd.com.bl.blandroidpro.provider.book";
    private static final String VND_CATEGORY_DIR =
            "vnd.android.cursor.dir/vnd.com.bl.blandroidpro.provider.category";
    private static final String VND_CATEGORY_ITEM =
            "vnd.android.cursor.item/vnd.com.bl.blandroidpro.provider.category";

    private static UriMatcher sUriMatcher;
    private MyDatabaseHelper dbHelper;

    static {
        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        sUriMatcher.addURI(AUTHORITY, SURFIX_BOOK, BOOK_DIR);
        sUriMatcher.addURI(AUTHORITY, SURFIX_BOOK_ID, BOOK_ITEM);
        sUriMatcher.addURI(AUTHORITY, SURFIX_CATEGORY, CATEGORY_DIR);
        sUriMatcher.addURI(AUTHORITY, SURFIX_CATEGORY_ID, CATEGORY_ITEM);

        URI_BOOK = PREFIX_CONTENT + AUTHORITY + "/" + SURFIX_BOOK;
        URI_CATEGORY = PREFIX_CONTENT + AUTHORITY + "/" + SURFIX_CATEGORY;
    }

    public MyContentProvider () {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int deleteRows = 0;
        switch (sUriMatcher.match(uri)) {
            case BOOK_DIR:
                deleteRows = db.delete(SURFIX_BOOK_TABLE, selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                deleteRows = db.delete(SURFIX_BOOK_TABLE,
                        "id = ?", new String[]{bookId});
                break;
            case CATEGORY_DIR:
                deleteRows = db.delete(SURFIX_CATEGORY_TABLE, selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                deleteRows = db.delete(SURFIX_CATEGORY_TABLE,
                        "id = ?", new String[]{categoryId});
                break;
            default:
                break;

        }
        return deleteRows;
    }

    @Override
    public String getType(Uri uri) {
        switch (sUriMatcher.match(uri)) {
            case BOOK_DIR:
                return VND_BOOK_DIR;
            case BOOK_ITEM:
                return VND_BOOK_ITEM;
            case CATEGORY_DIR:
                return VND_CATEGORY_DIR;
            case CATEGORY_ITEM:
                return VND_CATEGORY_ITEM;
        }
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        Uri uriReturn = null;
        switch (sUriMatcher.match(uri)) {
            case BOOK_DIR:
            case BOOK_ITEM:
                long newBookId = db.insert(SURFIX_BOOK_TABLE, null, values);
                uriReturn = Uri.parse(URI_BOOK + "/" + newBookId);
                break;
            case CATEGORY_DIR:
            case CATEGORY_ITEM:
                long newCategoryId = db.insert(SURFIX_CATEGORY_TABLE, null, values);
                uriReturn = Uri.parse(URI_CATEGORY + "/" + newCategoryId);
                break;
            default:
                break;

        }
        return uriReturn;
    }

    @Override
    public boolean onCreate() {
        dbHelper = new MyDatabaseHelper(getContext(), DB_NAME, null, 2);
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = null;
        switch (sUriMatcher.match(uri)) {
            case BOOK_DIR:
                cursor = db.query(SURFIX_BOOK_TABLE, projection, selection,
                        selectionArgs, null, null, sortOrder);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                cursor = db.query(SURFIX_BOOK_TABLE, projection, "id = ?",
                        new String[]{bookId}, null, null, sortOrder);
                break;
            case CATEGORY_DIR:
                cursor = db.query(SURFIX_CATEGORY_TABLE, projection, selection,
                        selectionArgs, null, null, sortOrder);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                cursor = db.query(SURFIX_CATEGORY_TABLE, projection, "id = ?",
                        new String[]{categoryId}, null, null, sortOrder);
                break;
            default:
                break;
        }
        return cursor;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        int updateRows = 0;
        switch (sUriMatcher.match(uri)) {
            case BOOK_DIR:
                updateRows = db.update(SURFIX_BOOK_TABLE, values, selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                updateRows = db.update(SURFIX_BOOK_TABLE, values,
                        "id = ?", new String[]{bookId});
                break;
            case CATEGORY_DIR:
                updateRows = db.update(SURFIX_CATEGORY_TABLE, values, selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                updateRows = db.update(SURFIX_CATEGORY_TABLE, values,
                        "id = ?", new String[]{categoryId});
                break;
            default:
                break;

        }
        return updateRows;
    }
}

activity_content_provider.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".chapter07.ContentProviderCustomActivity"
    android:orientation="vertical">

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/btn_cpc_addbook"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="添加一本书" />
            <Button
                android:id="@+id/btn_cpc_querybook"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="查询书籍" />
            <Button
                android:id="@+id/btn_cpc_updatebook"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="修改一本书" />
            <Button
                android:id="@+id/btn_cpc_deletebook"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="删除一本书" />
            <TextView
                android:id="@+id/tv_cpc_info"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>

ContentProviderActivity.java

public class ContentProviderActivity extends AppCompatActivity {

    public String newId;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_content_provider);

        final TextView tv_cpc_info = findViewById(R.id.tv_cpc_info);

        // 添加书籍
        Button btn_cpc_addbook = findViewById(R.id.btn_cpc_addbook);
        btn_cpc_addbook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ContentValues values = new ContentValues();
                values.put("name", "Book");
                values.put("author", "BL");
                values.put("pages", 308);
                values.put("price", 38);
                Uri uri = Uri.parse(MyContentProvider.URI_BOOK);
                Uri newUri = getContentResolver().insert(uri, values);

                newId = newUri.getPathSegments().get(1);
                tv_cpc_info.setText(queryBooks());
            }
        });
        // 查询书籍
        Button btn_cpc_querybook = findViewById(R.id.btn_cpc_querybook);
        btn_cpc_querybook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_cpc_info.setText(queryBooks());
            }
        });
        // 修改书籍
        Button btn_cpc_updatebook = findViewById(R.id.btn_cpc_updatebook);
        btn_cpc_updatebook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = Uri.parse(MyContentProvider.URI_BOOK + "/" + newId);
                ContentValues values = new ContentValues();
                values.put("name", "Good Book");
                values.put("author", "Andy");
                values.put("pages", 400);
                values.put("price", 40);
                getContentResolver().update(uri, values, null, null);
                tv_cpc_info.setText(queryBooks());
            }
        });

        // 删除书籍
        Button btn_cpc_deletebook = findViewById(R.id.btn_cpc_deletebook);
        btn_cpc_deletebook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri uri = Uri.parse(MyContentProvider.URI_BOOK + "/" + newId);
                getContentResolver().delete(uri, null, null);
                tv_cpc_info.setText(queryBooks());
            }
        });
    }

    public String queryBooks() {
        StringBuilder sb = new StringBuilder();
        sb.append("书名    作者    页数    价格\n");

        Uri uri = Uri.parse(MyContentProvider.URI_BOOK);
        Cursor cursor = getContentResolver().query(uri,
                null, null, null, null);
        if (cursor != null) {
            while (cursor.moveToNext()) {
                String name = cursor.getString(
                        cursor.getColumnIndex("name"));
                String author = cursor.getString(
                        cursor.getColumnIndex("author"));
                int pages = cursor.getInt(
                        cursor.getColumnIndex("pages"));
                double price = cursor.getDouble(
                        cursor.getColumnIndex("price"));
                sb.append(name + "    " + author + "    " + pages + "    " + price + "\n");
            }
            cursor.close();
        }
        return sb.toString();
    }
}

相关文章

  • 内容提供器

    1.ContentResolver  对于每一个应用程序来说,如果想要访问内容提供器(ContentProvide...

  • 内容提供器

    Content Provider 主要用于在不同App间共享数据。 权限申请 App中某些功能的执行需要申请And...

  • 内容提供器

    一般有两种,一种是使用现有的内容提供器,读取和操作相应程序的数据,另一种是创建自己的内容提供器给其他程序提供数据。...

  • 内容提供器简介

    内容提供器是Android中实现跨程序共享数据的标准方式,内容提供器主要用于在不同的应用程序之间实现数据共享的功能...

  • ContentProvider-内容提供器

    1. 概述 content provider主要是在不同的应用程序之中实现数据共享功能,提供了一套完整的机制,允许...

  • 第一行代码(七)

    第七章内容主讲内容提供器 一、内容提供器简介   虽然文件和 SharedPreferences 存储中提供了 M...

  • 安卓四大组件之Provider

    内容提供器介绍## 内容提供器用法## 内容提供器介绍内容提供者主要用于在不同的应用程序之间实现数据共享的功能,它...

  • 第六章(内容提供器-Content Provider)

    内容提供器(Content Provider) 内容提供器简介: Content Provider主要用于在不同的...

  • <第一行代码>chapter7 ContentPro

    内容提供器 思维导图 最近在练习使用思维导图,献一下丑。。。 什么是内容提供器 内容提供器主要用于在不同应用程序间...

  • Android10-跨程序共享数据

    使用内容提供器(Content Provider),可以实现不同应用程序建的数据共享功能。内容提供器提供了一套完整...

网友评论

      本文标题:内容提供器

      本文链接:https://www.haomeiwen.com/subject/lndfnqtx.html