com.ultramegasoft.flavordex2.util.PermissionUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.ultramegasoft.flavordex2.util.PermissionUtils.java

Source

/*
 * The MIT License (MIT)
 * Copyright  2016 Steve Guidetti
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the Software?), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED AS IS?, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.ultramegasoft.flavordex2.util;

import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.PermissionChecker;
import android.support.v7.app.AlertDialog;

import com.ultramegasoft.flavordex2.FlavordexApp;
import com.ultramegasoft.flavordex2.R;

/**
 * Helpers for dealing with permissions.
 *
 * @author Steve Guidetti
 */
public class PermissionUtils {
    /**
     * Request codes
     */
    private static final int REQUEST_STORAGE = 10;
    private static final int REQUEST_LOCATION = 20;

    /**
     * Keys for the backend shared preferences
     */
    private static final String PREFS_KEY = "perms";
    private static final String PREF_ASKED_STORAGE = "pref_asked_storage";
    private static final String PREF_ASKED_LOCATION = "pref_asked_location";

    /**
     * Check whether we have permission to read and write external storage.
     *
     * @param context The Context
     * @return Whether we have permission to read and write external storage
     */
    public static boolean hasExternalStoragePerm(@NonNull Context context) {
        return PermissionChecker.checkSelfPermission(context,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PermissionChecker.PERMISSION_GRANTED;
    }

    /**
     * Make a request for external storage permissions from the user if they are not already
     * granted.
     *
     * @param activity  The Activity making the request
     * @param rationale Rationale for requesting external storage permissions
     * @return Whether we already have external storage permissions
     */
    public static boolean checkExternalStoragePerm(@NonNull FragmentActivity activity, int rationale) {
        if (hasExternalStoragePerm(activity)) {
            return true;
        }

        if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            PermissionDialog.showDialog(activity.getSupportFragmentManager(),
                    Manifest.permission.WRITE_EXTERNAL_STORAGE, REQUEST_STORAGE, activity.getString(rationale),
                    null);
            getPreferences(activity).edit().putBoolean(PREF_ASKED_STORAGE, true).apply();
        } else {
            requestExternalStoragePerm(activity);
        }

        return false;
    }

