Android 6.0の稼働時間の適正化を迅速に実現するクラス
9929 ワード
前言
今、Android 6.0の運行時限が適切で、時代遅れと言えるのですが、なぜ書くのでしょうか.一つは、現在のGitHubで上位にランクされているオープンソースプロジェクトを試してみると、確かに素晴らしいですが、使いやすさでは満足できず、自分で1つの考えが芽生えました.二つ目は、現在の国内の主流の応用を見てみると、Android 6.0に適していないことが多いので、この文章には意味があると思います.
使用
使いやすさについて述べた以上、まず、申請権限が必要な場所で使用方法を呼び出してみましょう.
ここにはもう一つのハイライトがありますが、皆さんが気づいたかどうか分かりません.私たちは
ソース解析
使用方法を見た後、内部実装を見てみましょう.プロセス別に見てみましょう.
まず、Appに登録されている権限を確認します.申請する権限がManifestに登録されていない場合は、失敗します.
申請する権限がすでにManifestに登録されている場合は、次にシステムのバージョンを区別します.システムのバージョンが26未満であれば、直接成功に戻ります.そうしないと、申請権限が必要になります.このコードは簡単です.貼らないでください.
システムバージョン>=26であれば、本格的な申請プロセスが開始され、申請する権限が許可されているかどうかを確認し、許可されている場合は、これ以上申請する必要はありません.
システムへの申請の送信
申請結果が到着した後に申請者に通知する
完全なコード
皆さんが使いやすいように、私は完全なコードを貼ります.
本文では、Android 6.0の実行時権限を迅速かつ簡単に適合させる方法を紹介しました.もしあなたが本文を読む時に何か問題や漏れを発見したり、異なる見方をしたりしたら、指摘を歓迎します.
今、Android 6.0の運行時限が適切で、時代遅れと言えるのですが、なぜ書くのでしょうか.一つは、現在のGitHubで上位にランクされているオープンソースプロジェクトを試してみると、確かに素晴らしいですが、使いやすさでは満足できず、自分で1つの考えが芽生えました.二つ目は、現在の国内の主流の応用を見てみると、Android 6.0に適していないことが多いので、この文章には意味があると思います.
使用
使いやすさについて述べた以上、まず、申請権限が必要な場所で使用方法を呼び出してみましょう.
PermissionReq.with(this) // Activity or Fragment
.permissions(Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE) //
.result(new PermissionReq.Result() { //
@Override
public void onGranted() { //
// do something
}
@Override
public void onDenied() { //
// do something
}
})
.request();
ActivityベースクラスとFragmentベースクラスに次のコードを追加します.@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
PermissionReq.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
APIのデザインは比較的ポピュラーなストリーム呼び出しを採用しており、皆さんが見てどんな感じなのか分かりませんが、使用するのは簡単で、元のコード構造を破壊することはないと思います.ここまで言うと、今では多くのオープンソースフレームワークが注釈方式で申請結果をコールバックしているので、この方式ではコード階層が少なくなったが、可読性が悪くなり、元のコード構造を破壊する可能性があると思います.ここにはもう一つのハイライトがありますが、皆さんが気づいたかどうか分かりません.私たちは
RequestCode
を使っていません.RequestCode
はどこへ行きましたか.次の内容で教えてあげます.これも私の大好きな場所で、申請権限ごとにRequestCode
を定義する必要はありません.RequestCode
が繰り返される心配はありません.PermissionReq
はすでに処理されているからです.ソース解析
使用方法を見た後、内部実装を見てみましょう.プロセス別に見てみましょう.
まず、Appに登録されている権限を確認します.申請する権限がManifestに登録されていない場合は、失敗します.
initManifestPermission(activity);
for (String permission : mPermissions) {
if (!sManifestPermissionSet.contains(permission)) {
if (mResult != null) {
mResult.onDenied();
}
return;
}
}
private static Set sManifestPermissionSet;
private static synchronized void initManifestPermission(Context context) {
if (sManifestPermissionSet == null) {
sManifestPermissionSet = new HashSet<>();
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
String[] permissions = packageInfo.requestedPermissions;
Collections.addAll(sManifestPermissionSet, permissions);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
スレッドのセキュリティのためにsynchronized
修飾子を追加しました.申請する権限がすでにManifestに登録されている場合は、次にシステムのバージョンを区別します.システムのバージョンが26未満であれば、直接成功に戻ります.そうしないと、申請権限が必要になります.このコードは簡単です.貼らないでください.
システムバージョン>=26であれば、本格的な申請プロセスが開始され、申請する権限が許可されているかどうかを確認し、許可されている場合は、これ以上申請する必要はありません.
List deniedPermissionList = getDeniedPermissions(activity, mPermissions);
if (deniedPermissionList.isEmpty()) {
if (mResult != null) {
mResult.onGranted();
}
return;
}
private static List getDeniedPermissions(Context context, String[] permissions) {
List deniedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
deniedPermissionList.add(permission);
}
}
return deniedPermissionList;
}
申請する権限がすべて許可されていない場合は、RequestCodeの生成をシステムに送信する必要があります.int requestCode = genRequestCode();
private static AtomicInteger sRequestCode = new AtomicInteger(0);
private static int genRequestCode() {
return sRequestCode.incrementAndGet();
}
RequestCodeを定義する必要はありません.これで、RequestCodeはついに浮上しました.内部で静的に増加したAtomicIntegerをRequestCodeとして使用し、RequestCodeが重複しないことを保証します.AtomicIntegerを使用してintを直接使用しないのはスレッドの安全のためです.システムへの申請の送信
String[] deniedPermissions = deniedPermissionList.toArray(new String[deniedPermissionList.size()]);
requestPermissions(mObject, deniedPermissions, requestCode);
sResultArray.put(requestCode, mResult);
@TargetApi(Build.VERSION_CODES.M)
private static void requestPermissions(Object object, String[] permissions, int requestCode) {
if (object instanceof Activity) {
((Activity) object).requestPermissions(permissions, requestCode);
} else if (object instanceof Fragment) {
((Fragment) object).requestPermissions(permissions, requestCode);
}
}
申請時に出所を区別し、申請後にResultをArrayに入れて保存し、申請結果の到着を待つ申請結果が到着した後に申請者に通知する
public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Result result = sResultArray.get(requestCode);
if (result == null) {
return;
}
sResultArray.remove(requestCode);
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
result.onDenied();
return;
}
}
result.onGranted();
}
ここまで私たちの申請権限の流れはもう終わりました.ソースも読み終わりました.完全なコード
皆さんが使いやすいように、私は完全なコードを貼ります.
public class PermissionReq {
private static AtomicInteger sRequestCode = new AtomicInteger(0);
private static SparseArray sResultArray = new SparseArray<>();
private static Set sManifestPermissionSet;
public interface Result {
void onGranted();
void onDenied();
}
private Object mObject;
private String[] mPermissions;
private Result mResult;
private PermissionReq(Object object) {
mObject = object;
}
public static PermissionReq with(@NonNull Activity activity) {
return new PermissionReq(activity);
}
public static PermissionReq with(@NonNull Fragment fragment) {
return new PermissionReq(fragment);
}
public PermissionReq permissions(@NonNull String... permissions) {
mPermissions = permissions;
return this;
}
public PermissionReq result(@Nullable Result result) {
mResult = result;
return this;
}
public void request() {
Activity activity = getActivity(mObject);
if (activity == null) {
throw new IllegalArgumentException(mObject.getClass().getName() + " is not supported");
}
initManifestPermission(activity);
for (String permission : mPermissions) {
if (!sManifestPermissionSet.contains(permission)) {
if (mResult != null) {
mResult.onDenied();
}
return;
}
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (mResult != null) {
mResult.onGranted();
}
return;
}
List deniedPermissionList = getDeniedPermissions(activity, mPermissions);
if (deniedPermissionList.isEmpty()) {
if (mResult != null) {
mResult.onGranted();
}
return;
}
int requestCode = genRequestCode();
String[] deniedPermissions = deniedPermissionList.toArray(new String[deniedPermissionList.size()]);
requestPermissions(mObject, deniedPermissions, requestCode);
sResultArray.put(requestCode, mResult);
}
public static void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Result result = sResultArray.get(requestCode);
if (result == null) {
return;
}
sResultArray.remove(requestCode);
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
result.onDenied();
return;
}
}
result.onGranted();
}
@TargetApi(Build.VERSION_CODES.M)
private static void requestPermissions(Object object, String[] permissions, int requestCode) {
if (object instanceof Activity) {
((Activity) object).requestPermissions(permissions, requestCode);
} else if (object instanceof Fragment) {
((Fragment) object).requestPermissions(permissions, requestCode);
}
}
private static List getDeniedPermissions(Context context, String[] permissions) {
List deniedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
deniedPermissionList.add(permission);
}
}
return deniedPermissionList;
}
private static synchronized void initManifestPermission(Context context) {
if (sManifestPermissionSet == null) {
sManifestPermissionSet = new HashSet<>();
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
String[] permissions = packageInfo.requestedPermissions;
Collections.addAll(sManifestPermissionSet, permissions);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
private static Activity getActivity(Object object) {
if (object != null) {
if (object instanceof Activity) {
return (Activity) object;
} else if (object instanceof Fragment) {
return ((Fragment) object).getActivity();
}
}
return null;
}
private static int genRequestCode() {
return sRequestCode.incrementAndGet();
}
}
まとめ本文では、Android 6.0の実行時権限を迅速かつ簡単に適合させる方法を紹介しました.もしあなたが本文を読む時に何か問題や漏れを発見したり、異なる見方をしたりしたら、指摘を歓迎します.