android_content_provider

此插件暴露了 Android 上的 ContentProvider 和相关的 ContentResolver API。

Android 11 包可见性

Android 11 引入了一个名为包可见性的安全机制。

如果您正在使用 AndroidContentResolver 并尝试访问某个包中的内容提供程序,而该包默认
不可见,
则您的应用程序将无法连接到它。

要解决此问题,请在您的 AndroidManifest.xml 文件中添加一个名为<queries> 的新元素。

<manifest>
...
    <queries>
        <package android:name="com.example.app" />
    </queries>
...
</manifest>

配置 AndroidContentProvider

如果您只想使用 AndroidContentResolver,可以忽略这些步骤。

  1. 在您的 MainActivity 中使用插件提供的 FlutterEngineGroup
    以提高性能并减少引擎创建的内存占用。

    此步骤是可选的,但强烈推荐。

  • Kotlin

import android.content.Context
import com.nt4f04und.android_content_provider.AndroidContentProvider
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine

class MainActivity : FlutterActivity() {
    override fun provideFlutterEngine(context: Context): FlutterEngine? {
        return AndroidContentProvider.getFlutterEngineGroup(this)
                .createAndRunDefaultEngine(this)
    }
}
  • Java

import android.content.Context;

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

import com.nt4f04und.android_content_provider.AndroidContentProvider;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;

public class MainActivity extends FlutterActivity {
    @Nullable
    @Override
    public FlutterEngine provideFlutterEngine(@NonNull Context context) {
        return AndroidContentProvider.Companion.getFlutterEngineGroup(this)
                .createAndRunDefaultEngine(this);
    }
}
  1. 在原生代码中继承 AndroidContentProvider,并设置您要使用的 authority
  • Kotlin

import com.nt4f04und.android_content_provider.AndroidContentProvider

class MyAndroidContentProvider : AndroidContentProvider() {
   override val authority: String = "com.example.myapp.MyAndroidContentProvider"
   override val entrypointName = "exampleContentProviderEntrypoint"
}
  • Java

import com.nt4f04und.android_content_provider.AndroidContentProvider;

import org.jetbrains.annotations.NotNull;

public class MyAndroidContentProvider extends AndroidContentProvider {
    @NotNull
    @Override
    public String getAuthority() {
        return "com.example.myapp.MyAndroidContentProvider";
    }

    @NotNull
    @Override
    public String getEntrypointName() {
        return "exampleContentProviderEntrypoint";
    }
}
  1. AndroidManifest.xml 中声明您的 ContentProvider。
  • 如果您希望允许其他应用无条件访问提供程序

<provider
   android:name=".MyAndroidContentProvider"
   android:authorities="com.example.myapp.MyAndroidContentProvider"
   android:exported="true" />
  • 如果您希望其他应用声明 <uses-permission>

<provider
   android:name=".MyAndroidContentProvider"
   android:authorities="com.example.myapp.MyAndroidContentProvider"
   android:exported="false"
   android:readPermission="com.example.myapp.permission.READ"
   android:writePermission="com.example.myapp.permission.WRITE" />
  1. 在 Dart 代码中继承 AndroidContentProvider 并覆盖所需的方法

import 'package:android_content_provider/android_content_provider.dart';

class MyAndroidContentProvider extends AndroidContentProvider {
  MyAndroidContentProvider(String authority) : super(authority);

  @override
  Future<int> delete(
    String uri,
    String? selection,
    List<String>? selectionArgs,
  ) async {
    return 0;
  }

  @override
  Future<String?> getType(String uri) async {
    return null;
  }

  @override
  Future<String?> insert(String uri, ContentValues? values) async {
    return null;
  }

  @override
  Future<CursorData?> query(
    String uri,
    List<String>? projection,
    String? selection,
    List<String>? selectionArgs,
    String? sortOrder,
  ) async {
    return null;
  }

  @override
  Future<int> update(
    String uri,
    ContentValues? values,
    String? selection,
    List<String>? selectionArgs,
  ) async {
    return 0;
  }
}
  1. 创建 Dart 入口点

@pragma('vm:entry-point')
void exampleContentProviderEntrypoint() async {
   MyAndroidContentProvider('com.example.myapp.MyAndroidContentProvider');
}

GitHub

查看 Github