Android M から新しいパーミッションモデルになり、アプリから一部のパーミッションの権限を要求することが可能になりました。この実装を調べていてハマったところがあるので共有します。
パーミッション権限を要求するときは以下のような感じです。
公式には、 Activity#requestPermissions()
を呼び出して、要求結果を Activity#onRequestPermissionsResult()
で受け取る、と書いてあります。
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;
}
@Override
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
}
}
ハマったところ
1. Fragment にも requestPermissions() はある
@hotchemi のおかげで Fragment にも requestPermissions()
が実装されてるのを知りました。公式を見る限り Activity
だけにしか無いように見えるのつらい...
Android M Preview 版のソースコードを見ると、ちゃんと requestPermissions()
と onRequestPermissionsResult()
が実装されていることが分かりました。
なので、安心して Fragment でパーミッション要求を実装できそうですね!!!!!!!!
package android.app;
public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListener {
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
Intent intent =
mHost.getContext().getPackageManager().buildRequestPermissionsIntent(permissions);
mHost.onStartActivityFromFragment(this, intent, requestCode, null);
}
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
/* callback - do nothing */
}
2. Fragment に requestPermissions() はなかった
タイトル詐欺です。
Fragment に requestPermissions()
があるとのことなので、満身創痍で App Permission のサンプルを実装していましたが、コード補完に requestPermissions()
が候補リストに出てきませんでした!!!!!!!!!!!!!!!!
「うーーーん......うーーーん......」と時間を無駄に消費したのですが、原因はすごく簡単に解決できるものでした。
まちがい
import android.support.v4.app.Fragment;
public class PermissionFragment extends Fragment {
private void requestReadContactsPermission() {
requestPermissions(
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
せいかい
import android.app.Fragment;
public class PermissionFragment extends Fragment {
private void requestReadContactsPermission() {
requestPermissions(
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
まとめ
現状はイカのどれかで対処する必要があります。
-
android.app.Fragment
のほうを import する - support v4 のアップデートを待つ
-
Activity
のほうで実装
無駄にハマった...
追記 7/13
support v4 のソースコードを見たら
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
mHost.onRequestPermissionsFromFragment(this, permissions,requestCode);
}
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
/* callback - do nothing */
}
public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
if (mHost != null) {
return mHost.onShouldShowRequestPermissionRationale(permission);
}
return false;
}
のように、ちゃんと実装されていました。なので、安心して v4 を使えますね。