    /**
     * Make the actual request from the user for external storage permissions.
     *
     * @param activity The Activity making the request
     */
    public static void requestExternalStoragePerm(@NonNull Activity activity) {
        ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
                REQUEST_STORAGE);
        getPreferences(activity).edit().putBoolean(PREF_ASKED_STORAGE, true).apply();
    }

    /**
     * Should we ask for external storage permissions? Returns true if the user has not checked
     * 'Never ask again.'
     *
     * @param activity The Activity making the request
     * @return Whether we should ask for external storage permissions
     */
    public static boolean shouldAskExternalStoragePerm(@NonNull Activity activity) {
        return !getPreferences(activity).getBoolean(PREF_ASKED_STORAGE, false) || ActivityCompat
                .shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    /**
     * Check whether we have permission to access the device's location.
     *
     * @param context The Context
     * @return Whether we have permission to access the device's location
     */
    public static boolean hasLocationPerm(@NonNull Context context) {
        return PermissionChecker.checkSelfPermission(context,
                Manifest.permission.ACCESS_COARSE_LOCATION) == PermissionChecker.PERMISSION_GRANTED;
    }

    /**
     * Make a request for location permissions from the user if they are not already granted.
     *
     * @param fragment The Fragment making the request
     * @return Whether we already have location permissions
     */
    public static boolean checkLocationPerm(@NonNull Fragment fragment) {
        final Context context = fragment.getContext();
        if (context != null) {
            if (hasLocationPerm(context)) {
                return true;
            }

            requestLocationPerm(fragment);
        }

        return false;
    }

    /**
     * Make the actual request from the user for location permissions.
     *
     * @param fragment The Fragment making the request
     */
    private static void requestLocationPerm(@NonNull Fragment fragment) {
        fragment.requestPermissions(new String[] { Manifest.permission.ACCESS_COARSE_LOCATION }, REQUEST_LOCATION);

        final Context context = fragment.getContext();
        if (context != null) {
            getPreferences(context).edit().putBoolean(PREF_ASKED_LOCATION, true).apply();
        }
    }

    /**
     * Should we ask for location permissions? Returns true if the user has not checked 'Never ask
     * again.'
     *
     * @param activity The Activity making the request
     * @return Whether we should ask for location permissions
     */
    public static boolean shouldAskLocationPerm(@NonNull Activity activity) {
        return !getPreferences(activity).getBoolean(PREF_ASKED_LOCATION, false) || ActivityCompat
                .shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_COARSE_LOCATION);
    }

    /**
     * Callback for permission requests. If external storage permissions are granted, this will
     * restart the application.
     *
     * @param context      The Context
     * @param requestCode  The request code
     * @param permissions  Array of permissions requested
     * @param grantResults Array of results of the permission requests
     */
    public static void onRequestPermissionsResult(@NonNull Context context, int requestCode,
            @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
        case REQUEST_LOCATION:
            for (int i = 0; i < grantResults.length; i++) {
                if (!Manifest.permission.ACCESS_COARSE_LOCATION.equals(permissions[i])) {
                    continue;
                }
                if (grantResults[i] == PermissionChecker.PERMISSION_GRANTED) {
                    PreferenceManager.getDefaultSharedPreferences(context).edit()
                            .putBoolean(FlavordexApp.PREF_DETECT_LOCATION, true).apply();
                }
            }
            break;
        }
    }

    /**
     * Get the shared preferences for the permissions.
     *
     * @param context The Context
     * @return The SharedPreferences
     */
    @NonNull
    private static SharedPreferences getPreferences(@NonNull Context context) {
        return context.getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE);
    }

    /**
     * Dialog for showing a permission request rationale to the user.
     */
    public static class PermissionDialog extends DialogFragment {
        private static final String TAG = "PermissionDialog";

        /**
         * Arguments for the Fragment
         */
        private static final String ARG_PERMISSION = "permission";
        private static final String ARG_MESSAGE = "message";

        /**
         * Show the dialog.
         *
         * @param fm          The FragmentManager to use
         * @param permission  The permission being requested
         * @param requestCode The permission request code
         * @param target      The target Fragment
         * @param message     The rationale message
         */
        @SuppressWarnings("SameParameterValue")
        static void showDialog(@NonNull FragmentManager fm, @NonNull String permission, int requestCode,
                @NonNull CharSequence message, @Nullable Fragment target) {
            final DialogFragment fragment = new PermissionDialog();
            fragment.setTargetFragment(target, requestCode);

            final Bundle args = new Bundle();
            args.putString(ARG_PERMISSION, permission);
            args.putCharSequence(ARG_MESSAGE, message);
            fragment.setArguments(args);

            fragment.show(fm, TAG);
        }

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final Context context = getContext();
            if (context == null) {
                return super.onCreateDialog(savedInstanceState);
            }

            final Bundle args = getArguments();
            return new AlertDialog.Builder(context).setIcon(R.drawable.ic_info).setTitle(R.string.title_permission)
                    .setMessage(args != null ? args.getCharSequence(ARG_MESSAGE) : null)
                    .setPositiveButton(R.string.button_ok, null).create();
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            super.onDismiss(dialog);

            final Bundle args = getArguments();
            if (args == null) {
                return;
            }

            final String permission = args.getString(ARG_PERMISSION);
            final Fragment target = getTargetFragment();
            if (target != null) {
                target.requestPermissions(new String[] { permission }, getTargetRequestCode());
            } else {
                final Activity activity = getActivity();
                if (activity != null) {
                    ActivityCompat.requestPermissions(activity, new String[] { permission },
                            getTargetRequestCode());
                }
            }
        }
    }
}