当前位置:   article > 正文

安卓四大组件之contentprovider_安卓contentprovider

安卓contentprovider

简介

ContentProvider 是 Android 的四大组件之一,有时候我们需要操作其他应用程序的一些数据,就会用到 ContentProvider,ContentProvider 本质上是一个中间者,真正 存储和操作数据 的数据源还是原来存储数据的方式,如数据库、文件或网络等。

ContentProvider 以相对安全的方式封装了数据并提供简易的处理机制和统一的访问接口供其他程序调用。它的底层采用了 Binder 机制来实现,ContentProvider 为应用间的数据交互提供了一个安全的环境:允许把自己的应用数据根据需求开放给 其他应用进行增删改查,而不用担心因为直接开放数据库权限而带来的安全问题。当然,ContentProvider不仅可以实现跨进程通信,也可实现进程内的通信。

在 Android 中,为一些常见的数据提供了默认的 ContentProvider,如通讯录等。
 

1.我们首先需要创建一个provider

 这个uri填写你创建的那个文件夹的目录

 代码演示

步骤一:创建数据库类,并建立一个student表

  1. package com.example.provider;
  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteOpenHelper;
  5. import android.widget.Button;
  6. import androidx.annotation.Nullable;
  7. public class MyDBhelper extends SQLiteOpenHelper {
  8. public MyDBhelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
  9. super(context,name ,null, version);
  10. }
  11. @Override
  12. public void onCreate(SQLiteDatabase sqLiteDatabase) {
  13. sqLiteDatabase.execSQL("create table student(" +
  14. "id integer primary key autoincrement," +
  15. "name varchar(20)," +
  16. "age interger)");
  17. }
  18. @Override
  19. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  20. }
  21. }

步骤二:创建一个 MyContentProvider ,继承自 ContentProvider 抽象类。其中,在 onCreate() 方法中,先对数据库初始化,并往数据库中的student表中添加两条数据。

  1. package com.example.provider;
  2. import android.content.ContentProvider;
  3. import android.content.ContentValues;
  4. import android.database.Cursor;
  5. import android.net.Uri;
  6. public class MyContentProvider extends ContentProvider {
  7. public MyContentProvider() {
  8. }
  9. @Override
  10. public int delete(Uri uri, String selection, String[] selectionArgs) {
  11. return 0;
  12. }
  13. @Override
  14. public String getType(Uri uri) {
  15. return null;
  16. }
  17. @Override
  18. public Uri insert(Uri uri, ContentValues values) {
  19. System.out.println(uri+"====insert方法被调用====");
  20. System.out.println("values参数为:"+values);
  21. return null;
  22. }
  23. @Override
  24. public boolean onCreate() {
  25. System.out.println("====onCreate方法被调用====");
  26. return true;
  27. }
  28. @Override
  29. public Cursor query(Uri uri, String[] projection, String selection,
  30. String[] selectionArgs, String sortOrder) {
  31. System.out.println(uri+"===query方法被调用===");
  32. System.out.println("where参数为:"+"where");
  33. return null;
  34. }
  35. @Override
  36. public int update(Uri uri, ContentValues values, String selection,
  37. String[] selectionArgs) {
  38. System.out.println(uri+"===update方法被调用===");
  39. System.out.println("where参数为:“where+”,values参数为:"+values);
  40. return 0;
  41. }
  42. }

步骤三:注册(一般建立的时候会自动注册,不过还是最好瞅一下有没有)

  1. <provider
  2. android:name=".MyContentProvider"
  3. android:authorities="com.example.provider"
  4. android:enabled="true"
  5. android:exported="true" >
  6. </provider>

步骤四:进程内使用 ContentResolver 操作 ContentProvider。

  1. private fun operateData() {
  2. val student = Uri.parse("content://com.example.provider/student")
  3. // 向 student 表插入一条数据
  4. contentResolver.insert(userUri, ContentValues().apply {
  5. put("id", 3)
  6. put("name", "chen")
  7. put("age","18")
  8. })
  9. // 查询 student 表数据
  10. val cursor = contentResolver.query(userUri, arrayOf("id", "name","age"), null, null, null)
  11. while (cursor!!.moveToNext()) {
  12. println("query user:" + cursor.getInt(0) + " " + cursor.getString(1))
  13. }
  14. // 主动关闭游标
  15. cursor.close()
  16. }

上面是一个app的操作,下面是两个app的跨进程使用

步骤一:创建数据库类,建表

  1. class DBHelper(
  2. context: Context
  3. ) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
  4. override fun onCreate(db: SQLiteDatabase) {
  5. // 创建两个表格:用户表 和 职业表
  6. db.execSQL("CREATE TABLE IF NOT EXISTS $USER_TABLE_NAME(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)")
  7. db.execSQL("CREATE TABLE IF NOT EXISTS $JOB_TABLE_NAME(_id INTEGER PRIMARY KEY AUTOINCREMENT, job TEXT)")
  8. }
  9. override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {}
  10. companion object {
  11. // 数据库名
  12. private const val DATABASE_NAME = "finch.db"
  13. // 表名
  14. const val USER_TABLE_NAME = "user"
  15. const val JOB_TABLE_NAME = "job"
  16. //数据库版本号
  17. private const val DATABASE_VERSION = 1
  18. }
  19. }

