实例讲解Android中ContentProvider组件的使用方法

ContentProvider基本使用
为了在应用程序之间交换数据,android提供了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API,当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用程序就可以通过提供ContentPRovider来实现,其他应用程序就可以通过ContentResolver来操作ContentProvider暴露的数据。

实现ContentProvider的步骤:

1)编写一个类,继承ContentProvider,并且重写里面的CRUD方法。

2)在androidmanifest.xml文件中注册provider。

在androidmanifest.xml中注册provider需要以下3个属性:

android:name              provider的实现类。

android:authorities       provider的uri。

android:exported          provider是否暴露给其他程序。

ContentResovler操作ContentProvider:

1)获取ContentResolver,getContentResovler()方法来自于ContextWrapper,所以activity和service中都可以使用。

2)调用CURD方法,通过参数url,调用指定的ContentProvider的方法。

下面是一个demo,向contentProvider中插入一条数据,并且返回到listview中。

main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".Main" >

  <ListView
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

</RelativeLayout>

MySQLiteOpenHelper类

package com.app.dao;

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

public class MySQLiteOpenHelper extends SQLiteOpenHelper {

  public MySQLiteOpenHelper(Context context, String name,
      CursorFactory factory, int version) {
    super(context, name, factory, version);

  }

  @Override
  public void onCreate(SQLiteDatabase db) {

    String create_sql = "create table tb_test(_id integer primary key autoincrement,name,gender,age)";

    db.execSQL(create_sql);
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

  }

}

MyContentProvider类

package com.app.dao;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;

public class MyContentProvider extends ContentProvider{

  MySQLiteOpenHelper helper=null;
  @Override
  public int delete(Uri arg0, String arg1, String[] arg2) {

    return 0;
  }

  @Override
  public String getType(Uri arg0) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Uri insert(Uri arg0, ContentValues values) {

    String insert_sql="insert into tb_test values(null,'wx','boy',17)";

    helper.getReadableDatabase().execSQL(insert_sql);

    return null;
  }

  @Override
  public boolean onCreate() {

    helper=new MySQLiteOpenHelper(this.getContext(),"test.db3",null,1);

    return true;
  }

  @Override
  public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
      String arg4) {

    String query_sql="select * from tb_test";

    Cursor cursor=helper.getReadableDatabase().rawQuery(query_sql, null);

    return cursor;
  }

  @Override
  public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
    // TODO Auto-generated method stub
    return 0;
  }

}

listview的显示界面show.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="horizontal" >

  <TextView
    android:id="@+id/name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

  <TextView
    android:id="@+id/gender"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="60dp" />

  <TextView
    android:id="@+id/age"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="60dp" />

</LinearLayout>

Main.java

package com.app.main;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class Main extends Activity {

  ContentResolver resolver = null;

  ListView lv = null;

  @SuppressLint("NewApi")
  @Override
  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    lv = (ListView) this.findViewById(R.id.listview);

    resolver = this.getContentResolver();

    String str = "content://com.app.test.db/";

    Uri uri = Uri.parse(str);

    resolver.insert(uri, null);

    Cursor cursor = resolver.query(uri, null, null, null, null);

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
        R.layout.show, cursor,
        new String[] { "name", "gender", "age" }, new int[] {
            R.id.name, R.id.gender, R.id.age },
        CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

    lv.setAdapter(adapter);

  }

}

实现效果:(执行了3次插入后的效果)

ContentProvider的单元测试
ContentProvider是android的四大组件之一,在编写代码的时候最好是加上单元测试,这样可以确定对数据的CRUD的正确。本篇文章主要介绍ContentProvider中两个主要辅助类的使用还有单元测试的在ContentProvider中的使用。

需要用到的两个辅助类:UriMatcher类和ContentUris类。

UriMatcher类:能够对输入的uri参数就行匹配,以确定对什么表执行什么样的操作。

ContentUris类:有些方法需要返回uri,运用此类可以方便的生成uri类。

对于单元测试,个人觉得非常有必要在今后写代码的时候使用,这样可以非常准确的确定代码的正确性。

使用单元测试的步骤:

1)加入instrumentation,这个部分的代码是固定,也可以完全在ADT提供的向导中导入。

<instrumentation
    android:name="android.test.InstrumentationTestRunner"
    android:targetPackage="com.example.android_contentprovider" >
  </instrumentation>

2)添加<uses-library>,这个部分的代码也是固定的写法。

 <uses-library android:name="android.test.runner" />

好了,必备的知识已经讲完了,现在上代码:

