Android MとNの新機能:実行時の権限
Androidでは、権限システムはさまざまな理由から、プラットフォームにおける主要なセキュリティ上の懸念事項の一つでした。
Androidでは、権限システムは次のようなさまざまな理由から、プラットフォームにおける主要なセキュリティ上の懸念事項の一つでした。
- ユーザーには2つの選択肢しかありません。アプリがいつ、なぜ権限を使うのかまったくわからないまま、インストール時にすべての権限をアプリケーションに与えるか、権限を拒否してアプリケーションをまったく使えなくなるか(受け入れるか諦めるかの二択)です。
- インストール時に一度権限が付与されると、アプリケーションはそのライフサイクルを通じて何の通知もなく権限を使用でき、ユーザーは端末からアプリケーションを削除しない限り権限を拒否できません。
- ユーザーにとってだけでなく、開発者にとっても透明性がありません。アプリに特定の権限を必要とする便利な機能があったとしても、ユーザーに説明せず、なぜその権限が必要なのかという背景を伝えなければ、ユーザーは不審に感じてアプリケーションをインストールしないと判断するかもしれません。
- Androidには130を超える固有の権限が用意されています。ユーザーがインストール時に権限を一つずつ確認したとしても、すぐに混乱してしまう可能性があります(BODY_SENSORSとは正確には何か、BLUETOOTH、BLUETOOTH_ADMIN、BLUETOOTH_PRIVILEGEDの違いは何か)。
ついにAndroidの権限システムが再設計される
Android(6.0 Marshmallow)以降、アプリケーションにはインストール時に権限が一切付与されなくなります。代わりに、アプリケーションは実行時に権限を一つずつユーザーに要求しなければなりません。これは、アプリケーションが何にアクセスでき、何にアクセスできないかをユーザー自身が選べるようにすることで、ユーザーのプライバシーを保護するための重要な一歩です。しかも、ユーザーは引き続きアプリケーションを使用することができます。
開発者は新しい権限システムを理解し、あらゆるケースに対応してユーザーに良好なユーザー体験を提供できるよう、アプリケーションを適応させる必要があります。
では、開発者として、Androidの新しい権限システムについて何を知っておくべきでしょうか。
1- 権限には、通常の権限と危険な権限の2種類があります
- 通常の権限は、ユーザーの個人情報を除く外部データへのアクセスをアプリケーションに許可します。
完全な一覧はこちらで確認できます。
- 危険な権限は、ユーザーの個人情報へのアクセスをアプリケーションに許可します。
2- すべてのAndroidバージョンで、権限(通常の権限と危険な権限の両方)を使用するたびに、アプリのマニフェストに適切な
3- 通常の権限は自動的に付与され、実行時に要求する必要はありません。
4- 個人情報にアクセスしようとする場合は、実行時にその「危険な権限」を明示的に要求する必要があります。そうしないと、メソッドがSecurityExceptionをスローし、アプリケーションがクラッシュします。
5- ユーザーは、付与した権限をいつでも取り消すことができます。
6- 権限は権限グループにまとめられています。そのため、ユーザーが特定のグループの権限を以前に付与していれば、そのグループの他のすべての権限を再度要求することなく使用できます。
7- アプリケーションを新しい権限システムに適応させるには、次のロジックに従う必要があります。

8- 百聞は一見にしかずということで、コードを見ていきましょう。この例では、SEND_SMS権限を要求します(コメントを参照)。
//Unique identifier to identify each permission request
final private int REQUEST_CODE_ASK_PERMISSIONS = 999;
private void sendSMSWrapper() {
//Check to see if the permission is available
int hasSendSMSPermission = checkSelfPermission(Manifest.permission.SEND_SMS);
if (hasSendSMSPermission != PackageManager.PERMISSION_GRANTED) {
//if the permission is not granted, check if the user has already denied this request
if (!shouldShowRequestPermissionRationale(Manifest.permission.SEND_SMS)) {
//Explain to the user why we need to send the sms
Snackbar.Make(layout, "Send SMS is required to share the new events with your contacts.", Snackbar.LengthIndefinite)
.SetAction("OK", v => RequestPermissions(Manifest.permission.SEND_SMS, REQUEST_CODE_ASK_PERMISSIONS))
.Show();
return;
}
// request the permission
requestPermissions(new String[] {Manifest.permission.SEND_SMS},
REQUEST_CODE_ASK_PERMISSIONS);
return;
}
// execute your code using the user's private information
sendSMS();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_PERMISSIONS:
{
// Check for SEND_SMS
if (CheckSelfPermission(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
{
//Permission Granted
sendSMS();
} else {
// Permission Denied
var snack = Snackbar.Make(layout, "Send SMS permission is denied.", Snackbar.LengthShort);
snack.Show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
9- 後方互換性を確保するために、Android APIレベル< 23向けに新しいメソッドを実装しているSupport Library v4の使用をお勧めします。これにより、コードを一つ書くだけで、ライブラリがAndroidのバージョンに応じて対応する値を返してくれます。そうでない場合は、Androidのバージョンを手動で確認し、Android APIレベル< 23には古い権限システムを、より新しいAndroid APIレベルには新しい権限システムを適用する必要があります。
if (Build.VERSION.SDK_INT >= 23) {
// Runtime permission system
} else {
// Old permission system
}
10- ユーザーにより良いユーザー体験を提供するためには、Androidの新しい権限システムを理解することが重要です。ただし、コードをより短く簡潔にするために、サードパーティのライブラリを使って権限を処理することもできます。当社のお気に入りはPermissionsDispatcherで、シンプルなアノテーションベースのAPIを提供し、基本的な用途をすべてカバーしています。
11- 新しい権限システムについてさらに詳しく知るには、次の資料を参照してください。
- 権限の宣言
- 権限の使用
- 権限のベストプラクティス
- Androidの全権限の一覧
- Android Marshmallow 6.0:権限の要求