步骤二:创建一个 MyContentProvider ,继承自 ContentProvider 抽象类。其中,在 onCreate() 方法中,先对数据库初始化,并往数据库中的 user 表和 job 表分别添加两条数据。

  1. class MyContentProvider : ContentProvider() {
  2. private lateinit var mDbHelper: DBHelper
  3. private lateinit var db: SQLiteDatabase
  4. private val mMatcher: UriMatcher by lazy {
  5. val matcher = UriMatcher(UriMatcher.NO_MATCH)
  6. matcher.addURI(AUTHORITY, "user", User_Code)
  7. matcher.addURI(AUTHORITY, "job", Job_Code)
  8. matcher
  9. }
  10. override fun onCreate(): Boolean {
  11. mDbHelper = DBHelper(context!!)
  12. db = mDbHelper.writableDatabase
  13. // 初始化两个表的数据 (先清空两个表,再各加入一个记录)
  14. db.execSQL("delete from user")
  15. db.execSQL("insert into user values(1,'yang');")
  16. db.execSQL("insert into user values(2,'zhang');")
  17. db.execSQL("delete from job")
  18. db.execSQL("insert into job values(1,'Android');")
  19. db.execSQL("insert into job values(2,'iOS');")
  20. return true
  21. }
  22. override fun insert(uri: Uri, values: ContentValues?): Uri {
  23. val table = getTableName(uri)
  24. db.insert(table, null, values)
  25. // 通知外部调用者数据发生变化
  26. context?.contentResolver?.notifyChange(uri, null)
  27. return uri
  28. }
  29. override fun query(
  30. uri: Uri, projection: Array<String>?, selection: String?,
  31. selectionArgs: Array<String>?, sortOrder: String?
  32. ): Cursor? {
  33. val table = getTableName(uri)
  34. return db.query(table, projection, selection, selectionArgs, null, null, sortOrder, null)
  35. }
  36. override fun update(
  37. uri: Uri, values: ContentValues?, selection: String?,
  38. selectionArgs: Array<String>?
  39. ): Int {
  40. return 0
  41. }
  42. override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
  43. return 0
  44. }
  45. override fun getType(uri: Uri): String? {
  46. return null
  47. }
  48. private fun getTableName(uri: Uri): String? {
  49. var tableName: String? = null
  50. when (mMatcher.match(uri)) {
  51. User_Code -> tableName = DBHelper.USER_TABLE_NAME
  52. Job_Code -> tableName = DBHelper.JOB_TABLE_NAME
  53. }
  54. return tableName
  55. }
  56. companion object {
  57. private const val AUTHORITY = "com.yang.provider.myprovider"
  58. const val User_Code = 1
  59. const val Job_Code = 2
  60. }
  61. }

步骤三:在 androidManifest.xml 中注册 MyContentProvider

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="xxx.xxxx">
  4. <!--声明使用 MyContentProvider 的通信的权限 (开放所有权限) -->
  5. <permission
  6. android:name="com.yang.provider.myprovider.PROVIDER"
  7. android:protectionLevel="normal" />
  8. <!--声明使用 MyContentProvider 的通信的权限 (开放读权限) -->
  9. <permission
  10. android:name="com.yang.provider.myprovider.Read"
  11. android:protectionLevel="normal" />
  12. <!--声明使用 MyContentProvider 的通信的权限 (开放写权限) -->
  13. <permission
  14. android:name="com.yang.provider.myprovider.Write"
  15. android:protectionLevel="normal" />
  16. <application>
  17. <!--通过 android:permission、readPermission、writePermission 等属性定义 MyContentProvider 的通信权限-->
  18. <provider
  19. android:name=".MyContentProvider"
  20. android:authorities="com.yang.provider.myprovider"
  21. android:exported="true"
  22. android:permission="com.yang.provider.myprovider.PROVIDER"
  23. // android:readPermission="com.yang.provider.myprovider.Read"
  24. // android:writePermission="com.yang.provider.myprovider.Write"
  25. />
  26. </application>
  27. </manifest>

第二个app中

步骤一:声明访问进行 1 中的 ContentProvider 所需要的权限

<uses-permission android:name="com.yang.provider.myprovider.PROVIDER" />

步骤二:使用 ContentResolver 操作 进程 1 的 ContentProvider。

  1. private fun operateData() {
  2. val userUri = Uri.parse("content://com.yang.provider.myprovider/user")
  3. val jobUri = Uri.parse("content://com.yang.provider.myprovider/job")
  4. // 对 user 表进行操作
  5. contentResolver.insert(userUri, ContentValues().apply {
  6. put("_id", 4)
  7. put("name", "huang")
  8. })
  9. val cursor = contentResolver.query(userUri, arrayOf("_id", "name"), null, null, null)
  10. while (cursor!!.moveToNext()) {
  11. println("ipc query user:" + cursor.getInt(0) + " " + cursor.getString(1))
  12. }
  13. cursor.close()
  14. // 对 job 表进行操作
  15. contentResolver.insert(jobUri, ContentValues().apply {
  16. put("_id", 4)
  17. put("job", "algorithm")
  18. })
  19. val cursor2 = contentResolver.query(jobUri, arrayOf("_id", "job"), null, null, null)
  20. while (cursor2!!.moveToNext()) {
  21. println("ipc query job:" + cursor2.getInt(0) + " " + cursor2.getString(1))
  22. }
  23. cursor2.close()
  24. }
  25. // 执行 operateData() 方法,输出结果如下:
  26. I/System.out: ipc query user:1 yang
  27. I/System.out: ipc query user:2 zhang
  28. I/System.out: ipc query user:4 huang
  29. I/System.out: ipc query job:1 Android
  30. I/System.out: ipc query job:2 iOS
  31. I/System.out: ipc query job:4 algorithm

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/932795
推荐阅读
相关标签
  

闽ICP备14008679号