IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 安卓开发(七)内容提供器(ContentProvider) -> 正文阅读

[移动开发]安卓开发(七)内容提供器(ContentProvider)

七 内容提供器(ContentProvider)

7.1 介绍

  • 内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。目前,使用内容提供器是Android实现跨程序共享数据的标准方式。
  • 不同于文件存储和SharedPreferences存储中的两种全局可读写操作模式,内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。

7.2 运行时权限

  • Android的权限机制并不是什么新鲜事物,从系统的第一个版本开始就已经存在了。但其实之前Android的权限机制在保护用户安全和隐私等方面起到的作用比较有限,尤其是一些大家都离不开的常用软件,非常容易店大欺客。
  • 为此,Android开发团队在Android 6.0系统中引用了运行时权限这个功能,从而更好地保护了用户的安全和隐私,那么本节我们就来详细学习一下这个6.0系统中引入的新特性。
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

epub_26211889_201.jpg

7.3 动态申请权限

  • 先声明AndroidManifest权限
<uses-permission android:name="android.permission.CALL_PHONE" />
  • 布局文件
<?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=".MainActivity">


    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="打电话"
        android:onClick="call"
        />


</LinearLayout>
  • 主要代码
package com.shu;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
    
    /**
    * 打电话
    * @param view
    */
    public void call(View view){
        //检查用户是否授权
        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE)!= PackageManager.PERMISSION_GRANTED){
            //没有授权则提示用户进行授权
            ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE},1);
        }else {
            //内置动作,需要申明权限
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        }
    }
    
    /**
    * 权限请求结果
    * @param requestCode
    * @param permissions
    * @param grantResults
    */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode){
            case 1:
                if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    Intent intent = new Intent(Intent.ACTION_CALL);
                    intent.setData(Uri.parse("tel:10086"));
                    startActivity(intent);
                }
                else {
                    Toast.makeText(this,"权限未通过",Toast.LENGTH_LONG).show();
                }
                break;
            default:
        }
    }
}
  • 因此,第一步就是要先判断用户是不是已经给过我们授权了,借助的ContextCompat.checkSelfPermission()方法。
  • checkSelfPermission()方法接收两个参数,第一个参数是Context,这个没什么好说的,第二个参数是具体的权限名,比如打电话的权限名就是Manifest.permission.CALL_PHONE,然后我们使用方法的返回值和PackageManager. PERMISSION_GRANTED做比较,相等就说明用户已经授权,不等就表示用户没有授权。
  • 如果已经授权的话就简单了,直接去执行拨打电话的逻辑操作就可以了,这里我们把拨打电话的逻辑封装到了call()方法当中。如果没有授权的话,则需要调用ActivityCompat. requestPermissions()方法来向用户申请授权,requestPermissions()方法接收3个参数,第一个参数要求是Activity的实例,第二个参数是一个String数组,我们把要申请的权限名放在数组中即可,第三个参数是请求码,只要是唯一值就可以了,这里传入了1。

image.png
image.png

7.4 ContentResolver

  • 对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助Content-Resolver类,可以通过Context中的getContentResolver()方法获取到该类的实例。
  • Content-Resolver中提供了一系列的方法用于对数据进行CRUD操作,其中insert()方法用于添加数据,update()方法用于更新数据,delete()方法用于删除数据,query()方法用于查询数据。
  • 不同于SQLiteDatabase, ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri参数代替,这个参数被称为内容URI。内容URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authority和path。
  • authority是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名。
content://com.android.contacts/data/phones 
手机联系人url

查询方法

 cursor=getContentResolver().query();

  public final  Cursor query( Uri uri,
            String[] projection, String selection,
            String[] selectionArgs,  String sortOrder) {
        return query(uri, projection, selection, selectionArgs, sortOrder, null);
 }

