Android6 互換モード(3) コンテントプロパイダーの動作
互換モード:「Android6.0以上の端末で、インストールタイムパーミッションモデルで実行しているアプリケーションが、端末の設定画面から、特定のパーミッションをはく奪された時」の動作確認記事三本目です。
連絡先アクセス(コンテントプロパイダー経由)での動作を調査してみました。
結論としては、読み込み時は取得したCursorのsizeが0となりあまり影響はないといった感じです。
結論としては、読み込み時は取得したCursorのsizeが0となりあまり影響はないといった感じです。
以下調査結果です。
互換モードでどのような動作をするかを調査するために、targetSdkVersion=21で作成したアプリをAndroid OS 6.0の端末にインストールし、設定画面より電話帳のアクセス(READ_CONTACTS及びWRITE_CONTACTS)を不許可にした時の動作を確認しました。
また、比較のため、同じコードをtargetSdkVersion=23に変更しAndroid 6.0の端末にインストールした時の動作も確認しました(requestPermissionはしていないので必ずSecurityException等なんらかのExceptionを吐く)
連絡先グループとパーミッション
パーミッショングループ | パーミッション | 説明 |
---|---|---|
CONTACTS | READ_CONTACTS | 連絡先の読み取り 携帯端末に保存されている連絡先に関するデータの読み取りをアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、アプリに連絡先データの保存を許可することになり、悪意のあるアプリによって知らないうちに連絡先データが共有される恐れがあります。 |
WRITE_CONTACTS | 連絡先の変更 携帯端末に保存されている連絡先に関するデータの変更をアプリに許可します。このデータには、電話、メール、または他の手段で特定の相手と連絡をとった頻度も含まれます。これにより、アプリが連絡先データを削除できるようになります。 |
|
GET_ACCOUNTS | この端末上のアカウントの検索 携帯端末で認識されているアカウントのリストの取得をアプリに許可します。これには、インストールしたアプリによって作成されたアカウントも含まれます。 |
連絡先読み取りのテストコード
AndroidManifest.xmltargetSdkVersion=xxx <uses-permission android:name="android.permission.READ_CONTACTS"/>ソース
// 連絡先情報の取得 Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); ….
連絡先変更のテストコード
AndroidManifest.xmltargetSdkVersion=xxx <uses-permission android:name="android.permission.WRITE_CONTACTS"/>ソース
ContentValues values = new ContentValues(); // 連絡先情報の追加 Uri uri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values); long id = ContentUris.parseId(uri); values.put(ContactsContract.Data.RAW_CONTACT_ID, id); values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); values.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, ("TestContact" + id)); getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values); // 連絡先情報の更新 values.clear(); values.put(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY, "CustomContact"); getContentResolver().update(ContactsContract.RawContacts.CONTENT_URI, values, (ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE 'TestContact%' "), null); // 連絡先情報の削除 getContentResolver().delete(ContactsContract.RawContacts.CONTENT_URI, (ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " = 'CustomContact' "), null); ….
テスト環境
- Nexsus 5をAndroid 6.0にバージョンアップした物
- イメージバージョン番号:MRA58K
※アンドキュメントな部分なので確認した環境です
結果
Android6.0上で設定メニューから「連絡先」パーミッショングループを不許可にした場合
targetSdkVersion=21
互換モードの動作です。
- 連絡先情報の読み取り時:
- 無条件で空(Cursor#getCount()が0)のCursorが返却される
- 連絡先情報の追加時:
- ContentProviderへの書き込みが行われず、IDが0となる以下のUriが返却される
- ContactsContract.RawContacts.CONTENT_URIへの書き込み:
- content://com.android.contacts/raw_contacts/0
- ContactsContract.Data.CONTENT_URIへの書き込み:
- content://com.android.contacts/data/0
- 連絡先情報の更新時:
- ContentProvider上のデータの更新が行われず、更新件数として0が返却される
- 連絡先情報の削除時:
- ContentProvider上のデータの削除が行われず、削除件数として0が返却される
targetSdkVersion=23
本来requestPermissionすべきですがしてませんのでエラー系となるのが当然です。
- 連絡先情報の読み取り時:
- ContentResolver#query()呼び出し時に以下のSecurityExceptionが発生
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{39efe3a 7259:com.example.taosoftware.contactstest/u0a120} (pid=7259, uid=10120) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
- 連絡先情報の追加・更新・削除時:
- ContentResolver#insert(),ContentResolver#update(),ContentResolver#delete()呼び出し時に以下のSecurityExceptionが発生
ava.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{55a5f77 7412:com.example.taosoftware.contactstest/u0a120} (pid=7412, uid=10120) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
まとめ
互換モードの時、連絡先情報は0件として扱わる。NULLが返るわけではないので、既存アプリがぬるぽでおちるといった事はない。更新や削除は「0件処理をしました」という結果がかえりこれもあまり影響はないと考えられる。一部のアプリでは書き込み処理をした後のIDを取得して処理等行う事があるかもしれないが、最終的にハングアップという動作は考えにくい。
他のパミッションが必要なContentProvider(ブックマーク等)も同じような動作をすると考えられますが、動作確認はしていません。多分同じ仕様なんだろうと思ってます。
というか、自身がContentProviderを設計する時には、同じような実装にすべきだと感じました。
しかし、シャープ端末でのアクセス制限方法と同じですね。
ちょっと時代が早かった?>シャープさん