zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

android基础---->ContentProvider的使用

Android基础 gt ----& contentprovider 使用
2023-09-27 14:20:11 时间

  内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。目前,使用内容提供器是Android 实现跨程序共享数据的标准方式。不同于文件存储和SharedPreferences 存储中的两种全局可读写操作模式,内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。接下来,我们开始内容提供器的学习。content provider的原理说明,参见另外一篇博客(android高级---->ContentProvider的源码分析)

 

 目录导航:

  1.   内容提供器简单说明
  2.   访问其它的Content Provider
  3.   创建自己的Content Provider
  4.   友情链接

 

内容提供器简单说明

一、 内容提供器的用法:

  • 使用现有的内容提供器来读取和操作相应程序中的数据
  • 创建自己的内容提供器给我们程序的数据提供外部访问接口,需要继承ContentProvider类

二、 ContentResolver的基本用法:

  • 得到实例:  可以通过Context 中的getContentResolver()方法获取到该类的实例
  • 基本方法:  提供了一系列的方法用于对数据进行CRUD 操作
  • 使用注意:  ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri 参数代替,这个参数被称为Content URI。

三、 内容URI的基本介绍:

  • 重要用作:  内容URI 给内容提供器中的数据建立了唯一标识符
  • 组成部分:  权限(authority)和路径(path)。
  • 权限路径:  权限是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名;路径则是用于对同一应用程序中不同的表做区分的,通常都会添加到权限的后面。

 

访问其它的Content Provider

创建一个简单项目,结构如下

 

一、 在activity_main.xml文件中创建一个ListView的布局:

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

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

 

二、 在MainActivity.java中:

package com.example.linux.getcontact;