1)生成一个SQLiteDatabase类,这个是必需的类MySQLiteOpenHelper类

package com.app.db;

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

public class MySQLiteOpenHelper extends SQLiteOpenHelper {

  private static String DB_NAME = "test.db3";
  private static int VERSION = 1;

  public MySQLiteOpenHelper(Context context) {
    super(context, DB_NAME, null, VERSION);

  }

  @Override
  public void onCreate(SQLiteDatabase db) {
       //建表语句
    String create_student = "create table student(_id integer primary key autoincrement,name varchar(10),age integer,gender vachar(10))";

    db.execSQL(create_student);
       //千万不能执行这句  // db.close();

  }

  @Override
  public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {

  }

}

然后添加我们需要的MyContentProvider类:

package com.app.contentprovider;

import com.app.db.MySQLiteOpenHelper;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;

public class MyContentProvider extends ContentProvider {

  MySQLiteOpenHelper helper = null;

  private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

  // 匹配单条记录
  private static final int student = 1;
  // 匹配多条记录
  private static final int students = 2;

  static {
    matcher.addURI("com.app.wx", "student/#", student);

    matcher.addURI("com.app.wx", "student", students);
  }

  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs) {

    SQLiteDatabase db = helper.getWritableDatabase();

    int action = matcher.match(uri);

    switch (action) {

    // 匹配单条记录
    case student:

      long id = ContentUris.parseId(uri);
     //获取单条记录的id号
      String delete_id = "_id=" + id;

      if (selection != null) {
        delete_id += delete_id + " and " + selection;
      }

      db.delete("student", delete_id, selectionArgs);

      break;

    // 匹配多条记录
    case students:

      db.delete("student", selection, selectionArgs);

      break;
    }

    return 0;
  }

  //必需实现这个方法,这个方法与intent有关系,以后再讲
  @Override
  public String getType(Uri uri) {

    int code = matcher.match(uri);
    switch (code) {
    case student:
      return "vnd.android.cursor.item/student_item";
    case students:
      return "vnd.android.cursor.dir/students";
    default:
      return null;
    }
  }

  @Override
  public Uri insert(Uri uri, ContentValues values) {

    SQLiteDatabase db = helper.getWritableDatabase();

    int action = matcher.match(uri);

    switch (action) {

    case students:

      long id1 = db.insert("student", "_id", values);

      Log.i("--------", ContentUris.withAppendedId(uri, id1).toString());

      return ContentUris.withAppendedId(uri, id1);

    }

    return null;
  }

  @Override
  public boolean onCreate() {

    helper = new MySQLiteOpenHelper(this.getContext());

    return true;
  }

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

    SQLiteDatabase db = helper.getWritableDatabase();

    Cursor cursor = null;

    int action = matcher.match(uri);

    switch (action) {

    case students:

      cursor = db.query("student", projection, selection, selectionArgs,
          null, null, orderBy);

      break;

    }

    System.out.println("-----------count:" + cursor.getCount());

    return cursor;
  }

  @Override
  public int update(Uri uri, ContentValues values, String selection,
      String[] arg3) {

    int count = -1;

    SQLiteDatabase db = helper.getWritableDatabase();

    int action = matcher.match(uri);

    switch (action) {

    case student:
      // 以id来处理更新
      long id = ContentUris.parseId(uri);

      String id_selection = "_id=" + id;

      if (selection != null && !selection.equals("")) {

        id_selection = id_selection + " and " + values;

      }

      count = db.update("student", values, id_selection, arg3);

      System.out.println("----------count:" + count);

      break;
    }

    return count;
  }

}

这个类很长,但是执行的方法都是比较常见的CURD的方法,重要的是UriMatcher和ContentUris类的使用。

接着执行单元测试类:Test

package com.app.contentprovider;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;

public class Test extends AndroidTestCase {

  public void insert() {

    ContentResolver resolver = this.getContext().getContentResolver();

    String str = "content://com.app.wx/student";

    ContentValues values = new ContentValues();

    values.put("name", "wzq");

    values.put("age", 18);

    values.put("gender", "boy");

    resolver.insert(Uri.parse(str), values);

  }

  public void update() {

    ContentResolver resolver = this.getContext().getContentResolver();

    String str = "content://com.app.wx/student/2";

    ContentValues values = new ContentValues();

    values.put("name", "哈哈");

    resolver.update(Uri.parse(str), values, null, null);

  }

