首页 > 解决方案 > 在低于 6.0 的 android 上获取 READ_CONTACTS 的 SercurityException

问题描述

当我尝试从 ContentProvider 查询联系信息时,我的应用程序的 Fabric Crashlytics 不断出现 SercurityException 权限拒绝 READ_CONTACTS。奇怪的是日志显示所有这些事情都发生在低于 Marshmallow(特别是 5.1.1)的 android 上,包括有根和无根,这没有任何意义,因为运行时权限只需要 6.0 及更高版本的 android .

我永远无法重现该问题。在结构上获取数以千计的日志,无论我多么努力,我都无法在我的所有设备上得到任何真实的日志。

操作在一个派生自 WorkerManager 框架的 RxWorker 的 Worker 实例中运行。像这样从函数 createWork 开始

override fun createWork(): Single<Result> {
        if (!isContactPermissionGranted()) {
            return Single.just(Result.failure())
        }

        return Observable.create { 
            it.onNext(contactFetcher.fetchAll())
            it.onComplete()
        }
        .flatMap { // Do something with the data }
        .map { Result.success() }
        .onErrorReturn { Result.failure() }       
}

这是contactFetcher中的fetchAll函数

public ArrayList<Contact> fetchAll() throws Exception {

        String[] projectionFields = new String[]{
                ...
        };
        ...
        Cursor c = null;
        try {
            c = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, projectionFields, null, null, ContactsContract.Contacts.DISPLAY_NAME);
            if (c != null && c.moveToFirst()) {
                // Do something with the return cursor...
            }
        } finally {
            if (c != null) {
                c.close();
            }
        }
        ...
}

这是 crashlytics 日志:

Non-fatal Exception: java.lang.SecurityException
Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{3bd623d1 11061:vn.com/u0a175} (pid=11061, uid=10175) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS

是的,我确实把<uses-permission android:name="android.permission.READ_CONTACTS" />我的清单

标签: androidkotlinandroid-contentproviderandroid-workmanager

解决方案


请在您的添加以下权限AndroidManifest.xml

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

以下java代码正在我身边

private ArrayList<Contacts> fetchAll() {
    ArrayList<Contacts> contacts = new ArrayList<>();
    Cursor c = null;
    try {
        c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
                null, null, null, ContactsContract.Contacts.DISPLAY_NAME);
        if (c != null && c.moveToFirst()) {

            do {

            }while (c.moveToNext());
        }
    } finally {
        if (c != null) {
            c.close();
        }
    }

    return contacts;
}

推荐阅读