从内容uri访问联系人照片

时间:2017-05-25 05:18:54

标签: android

我正在尝试从联系人ACTION_PICK意图名称,电话号码和照片返回的联系人中访问许多内容。检索姓名和电话号码没有问题,但是当我尝试访问照片时,我每次都会收到SecurityException,并说明需要GLOBAL_SEARCH权限。这是logcat ......

Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.ContactsProvider2 uri content://com.android.contacts/contacts/14/photo from pid=4526, uid=10223 requires android.permission.GLOBAL_SEARCH, or grantUriPermission()

我已经梳理了stackoverflow并尝试了我发现的每一种方法,并且作为一项完整性检查我现在正在使用谷歌推荐的方法,如下所示

public InputStream retrieveContactPhoto() {

    Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.valueOf(mContactID));
    Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
    Cursor cursor = getContentResolver().query(photoUri,
            new String[] {Contacts.Photo.PHOTO}, null, null, null);
    if (cursor == null) {
        return null;
    }
    try {
        if (cursor.moveToFirst()) {
            byte[] data = cursor.getBlob(0);
            if (data != null) {
                return new ByteArrayInputStream(data);
            }
        }
    } finally {
        cursor.close();
    }
    return null;

}

但是,我在每种情况下都得到相同的SecurityException。它在contentResolver查询行中抛出。显然,没有办法获得GLOBAL_READ权限,所以我不太清楚如何解决这个问题。 此外,由于我能够毫无问题地检索姓名和电话号码,我无法想象我是如何创建意图的,但是为了完整性,这是startActivityForResult()调用

Intent contactIntent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);

startActivityForResult(contactIntent, INTERVIEWEE_FROM_CONTACTS);

我已经浏览过互联网,无法找到有人接收此SecurityException的案例,我所看到的只是需要READ_CONTACTS和WRITE_CONTACTS权限的应用,因此我确信我和忽略了一些显而易见的东西,但我只是完全被难倒了。我在运行Nougat的Nexus 6p上进行测试。 请帮忙!

2 个答案:

答案 0 :(得分:0)

menifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8"/>

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

    <application android:label="@string/app_name">
        <activity android:name="MyActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

main.xml中

<?xml version="1.0" encoding="utf-8"?>
<!-- @res/layout/main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent" >

    <Button android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Select a Contact"
            android:onClick="onClickSelectContact" />

    <ImageView android:id="@+id/img_contact"
               android:layout_height="wrap_content"
               android:layout_width="match_parent"
               android:adjustViewBounds="true"
               android:contentDescription="Contacts Image"
                />
</LinearLayout>

MyActivity .java

 public class MyActivity extends Activity {

        private static final String TAG = MyActivity.class.getSimpleName();
        private static final int REQUEST_CODE_PICK_CONTACTS = 1;
        private Uri uriContact;
        private String contactID;     // contacts unique ID


        /**
         * Called when the activity is first created.
         */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
getPermissionToReadUserContacts(); 
        }
     public void getPermissionToReadUserContacts() {
        // 1) Use the support library version ContextCompat.checkSelfPermission(...) to avoid
        // checking the build version since Context.checkSelfPermission(...) is only available
        // in Marshmallow
        // 2) Always check for permission (even if permission has already been granted)
        // since the user can revoke permissions at any time through Settings
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {

            // The permission is NOT already granted.
            // Check if the user has been asked about this permission already and denied
            // it. If so, we want to give more explanation about why the permission is needed.
            if (shouldShowRequestPermissionRationale(
                    Manifest.permission.READ_CONTACTS)) {
                // Show our own UI to explain to the user why we need to read the contacts
                // before actually requesting the permission and showing the default UI
            }

            // Fire off an async request to actually get the permission
            // This will show the standard permission request dialog UI
            requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
                    READ_CONTACTS_PERMISSIONS_REQUEST);
        }
    }
        public void onClickSelectContact(View btnSelectContact) {

            // using native contacts selection
            // Intent.ACTION_PICK = Pick an item from the data, returning what was selected.
            startActivityForResult(new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI), REQUEST_CODE_PICK_CONTACTS);
        }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);

            if (requestCode == REQUEST_CODE_PICK_CONTACTS && resultCode == RESULT_OK) {
                Log.d(TAG, "Response: " + data.toString());
                uriContact = data.getData();

                retrieveContactName();
                retrieveContactNumber();
                retrieveContactPhoto();

            }
        }

        private void retrieveContactPhoto() {

            Bitmap photo = null;

            try {
                InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(),
                        ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, new Long(contactID)));

                if (inputStream != null) {
                    photo = BitmapFactory.decodeStream(inputStream);
                    ImageView imageView = (ImageView) findViewById(R.id.img_contact);
                    imageView.setImageBitmap(photo);
                }

                assert inputStream != null;
                inputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        private void retrieveContactNumber() {

            String contactNumber = null;

            // getting contacts ID
            Cursor cursorID = getContentResolver().query(uriContact,
                    new String[]{ContactsContract.Contacts._ID},
                    null, null, null);

            if (cursorID.moveToFirst()) {

                contactID = cursorID.getString(cursorID.getColumnIndex(ContactsContract.Contacts._ID));
            }

            cursorID.close();

            Log.d(TAG, "Contact ID: " + contactID);

            // Using the contact ID now we will get contact phone number
            Cursor cursorPhone = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},

                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ? AND " +
                            ContactsContract.CommonDataKinds.Phone.TYPE + " = " +
                            ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE,

                    new String[]{contactID},
                    null);

            if (cursorPhone.moveToFirst()) {
                contactNumber = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            }

            cursorPhone.close();

            Log.d(TAG, "Contact Phone Number: " + contactNumber);
        }

        private void retrieveContactName() {

            String contactName = null;

            // querying contact data store
            Cursor cursor = getContentResolver().query(uriContact, null, null, null, null);

            if (cursor.moveToFirst()) {

                // DISPLAY_NAME = The display name for the contact.
                // HAS_PHONE_NUMBER =   An indicator of whether this contact has at least one phone number.

                contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            }

            cursor.close();

            Log.d(TAG, "Contact Name: " + contactName);

        }






    }

答案 1 :(得分:0)

您通过以下方式检查是否授予了权限:

checkSelfPermission(Manifest.permission.READ_CONTACTS)

必要时请求权限

if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {
    requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
    // app-defined int constant

    return;
}

处理权限请求响应

 public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! do the
                // calendar task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'switch' lines to check for other
        // permissions this app might request
    }
}