import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    ArrayAdapter<String> adapter;
    List<String> contactsList = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.listView);
        adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList);
        listView.setAdapter(adapter);
        readContacts();
    }

    private void readContacts() {
        Cursor cursor = null;
        try {
            // 查询联系人数据
            cursor = getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            while (cursor.moveToNext()) {
                // 获取联系人姓名
                String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                // 获取联系人手机号
                String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                contactsList.add(displayName + "\n" + number);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}

 

三、 读取系统联系人是需要声明权限的,在AndroidManifest.xml中增加权限:

 <uses-permission android:name="android.permission.READ_CONTACTS" />

 

创建自己的Content Provider

  上一个自己的程序中访问其他应用程序的数据。总体来说思路还是非常简单的,只需要获取到该应用程序的内容URI,然后借助ContentResolver进行CRUD 操作就可以了。以下我们创建自己的内容提供器。

创建内容提供器--Server

项目结构:

 

一、 创建一个与数据库表对应的Bean:Person.java:

package com.example.linux.contentproviderserver.model;

/**
 * Created by Linux on 2016/3/4.
 */
public class Person {

    private Integer _id;
    private String name;
    private String age;

    public Integer get_id() {
        return _id;
    }

    public void set_id(Integer _id) {
        this._id = _id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

 

二、 接着建立一个关于数据库的工具类:DBOpenHelper.java

package com.example.linux.contentproviderserver.util;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by Linux on 2016/3/4.
 */
public class DBOpenHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "person.db"; //数据库名称
    private static final int DATABASE_VERSION = 1;//数据库版本
    private static final String CREATE_TABLE_PERSON = "CREATE TABLE person (_id integer primary key autoincrement, name varchar(20), age varchar(10))";
    private static final String DROP_TABLE_PERSON = "DROP TABLE IF EXISTS person";

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

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

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(DROP_TABLE_PERSON);
        onCreate(db);
    }
}

 

三、 创建一个自己的继承了ContentProvider的内容提供器:PersonProvider.java

  • 做一些初始化的工作:
private final static String TAG = "PersonProvider";
private DBOpenHelper dbOpenHelper;
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int PERSONS = 1;
private static final int PERSON = 2;
private static final String AUTHORITY = "com.example.linux.contentproviderserver.action.PersonProvider";
private static final String PATH_1 = "person";
private static final String PATH_2 = "person/#";

static {
    Log.i(TAG, "on PersonProvider static");
    MATCHER.addURI(AUTHORITY, PATH_1, PERSONS);
    MATCHER.addURI(AUTHORITY, PATH_2, PERSON);
}

@Override
public boolean onCreate() {
    Log.i(TAG, "on PersonProvider  create");
    this.dbOpenHelper = new DBOpenHelper(this.getContext());
    return false;
}
  • 重写它的查插入方法:insert()
// 插入person表中的所有记录 /person
// 插入person表中指定id的记录 /person/10
@Override
public Uri insert(Uri uri, ContentValues values) {
    Log.i(TAG, "uri: " + uri.getPath() + ", values: " + values.getAsString("name"));
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    switch (MATCHER.match(uri)) {
        case PERSONS:
            // 特别说一下第二个参数是当name字段为空时,将自动插入一个NULL。
            long rowid = db.insert("person", "name", values);
            Uri insertUri = ContentUris.withAppendedId(uri, rowid);// 得到代表新增记录的Uri
            this.getContext().getContentResolver().notifyChange(uri, null);
            return insertUri;
        case PERSON:
            Log.i("some", "soem");
            return null;
        default:
            throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
    }
}
  • 重写它的删除方法,delete()方法:
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    int count = 0;
    switch (MATCHER.match(uri)) {
        case PERSONS:
            count = db.delete("person", selection, selectionArgs);
            return count;
        case PERSON:
            long id = ContentUris.parseId(uri);
            String where = "_id=" + id;
            if (selection != null && !"".equals(selection)) {
                where = selection + " and " + where;
            }
            count = db.delete("person", where, selectionArgs);
            return count;
        default:
            throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
    }
}
  • 重写它的更新方法:update()
@Override
public int update(Uri uri, ContentValues values, String selection,
                  String[] selectionArgs) {
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    int count = 0;
    switch (MATCHER.match(uri)) {
        case PERSONS:
            count = db.update("person", values, selection, selectionArgs);
            return count;
        case PERSON:
            long id = ContentUris.parseId(uri);
            String where = "_id=" + id;
            if (selection != null && !"".equals(selection)) {
                where = selection + " and " + where;
            }
            count = db.update("person", values, where, selectionArgs);
            return count;
        default:
            throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
    }
}
  • 重写它的查询方法,query()
@Override
public Cursor query(Uri uri, String[] projection, String selection,
                    String[] selectionArgs, String sortOrder) {
    Log.i(TAG, "PersonProvider query");
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    int matchResult = MATCHER.match(uri);
    switch (MATCHER.match(uri)) {
        case PERSONS:
            return db.query("person", projection, selection, selectionArgs,
                    null, null, sortOrder);

        case PERSON:
            long id = ContentUris.parseId(uri);
            String where = "_id=" + id;
            if (selection != null && !"".equals(selection)) {
                where = selection + " and " + where;
            }
            return db.query("person", projection, where, selectionArgs, null,
                    null, sortOrder);
        default:
            throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
    }
}
  • 重写它的类型方法,getType()
//返回数据的MIME类型。
@Override
public String getType(Uri uri) {
    Log.i(TAG, "PersonProvider get type");
    switch (MATCHER.match(uri)) {
        case PERSONS:
            return "vnd.android.cursor.dir/person";

        case PERSON:
            return "vnd.android.cursor.item/person";

        default:
            throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
    }
}

 

 五、 在MainActivity方法,为了方便得到数据库中的数据,添加了查询与增加方法:

package com.example.linux.contentproviderserver;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.example.linux.contentproviderserver.util.DBOpenHelper;

/**
 * writer: huhx
 * 内容提供器的服务端
 */
public class MainActivity extends AppCompatActivity {
    private final static String TAG = "PersonProvider";
    private DBOpenHelper dbOpenHelper;
    SQLiteDatabase database = null;
    private StringBuffer stringBuffer = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "main on create.");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbOpenHelper = new DBOpenHelper(this);
        database = dbOpenHelper.getWritableDatabase();
    }

    // 查询所有的数据
    public void queryAll(View view) {
        stringBuffer = new StringBuffer();
        Cursor cursor = database.rawQuery("select * from person", null);
        cursor.moveToFirst();
        while(cursor.moveToNext()) {
            String name = cursor.getString(1);
            int age = cursor.getInt(2);
            stringBuffer.append("name: " + name + ", age: " + age + "\n");
        }
        if (stringBuffer.toString().equals("")) {
            Toast.makeText(MainActivity.this, "nothing", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(MainActivity.this, stringBuffer, Toast.LENGTH_SHORT).show();
        }
    }

    //插入数据
    public void insertData(View view) {
        Object[] object = new Object[]{"linux", 23};
        database.execSQL("insert into person(name, age) values(?, ?)", object);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        database.close();
    }
}

 

使用内容提供器--Client

项目结构:

一、在MainActivity中增加了查询与插入功能:

package com.example.linux.contentproviderclient;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

/**
 * 内容提供器的客户端
 */
public class MainActivity extends AppCompatActivity {

    private StringBuffer stringBuffer = new StringBuffer();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // 插入数据
    public void insert(View view) {
        ContentResolver contentResolver = getContentResolver();
        Uri insertUri = Uri.parse("content://com.example.linux.contentproviderserver.action.PersonProvider/person");
        ContentValues values = new ContentValues();
        values.put("name", "wangkuifeng");
        values.put("age", 23);
        Uri uri = contentResolver.insert(insertUri, values);
        Toast.makeText(MainActivity.this, "insert success: " + uri, Toast.LENGTH_SHORT).show();
    }

    // 查询数据
    public void query(View view) {
        ContentResolver contentResolver = getContentResolver();
        Uri queryUri = Uri.parse("content://com.example.linux.contentproviderserver.action.PersonProvider/person/5");
        Cursor queryResult = contentResolver.query(queryUri, null, null, null, null);
        int count = queryResult.getCount();
        for (queryResult.moveToFirst(); !queryResult.isAfterLast(); queryResult.moveToNext()) {
            String name = queryResult.getString(1);
            int age = queryResult.getInt(2);
            stringBuffer.append("name: " + name + ", age: " + age + "\n");
        }
        Toast.makeText(MainActivity.this, stringBuffer.toString() + "\ncount: " + count, Toast.LENGTH_SHORT).show();
        queryResult.close();
    }
}

 

友情链接