public class AppCommons {
    private static final String TAG = AppCommons.class.getSimpleName();
    private static Application application;
    private static AppCommonsConfiguration appCommonsConfiguration;

    public static void install(Application application, AppCommonsConfiguration appCommonsConfiguration) {
        AppCommons.application = application;
        AppCommons.appCommonsConfiguration = appCommonsConfiguration;
        Log.d(TAG, "AppCommmons Installed");
    }

    public static void install(Application application) {
        AppCommons.application = application;
        AppCommons.appCommonsConfiguration = new AppCommonsDefaultConfiguration();
        Log.d(TAG, "AppCommmons Installed");

    }

    public static Application getApplication() {
        return application;
    }

    public static AppCommonsConfiguration getAppCommonsConfiguration() {
        return appCommonsConfiguration;
    }
} public abstract class AppCommonsContext implements Serializable {

} public interface ActivityOperations {

    public void startActivity(Intent intent);

    AppCommonsContext getAppCommonsContext();

    void setAppCommonsContext(AppCommonsContext appCommonsContext);

    void restartApp(Context context, Class starupClass);

    void hideKeyBoard();

    void hideToolBar();

    void showToolBar();

    void setActionBarTitle(int messageId);

    void setActionBarTitle(String message);
} public interface FeedbackOperations {

    Snackbar showShortSnackBar(View view, int messageId, int actionLabel, View.OnClickListener onClickListener, AlertLevel alertLevel);

    Snackbar showShortSnackBar(View view, int messageId, AlertLevel alertLevel);

    Snackbar showIndefiniteSnackBar(View view, int messageId, int actionLabel, AlertLevel alertLevel);

    Snackbar showIndefiniteSnackBar(View view, int messageId, AlertLevel alertLevel);

    Snackbar showIndefiniteSnackBar(View view, int messageId, View.OnClickListener onClickListener, AlertLevel alertLevel);

    Snackbar showIndefiniteSnackBar(View view, int messageId, int actionLabel, View.OnClickListener onClickListener, AlertLevel alertLevel);

    Snackbar showLongSnackBar(View view, int messageId, AlertLevel alertLevel);

    void showLongToast(int messageId);

    void showShortToast(int messageId);
} public interface FragmentOperations {
    void clearBackStack();

    void popBackStack(FragmentManager fragmentManager);

    void switchFragmentsAddToBackStack(int contentFrameId, Fragment replacingFragment);

    void switchFragments(int contentFrameId, Fragment replacingFragment);

    void switchChildFragmentsAddToBackStack(int contentFrameId, Fragment parentFragment, Fragment replacingFragment);

    void switchChildFragments(int contentFrameId, Fragment parentFragment, Fragment replacingFragment);

    void showFragmentDialog(DialogFragment dialogFragment);

    void dismissFragmentDialog(DialogFragment dialogFragment);
} public abstract class AppCommonsConfiguration implements Serializable {

    protected Integer fragmentEnterAnimation;
    protected Integer fragmentExitAnimation;
    protected Integer fragmentPopEnterAnimation;
    protected Integer fragmentPopExitAnimation;
    private Integer snackbarActionTextColor;
    private Integer snackbarTextColor;
    private Integer snackbarTextSize;
    private String preferredStringLocale;
    private Integer picUtilImageSampleSize;
    private Integer spinnerLabelValidColor;
    private Integer spinnerLabelErrorColor;
    private Integer editTextRequiredErrorMessage;
    private int editTextInvalidUsernameErrorMessage;
    private int editTextInvalidEmailErrorMessage;
    private int editTextInvalidNumberRangeErrorMessage;
    private int editTextInvalidPositiveNumberErrorMessage;
    private int editTextTextLengthErrorMessage;
    private int enableRequiredPermissionsMessage;
    private List<AndroidPermissionItem> dangerousPermissions;
    private int editTextDateEarlierThanTodayErrorMessage;
    private int editTextStartDateGreaterThanTodayErrorMessage;
    private int editTextPhoneNumberValidatorErrorMessage;
    private int maximumCurrencyFractionDigits = 2;

    public AppCommonsConfiguration() {
    }

    public int getFragmentEnterAnimation() {
        return fragmentEnterAnimation;
    }

    public void setFragmentEnterAnimation(int fragmentEnterAnimation) {
        this.fragmentEnterAnimation = fragmentEnterAnimation;
    }


    public void setEditTextRequiredErrorMessage(int editTextRequiredErrorMessage) {
        this.editTextRequiredErrorMessage = editTextRequiredErrorMessage;
    }

    public int getEditTextRequiredErrorMessage() {
        return editTextRequiredErrorMessage;
    }

    public void setPicUtilImageSampleSize(int picUtilImageSampleSize) {
        this.picUtilImageSampleSize = picUtilImageSampleSize;
    }

    public int getPicUtilImageSampleSize() {
        return picUtilImageSampleSize;
    }

    public int getFragmentExitAnimation() {
        return fragmentExitAnimation;
    }

    public void setFragmentExitAnimation(int fragmentExitAnimation) {
        this.fragmentExitAnimation = fragmentExitAnimation;
    }

    public int getFragmentPopEnterAnimation() {
        return fragmentPopEnterAnimation;
    }

    public void setFragmentPopEnterAnimation(int fragmentPopEnterAnimation) {
        this.fragmentPopEnterAnimation = fragmentPopEnterAnimation;
    }

    public int getFragmentPopExitAnimation() {
        return fragmentPopExitAnimation;
    }

    public void setFragmentPopExitAnimation(int fragmentPopExitAnimation) {
        this.fragmentPopExitAnimation = fragmentPopExitAnimation;
    }


    public void setSnackbarActionTextColor(int snackbarActionTextColor) {
        this.snackbarActionTextColor = snackbarActionTextColor;
    }

    public int getSnackbarActionTextColor() {
        return snackbarActionTextColor;
    }

    public void setSnackbarTextColor(int snackbarTextColor) {
        this.snackbarTextColor = snackbarTextColor;
    }

    public int getSnackbarTextColor() {
        return snackbarTextColor;
    }

    public void setSnackbarTextSize(int snackbarTextSize) {
        this.snackbarTextSize = snackbarTextSize;
    }

    public int getSnackbarTextSize() {
        return snackbarTextSize;
    }


    public void setPreferredStringLocale(String preferredStringLocale) {
        this.preferredStringLocale = preferredStringLocale;
    }

    public String getPreferredStringLocale() {
        return preferredStringLocale;
    }

    public int getSpinnerLabelValidColor() {
        return spinnerLabelValidColor;
    }

    public void setSpinnerLabelValidColor(int spinnerLabelValidColor) {
        this.spinnerLabelValidColor = spinnerLabelValidColor;
    }

    public int getSpinnerLabelErrorColor() {
        return spinnerLabelErrorColor;
    }

    public void setSpinnerLabelErrorColor(int spinnerLabelErrorColor) {
        this.spinnerLabelErrorColor = spinnerLabelErrorColor;
    }

    public int getEditTextInvalidUsernameErrorMessage() {
        return editTextInvalidUsernameErrorMessage;
    }

    public void setEditTextInvalidUsernameErrorMessage(int editTextInvalidUsernameErrorMessage) {
        this.editTextInvalidUsernameErrorMessage = editTextInvalidUsernameErrorMessage;
    }

    public int getEditTextInvalidEmailErrorMessage() {
        return editTextInvalidEmailErrorMessage;
    }

    public void setEditTextInvalidEmailErrorMessage(int editTextInvalidEmailErrorMessage) {
        this.editTextInvalidEmailErrorMessage = editTextInvalidEmailErrorMessage;
    }

    public int getEditTextInvalidNumberRangeErrorMessage() {
        return editTextInvalidNumberRangeErrorMessage;
    }

    public void setEditTextInvalidNumberRangeErrorMessage(int editTextInvalidNumberRangeErrorMessage) {
        this.editTextInvalidNumberRangeErrorMessage = editTextInvalidNumberRangeErrorMessage;
    }

    public int getEditTextInvalidPositiveNumberErrorMessage() {
        return editTextInvalidPositiveNumberErrorMessage;
    }

    public void setEditTextInvalidPositiveNumberErrorMessage(int editTextInvalidPositiveNumberErrorMessage) {
        this.editTextInvalidPositiveNumberErrorMessage = editTextInvalidPositiveNumberErrorMessage;
    }

    public int getEditTextTextLengthErrorMessage() {
        return editTextTextLengthErrorMessage;
    }

    public void setEditTextTextLengthErrorMessage(int editTextTextLengthErrorMessage) {
        this.editTextTextLengthErrorMessage = editTextTextLengthErrorMessage;
    }

    public int getEnableRequiredPermissionsMessage() {
        return enableRequiredPermissionsMessage;
    }

    public void setEnableRequiredPermissionsMessage(int enableRequiredPermissionsMessage) {
        this.enableRequiredPermissionsMessage = enableRequiredPermissionsMessage;
    }

    public List<AndroidPermissionItem> getDangerousPermissions() {
        return dangerousPermissions;
    }

    public void setDangerousPermissions(List<AndroidPermissionItem> dangerousPermissions) {
        this.dangerousPermissions = dangerousPermissions;
    }

    public int getEditTextDateEarlierThanTodayErrorMessage() {
        return editTextDateEarlierThanTodayErrorMessage;
    }

    public void setEditTextDateEarlierThanTodayErrorMessage(int editTextDateLaterThanErrorMessage) {
        this.editTextDateEarlierThanTodayErrorMessage = editTextDateLaterThanErrorMessage;
    }

    public int getEditTextStartDateGreaterThanTodayErrorMessage() {
        return editTextStartDateGreaterThanTodayErrorMessage;
    }

    public void setEditTextStartDateGreaterThanTodayErrorMessage(int editTextStartDateGreaterThanTodayErrorMessage) {
        this.editTextStartDateGreaterThanTodayErrorMessage = editTextStartDateGreaterThanTodayErrorMessage;
    }

    public int getEditTextPhoneNumberValidatorErrorMessage() {
        return editTextPhoneNumberValidatorErrorMessage;
    }

    public void setEditTextPhoneNumberValidatorErrorMessage(int editTextPhoneNumberValidatorErrorMessage) {
        this.editTextPhoneNumberValidatorErrorMessage = editTextPhoneNumberValidatorErrorMessage;
    }

    public int getMaximumCurrencyFractionDigits() {
        return maximumCurrencyFractionDigits;
    }

    public void setMaximumCurrencyFractionDigits(int maximumCurrencyFractionDigits) {
        this.maximumCurrencyFractionDigits = maximumCurrencyFractionDigits;
    }
} public abstract class AlertLevel {

    public static AlertLevel INFO = new InfoAlertLevel();
    public static AlertLevel WARN = new WarnAlertLevel();
    public static AlertLevel ERROR = new ErrorAlertLevel();
    public static AlertLevel SUCCESS = new SuccessAlertLevel();

    protected int bgColor;
    protected int fgColor;

    AlertLevel(int bgColor, int fgColor) {
        this.bgColor = bgColor;
        this.fgColor = fgColor;
    }

    public int getBgColor() {
        return bgColor;
    }

    public void setBgColor(int bgColor) {
        this.bgColor = bgColor;
    }

    public int getFgColor() {
        return fgColor;
    }

    public void setFgColor(int fgColor) {
        this.fgColor = fgColor;
    }
} public class AndroidPermissionItem {
    private String permissionDescription;
    private String permissionConstant;


    public AndroidPermissionItem(String permissionDescription, String permissionConstant) {
        this.permissionDescription = permissionDescription;
        this.permissionConstant = permissionConstant;
    }

    public String getPermissionConstant() {
        return permissionConstant;
    }

    public void setPermissionConstant(String permissionConstant) {
        this.permissionConstant = permissionConstant;
    }

    public String getPermissionDescription() {
        return permissionDescription;
    }

    public void setPermissionDescription(String permissionDescription) {
        this.permissionDescription = permissionDescription;
    }

    public static List<AndroidPermissionItem> listDangerousPermissions() {
        List<AndroidPermissionItem> list = new ArrayList<>();

        list.add(new AndroidPermissionItem(PermissionUtil.getPermissionDescription(Manifest.permission.READ_PHONE_STATE), Manifest.permission.READ_PHONE_STATE));
        list.add(new AndroidPermissionItem(PermissionUtil.getPermissionDescription(Manifest.permission.ACCESS_FINE_LOCATION), Manifest.permission.ACCESS_FINE_LOCATION));
        list.add(new AndroidPermissionItem(PermissionUtil.getPermissionDescription(Manifest.permission.ACCESS_COARSE_LOCATION), Manifest.permission.ACCESS_COARSE_LOCATION));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            list.add(new AndroidPermissionItem(PermissionUtil.getPermissionDescription(Manifest.permission.READ_EXTERNAL_STORAGE), Manifest.permission.READ_EXTERNAL_STORAGE));
        }
        list.add(new AndroidPermissionItem(PermissionUtil.getPermissionDescription(Manifest.permission.WRITE_EXTERNAL_STORAGE), Manifest.permission.WRITE_EXTERNAL_STORAGE));

        return list;
    }
} public class PermissionUtil {

    private static final String TAG = PermissionUtil.class.getSimpleName();


    public static List<AndroidPermissionItem> listNotGrantedPermissions(List<AndroidPermissionItem> androidPermissionItemList) {
        List<AndroidPermissionItem> notGrantedPermissions = new ArrayList<>();
        Context context = AppCommons.getApplication().getApplicationContext();

        if (androidPermissionItemList == null || androidPermissionItemList.isEmpty()) {
            return notGrantedPermissions;
        }

        for (AndroidPermissionItem androidPermissionItem : androidPermissionItemList) {
            if (checkIfPermissionIsNotGranted(context, androidPermissionItem.getPermissionConstant())) {
                notGrantedPermissions.add(androidPermissionItem);
            }
        }

        return notGrantedPermissions;
    }

    /**
     * Iterate through the requested permissions and returns true if all the permissions are not granted.
     *
     * @param context
     * @param requestedPermissions
     * @return
     */
    public static boolean checkIfPermissionIsNotGranted(Context context, String... requestedPermissions) {
        boolean isNotGranted = false;

        for (String onePermission : requestedPermissions) {
            isNotGranted = ActivityCompat.checkSelfPermission(context, onePermission) != PackageManager.PERMISSION_GRANTED;
            Log.d(TAG, onePermission + " : " + !isNotGranted);
            if (isNotGranted) {
                break;
            }
        }

        return isNotGranted;
    }

    //http://stackoverflow.com/a/16872728
    public static String getPermissionDescription(String permissionId) {
        PackageManager packageManager = AppCommons.getApplication().getPackageManager();
        PermissionInfo pinfo;
        try {
            pinfo = packageManager.getPermissionInfo(permissionId, PackageManager.GET_META_DATA);
            return pinfo.loadLabel(packageManager).toString();

        } catch (PackageManager.NameNotFoundException e) {
            Log.d(TAG, e.getMessage());
        }
        return permissionId;
    }
} public abstract class DeferredFragmentTransaction {

    private int contentFrameId;
    private Fragment replacingFragment;
    private Fragment parentFragment;

    public abstract void commit(AppCommonsActivity appCommonsActivity) ;

    public int getContentFrameId() {
        return contentFrameId;
    }

    public void setContentFrameId(int contentFrameId) {
        this.contentFrameId = contentFrameId;
    }

    public Fragment getReplacingFragment() {
        return replacingFragment;
    }

    public void setReplacingFragment(Fragment replacingFragment) {
        this.replacingFragment = replacingFragment;
    }

    public void setParentFragment(Fragment parentFragment) {
        this.parentFragment = parentFragment;
    }

    public Fragment getParentFragment() {
        return parentFragment;
    }
}
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.Toast;
import com.bentech.android.appcommons.AppCommons;
import com.bentech.android.appcommons.AppCommonsContext;
import com.bentech.android.appcommons.R;
import com.bentech.android.appcommons.activity.operations.ActivityOperations;
import com.bentech.android.appcommons.activity.operations.FeedbackOperations;
import com.bentech.android.appcommons.activity.operations.FragmentOperations;
import com.bentech.android.appcommons.config.AppCommonsConfiguration;
import com.bentech.android.appcommons.constants.alert.AlertLevel;
import com.bentech.android.appcommons.permission.AndroidPermissionItem;
import com.bentech.android.appcommons.permission.PermissionUtil;
import com.bentech.android.appcommons.utils.DeferredFragmentTransaction;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
package com.bentech.android.appcommons.activity;





/**
 * Created by Daniel on 07/11/2015.
 */
public class AppCommonsActivity extends AppCompatActivity implements ActivityOperations, FragmentOperations,
        FeedbackOperations {
    //PERMISSIONS
    private static final int PERMISSION_REQUEST_CODE = 2;
    private final AppCommonsConfiguration appCommonsConfiguration;
    Queue<DeferredFragmentTransaction> deferredFragmentTransactions = new ArrayDeque<>();
    private AppCommonsContext appCommonsContext;
    private String TAG = AppCommonsActivity.class.getSimpleName();
    private Snackbar currentlyDisplayedSnackbar;
    private boolean isRunning;

    public AppCommonsActivity() {
        appCommonsConfiguration = AppCommons.getAppCommonsConfiguration();