  public void query() {

    ContentResolver resolver = this.getContext().getContentResolver();

    String str = "content://com.app.wx/student";

    Uri uri = Uri.parse(str);

    Cursor cursor = resolver.query(uri, new String[] { "_id",
        "name,age,gender" }, null, null, "_id desc");

    Log.d("------count",cursor.getCount()+"");
  }

  public void delete() {
    ContentResolver resolver = this.getContext().getContentResolver();

    String str = "content://com.app.wx/student/2";

    Uri uri = Uri.parse(str);

    long id=resolver.delete(uri, null, null);

  }

}

执行insert方法之后(执行了三次):

执行了update方法之后:

执行了query方法之后:

执行了delete方法之后:

(0)

相关推荐

  • Android 自定义ContentProvider简单实例

    Android 自定义ContentProvider简单实例 Android允许我们定义自己的的ContentProvider对象来共享数据,练练手,简单来实现一下. 要使用ContentProvider来操作数据,必须要有保存数据的场所.可以使用文件或SQLite数据库的方式来保存数据,通常使用SQLite数据库. 1,创建一个数据库帮助类,归根结底都是它在操作数据库.代码如下: package com.njue; import android.content.Context; import

  • Android 中ContentProvider的实例详解

    Android 中ContentProvider的实例详解 Content Provider 的简单介绍: * Android中的Content Provider 机制可支持在多个应用中存储和读取数据.这也是跨应用 共享数据的唯一方式.在Android系统中,没有一个公共的内存区域,供多个应用共享存储数据: * Android 提供了一些主要数据类型的ContentProvider ,比如:音频.视频.图片和私人通讯录等: 在android.provider 包下面找到一些android提供的C

  • Android数据持久化之ContentProvider机制详解

    本文实例讲述了Android数据持久化之ContentProvider机制.分享给大家供大家参考,具体如下: 一般而言,android操作系统的应用程序所建立的数据只允许自己使用,应用程序彼此间无法借助公用存储器来共享数据,android系统提供了一个机制,即内容提供器(ContentProvider),来公开自己私有的数据到数据内容器,通过该机制,可以供其他应用程序来读取自己内部的数据,当然也可以访问其他应用程序的数据.通常,内容提供器背后都有SQLite数据库的支持,用以存储内容提供内部数据

  • Android ContentProvider实现获取手机联系人功能

    在之前项目中有用到关于获取手机联系人的部分,闲置就想和大家分享一下,话不多说,上代码: java部分: package com.example.content; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle

  • android基础总结篇之八:创建及调用自己的ContentProvider

    今天我们来讲解一下如何创建及调用自己的ContentProvider. 在前面两篇文章中我们分别讲了如何读写联系人和短消息,相信大家对于ContentProvider的操作方法已经有了一定程度的了解.在有些场合,除了操作ContentProvider之外,我们还有可能需要创建自己的ContentProvider,来提供信息共享的服务,这就要求我们很好的掌握ContentProvider的创建及使用技巧.下面我们就由表及里的逐步讲解每个步骤. 在正式开始实例演示之前,我们先来了解以下两个知识点:

  • Android应用中使用ContentProvider扫描本地图片并显示

    之前群里面有朋友问我,有没有关于本地图片选择的Demo,类似微信的效果,他说网上没有这方面的Demo,问我能不能写一篇关于这个效果的Demo,于是我研究了下微信的本地图片选择的Demo,自己仿照的写了下分享给大家,希望对以后有这样子需求的朋友有一点帮助吧,主要使用的是ContentProvider扫描手机中的图片,并用GridView将图片显示出来,关于GridView和ListView显示图片的问题,一直是一个很头疼的问题,因为我们手机的内存有限,手机给每个应用程序分配的内存也有限,所以图片多

  • Android ContentProvider获取手机联系人实例

    在做项目的时候,因为要用到我们自动获取联系人的姓名和电话,就想到了ContentProvider分享数据的功能,这样做既节省了时间,也减少了我们输入错误号码的几率,所以,想在这里把小demo分享给大家,方便以后要用的时候可以看看 我们先看下获取所有联系人的方式,把所有联系人展示在listView上 public void getLinkMan(View view){ //获取联系人 Uri uri=Uri.parse("content://com.android.contacts/raw_con

  • Android 中自定义ContentProvider与ContentObserver的使用简单实例

    Android 中自定义ContentProvider与ContentObserver的使用简单实例 示例说明: 该示例中一共包含两个工程.其中一个工程完成了自定义ContentProvider,另外一个工程用于测试该自定义ContentProvider且在该工程中使用了ContentObserver监听自定义ContentProvider的数据变化 以下代码为工程TestContentProvider ContentProviderTest如下: package cn.testcontentp

  • 实例讲解Android中ContentProvider组件的使用方法

    ContentProvider基本使用 为了在应用程序之间交换数据,android提供了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API,当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用程序就可以通过提供ContentPRovider来实现,其他应用程序就可以通过ContentResolver来操作ContentProvider暴露的数据. 实现ContentProvider的步骤: 1)编写一个类,继承ContentProvid

  • 实例讲解Android中ViewPager组件的一些进阶使用技巧

    我们经常看到使用了ViewPager的App,在每页上面都会有一个滑块来标志当前处于哪一页.在PagerView包里有android.support.v4.view.PagerTitleStrip和android.support.v4.view.PagerTabStrip两个组件,可以在布局文件中,作为ViewPager的子标签,并设定相对与ViewPager的位置(比如顶部).但这两个组件都很丑,并且标题会随着页面一起滑动,所以一般都不用. 其实实现一个滑块标志当前页面也很简单,大概需要两步:

  • 实例讲解Android中的AutoCompleteTextView自动补全组件

    AutoCompleteTextView是一个具有自动补全功能的EditView,当用户输入数据后,AutoCompleteTextView就会将用户输入的数据与他自己的adapter中的数据对比,如果用户数据与adapter中的某条数据的开始部分完全匹配,那么adapter中的这条数据就会出现在下拉提示框中. 其常用属性定义如下 <AutoCompleteTextView android:id="@+id/mp002_top_place_input" android:layou

  • 实例讲解Android中的AIDL内部进程通信接口使用

    首先描述下我们想要实现的内容,我们希望在一个应用中通过点击按钮,去操作另一个进程中应用的音乐播放功能. 如图,我们点击"播放"时,系统就会去远程调用我们提供的一个service(与当前service不是同一个应用哦),然后操作service中的音乐播放,点击"停止"则会终止播放.想要重新播放的话,必须先点"销毁service",再点播放按钮哦.(至于这里为什么要先点销毁按钮才能播放,完全是为了给大家展示下,远程调用service时,怎么去解绑se

  • 实例讲解Android中SQLiteDatabase使用方法

    SQLite数据库是android系统内嵌的数据库,小巧强大,能够满足大多数SQL语句的处理工作,而SQLite数据库仅仅是个文件而已.虽然SQLite的有点很多,但并不是如同PC端的mysql般强大,而且android系统中不允许通过JDBC操作远程数据库,所以只能通过webservice等手段于php.servlet交互获取数据. SQLiteDatabase类,代表了一个数据库对象,通过SQLiteDatabase来操作管理数据库. 一些基本的用法:   static  SQLiteDat

  • 实例讲解Android中的View类以及自定义View控件的方法

    View的简单理解和实例 1.View的基本概念 在Activity显示的控件 都叫做View(View类 是所有的控件类的父类  比如 文本 按钮) 2.在Activity当中获取代表View的对象 Activity读取布局文件生成相对应的 各种View对象 TextView textView=(TextView)findViewBy(R.id.textView) 3.设置view的属性 Activity_mian.xml 这样的xml布局文件中发现了,类似@+id/和@id/到底有什么区别呢

  • 实例讲解Android Fragment的两种使用方法

    一.第一种方法: (1)Fragment的第一种使用方法是使用fragment加载单独的布局文件:(也就是xml的方式实现) 结构如下: activity_main.xml主要是在一个线性布局中添加两个线性布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" androi

  • Android中Activity组件实例介绍

    目录 Activity 概述 启动 Activity 的两种情况 关闭 Activity 总结 Activity 概述 在 Android 应用中,提供了 4 大基本组件,分别是 Activity.Service.BroadcastReceiver 和 ContentProvider.而 Activity 是 Android 应用最常见的组件之一.Activity 的中文意思是活动.在 Android 中,Activity 代表手机或者平板电脑中的一屏,它提供了和用户交互的可视化界面.在一个 A

  • Android中PopupMenu组件的使用实例

    最近学习研究了一下Android中PopupMenu组件的使用,发现很实用,所以留个笔记留作日后查询 估计很多人遇到过这种场景: 要求弹出的PopupWindow里面是一个列表,我们使用时都是在里面套个ListView或RecyclerView ,现在我们不需要在做这样繁琐的工作了. 在官方android.support.v7.widget 包下提供的 PopupMenu 组件,已经被越来越多的项目所采用.我们先看一下几个 app 的效果: 这是一个非常轻量化的上下文菜单组件,简洁.使用方便.

随机推荐