at.alladin.rmbt.android.util.PermissionHelper.java Source code

Java tutorial

Introduction

Here is the source code for at.alladin.rmbt.android.util.PermissionHelper.java

Source

/*******************************************************************************
 * Copyright 2016 Specure GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package at.alladin.rmbt.android.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import at.alladin.openrmbt.android.R;
import at.alladin.rmbt.android.main.RMBTMainActivity;

public abstract class PermissionHelper {
    private static final String TAG = "PermissionHelper";

    public static final int REQUEST_AT_INIT = 1;
    public static final int REQUEST_AT_TEST_START = 2;
    protected static final String PREF_LAST_TIME_PERMISSION_SHOWN = "lastTimePermissionShown";
    protected static final long SHOW_PERMISSION_DIALOG_INTERVAL_SEC = 3600; // 1h

    //    protected static final long SHOW_PERMISSION_DIALOG_INTERVAL_SEC = 10; // TODO: REMOVE, only for debugging

    protected static final ConcurrentHashMap<String, Boolean> DYNAMIC_PERMISSIONS = new ConcurrentHashMap<String, Boolean>();

    protected static class PermissionGroup {
        private final String groupName;
        private final String[] permissions;
        private final int dialogTitle;
        private final int dialogMessage;

        public PermissionGroup(String groupName, String[] permissions) {
            this.groupName = groupName;
            this.dialogTitle = -1;
            this.dialogMessage = -1;
            this.permissions = permissions;
        }

        public PermissionGroup(String groupName, int dialogTitle, int dialogMessage, String[] permissions) {
            this.groupName = groupName;
            this.dialogTitle = dialogTitle;
            this.dialogMessage = dialogMessage;
            this.permissions = permissions;
        }
    }

    protected static final PermissionGroup LOCATION_GROUP = new PermissionGroup("location",
            new String[] { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, });

    protected static final PermissionGroup TELEPHONY_GROUP = new PermissionGroup("telephony",
            R.string.permission_telephony_dialog_title, R.string.permission_telephony_dialog_text,
            new String[] { Manifest.permission.READ_PHONE_STATE });

    protected static final PermissionGroup[] GROUPS = new PermissionGroup[] { LOCATION_GROUP, TELEPHONY_GROUP };

    protected static final String[] PERMISSIONS = mergePermissions(GROUPS);

    protected static String[] mergePermissions(PermissionGroup[] groups) {
        final List<String> permissions = new ArrayList<String>();
        for (PermissionGroup group : groups)
            permissions.addAll(Arrays.asList(group.permissions));
        return permissions.toArray(new String[permissions.size()]);
    }

    public static boolean checkPermission(Context ctx, String permission) {
        return ContextCompat.checkSelfPermission(ctx, permission) == PackageManager.PERMISSION_GRANTED;
    }

    public static boolean checkAllPermissions(Context ctx, List<String> permissions) {
        for (String permission : permissions)
            if (!checkPermission(ctx, permission))
                return false;
        return true;
    }

    public static boolean checkAllPermissions(Context ctx, String[] permissions) {
        for (String permission : permissions)
            if (!checkPermission(ctx, permission))
                return false;
        return true;
    }

    public static boolean checkAnyPermission(Context ctx, String[] permissions) {
        for (String permission : permissions)
            if (checkPermission(ctx, permission))
                return true;
        return false;
    }

    public static boolean checkCoarseLocationPermission(Context ctx) {
        return checkPermission(ctx, Manifest.permission.ACCESS_COARSE_LOCATION);
    }

    public static boolean checkFineLocationPermission(Context ctx) {
        return checkPermission(ctx, Manifest.permission.ACCESS_FINE_LOCATION);
    }

    public static boolean checkReadPhoneStatePermission(Context ctx) {
        return checkPermission(ctx, Manifest.permission.READ_PHONE_STATE);
    }

    public static boolean checkAnyLocationPermission(Context ctx) {
        return checkAnyPermission(ctx, LOCATION_GROUP.permissions);
    }

    protected static boolean checkAllDynamicPermissions(Context ctx, String[] permissions) {
        return checkAllPermissions(ctx, filterDynamicPermissions(PERMISSIONS));
    }

    protected static List<String> getMissingDynamicPermissions(Context ctx, String[] permissions) {
        final List<String> missingPermissions = new ArrayList<String>();
        for (String permission : filterDynamicPermissions(permissions)) {
            if (!checkPermission(ctx, permission))
                missingPermissions.add(permission);
        }
        return missingPermissions;
    }

    protected static List<String> filterDynamicPermissions(String[] permissions) {
        final List<String> result = new ArrayList<String>();
        for (String permission : permissions) {
            final Boolean request = DYNAMIC_PERMISSIONS.get(permission);
            if (request == null || request) // default to true if not set
                result.add(permission);
        }
        return result;
    }

    protected static boolean shouldShowRequestPermissionRationale(Activity act, String[] permissions) {
        for (String permission : filterDynamicPermissions(permissions)) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(act, permission))
                return true;
        }
        return false;
    }

    public static void checkPermissionAtTestStartAndStartTest(final RMBTMainActivity act) {
        if (checkAllDynamicPermissions(act, PERMISSIONS)) // everything is fine
        {
            act.startTest();
            return;
        }

        final List<PermissionGroup> neededGroups = new ArrayList<PermissionHelper.PermissionGroup>();
        for (PermissionGroup group : GROUPS) {
            if (!checkAllDynamicPermissions(act, group.permissions)
                    && isItTimeToShowPermissionDialogAgain(act, group.groupName))
                neededGroups.add(group);
        }

        if (neededGroups.isEmpty()) // nothing to do
        {
            act.startTest();
            return;
        }

        final List<String> neededPermissions = new ArrayList<String>();
        handleGroup(act, neededGroups, neededPermissions, 0);
    }

    protected static void handleGroup(final RMBTMainActivity act, final List<PermissionGroup> neededGroups,
            final List<String> neededPermissions, final int i) {
        final boolean afterLastGroup = i >= neededGroups.size();

        if (!afterLastGroup) {
            final PermissionGroup group = neededGroups.get(i);

            updatePermissionDialogTime(act, group.groupName);

            if (group.dialogTitle != -1 && group.dialogMessage != -1
                    && shouldShowRequestPermissionRationale(act, group.permissions)) {
                final AlertDialog.Builder builder = new AlertDialog.Builder(act);
                builder.setTitle(group.dialogTitle).setMessage(group.dialogMessage)
                        /*
                        .setNegativeButton("Abbrechen", new OnClickListener()
                        {
                            @Override
                            public void onClick(DialogInterface dialog, int which)
                            {
                                handleGroup(act, neededGroups, neededPermissions, i + 1);
                            }
                        })
                        */
                        .setPositiveButton("Weiter", new OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                neededPermissions.addAll(getMissingDynamicPermissions(act, group.permissions));
                                handleGroup(act, neededGroups, neededPermissions, i + 1);
                            }
                        }).show();
            } else {
                neededPermissions.addAll(getMissingDynamicPermissions(act, group.permissions));
                handleGroup(act, neededGroups, neededPermissions, i + 1);
            }
        } else // afterLastGroup
        {
            if (neededPermissions.isEmpty())
                act.startTest();
            else
                ActivityCompat.requestPermissions(act,
                        neededPermissions.toArray(new String[neededPermissions.size()]), REQUEST_AT_TEST_START);
        }
    }

    public static void checkPermissionAtInit(final Activity act) {
        // request location permissions
        if (checkAllPermissions(act, LOCATION_GROUP.permissions))
            return;
        updatePermissionDialogTime(act, LOCATION_GROUP.groupName);
        ActivityCompat.requestPermissions(act, LOCATION_GROUP.permissions, REQUEST_AT_INIT);
    }

    public static boolean isItTimeToShowPermissionDialogAgain(Context ctx, String groupName) {
        final long lastTime = ConfigHelper.getSharedPreferences(ctx)
                .getLong(PREF_LAST_TIME_PERMISSION_SHOWN + "_" + groupName, 0);
        return (lastTime <= 0
                || lastTime + SHOW_PERMISSION_DIALOG_INTERVAL_SEC * 1000 < System.currentTimeMillis());
    }

    public static void updatePermissionDialogTime(Context ctx, String groupName) {
        ConfigHelper.getSharedPreferences(ctx).edit()
                .putLong(PREF_LAST_TIME_PERMISSION_SHOWN + "_" + groupName, System.currentTimeMillis()).commit();
    }

    public static JSONArray getPermissionStatusAsJSONArray(Context ctx) {
        final JSONArray result = new JSONArray();
        for (String permission : PERMISSIONS) {
            final JSONObject obj = new JSONObject();
            try {
                obj.put("permission", permission);
                obj.put("status", checkPermission(ctx, permission));
                result.put(obj);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        Log.d(TAG, result.toString());
        return result;
    }

    public static void setRequestPermissions(JSONArray permissions) {
        DYNAMIC_PERMISSIONS.clear();
        for (int i = 0; i < permissions.length(); i++) {
            final JSONObject obj = permissions.optJSONObject(i);
            if (obj != null) {
                final String permission = obj.optString("permission");
                final boolean request = obj.optBoolean("request");
                if (permission != null)
                    DYNAMIC_PERMISSIONS.put(permission, request);
            }
        }
    }

}