在低于6.0的android上获取READ_CONTACTS的SercurityException

时间:2019-07-08 09:21:09

标签: android kotlin android-contentprovider android-workmanager

当我尝试从ContentProvider查询联系信息时,我的应用程序的Fabric Crashlytics始终显示READ_CONTACTS的SercurityException权限拒绝。奇怪的是,日志显示所有这些事情都发生在低于Marshmallow(特别是5.1.1)的android系统上,无论是root用户还是非root用户,这都没有任何意义,因为只有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" />

1 个答案:

答案 0 :(得分:0)

请在您的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;
}