![epub_26211889_207.jpg](https://img-blog.csdnimg.cn/img_convert/7b3423a379f8bfcdeb42b782fbdab64e.png#clientId=ubda6a572-d1fe-4&crop=0&crop=0&crop=1&crop=1&from=drop&id=u8be2f858&margin=[object Object]&name=epub_26211889_207.jpg&originHeight=272&originWidth=1280&originalType=binary&ratio=1&rotation=0&showTitle=false&size=41739&status=done&style=none&taskId=u7e351c8b-f4d1-42af-ba49-a43c2732732&title=)

//读取电话通讯录
    private void read(){
        Cursor cursor = null;
        try {
            System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
            cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
            if(cursor!=null){
                while (cursor.moveToNext()){
                    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    listViews.add(name+"\n"+phone);
                }
                adapter.notifyDataSetChanged();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(cursor!=null){
                cursor.close();
            }
        }
    }

插入数据
将待添加的数据组装到ContentValues中,然后调用ContentResolver的insert()方法,将Uri和ContentValues作为参数传入即可。

/**
     * 插入一条数据
     */
    public void add(){
        System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        ContentValues contentValues=new ContentValues();
        contentValues.put("admin",10086);
        getContentResolver().insert(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues)

    }

修改数据

/**
     * 修改数据
     */
    public void update(){
        System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        ContentValues contentValues=new ContentValues();
        contentValues.put("admin","");
        getContentResolver().update(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues,"admin=?",new String[]{"10001"});
    }

删除数据

 /**
     * 删除数据
     */
    public void delete(){
        System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        ContentValues contentValues=new ContentValues();
        contentValues.put("admin","");
        getContentResolver().delete(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,"admin=?",new String[]{"10001"});
    }

7.5 读取通讯录

  • 声明读取权限
  <uses-permission android:name="android.permission.READ_CONTACTS"/>
  • 界面
<?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=".FirstActivity">
    <ListView
        android:id="@+id/listview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>
  • 主要代码
package com.shu;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

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

public class FirstActivity extends AppCompatActivity {
    ArrayAdapter<String> adapter;
    List<String> listViews=new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        ListView listView = (ListView) findViewById(R.id.listview);
        adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, listViews);
        listView.setAdapter(adapter);
        //没有权限
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(FirstActivity.this,new String[]{Manifest.permission.READ_CONTACTS},1);
        }else{
            read();
        }
    }
    
    
    //读取电话通讯录
    private void read(){
        Cursor cursor = null;
        try {
            System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
            cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
            if(cursor!=null){
                while (cursor.moveToNext()){
                    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    listViews.add(name+"\n"+phone);
                }
                adapter.notifyDataSetChanged();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(cursor!=null){
                cursor.close();
            }
        }
    }
    
    
    /**
    * 插入一条数据
    */
    public void add(){
        System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        ContentValues contentValues=new ContentValues();
        contentValues.put("admin",10086);
        getContentResolver().insert(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues);
    }
    
    
    /**
    * 修改数据
    */
    public void update(){
        System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        ContentValues contentValues=new ContentValues();
        contentValues.put("admin","");
        getContentResolver().update(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,contentValues,"admin=?",new String[]{"10001"});
    }
    
    
    /**
    * 删除数据
    */
    public void delete(){
        System.out.println("xxx读取url:"+ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        ContentValues contentValues=new ContentValues();
        contentValues.put("admin","");
        getContentResolver().delete(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,"admin=?",new String[]{"10001"});
    }
    
    
    
    //权限不足时申明权限
    @Override
    public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) {
        switch (requestCode){
            case 1:
                if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    read();
                }
                else {
                    Toast.makeText(this,"权限未通过",Toast.LENGTH_LONG).show();
                }
                break;
            default:
        }
    }
}

image.png

7.6 自定义内容提供器

方推荐的方式就是使用内容提供器,可以通过新建一个类去继承ContentProvider的方式来创建一个自己的内容提供器。ContentProvider类中有6个抽象方法,我们在使用子类继承它的时候,需要将这6个方法全部重写。

