/*
* The MIT License (MIT)
* Copyright (c) 2015 Michal Tajchert
* 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.wm.remusic.permissions;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Created by Michal Tajchert on 2015-06-04.
*/
public class Nammu {
private static final String TAG = Nammu.class.getSimpleName();
private static final String KEY_PREV_PERMISSIONS = "previous_permissions";
private static final String KEY_IGNORED_PERMISSIONS = "ignored_permissions";
private static Context context;
private static SharedPreferences sharedPreferences;
private static ArrayList<PermissionRequest> permissionRequests = new ArrayList<PermissionRequest>();
public static void init(Context context) {
sharedPreferences = context.getSharedPreferences("pl.tajchert.runtimepermissionhelper", Context.MODE_PRIVATE);
Nammu.context = context;
}
/**
* Check that all given permissions have been granted by verifying that each entry in the
* given array is of the value {@link PackageManager#PERMISSION_GRANTED}.
*/
public static boolean verifyPermissions(int[] grantResults) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* Returns true if the Activity has access to given permissions.
*/
public static boolean hasPermission(Activity activity, String permission) {
return activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
/**
* Returns true if the Activity has access to a all given permission.
*/
public static boolean hasPermission(Activity activity, String[] permissions) {
for (String permission : permissions) {
if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/*
* If we override other methods, lets do it as well, and keep name same as it is already weird enough.
* Returns true if we should show explanation why we need this permission.
*/
public static boolean shouldShowRequestPermissionRationale(Activity activity, String permissions) {
return activity.shouldShowRequestPermissionRationale(permissions);
}
public static void askForPermission(Activity activity, String permission, PermissionCallback permissionCallback) {
askForPermission(activity, new String[]{permission}, permissionCallback);
}
public static void askForPermission(Activity activity, String[] permissions, PermissionCallback permissionCallback) {
if (permissionCallback == null) {
return;
}
if (hasPermission(activity, permissions)) {
permissionCallback.permissionGranted();
return;
}
PermissionRequest permissionRequest = new PermissionRequest(new ArrayList<String>(Arrays.asList(permissions)), permissionCallback);
permissionRequests.add(permissionRequest);
activity.requestPermissions(permissions, permissionRequest.getRequestCode());
}
public static void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
PermissionRequest requestResult = new PermissionRequest(requestCode);
if (permissionRequests.contains(requestResult)) {
PermissionRequest permissionRequest = permissionRequests.get(permissionRequests.indexOf(requestResult));
if (verifyPermissions(grantResults)) {
//Permission has been granted
permissionRequest.getPermissionCallback().permissionGranted();
} else {
permissionRequest.getPermissionCallback().permissionRefused();
}
permissionRequests.remove(requestResult);
}
refreshMonitoredList();
}
//Permission monitoring part below
/**
* Get list of currently granted permissions, without saving it inside Nammu
*
* @return currently granted permissions
*/
public static ArrayList<String> getGrantedPermissions() {
if (context == null) {
throw new RuntimeException("Must call initCatchException() earlier");
}
ArrayList<String> permissions = new ArrayList<String>();
ArrayList<String> permissionsGranted = new ArrayList<String>();
//Group location
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
//Group Calendar
permissions.add(Manifest.permission.WRITE_CALENDAR);
permissions.add(Manifest.permission.READ_CALENDAR);
//Group Camera
permissions.add(Manifest.permission.CAMERA);
//Group Contacts
permissions.add(Manifest.permission.WRITE_CONTACTS);
permissions.add(Manifest.permission.READ_CONTACTS);
permissions.add(Manifest.permission.GET_ACCOUNTS);
//Group Microphone
permissions.add(Manifest.permission.RECORD_AUDIO);
//Group Phone
permissions.add(Manifest.permission.CALL_PHONE);
permissions.add(Manifest.permission.READ_PHONE_STATE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
permissions.add(Manifest.permission.READ_CALL_LOG);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
permissions.add(Manifest.permission.WRITE_CALL_LOG);
}
permissions.add(Manifest.permission.ADD_VOICEMAIL);
permissions.add(Manifest.permission.USE_SIP);
permissions.add(Manifest.permission.PROCESS_OUTGOING_CALLS);
//Group Body sensors
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
permissions.add(Manifest.permission.BODY_SENSORS);
}
//Group SMS
permissions.add(Manifest.permission.SEND_SMS);
permissions.add(Manifest.permission.READ_SMS);
permissions.add(Manifest.permission.RECEIVE_SMS);
permissions.add(Manifest.permission.RECEIVE_WAP_PUSH);
permissions.add(Manifest.permission.RECEIVE_MMS);
//Group Storage
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
for (String permission : permissions) {
if (context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
permissionsGranted.add(permission);
}
}
return permissionsGranted;
}
/**
* Refresh currently granted permission list, and save it for later comparing using @permissionCompare()
*/
public static void refreshMonitoredList() {
ArrayList<String> permissions = getGrantedPermissions();
Set<String> set = new HashSet<String>();
for (String perm : permissions) {
set.add(perm);
}
sharedPreferences.edit().putStringSet(KEY_PREV_PERMISSIONS, set).apply();
}
/**
* Get list of previous Permissions, from last refreshMonitoredList() call and they may be outdated,
* use getGrantedPermissions() to get current
*/
public static ArrayList<String> getPreviousPermissions() {
ArrayList<String> prevPermissions = new ArrayList<String>();
prevPermissions.addAll(sharedPreferences.getStringSet(KEY_PREV_PERMISSIONS, new HashSet<String>()));
return prevPermissions;
}
public static ArrayList<String> getIgnoredPermissions() {
ArrayList<String> ignoredPermissions = new ArrayList<String>();
ignoredPermissions.addAll(sharedPreferences.getStringSet(KEY_IGNORED_PERMISSIONS, new HashSet<String>()));
return ignoredPermissions;
}
/**
* Lets see if we already ignore this permission
*/
public static boolean isIgnoredPermission(String permission) {
if (permission == null) {
return false;
}
return getIgnoredPermissions().contains(permission);
}
/**
* Use to ignore to particular Permission - even if user will deny or add it we won't receive a callback.
*
* @param permission Permission to ignore
*/
public static void ignorePermission(String permission) {
if (!isIgnoredPermission(permission)) {
ArrayList<String> ignoredPermissions = getIgnoredPermissions();
ignoredPermissions.add(permission);
Set<String> set = new HashSet<String>();
set.addAll(ignoredPermissions);
sharedPreferences.edit().putStringSet(KEY_IGNORED_PERMISSIONS, set).apply();
}
}
/**
* Used to trigger comparing process - @permissionListener will be called each time Permission was revoked, or added (but only once).
*
* @param permissionListener Callback that handles all permission changes
*/
public static void permissionCompare(PermissionListener permissionListener) {
if (context == null) {
throw new RuntimeException("Before comparing permissions you need to call Nammu.initCatchException(context)");
}
ArrayList<String> previouslyGranted = getPreviousPermissions();
ArrayList<String> currentPermissions = getGrantedPermissions();
ArrayList<String> ignoredPermissions = getIgnoredPermissions();
for (String permission : ignoredPermissions) {
if (previouslyGranted != null && !previouslyGranted.isEmpty()) {
if (previouslyGranted.contains(permission)) {
previouslyGranted.remove(permission);
}
}
if (currentPermissions != null && !currentPermissions.isEmpty()) {
if (currentPermissions.contains(permission)) {
currentPermissions.remove(permission);
}
}
}
for (String permission : currentPermissions) {
if (previouslyGranted.contains(permission)) {
//All is fine, was granted and still is
previouslyGranted.remove(permission);
} else {
//We didn't have it last time
if (permissionListener != null) {
permissionListener.permissionsChanged(permission);
permissionListener.permissionsGranted(permission);
}
}
}
if (previouslyGranted != null && !previouslyGranted.isEmpty()) {
//Something was granted and removed
for (String permission : previouslyGranted) {
if (permissionListener != null) {
permissionListener.permissionsChanged(permission);
permissionListener.permissionsRemoved(permission);
}
}
}
refreshMonitoredList();
}
/**
* Not that needed method but if we override others it is good to keep same.
*/
public static boolean checkPermission(String permissionName) {
if (context == null) {
throw new RuntimeException("Before comparing permissions you need to call Nammu.initCatchException(context)");
}
return PackageManager.PERMISSION_GRANTED == context.checkSelfPermission(permissionName);
}
}