美文网首页
Android 11 (API 30) ContentProvi

Android 11 (API 30) ContentProvi

作者: burglar | 来源:发表于2021-07-30 20:22 被阅读0次

参考:

《疯狂Android讲义》第四版,第九章

问题解决,参考:

https://stackoverflow.com/questions/63563995/failed-to-find-content-provider-in-api-30

https://www.sohu.com/a/448764139_611601

测试包含两个应用程序:FirstContentProviderFirstContentResolver,下面分别对两者进行说明

注意:本次开发在Android 11 (API 30)下完成

build.gradle关于版本的内容:

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.0"

    defaultConfig {
        applicationId "com.example.contentprovidertest"
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

FirstContentProvider

新建应用程序项目后(创建时可以选择Empty Activity),修改AndroidManifest.xml,增加如下内容:

        <provider
            android:authorities="com.example.provider"
            android:name=".FirstProvider"
            android:exported="true" />
image-20210730195012670.png

android:authorities="com.example.provider"字段可以自定义

android:name=".FirstProvider"中的FirstProvider就是需要创建的类,在MainActivity所在的包下新建该类:

package com.example.firstcontentprovider;

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

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

public class FirstProvider extends ContentProvider {
  @Override
  public boolean onCreate() {
    Log.d("--oncreate--", "--onCreate--方法被调用");
    return false;
  }

  @Nullable
  @Override
  public Cursor query(
      @NonNull Uri uri,
      @Nullable String[] strings,
      @Nullable String s,
      @Nullable String[] strings1,
      @Nullable String s1) {
    Log.d("--query--", "--query--方法被调用" + "," + " where参数为:" + s);
    return null;
  }

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

  @Nullable
  @Override
  public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
    Log.d("--insert--", "--insert--方法被调用" + "," + " value参数为:" + contentValues);
    return null;
  }

  @Override
  public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
    Log.d("--delete--", "--delete--方法被调用" + "," + " where参数为:" + s);
    return 0;
  }

  @Override
  public int update(
      @NonNull Uri uri,
      @Nullable ContentValues contentValues,
      @Nullable String s,
      @Nullable String[] strings) {
    Log.d(
        "--update--",
        "--update--方法被调用" + "," + " where参数为:" + s + ", " + "value参数为: " + contentValues);
    return 0;
  }
}

修改activity_main.xml,只是修改TextView的文本内容(不影响程序功能,这一步可做可不做):

image-20210730194644472.png

FirstContentResolver

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="query"
        android:id="@+id/btn_query" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="insert"
        android:id="@+id/btn_insert" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="update"
        android:id="@+id/btn_update" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="delete"
        android:id="@+id/btn_delete" />

</LinearLayout>

MainActivity.java

package com.example.firstcontentresolver;

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Button;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

  private Uri uri = Uri.parse("content://com.example.provider");
  private Button mBtnQuery, mBtnInsert, mBtnUpdate, mBtnDelete;

  @Override
  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mBtnQuery = findViewById(R.id.btn_query);
    mBtnInsert = findViewById(R.id.btn_insert);
    mBtnUpdate = findViewById(R.id.btn_update);
    mBtnDelete = findViewById(R.id.btn_delete);

    mBtnQuery.setOnClickListener(
        view -> {
          Cursor cursor = getContentResolver().query(uri, null, "query where", null, null);
          Toast.makeText(this, "远程ContentProvider返回的Cursor为:" + cursor, Toast.LENGTH_SHORT).show();
        });

    mBtnInsert.setOnClickListener(
        view -> {
          ContentValues values = new ContentValues();
          values.put("name", "android_insert");
          Uri newUri = getContentResolver().insert(uri, values);
          Toast.makeText(this, "远程ContentProvider新插入记录的Uri为:" + newUri, Toast.LENGTH_SHORT).show();
        });

    mBtnUpdate.setOnClickListener(
        view -> {
          ContentValues values = new ContentValues();
          values.put("name", "android_update");
          int count = getContentResolver().update(uri, values, "update_where", null);
          Toast.makeText(this, "远程ContentProvider更新记录数为:" + count, Toast.LENGTH_SHORT).show();
        });

    mBtnDelete.setOnClickListener(
        view -> {
          int count = getContentResolver().delete(uri, "delete_where", null);
          Toast.makeText(this, "远程ContentProvider删除记录数为:" + count, Toast.LENGTH_SHORT).show();
        });
  }
}

碰到的问题:Unknown URL content

如果编写完上述两个源文件,就运行两个程序,那么FristContentResolvert在点击主界面的按钮后,程序会崩溃,查看日志得到如下错误:

image-20210730195430019.png

经过一番搜索,这是在 Android 11 下才会出现的问题,简单来说,就是出于安全考虑,Android 11 要求应用事先说明需要访问的其他软件包

可以使用:adb shell dumpsys package queries查看哪些软件包是可以访问的,使用grep可以过滤出我们想要看的软件包,例如:

image-20210730200147582.png

解决的方法:使用<queries>标签说明需要访问的其他软件包

AndroidManifest.xml中添加<queries>

    <queries>
        <package android:name="com.example.firstcontentprovider" />
    </queries>
image-20210730200414162.png

运行程序进行测试

启动两个程序,打开FirstContentProviderLogCat

image-20210730200750156.png

按图中箭头标注的条件进行过滤

依次点击FirstContentResolver的四个按钮,可以看到:

image-20210730200955269.png

至此,测试完成

相关文章

网友评论

      本文标题:Android 11 (API 30) ContentProvi

      本文链接:https://www.haomeiwen.com/subject/ndmcvltx.html