package com.shu;

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

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * @author shu
 * @date 2021/7/22
 * @description 自定义内容处理器
 */
public class MyProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
}

  • onCreate()初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。

  • query()从内容提供器中查询数据。使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。

  • insert()向内容提供器中添加一条数据。使用uri参数来确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。

  • update()更新内容提供器中已有的数据。使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。

  • delete()从内容提供器中删除数据。使用uri参数来确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。

  • getType()根据传入的内容URI来返回相应的MIME类型,是所有的内容提供器都必须提供的一个方法,用于获取Uri对象所对应的MIME类型。一个内容URI所对应的MIME字符串主要由3部分组成,Android对这3个部分做了如下格式规定。必须以vnd开头。如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/。 最后接上vnd.. 。

content://com.shu.provider/table1

vnd.android.cursor.dir/vnd.com.shu. provider.table1

7.7 实战

先定义一个内容提供器完成对数据的操作

package com.shu;


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

/**
 * @author shu
 * @date 2022/3/29
 * @description 跨程序共享处理器
 */

public class DatabaseProvider 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 final String AUTHORITY = "com.shu.databasesave.provider";

    private static final UriMatcher uriMatcher;

    private MyDatabaseHelper helper;

    static {
        //在静态代码块中对UriMatcher进行初始化操作,并将期望匹配的几种URI格式添加进去
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY, "book", BOOK_DIR);
        uriMatcher.addURI(AUTHORITY, "book/#", BOOK_ITEM);
        uriMatcher.addURI(AUTHORITY, "category", CATEGORY_DIR);
        uriMatcher.addURI(AUTHORITY, "category/#", CATEGORY_ITEM);
    }

    @Override
    public boolean onCreate() {
        //完成创建、升级 BookStore数据库
        helper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);
        return true;
    }


    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        //查询数据
        SQLiteDatabase db = helper.getWritableDatabase();
        Cursor cursor = null;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                cursor = db.query("Book", projection, "id = ?", new String[]{bookId}, null, null, sortOrder);
                break;
            case CATEGORY_DIR:
                cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                cursor = db.query("Category", projection, "id = ?", new String[]{categoryId}, null, null, sortOrder);
                break;
            default:
                break;
        }
        return cursor;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        //添加数据
        SQLiteDatabase db = helper.getWritableDatabase();
        Uri uriReturn = null;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
            case BOOK_ITEM:
                long newBookId = db.insert("Book", null, values);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/book/" + newBookId);
                break;
            case CATEGORY_DIR:
            case CATEGORY_ITEM:
                long newCategoryId = db.insert("Category", null, values);
                uriReturn = Uri.parse("content://" + AUTHORITY + "/category/" + newCategoryId);
                break;
            default:
                break;
        }
        return uriReturn;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        //更新数据
        SQLiteDatabase db = helper.getWritableDatabase();
        int updateRows = 0;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                updateRows = db.update("Book", values, selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                updateRows = db.update("Book", values, "id = ?", new String[]{bookId});
                break;
            case CATEGORY_DIR:
                updateRows = db.update("Category", values, selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                updateRows = db.update("Category", values, "id = ?", new String[]{categoryId});
                break;
            default:
                break;
        }
        return updateRows;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        //删除数据
        SQLiteDatabase db = helper.getWritableDatabase();
        int deleteRows = 0;
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                deleteRows = db.delete("Book", selection, selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId = uri.getPathSegments().get(1);
                deleteRows = db.delete("Book", "id = ?", new String[]{bookId});
                break;
            case CATEGORY_DIR:
                deleteRows = db.delete("Category", selection, selectionArgs);
                break;
            case CATEGORY_ITEM:
                String categoryId = uri.getPathSegments().get(1);
                deleteRows = db.delete("Category", "id = ?", new String[]{categoryId});
                break;
            default:
                break;
        }
        return deleteRows;
    }

    @Override
    public String getType(Uri uri) {
        switch (uriMatcher.match(uri)) {
            case BOOK_DIR:
                return "vnd.android.cursor.dir/vnd.com.shu.databasesave.provider.book";
            case BOOK_ITEM:
                return "vnd.android.cursor.item/vnd.com.shu.databasesave.provider.book";
            case CATEGORY_DIR:
                return "vnd.android.cursor.dir/vnd.com.shu.databasesave.provider.category";
            case CATEGORY_ITEM:
                return "vnd.android.cursor.item/vnd.com.shu.databasesave.provider.category";
        }
        return null;
    }

}
package com.shu;


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

