READ_CONTACTSなしで電話帳から電話番号を取得する方法

ちょっと間が空きましたが、連載企画?として、このブログにてCAMERAパミッションなしに写真を取る方法SEND_SMSパーミッションなしにSMSを送る方法をご紹介しました。知っている方は、知っていると思うのですが、パミッションがいるんじゃないか?と勘違いしやすい機能について解説しております。基本は同じで、ユーザの操作を介して他のアプリケーションからデータを取得する場合は、パーミッションはいらないということです。

no_read_contacts.png

今回の「READ_CONTACTSなしで電話帳から電話番号を取得する方法」については、QRコードアプリ等で利用可能です。世の中には「連絡先をQRコードで表示するので、READ_CONTACTSパミッションが必要です」という理由を付けた、グレーゾーンアプリが存在します。今回説明する方法を使えば回避できますので、この理由は正しくありません。できればそのようなアプリはインストールしないようにする必要がありますし、作る立場ではREAD_CONTACTSを付ける必要がないのに付けてしまった!といった事がないように注意してください。

READ_CONTACTパーミッション

電話帳を参照するには、AndroidManifestにREAD_CONTACTパーミッションの利用宣言をする必要があります。

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

READ_CONTACTSのprotection levelは、dangerousで、パーミッショングループは、PERSONAL_INFOです。このパーミッションを持っているアプリケーションは自由に電話帳を参照できるので、INTERNETパーミッションと組み合わせる事で端末内の電話番号を全て別のサーバーに送る事が可能です。
電話帳データは端末を持っている個人情報のみならず、友人、会社関係者等の電話番号が格納されているため、名簿販売目的のために収集されたり、電話帳に入っているデータから個人の属性である、男性か女性かおおよその年齢、職業まで類推可能なため、広告業者のターゲッティング広告目的で収集される事があります。
多くのマルウェアではこの電話帳データの収集を目的としているため、READ_CONTACTSが付いているアプリケーションはマルウェアと間違えられたり、ユーザがインストールを躊躇する事がありますので、なるべく付けないようにする事が必要です。

電話帳からデータ取得も電話帳アプリケーション自体のUIを一度経由する事でREAD_CONTACTパーミッションを利用宣言することなく、特定のユーザの情報(電話番号、メールアドレス等)を取得する事が可能です。

ACTION_GET_CONTENT

アクションにACTION_GET_CONTENT、タイプにPhone.CONTENT_ITEM_TYPEを設定し、startActivityForResultを利用してアクティビティを起動します。他にこのIntentに対応するアプリがない場合は電話帳アプリが起動し、電話帳内のデータ選択画面が表示されます。
ユーザがデータを選択すると、電話帳アプリは終了し、Intent発行したアプリケーションに制御が移ります。startActivityForResultでアクティビティの起動を行ったので、onActivityResultにて結果を受け取る事が可能です。

Intentにより起動された電話帳アプリ

contact_select.png

onActivityResulで受け取ったIntentから、getDataする事で選択したユーザのContent URIが取得できます。このURIは電話帳のコンテントプロパイダーへのURIそのもので通常は、READ_CONTACTパーミッションがないとアクセスできない物ですが、電話帳アプリはAndroid Security Book 7章コンテントプロパイダで解説をしたGrant-uri-permission機能を使用して、1回のみのアクセスを可能にしています。
アクセス可能なURIを取得した後は、getContentResolver.query()を利用してデータを取り出します。

READ_CONTACTパーミッションが必要ないパターンのソース

public void onClickActionGetContent(View view){Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType(Phone.CONTENT_ITEM_TYPE);startActivityForResult(Intent.createChooser(intent, "Pick a Phone Data"),MY_REQUEST_CODE);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if(data != null){Uri uri = data.getData();if(uri != null){String[] projection = new String[]{Phone.DISPLAY_NAME,Phone.NUMBER};Cursor cur = getContentResolver().query(uri,projection,null,null,null);if(cur != null){cur.moveToFirst();String displayName = cur.getString(0);String number = cur.getString(1);Log.v(TAG,"displayName="+displayName);Log.v(TAG,"number="+number);}}}}

このように単に一人のユーザ情報を取得するだけであれば、READ_CONTACTSはパーミッション必要ありません。ユーザのデータをQRコードで表示するアプリ、他の人と近距離通信で電話番号を交換するアプリケーション等はREAD_CONTACTSパーミッションなしで実現可能です。

電話帳データの収集は現在とても問題になっています。くれぐれもマルウェアと間違われないようにREAD_CONTACTSパミッションを付けるときには最新の注意を払ってください。

ブログ内の関連する記事


コメント

このブログの人気の投稿

島へ移住の話【炊飯】

ドローンプログラミング体験教室を伊豆大島の小学校でしてきました

情報処理安全確保支援士登録証のカード型が届きました。