Android ContentResolver 内容解析者(解析器)----重新认识Android(11)
16lz
2021-01-23
ContentResolver 内容解析者(解析器) 一、Content Provider (内容 提供者 )简介: (一)、引入: 数据库在Android当中是私有的 ,不能将数据库设为WORLD_READABLE, 每个数据库都只能创建它的包访问 。这意味着 只有创建这个数据库的应用程序才可访问它 。也就是说不能跨越进程和包,直接访问别的应用程序的数据库。那么如何在应用程序间交换数据呢?可以使用ContentProvider(内容提供者)来实现。这样就更加安全可靠(想从我家借东西,你不能直接进来拿,要我拿给你). 为什么要暴露数据呢?系统中的电话簿,短信,媒体库等数据,其他app希望访问. (二)、ContentProvider的功能和意义: 为了在应用程序之间交换数据,Android提供了 ContentProvider ,它是不同应用程序之间进行数据交换的标准API。 当一个应用程序需要把自己的数据暴露给其他应用程序使用时,该应用程序可以通过提供ContentProvider来实现; 而其他应用程序需要使用这些数据时,不管提供数据的应用程序是否启动,可以通过 ContentResolver 来操作ContentProvider暴露的数据。包括增加数据insert()、删除数据delete()、修改数据update()、查询数据query()等。 虽然大部分使用ContentProvider操作的数据都来自于数据库,但是也可以来自于文件、SharedPreferences、XML或网络等其他存储方式。 (三)、核心类: 1、 ContentProvider 内容提供者 :(需要暴露数据的A应用程序--类似于服务器端) 可以通过继承一个 ContentProvider 的 抽象类 将自己的数据暴露出去; A应用通过Uri向外暴露数据。只要将A应用安装到手机上。无论是否运行,其他应用都可以从A应用获取数据。 外界不知道,也无需知道A应用暴露的数据在A应用当中是如何存储的,(是用数据库存储还是用文件存储,还是通过网上获得),外界可以通过一套标准的接口 读取或修改A应用里的数据. 2、 ContentResolver 内容解析者 :(访问操作A应用所暴露的数据--类似于客户端) 外界的程序通过 ContentResolver 可以访问 ContentProvider 提供的数据; 3、 Uri统一资源标识符: Uri是ContentResolver和ContentProvider进行数据交换的标识。 例如一个Uri是 content://com.qf.day16_contentprovider_t/user/5 Uri 的标准前缀 (协议protocal) :以“ content:// ”作为前缀,表示该数据由 ContentProvider 管理。 Uri 的 authority 部分(授权,权限):" com.qf.day16_contentprovider_t "该部分是暴露数据的app的包名。(要求小写)。 Uri 的 path 部分(路径): " user " 用于判断请求的路径(哪些数据被请求)。 被请求的特定记录的 id 值[可选的]: "5" 如果请求不仅限于某个单条数据,该部分及其前面的斜线应该删除。 将一个字符串转换成Uri的方式: Uri uri = Uri.parse("..............") 【备注:】URI、URL的区别: 首先,URI,是 uniform resource identifier ,统一资源标识符,用来唯一的标识一个资源。 URL是 uniform resource locator ,统一资源定位器, 它是一种具体的URI ,即URL可以用来标识一个资源,而且还指明了如何 定位 这个资源。 也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL则是具体的资源标识的方式。可以认为 URL是一种具体的URI ,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI是一种语义上的抽象概念,可以是绝对的,也可以是相对的, 而URL则必须提供足够的信息来定位,所以,是绝对的。
整个通话记录列表lv 上下文菜单中的删除项:action_delete 通话记录编号tv_id 对方电话号码tv_number 通话开始时间tv_date 通话类型(呼出/呼入/未接)tv_type 注意需要申请权限,否则运行会出现异常:WRITE_CALL_LOG,READ_CALL_LOG
/** * ContentProvider内容提供者 1.主要用于不同的应用程序之间,共享数据的。 A:ContentProvider:向外提供数据的 * 用于通过Uri向外暴露数据。只要将应用安装到手机上。无论是否运行,都可以获取数据。 B:ContentResolver:获取并解析数据 * 用于解析通过ContentProvider暴露 出来的数据。 A应用暴露出的是Uri,B应用使用该Uri就可以访问A应用暴露出来的数据了。 * ===================================================== * 本例用于实现通过ContentResovler来获取手机中通话记录 * 通话记录存储在内部存储的系统应用目录中:data/data/com.android.providers.contacts/contacts2.db * 对外暴露的Uri:"content://call_log/calls" * step1:通过 getContentResolver ()获取ContentResovler对象 * step2:获取通话记录的Uri:"content://call_log/calls" * step3:执行查询:ContentResovler对象.query(uri,查询的字段, 条件,条件的参数,排序依据); * step4:添加权限: READ_CALL_LOG 读取通话记录, WRITE_CALL_LOG 写通话记录 通话记录表的核心字段" _id ", * " number "电话号码, " date "时间(毫秒值), " type ": 1:呼入 2:呼出 3:未接 */
/** * 短信息的程序的数据库文件:/data/data/com.android.providers.telephony/mmssms.db * Uri:content://sms * step1:获取contentResolver对象 * step2:获取短信息的Uri * step3:查询,插入 * step4:添加权限: READ_SMS , WRITE_SMS * @author Administrator * 核心字段: _id , address 电话号码, body 信息文本, type 类型(1.接收;2.发送), date 时间(毫秒) */ 四、使用 ContentResolver 查询 联系人 : (一)、 [总结]使用ContentResolver 操作数据的步骤: 1、调用Context的 getContentResolver ()方法获得ContentResolver 对象; 2、调用ContentResolver 的 query() 方法查询数据。 · Cursor query (Uri uri , String[] projection , String where, String[] whereArgs, String sortOrder) 参数解释: String[] projection :表示select语句中需要查询的所有的字段组成的字符串数组。 String where:表示带有 占位符 的where子句组成的字符串; String[] whereArgs:表示 替换 where参数中 占位符 的数据组成的字符串数组; String sortOrder:表示select语句中的order by子句组成的字符串; (二)、 联系人中 管理ContentProvider的几个Uri: 1、联系人的Uri==> content://com.android.contacts/ raw_contacts 2、电话/邮件地址等数据的Uri==> content://com.android.contacts/ data 数据库位置 :/data/data/com.android.providers.contacts/databases/contacts2.db 用可视化工具打开(例如SQLite Expert) 核心表: 1.raw_contacts原始联系人表 "_id":联系人的id "display_name":联系人的姓名 2.data数据表 "raw_contact_id":作为外键参照raw_contacts表的_id字段 "data1":具体数据,例如手机号,email,姓名等 "mimetype_id":数据的大类型,例如 1:email; 5:电话; 7:姓名; 在mimetypes表中对应于_id字段 3.mimetypes表 "_id":类型id "mimetype":具体类型,例如_id为7的mimetype是 vnd.android.cursor.item/name 1 电子邮件 2 即时通讯 3 昵称 4 组织,单位 5 电话号码 6 邮编 7 名字 8 地址 9 身份证识别号 10 头像 11 组群 /** * 操作手机的联系人: 应用程序数据所在的位置:/data/data/com.android.providers/contacts/contacts2.db * step1:获取ContentResolver对象 * step2:提供Uri 1、联系人的Uri==> * content://com.android.contacts/raw_contacts * 2、电话/邮件地址等数据的Uri==> content://com.android.contacts/data * step3:执行查询 * step4: 添加权限 : READ_CONTACTS * * @author Administrator */标签注册ContentProvider。 (二)、ContentProvider类中的六个抽象方法: 1、boolean onCreate () 初始化provider 注意没有ContentResolver试图访问你的Provider之前,它不会创建出来. 2、Uri insert (Uri uri, ContentValues values) 插入新数据到ContentProvider 3、int delete (Uri uri, String selection, String[] selectionArgs) 从ContentProvider中删除数据 4、int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) 更新ContentProvider已经存在的数据 5、Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 返回数据给调用者 6、String getType (Uri uri) 返回ContentProvider数据的MIME类型 (三)、在清单文件中声明注册ContentProvider: android:authorities ="com.qf.wordscontentprovider" android:exported ="true" /> // android:name 属性的值:ContentProvider类的子类的完整路径; // android:authorities 属性的值:对应于content:URI中的authority部分。 // android:exported 属性是否允许其他应用调用。如果是false,则该ContentProvider不允许其他应用调用。 【备注:】 ContentProvider是 单例模式 的,当多个应用程序通过使用ContentResolver 来操作使用ContentProvider 提供的数据时,ContentResolver 调用的数据操作会委托给同一个ContentProvider 来处理。这样就能保证数据的一致性。 数据库工具类DBHelper.java import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DBHelper extends SQLiteOpenHelper { public DBHelper(Context context , int versionCode ){ super ( context , "users.db" , null , versionCode ); } @Override public void onCreate(SQLiteDatabase db ) { // TODO 初始化创建表 db . execSQL ( "create table t_user(_id integer primary key ,uname,upass,money)" ); db . execSQL ( "create table t_order(_id integer primary key ,product_name,price,user_id)" ); //对于 sqlite 来说,只要是integer的主键,则是自动增长的,无需用 autoincrement 指定 db . execSQL ( "insert into t_user(uname,upass,money) values('disen','123',1000)" ); db . execSQL ( "insert into t_user(uname,upass,money) values('jack','234',10000)" ); } @Override public void onUpgrade(SQLiteDatabase db , int oldVersion , int newVersion ) { // TODO 升级数据库(删除旧表,创建新表) if ( newVersion > oldVersion ){ db .execSQL( "drop table if exists t_user" ); db .execSQL( "drop table if exists t_order" ); onCreate( db ); } } } 在AndroidManifest.xml中的标签中: < provider android:name = "com.user.contentprovider.UserContentProvider" android:authorities = "com.user.contentprovider.users" android:exported = "true" /> UserContentProvider.java public class UserContentProvider extends ContentProvider { // 声明当前ContentProvider组件的唯一标识(Authority),注:必须使用小写字母 private static final String AUTHORITY = "com. user .contentprovider.users" ; // 声明访问当前应用下的数据库中哪些资源,给这些访问资源声明code标识 private static final int CODE_USER = 0; private static final int CODE_ORDER = 6; // 声明完整的资源访问 Uri 的匹配器--UriMatcher,实例化它并增加资源访问的 Uri private static UriMatcher uriMatcher ; static { uriMatcher = new UriMatcher(UriMatcher. NO_MATCH ); // 值是-1 //UriMatcher. addURI (String authority, String path, int code) // 用Resolver访问时的 Uri 为 // content://com.qf.contentprovider.users/users uriMatcher .addURI( AUTHORITY , "users" , CODE_USER ); // content://com.qf.contentprovider.users/orders uriMatcher .addURI( AUTHORITY , "orders" , CODE_ORDER ); //假设是订单表 } /** * 自定义的数据库工具类 */ private DBHelper dbHelper ; @Override public boolean onCreate() { // TODO 初始化ConentProvider组件,实例化数据库操作工具类 dbHelper = new DBHelper( getContext (), 1);//第二个参数是版本号 return true ; // 成功返回true } @Override public Cursor query(Uri uri , String[] projection , String selection , String[] selectionArgs , String sortOrder ) { // TODO 查询数据表 SQLiteDatabase db = dbHelper .getReadableDatabase(); // 先以读写方式打开数据库,一旦磁盘空间满了, // 会继续尝试以只读方式打开数据库。 Cursor cursor = null ; // 查询的结果 // 通过 Uri 匹配器,判断当前请求的 Uri 是访问哪一资源的code switch ( uriMatcher .match( uri )) { case CODE_USER : // 查询t_users用户表的数据: cursor = db .query( "t_user" , projection , selection , selectionArgs , null , null , sortOrder ); break ; //case CODE_ORDER:..... } return cursor ; } @Override public Uri insert(Uri uri , ContentValues values ) { // TODO 向数据表中插入数据 SQLiteDatabase db = dbHelper .getReadableDatabase(); // 先以读写方式打开数据库,一旦磁盘空间满了, // 会继续尝试以只读方式打开数据库。 if ( uriMatcher .match( uri ) == CODE_USER ) {//如果是插入t_user表 long id = db .insert( "t_user" , null , values ); db .close(); return ContentUris. withAppendedId ( uri , id ); // 将给定的id追加到路径末尾返回 } //else if().... return null ; } @Override public int delete(Uri uri , String selection , String[] selectionArgs ) { // TODO 删除数据表中数据 SQLiteDatabase db = dbHelper .getReadableDatabase(); if ( uriMatcher .match( uri ) == CODE_USER ) { int cnt = db .delete( "t_user" , selection , selectionArgs ); db .close(); return cnt ;//返回收到影响的行数 } return 0; } @Override public int update(Uri uri , ContentValues values , String selection , String[] selectionArgs ) { // TODO 更新数据表中的数据 SQLiteDatabase db = dbHelper .getReadableDatabase(); if ( uriMatcher .match( uri ) == CODE_USER ) { int cnt = db .update( "t_user" , values , selection , selectionArgs ); db .close(); return cnt ;//返回收到影响的行数 } return 0; } @Override public String getType(Uri uri ) { // TODO Auto-generated method stub return null ; } } 在另外一个app中利用ContentResolver来使用自定义的ContentProvider暴露出来的数据:
整个通话记录列表lv 上下文菜单中的删除项:action_delete 通话记录编号tv_id 对方电话号码tv_number 通话开始时间tv_date 通话类型(呼出/呼入/未接)tv_type 注意需要申请权限,否则运行会出现异常:WRITE_CALL_LOG,READ_CALL_LOG
/** * ContentProvider内容提供者 1.主要用于不同的应用程序之间,共享数据的。 A:ContentProvider:向外提供数据的 * 用于通过Uri向外暴露数据。只要将应用安装到手机上。无论是否运行,都可以获取数据。 B:ContentResolver:获取并解析数据 * 用于解析通过ContentProvider暴露 出来的数据。 A应用暴露出的是Uri,B应用使用该Uri就可以访问A应用暴露出来的数据了。 * ===================================================== * 本例用于实现通过ContentResovler来获取手机中通话记录 * 通话记录存储在内部存储的系统应用目录中:data/data/com.android.providers.contacts/contacts2.db * 对外暴露的Uri:"content://call_log/calls" * step1:通过 getContentResolver ()获取ContentResovler对象 * step2:获取通话记录的Uri:"content://call_log/calls" * step3:执行查询:ContentResovler对象.query(uri,查询的字段, 条件,条件的参数,排序依据); * step4:添加权限: READ_CALL_LOG 读取通话记录, WRITE_CALL_LOG 写通话记录 通话记录表的核心字段" _id ", * " number "电话号码, " date "时间(毫秒值), " type ": 1:呼入 2:呼出 3:未接 */
public class Main3Activity extends AppCompatActivity { // step2:提供要解析数据对应的Uri,就是电话记录的uri private Uri uri_callLog = CallLog.Calls.CONTENT_URI;// 系统提供的常量,表示通话记录对外暴露的Uri // 上面常量的值就是 Uri.parse("content://call_log/calls")得到的结果. private ContentResolver contentResolver; private ListView lv_listview; private MyCursorAdapter adapter;// 自定义的适配器类对象 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); lv_listview = (ListView) findViewById(R.id.lv_listview); // step1:获取ContentResolver contentResolver = getContentResolver(); queryCallLog();// 调用自定义的方法,用于查询并显示通话记录 // 注册 上下文菜单:可以删除某个通话记录 registerForContextMenu(lv_listview); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); getMenuInflater().inflate(R.menu.call_menu, menu);// 上下文菜单,只有一个"删除"选项 } // 上下文菜单点击时间处理 @Override public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); int position = menuInfo.position;// 获得弹出上下文菜单时所选中的条目的位置 Cursor cursor = adapter.getCursor();// 调用CursorAdapter的获取cursor对象的方法 cursor.moveToPosition(position);// 把cursor作为数据源,移动到指定位置 int id = cursor.getInt(cursor.getColumnIndex("_id"));// 通话记录表calls中的字段 switch (item.getItemId()) { case R.id.action_delete: // 删除一条记录 int count = deleteCallLog(id);// 调用自定义的删除通话记录的方法 if (count > 0) { Toast.makeText(Main3Activity.this, "删除成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(Main3Activity.this, "删除失败", Toast.LENGTH_SHORT).show(); } break; default: break; } queryCallLog();// 调用自定义的重新查询的方法 return super.onContextItemSelected(item); } /** * 删除一条指定的通话记录 * * @param id * @return */ public int deleteCallLog(int id) { int count = contentResolver.delete(uri_callLog, "_id=?", new String[]{id + ""});// 也可以第二个参数传"_id="+id,第三参数传null return count; } /** * 通过contentResolver,查询uri所指向的通话记录数据 * 第一个参数:要操作的应用暴露出的uri。指向通话记录的数据 * 第二个参数:要查询的字段 * 第三个参数:查询的条件 * 第四个参数:条件的参数值 * 第五个参数:排序 */ // 查询数据 public void queryCallLog() { // step3:通过contentResolver获取数据 //Uri uri,String[] projection列名数组,String selection查询条件,String[] selectionArgs替换占位符的数组,String sortOrder Cursor cursor = contentResolver.query(uri_callLog, new String[]{"_id", "number", "date", "type"}, null, null, "date desc"); // SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, // R.layout.item_listview, cursor, new String[] { "_id", "number", // "date", "type" }, new int[] { R.id.tv_id, // R.id.tv_number, R.id.tv_date, R.id.tv_type }, // CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//这样填进去日期就只能显示成毫秒数了,不美观 // 因此可以使用继承CursorAdapter的自定义适配器来适配Cursor数据 // 父类CursorAdapter没有无参的构造方法,必须如此传参: adapter = new MyCursorAdapter(this, cursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); // 最后一个参数表示,如果数据源发生变化则在后面学习的Loader中可以动态更新. lv_listview.setAdapter(adapter); } // 自定义的继承抽象类CursorAdapter的适配器 class MyCursorAdapter extends CursorAdapter { // 继承抽象类,重写两个抽象方法 public MyCursorAdapter(Context context, Cursor c, int flags) { super(context, c, flags);// 父类没有无参的构造方法,必须如此传参 } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { // 指定布局文件,生成一个条目的View对象,注意,在内部类中,上下文是MainActivity.this return LayoutInflater.from(Main3Activity.this).inflate(R.layout.item_listview, null); } @Override public void bindView(View view, Context context, Cursor cursor) { // 填充数据到每个条目的内部组件上,类似于继承BaseAdapter中重写getView()方法 TextView tv_id = (TextView) view.findViewById(R.id.tv_id); TextView tv_number = (TextView) view.findViewById(R.id.tv_number); TextView tv_date = (TextView) view.findViewById(R.id.tv_date); TextView tv_type = (TextView) view.findViewById(R.id.tv_type); // 从cursor获取数据,显示到textview上 tv_id.setText("" + cursor.getInt(cursor.getColumnIndex("_id"))); tv_number.setText(cursor.getString(cursor.getColumnIndex("number"))); long dateNum = cursor.getLong(cursor.getColumnIndex("date"));// 获取以毫秒表示的date数据 Date date = new Date(dateNum);// 利用毫秒数构建Date对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); tv_date.setText(sdf.format(date)); int typeNum = cursor.getInt(cursor.getColumnIndex("type")); if (typeNum == 1) { tv_type.setText("呼入"); } else if (typeNum == 2) { tv_type.setText("呼出"); } else { tv_type.setText("未接"); } } }}
/** * 短信息的程序的数据库文件:/data/data/com.android.providers.telephony/mmssms.db * Uri:content://sms * step1:获取contentResolver对象 * step2:获取短信息的Uri * step3:查询,插入 * step4:添加权限: READ_SMS , WRITE_SMS * @author Administrator * 核心字段: _id , address 电话号码, body 信息文本, type 类型(1.接收;2.发送), date 时间(毫秒) */ 四、使用 ContentResolver 查询 联系人 : (一)、 [总结]使用ContentResolver 操作数据的步骤: 1、调用Context的 getContentResolver ()方法获得ContentResolver 对象; 2、调用ContentResolver 的 query() 方法查询数据。 · Cursor query (Uri uri , String[] projection , String where, String[] whereArgs, String sortOrder) 参数解释: String[] projection :表示select语句中需要查询的所有的字段组成的字符串数组。 String where:表示带有 占位符 的where子句组成的字符串; String[] whereArgs:表示 替换 where参数中 占位符 的数据组成的字符串数组; String sortOrder:表示select语句中的order by子句组成的字符串; (二)、 联系人中 管理ContentProvider的几个Uri: 1、联系人的Uri==> content://com.android.contacts/ raw_contacts 2、电话/邮件地址等数据的Uri==> content://com.android.contacts/ data 数据库位置 :/data/data/com.android.providers.contacts/databases/contacts2.db 用可视化工具打开(例如SQLite Expert) 核心表: 1.raw_contacts原始联系人表 "_id":联系人的id "display_name":联系人的姓名 2.data数据表 "raw_contact_id":作为外键参照raw_contacts表的_id字段 "data1":具体数据,例如手机号,email,姓名等 "mimetype_id":数据的大类型,例如 1:email; 5:电话; 7:姓名; 在mimetypes表中对应于_id字段 3.mimetypes表 "_id":类型id "mimetype":具体类型,例如_id为7的mimetype是 vnd.android.cursor.item/name 1 电子邮件 2 即时通讯 3 昵称 4 组织,单位 5 电话号码 6 邮编 7 名字 8 地址 9 身份证识别号 10 头像 11 组群 /** * 操作手机的联系人: 应用程序数据所在的位置:/data/data/com.android.providers/contacts/contacts2.db * step1:获取ContentResolver对象 * step2:提供Uri 1、联系人的Uri==> * content://com.android.contacts/raw_contacts * 2、电话/邮件地址等数据的Uri==> content://com.android.contacts/data * step3:执行查询 * step4: 添加权限 : READ_CONTACTS * * @author Administrator */
public class MainActivity extends Activity implements OnClickListener {private Uri uri_raw_contact = Uri.parse("content://com.android.contacts/raw_contacts");// raw_contacts表private Uri uri_data = Uri.parse("content://com.android.contacts/data");private ContentResolver contentResolver;private ListView lv_listview;private Button btn_queryData; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);contentResolver = getContentResolver();initView();// 自定义的获取组件引用和注册监听器的方法queryContacts();// 自定义的查询联系人的方法} public void initView() {lv_listview = (ListView) findViewById(R.id.lv_listview);btn_queryData = (Button) findViewById(R.id.btn_queryData);btn_queryData.setOnClickListener(this);} /** * 获取联系人的信息,并且显示到listview上。 用SimpleAdapter进行适配 */public void queryContacts() {List
一、自定义ContentProvider: (一)、操作步骤: 1、自己编写一个类,必须继承自 ContentProvider 类; 2、实现ContentProvider类中所有的抽象方法; 需要实现: onCreate () 、 getType() 、 query () 、 insert () 、 update ()、 delete () 等方法。 【备注:】 ContentProvider暴露出来的数据和方法是给其他应用程序来调用。 其他应用程序通过ContentResolver对象调用 query () 、 insert () 、 update ()、 delete () 等。 3、定义ContentProvider的Uri。这个Uri是ContentResolver对象执行CRUD操作时重要的参数; 4、使用UriMatcher对象映射Uri返回代码 ;【超纲】 5、在AndroidMainfest.xml文件中使用public class MainActivity extends Activity{ private TextView tv_info; private ContentResolver resolver; private Uri uri = Uri.parse("content://com.user.contentprovider.users/users"); @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.layout_main); tv_info = (TextView)findViewById(R.id.tv_info); resolver = getContentResolver(); } public void click(View v){ switch (v.getId()) { case R.id.bt_query: //建表时的语句:create table t_user(_id integer primary key,uname,upass,money) query();//调用自定义的查询所有数据的方法 break; case R.id.bt_insert: insert();//调用自定义的插入数据的方法 break; case R.id.bt_update: //请自行实现 break; default: break; } } private void insert() { //调用自定义的插入数据的方法(硬编码) ContentValues values = new ContentValues(); values.put("uname", "zhang"); values.put("upass", "321"); values.put("money", "99"); Uri nUri = resolver.insert(uri, values);//sqlite会自动指定主键id long newId = ContentUris.parseId(nUri);//获取新插入的id Toast.makeText(this, ""+newId, 0).show(); } private void query() { //自定义的查询所有数据的方法 Cursor c = resolver.query(uri , new String[]{"_id","uname","upass","money"}, null, null,null); String text = ""; while(c.moveToNext()){ text +=c.getString(0)+","+c.getString(1)+","+c.getString(2)+","+c.getString(3)+"\n"; } tv_info.setText(text); }}
更多相关文章
- 2020版本Android 开发者学习路线(热门技术+学习方法+书籍+必须知
- Android中有几种数据存储方式,每种方式有哪些特点?
- Ubuntu Linux下android源码下载方法
- ANDROID STRINGS.XML的特殊字符_安卓STRING.XML添加空格或字符的