/**
 * @author shu
 * @date 2022/3/29
 * @description 自定义工具类
 */
public class MyDatabaseHelper extends SQLiteOpenHelper {
    private Context context;

    public static final String CREATE_BOOK = "create table Book(" +
            "id integer primary key autoincrement," +
            "author text," +
            "price real," +
            "pages integer," +
            "name text)";

    public static final String CREATE_CATEGORY = "create table Category(" +
            "id integer primary key autoincrement," +
            "category_name text," +
            "category_code integer)";

    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        this.context = context;
    }


    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);//执行sql语句创建Book表
        db.execSQL(CREATE_CATEGORY);//执行sql语句创建Category表
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db);
    }
}
<!--注册内容提供器-->
<provider
          android:name=".DatabaseProvider"
          android:authorities="com.shu.databasesave.provider"
          android:enabled="true"
          android:exported="true">
</provider>

再定义一个测试

<?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="vertical">


    <Button
        android:id="@+id/btn_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add Data To Book"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Query Data From Book"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Update Book"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/btn_delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Delete Data From Book"
        android:textAllCaps="false"
        android:textSize="18sp"
        android:textStyle="bold" />


</LinearLayout>
package com.example.providertest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;


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

import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    private Button btn_add, btn_query, btn_update, btn_delete;
    private String newId;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();//初始化UI控件
    }
    
    private void initView() {
        btn_add = (Button) findViewById(R.id.btn_add);
        btn_query = (Button) findViewById(R.id.btn_query);
        btn_update = (Button) findViewById(R.id.btn_query);
        btn_delete = (Button) findViewById(R.id.btn_delete);
        
        btn_add.setOnClickListener(this);
        btn_query.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
    }
    
    
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_add:
                add();//添加数据
                Toast.makeText(this, "add successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_query:
                query();//查询数据
                Toast.makeText(this, "query successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_update:
                update();//更新数据
                Toast.makeText(this, "update successfully", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_delete:
                delete();//删除数据
                Toast.makeText(this, "delete successfully", Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
    }
    
    
    private void add() {
        Uri uri = Uri.parse("content://com.shu.databasesave.provider/book");
        ContentValues cv = new ContentValues();
        cv.put("name", "A Clash of Kings");
        cv.put("author", "George Martin");
        cv.put("pages", 1040);
        cv.put("price", 22.85);
        Uri newUri = getContentResolver().insert(uri, cv);
        newId = newUri.getPathSegments().get(1);
    }
    
    private void query() {
        Uri uri = Uri.parse("content://com.shu.databasesave.provider/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"));
                Log.e(TAG, "book name is " + name);
                Log.e(TAG, "book author is " + author);
                Log.e(TAG, "book pages are " + pages);
                Log.e(TAG, "book price is " + price);
            }
            cursor.close();
        }
    }
    
    private void update() {
        Uri uri = Uri.parse("content://com.shu.databasesave.provider/book/" + newId);
        ContentValues cv = new ContentValues();
        cv.put("name", "A Storm of Swords");
        cv.put("pages", 1216);
        cv.put("price", 24.05);
        getContentResolver().update(uri, cv, null, null);
    }
    
    private void delete() {
        Uri uri = Uri.parse("content://com.shu.databasesave.provider/book/" + newId);
        getContentResolver().delete(uri, null, null);
    }
}

image.png

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:22:54  更:2022-04-04 12:26:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 20:25:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码