core/src/main/java/com/dm/material/dashboard/candybar/utils/listeners/RequestListener.java
public interface RequestListener {

    void onPiracyAppChecked(boolean isPiracyAppInstalled);
    void onRequestSelected(int count);
    void onBuyPremiumRequest();
    void onPremiumRequestBought();
    void onRequestBuilt(Intent intent, int type);
}
core/src/main/java/com/dm/material/dashboard/candybar/helpers/DeviceHelper.java
public class DeviceHelper {

    @NonNull
    public static String getDeviceInfo(@NonNull Context context) {
        DisplayMetrics displaymetrics = context.getResources().getDisplayMetrics();
        StringBuilder sb = new StringBuilder();
        final int height = displaymetrics.heightPixels;
        final int width = displaymetrics.widthPixels;

        String appVersion = "";
        try {
            appVersion = context.getPackageManager().getPackageInfo(
                    context.getPackageName(), 0).versionName;
        } catch (PackageManager.NameNotFoundException ignored) {}

        sb.append("Manufacturer : ").append(Build.MANUFACTURER)
                .append("\nModel : ").append(Build.MODEL)
                .append("\nProduct : ").append(Build.PRODUCT)
                .append("\nScreen Resolution : ")
                .append(width).append(" x ").append(height).append(" pixels")
                .append("\nAndroid Version : ").append(Build.VERSION.RELEASE)
                .append("\nApp Version : ").append(appVersion)
                .append("\nCandyBar Version : ").append(BuildConfig.VERSION_NAME)
                .append("\n");
        return sb.toString();
    }

    @NonNull
    public static String getDeviceInfoForCrashReport(@NonNull Context context) {
        return "Icon Pack Name : " +context.getResources().getString(R.string.app_name)
                + "\n"+ getDeviceInfo(context);
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/applications/CandyBarApplication.java
public abstract class CandyBarApplication extends Application implements ApplicationCallback {

    private static Configuration mConfiguration;
    private Thread.UncaughtExceptionHandler mHandler;

    public static Request.Property sRequestProperty;
    public static String sZipPath = null;

    public static Configuration getConfiguration() {
        if (mConfiguration == null) {
            mConfiguration = new Configuration();
        }
        return mConfiguration;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Database.get(this).openDatabase();

        if (!ImageLoader.getInstance().isInited())
            ImageLoader.getInstance().init(ImageConfig.getImageLoaderConfiguration(this));

        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                .setDefaultFontPath("fonts/Font-Regular.ttf")
                .setFontAttrId(R.attr.fontPath)
                .build());

        //Enable or disable logging
        LogUtil.setLoggingTag(getString(R.string.app_name));
        LogUtil.setLoggingEnabled(true);

        mConfiguration = onInit();

        if (mConfiguration.mIsCrashReportEnabled) {
            mHandler = Thread.getDefaultUncaughtExceptionHandler();
            Thread.setDefaultUncaughtExceptionHandler(this::handleUncaughtException);
        }

        if (Preferences.get(this).isTimeToSetLanguagePreference()) {
            Preferences.get(this).setLanguagePreference();
            return;
        }

        LocaleHelper.setLocale(this);
    }

    private void handleUncaughtException(Thread thread, Throwable throwable) {
        try {
            StringBuilder sb = new StringBuilder();
            SimpleDateFormat dateFormat = new SimpleDateFormat(
                    "yyyy-MM-dd HH:mm:ss", Locale.getDefault());
            String dateTime = dateFormat.format(new Date());
            sb.append("Crash Time : ").append(dateTime).append("\n");
            sb.append("Class Name : ").append(throwable.getClass().getName()).append("\n");
            sb.append("Caused By : ").append(throwable.toString()).append("\n");

            for (StackTraceElement element : throwable.getStackTrace()) {
                sb.append("\n");
            sb.append(element.toString());
        }

            Preferences.get(this).setLatestCrashLog(sb.toString());

            Intent intent = new Intent(this, CandyBarCrashReport.class);
            intent.putExtra(CandyBarCrashReport.EXTRA_STACKTRACE, sb.toString());
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            startActivity(intent);
        } catch (Exception e) {
            if (mHandler != null) {
                mHandler.uncaughtException(thread, throwable);
                return;
            }
        }
        System.exit(1);
    }

    public static class Configuration {

        private NavigationIcon mNavigationIcon = NavigationIcon.STYLE_1;
        private NavigationViewHeader mNavigationViewHeader = NavigationViewHeader.NORMAL;

        private GridStyle mHomeGrid = GridStyle.CARD;
        private GridStyle mApplyGrid = GridStyle.CARD;
        private Style mRequestStyle = Style.PORTRAIT_FLAT_LANDSCAPE_CARD;
        private GridStyle mWallpapersGrid = GridStyle.CARD;
        private Style mAboutStyle = Style.PORTRAIT_FLAT_LANDSCAPE_CARD;
        private IconColor mIconColor = IconColor.PRIMARY_TEXT;
        private List<OtherApp> mOtherApps = null;

        private boolean mIsHighQualityPreviewEnabled = false;
        private boolean mIsColoredApplyCard = true;
        private boolean mIsAutomaticIconsCountEnabled = true;
        private int mCustomIconsCount = 0;
        private boolean mIsShowTabIconsCount = false;
        private boolean mIsShowTabAllIcons = false;
        private String mTabAllIconsTitle = "All Icons";
        private String[] mCategoryForTabAllIcons = null;

        private ShadowOptions mShadowOptions = new ShadowOptions();
        private boolean mIsDashboardThemingEnabled = true;
        private int mWallpaperGridPreviewQuality = 4;

        private boolean mIsGenerateAppFilter = true;
        private boolean mIsGenerateAppMap = false;
        private boolean mIsGenerateThemeResources = false;
        private boolean mIsIncludeIconRequestToEmailBody = true;

        private boolean mIsCrashReportEnabled = true;
        private JsonStructure mWallpaperJsonStructure = new JsonStructure.Builder("Wallpapers").build();

        public Configuration setNavigationIcon(@NonNull NavigationIcon navigationIcon) {
            mNavigationIcon = navigationIcon;
            return this;
        }

        public Configuration setNavigationViewHeaderStyle(@NonNull NavigationViewHeader navigationViewHeader) {
            mNavigationViewHeader = navigationViewHeader;
            return this;
        }

        public Configuration setAutomaticIconsCountEnabled(boolean automaticIconsCountEnabled) {
            mIsAutomaticIconsCountEnabled = automaticIconsCountEnabled;
            return this;
        }

        public Configuration setHomeGridStyle(@NonNull GridStyle gridStyle) {
            mHomeGrid = gridStyle;
            return this;
        }

        public Configuration setApplyGridStyle(@NonNull GridStyle gridStyle) {
            mApplyGrid = gridStyle;
            return this;
        }

        public Configuration setRequestStyle(@NonNull Style style) {
            mRequestStyle = style;
            return this;
        }

        public Configuration setWallpapersGridStyle(@NonNull GridStyle gridStyle) {
            mWallpapersGrid = gridStyle;
            return this;
        }

        public Configuration setAboutStyle(@NonNull Style style) {
            mAboutStyle = style;
            return this;
        }

        public Configuration setSocialIconColor(@NonNull IconColor iconColor) {
            mIconColor = iconColor;
            return this;
        }

        public Configuration setColoredApplyCard(boolean coloredApplyCard) {
            mIsColoredApplyCard = coloredApplyCard;
            return this;
        }

        public Configuration setCustomIconsCount(int customIconsCount) {
            mCustomIconsCount = customIconsCount;
            return this;
        }

        public Configuration setShowTabIconsCount(boolean showTabIconsCount) {
            mIsShowTabIconsCount = showTabIconsCount;
            return this;
        }

        public Configuration setShowTabAllIcons(boolean showTabAllIcons) {
            mIsShowTabAllIcons = showTabAllIcons;
            return this;
        }

        public Configuration setTabAllIconsTitle(@NonNull String title) {
            mTabAllIconsTitle = title;
            if (mTabAllIconsTitle.length() == 0) mTabAllIconsTitle = "All Icons";
            return this;
        }

        public Configuration setCategoryForTabAllIcons(@NonNull String[] categories) {
            mCategoryForTabAllIcons = categories;
            return this;
        }

        public Configuration setShadowEnabled(boolean shadowEnabled) {
            mShadowOptions = new ShadowOptions(shadowEnabled);
            return this;
        }

        public Configuration setShadowEnabled(@NonNull ShadowOptions shadowOptions) {
            mShadowOptions = shadowOptions;
            return this;
        }

        public Configuration setDashboardThemingEnabled(boolean dashboardThemingEnabled) {
            mIsDashboardThemingEnabled = dashboardThemingEnabled;
            return this;
        }

        public Configuration setWallpaperGridPreviewQuality(@IntRange (from = 1, to = 10) int quality) {
            mWallpaperGridPreviewQuality = quality;
            return this;
        }

        public Configuration setGenerateAppFilter(boolean generateAppFilter) {
            mIsGenerateAppFilter = generateAppFilter;
            return this;
        }

        public Configuration setGenerateAppMap(boolean generateAppMap) {
            mIsGenerateAppMap = generateAppMap;
            return this;
        }

        public Configuration setGenerateThemeResources(boolean generateThemeResources) {
            mIsGenerateThemeResources = generateThemeResources;
            return this;
        }

        public Configuration setIncludeIconRequestToEmailBody(boolean includeIconRequestToEmailBody) {
            mIsIncludeIconRequestToEmailBody = includeIconRequestToEmailBody;
            return this;
        }

        public Configuration setCrashReportEnabled(boolean crashReportEnabled) {
            mIsCrashReportEnabled = crashReportEnabled;
            return this;
        }

        public Configuration setWallpaperJsonStructure(@NonNull JsonStructure jsonStructure) {
            mWallpaperJsonStructure = jsonStructure;
            return this;
        }

        public Configuration setOtherApps(@NonNull OtherApp[] otherApps) {
            mOtherApps = Arrays.asList(otherApps);
            return this;
        }

        public Configuration setHighQualityPreviewEnabled(boolean highQualityPreviewEnabled) {
            mIsHighQualityPreviewEnabled = highQualityPreviewEnabled;
            return this;
        }

        public NavigationIcon getNavigationIcon() {
            return mNavigationIcon;
        }

        public NavigationViewHeader getNavigationViewHeader() {
            return mNavigationViewHeader;
        }

        public GridStyle getHomeGrid() {
            return mHomeGrid;
        }

        public GridStyle getApplyGrid() {
            return mApplyGrid;
        }

        public Style getRequestStyle() {
            return mRequestStyle;
        }

        public GridStyle getWallpapersGrid() {
            return mWallpapersGrid;
        }

        public Style getAboutStyle() {
            return mAboutStyle;
        }

        public IconColor getSocialIconColor() {
            return mIconColor;
        }

        public boolean isColoredApplyCard() {
            return mIsColoredApplyCard;
        }

        public boolean isAutomaticIconsCountEnabled() {
            return mIsAutomaticIconsCountEnabled;
        }

        public int getCustomIconsCount() {
            return mCustomIconsCount;
        }

        public boolean isShowTabIconsCount() {
            return mIsShowTabIconsCount;
        }

        public boolean isShowTabAllIcons() {
            return mIsShowTabAllIcons;
        }

        public String getTabAllIconsTitle() {
            return mTabAllIconsTitle;
        }

        public String[] getCategoryForTabAllIcons() {
            return mCategoryForTabAllIcons;
        }

        @NonNull
        public ShadowOptions getShadowOptions() {
            return mShadowOptions;
        }

        public boolean isDashboardThemingEnabled() {
            return mIsDashboardThemingEnabled;
        }

        public int getWallpaperGridPreviewQuality() {
            return mWallpaperGridPreviewQuality;
        }

        public boolean isGenerateAppFilter() {
            return mIsGenerateAppFilter;
        }

        public boolean isGenerateAppMap() {
            return mIsGenerateAppMap;
        }

        public boolean isGenerateThemeResources() {
            return mIsGenerateThemeResources;
        }

        public boolean isIncludeIconRequestToEmailBody() {
            return mIsIncludeIconRequestToEmailBody;
        }

        public boolean isHighQualityPreviewEnabled() {
            return mIsHighQualityPreviewEnabled;
        }

        public JsonStructure getWallpaperJsonStructure() {
            return mWallpaperJsonStructure;
        }

        @Nullable
        public List<OtherApp> getOtherApps() {
            return mOtherApps;
        }
    }

    public enum NavigationIcon {
        DEFAULT,
        STYLE_1,
        STYLE_2,
        STYLE_3,
        STYLE_4
    }

    public enum NavigationViewHeader {
        NORMAL,
        MINI,
        NONE
    }

    public enum GridStyle {
        CARD,
        FLAT
    }

    public enum Style {
        PORTRAIT_FLAT_LANDSCAPE_CARD,
        PORTRAIT_FLAT_LANDSCAPE_FLAT
    }

    public enum IconColor {
        PRIMARY_TEXT,
        ACCENT
    }

    public static class ShadowOptions {

        private boolean mIsToolbarEnabled;
        private boolean mIsCardEnabled;
        private boolean mIsFabEnabled;
        private boolean mIsTapIntroEnabled;

        public ShadowOptions() {
            mIsToolbarEnabled = mIsCardEnabled = mIsFabEnabled = mIsTapIntroEnabled = true;
        }

        public ShadowOptions(boolean shadowEnabled) {
            mIsToolbarEnabled = mIsCardEnabled = mIsFabEnabled = mIsTapIntroEnabled= shadowEnabled;
        }

        public ShadowOptions setToolbarEnabled(boolean toolbarEnabled) {
            mIsToolbarEnabled = toolbarEnabled;
            return this;
        }

        public ShadowOptions setCardEnabled(boolean cardEnabled) {
            mIsCardEnabled = cardEnabled;
            return this;
        }

        public ShadowOptions setFabEnabled(boolean fabEnabled) {
            mIsFabEnabled = fabEnabled;
            return this;
        }

        public ShadowOptions setTapIntroEnabled(boolean tapIntroEnabled) {
            mIsTapIntroEnabled = tapIntroEnabled;
            return this;
        }

        public boolean isToolbarEnabled() {
            return mIsToolbarEnabled;
        }

        public boolean isCardEnabled() {
            return mIsCardEnabled;
        }

        public boolean isFabEnabled() {
            return mIsFabEnabled;
        }

        public boolean isTapIntroEnabled() {
            return mIsTapIntroEnabled;
        }
    }

    public static class OtherApp {

        private String mIcon;
        private String mTitle;
        private String mDescription;
        private String mUrl;

        public OtherApp(String icon, String title, String description, String url) {
            mIcon = icon;
            mTitle = title;
            mDescription = description;
            mUrl = url;
        }

        public String getIcon() {
            return mIcon;
        }

        public String getTitle() {
            return mTitle;
        }

        public String getDescription() {
            return mDescription;
        }

        public String getUrl() {
            return mUrl;
        }
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/preferences/Preferences.java
public class Preferences {

    private final Context mContext;

    private static final String PREFERENCES_NAME = "candybar_preferences";

    private static final String KEY_FIRST_RUN = "first_run";
    private static final String KEY_DARK_THEME = "dark_theme";
    private static final String KEY_APP_VERSION = "app_version";
    private static final String KEY_ROTATE_TIME = "rotate_time";
    private static final String KEY_ROTATE_MINUTE = "rotate_minute";
    private static final String KEY_WIFI_ONLY = "wifi_only";
    private static final String KEY_WALLS_DIRECTORY = "wallpaper_directory";
    private static final String KEY_PREMIUM_REQUEST = "premium_request";
    private static final String KEY_PREMIUM_REQUEST_PRODUCT = "premium_request_product";
    private static final String KEY_PREMIUM_REQUEST_COUNT = "premium_request_count";
    private static final String KEY_PREMIUM_REQUEST_TOTAL = "premium_request_total";
    private static final String KEY_REGULAR_REQUEST_USED= "regular_request_used";
    private static final String KEY_INAPP_BILLING_TYPE = "inapp_billing_type";
    private static final String KEY_LICENSED = "licensed";
    private static final String KEY_LATEST_CRASHLOG = "last_crashlog";
    private static final String KEY_PREMIUM_REQUEST_ENABLED = "premium_request_enabled";
    private static final String KEY_AVAILABLE_WALLPAPERS_COUNT = "available_wallpapers_count";
    private static final String KEY_CROP_WALLPAPER = "crop_wallpaper";
    private static final String KEY_HOME_INTRO = "home_intro";
    private static final String KEY_ICONS_INTRO = "icons_intro";
    private static final String KEY_REQUEST_INTRO = "request_intro";
    private static final String KEY_WALLPAPERS_INTRO = "wallpapers_intro";
    private static final String KEY_WALLPAPER_PREVIEW_INTRO = "wallpaper_preview_intro";

    private static final String KEY_LANGUAGE_PREFERENCE = "language_preference";
    private static final String KEY_CURRENT_LOCALE = "current_locale";

    private static WeakReference<Preferences> mPreferences;

    @NonNull
    public static Preferences get(@NonNull Context context) {
        if (mPreferences == null || mPreferences.get() == null) {
            mPreferences = new WeakReference<>(new Preferences(context));
        }
        return mPreferences.get();
    }

    private Preferences(Context context) {
        mContext = context;
    }

    private SharedPreferences getSharedPreferences() {
        return mContext.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
    }

    public void clearPreferences() {
        boolean isLicensed = isLicensed();
        getSharedPreferences().edit().clear().apply();

        if (isLicensed) {
            setFirstRun(false);
            setLicensed(true);
        }
    }

    public boolean isFirstRun() {
        return getSharedPreferences().getBoolean(KEY_FIRST_RUN, true);
    }

    public void setFirstRun(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_FIRST_RUN, bool).apply();
    }

    public boolean isTimeToShowHomeIntro() {
        return getSharedPreferences().getBoolean(KEY_HOME_INTRO, true);
    }

    public void setTimeToShowHomeIntro(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_HOME_INTRO, bool).apply();
    }

    public boolean isTimeToShowIconsIntro() {
        return getSharedPreferences().getBoolean(KEY_ICONS_INTRO, true);
    }

    public void setTimeToShowIconsIntro(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_ICONS_INTRO, bool).apply();
    }

    public boolean isTimeToShowRequestIntro() {
        return getSharedPreferences().getBoolean(KEY_REQUEST_INTRO, true);
    }

    public void setTimeToShowRequestIntro(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_REQUEST_INTRO, bool).apply();
    }

    public boolean isTimeToShowWallpapersIntro() {
        return getSharedPreferences().getBoolean(KEY_WALLPAPERS_INTRO, true);
    }

    public void setTimeToShowWallpapersIntro(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_WALLPAPERS_INTRO, bool).apply();
    }

    public boolean isTimeToShowWallpaperPreviewIntro() {
        return getSharedPreferences().getBoolean(KEY_WALLPAPER_PREVIEW_INTRO, true);
    }

    public void setTimeToShowWallpaperPreviewIntro(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_WALLPAPER_PREVIEW_INTRO, bool).apply();
    }

    public boolean isDarkTheme() {
        boolean useDarkTheme = mContext.getResources().getBoolean(R.bool.use_dark_theme);
        boolean isThemingEnabled = CandyBarApplication.getConfiguration().isDashboardThemingEnabled();
        if (!isThemingEnabled) return useDarkTheme;
        return getSharedPreferences().getBoolean(KEY_DARK_THEME, useDarkTheme);
    }

    public void setDarkTheme(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_DARK_THEME, bool).apply();
    }

    public boolean isToolbarShadowEnabled() {
        return CandyBarApplication.getConfiguration().getShadowOptions().isToolbarEnabled();
    }

    public boolean isCardShadowEnabled() {
        return CandyBarApplication.getConfiguration().getShadowOptions().isCardEnabled();
    }

    public boolean isFabShadowEnabled() {
        return CandyBarApplication.getConfiguration().getShadowOptions().isFabEnabled();
    }

    public boolean isTapIntroShadowEnabled() {
        return CandyBarApplication.getConfiguration().getShadowOptions().isTapIntroEnabled();
    }

    public void setRotateTime (int time) {
        getSharedPreferences().edit().putInt(KEY_ROTATE_TIME, time).apply();
    }

    public int getRotateTime() {
        return getSharedPreferences().getInt(KEY_ROTATE_TIME, 3600000);
    }

    public void setRotateMinute (boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_ROTATE_MINUTE, bool).apply();
    }

    public boolean isRotateMinute() {
        return getSharedPreferences().getBoolean(KEY_ROTATE_MINUTE, false);
    }

    public boolean isWifiOnly() {
        return getSharedPreferences().getBoolean(KEY_WIFI_ONLY, false);
    }

    public void setWifiOnly (boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_WIFI_ONLY, bool).apply();
    }

    public void setWallsDirectory(String directory) {
        getSharedPreferences().edit().putString(KEY_WALLS_DIRECTORY, directory).apply();
    }

    public String getWallsDirectory() {
        return getSharedPreferences().getString(KEY_WALLS_DIRECTORY, "");
    }

    public boolean isPremiumRequestEnabled() {
        return getSharedPreferences().getBoolean(KEY_PREMIUM_REQUEST_ENABLED,
                mContext.getResources().getBoolean(R.bool.enable_premium_request));
    }

    public void setPremiumRequestEnabled(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_PREMIUM_REQUEST_ENABLED, bool).apply();
    }

    public boolean isPremiumRequest() {
        return getSharedPreferences().getBoolean(KEY_PREMIUM_REQUEST, false);
    }

    public void setPremiumRequest(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_PREMIUM_REQUEST, bool).apply();
    }

    public String getPremiumRequestProductId() {
        return getSharedPreferences().getString(KEY_PREMIUM_REQUEST_PRODUCT, "");
    }

    public void setPremiumRequestProductId(String productId) {
        getSharedPreferences().edit().putString(KEY_PREMIUM_REQUEST_PRODUCT, productId).apply();
    }

    public int getPremiumRequestCount() {
        return getSharedPreferences().getInt(KEY_PREMIUM_REQUEST_COUNT, 0);
    }

    public void setPremiumRequestCount(int count) {
        getSharedPreferences().edit().putInt(KEY_PREMIUM_REQUEST_COUNT, count).apply();
    }

    public int getPremiumRequestTotal() {
        int count = getPremiumRequestCount();
        return getSharedPreferences().getInt(KEY_PREMIUM_REQUEST_TOTAL, count);
    }

    public void setPremiumRequestTotal(int count) {
        getSharedPreferences().edit().putInt(KEY_PREMIUM_REQUEST_TOTAL, count).apply();
    }

    public int getRegularRequestUsed() {
        return getSharedPreferences().getInt(KEY_REGULAR_REQUEST_USED, 0);
    }

    public void setRegularRequestUsed(int used) {
        getSharedPreferences().edit().putInt(KEY_REGULAR_REQUEST_USED, used).apply();
    }

    public int getInAppBillingType() {
        return getSharedPreferences().getInt(KEY_INAPP_BILLING_TYPE, -1);
    }

    public void setInAppBillingType(int type) {
        getSharedPreferences().edit().putInt(KEY_INAPP_BILLING_TYPE, type).apply();
    }

    public boolean isLicensed() {
        return getSharedPreferences().getBoolean(KEY_LICENSED, false);
    }

    public void setLicensed(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_LICENSED, bool).apply();
    }

    public boolean isCropWallpaper() {
        return getSharedPreferences().getBoolean(KEY_CROP_WALLPAPER, false);
    }

    public void setCropWallpaper(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_CROP_WALLPAPER, bool).apply();
    }

    public String getLatestCrashLog() {
        return getSharedPreferences().getString(KEY_LATEST_CRASHLOG, "");
    }

    public void setLatestCrashLog(String string) {
        getSharedPreferences().edit().putString(KEY_LATEST_CRASHLOG, string).apply();
    }

    public int getAvailableWallpapersCount() {
        return getSharedPreferences().getInt(KEY_AVAILABLE_WALLPAPERS_COUNT, 0);
    }

    public void setAvailableWallpapersCount(int count) {
        getSharedPreferences().edit().putInt(KEY_AVAILABLE_WALLPAPERS_COUNT, count).apply();
    }

    private int getVersion() {
        return getSharedPreferences().getInt(KEY_APP_VERSION, 0);
    }

    private void setVersion(int version) {
        getSharedPreferences().edit().putInt(KEY_APP_VERSION, version).apply();
    }

    public boolean isNewVersion() {
        int version = 0;
        try {
            version = mContext.getPackageManager().getPackageInfo(
                    mContext.getPackageName(), 0).versionCode;
        } catch (PackageManager.NameNotFoundException ignored) {}
        if (version > getVersion()) {
            boolean resetLimit = mContext.getResources().getBoolean(R.bool.reset_icon_request_limit);
            if (resetLimit) setRegularRequestUsed(0);
            setVersion(version);
            return true;
        } else {
            return false;
        }
    }

    public Locale getCurrentLocale() {
        String code = getSharedPreferences().getString(KEY_CURRENT_LOCALE, "en_US");
        return LocaleHelper.getLocale(code);
    }

    public void setCurrentLocale(String code) {
        getSharedPreferences().edit().putString(KEY_CURRENT_LOCALE, code).apply();
    }

    public boolean isTimeToSetLanguagePreference() {
        return getSharedPreferences().getBoolean(KEY_LANGUAGE_PREFERENCE, true);
    }

    private void setTimeToSetLanguagePreference(boolean bool) {
        getSharedPreferences().edit().putBoolean(KEY_LANGUAGE_PREFERENCE, bool).apply();
    }

    public void setLanguagePreference() {
        Locale locale = Locale.getDefault();
        List<Language> languages = LocaleHelper.getAvailableLanguages(mContext);

        Locale currentLocale = null;
        for (Language language : languages) {
            Locale l = language.getLocale();
            if (locale.toString().equals(l.toString())) {
                currentLocale = l;
                break;
            }
        }

        if (currentLocale == null) {
            for (Language language : languages) {
                Locale l = language.getLocale();
                if (locale.getLanguage().equals(l.getLanguage())) {
                    currentLocale = l;
                    break;
                }
            }
        }

        if (currentLocale != null) {
            setCurrentLocale(currentLocale.toString());
            LocaleHelper.setLocale(mContext);
            setTimeToSetLanguagePreference(false);
        }
    }

    public boolean isConnectedToNetwork() {
        try {
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            return activeNetworkInfo != null && activeNetworkInfo.isConnected();
        } catch (Exception e) {
            return false;
        }
    }

    public boolean isConnectedAsPreferred() {
        try {
            if (isWifiOnly()) {
                ConnectivityManager connectivityManager = (ConnectivityManager)
                        mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
                return activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
                        activeNetworkInfo.isConnected();
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/databases/Database.java
public class Database extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "candybar_database";
    private static final int DATABASE_VERSION = 9;

    private static final String TABLE_REQUEST = "icon_request";
    private static final String TABLE_PREMIUM_REQUEST = "premium_request";
    private static final String TABLE_WALLPAPERS = "wallpapers";

    private static final String KEY_ID = "id";

    private static final String KEY_ORDER_ID = "order_id";
    private static final String KEY_PRODUCT_ID = "product_id";

    private static final String KEY_NAME = "name";
    private static final String KEY_ACTIVITY = "activity";
    private static final String KEY_REQUESTED_ON = "requested_on";

    private static final String KEY_AUTHOR = "author";
    private static final String KEY_THUMB_URL = "thumbUrl";
    private static final String KEY_URL = "url";
    private static final String KEY_ADDED_ON = "added_on";
    private static final String KEY_MIME_TYPE = "mimeType";
    private static final String KEY_COLOR = "color";
    private static final String KEY_WIDTH = "width";
    private static final String KEY_HEIGHT = "height";
    private static final String KEY_SIZE = "size";

    private final Context mContext;

    private static WeakReference<Database> mDatabase;
    private SQLiteDatabase mSQLiteDatabase;

    public static Database get(@NonNull Context context) {
        if (mDatabase == null || mDatabase.get() == null) {
            mDatabase = new WeakReference<>(new Database(context));
        }
        return mDatabase.get();
    }

    private Database(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_TABLE_REQUEST = "CREATE TABLE IF NOT EXISTS " +TABLE_REQUEST+ "(" +
                KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                KEY_NAME + " TEXT NOT NULL, " +
                KEY_ACTIVITY + " TEXT NOT NULL, " +
                KEY_REQUESTED_ON + " DATETIME DEFAULT CURRENT_TIMESTAMP, " +
                "UNIQUE (" +KEY_ACTIVITY+ ") ON CONFLICT REPLACE)";
        String CREATE_TABLE_PREMIUM_REQUEST = "CREATE TABLE IF NOT EXISTS " +TABLE_PREMIUM_REQUEST+ "(" +
                KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                KEY_ORDER_ID + " TEXT NOT NULL, " +
                KEY_PRODUCT_ID + " TEXT NOT NULL, " +
                KEY_NAME + " TEXT NOT NULL, " +
                KEY_ACTIVITY + " TEXT NOT NULL, " +
                KEY_REQUESTED_ON + " DATETIME DEFAULT CURRENT_TIMESTAMP, " +
                "UNIQUE (" +KEY_ACTIVITY+ ") ON CONFLICT REPLACE)";
        String CREATE_TABLE_WALLPAPER = "CREATE TABLE IF NOT EXISTS " +TABLE_WALLPAPERS+ "(" +
                KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                KEY_NAME+ " TEXT NOT NULL, " +
                KEY_AUTHOR + " TEXT NOT NULL, " +
                KEY_URL + " TEXT NOT NULL, " +
                KEY_THUMB_URL + " TEXT NOT NULL, " +
                KEY_MIME_TYPE + " TEXT, " +
                KEY_SIZE + " INTEGER DEFAULT 0, " +
                KEY_COLOR + " INTEGER DEFAULT 0, " +
                KEY_WIDTH + " INTEGER DEFAULT 0, " +
                KEY_HEIGHT + " INTEGER DEFAULT 0, " +
                KEY_ADDED_ON + " TEXT NOT NULL, " +
                "UNIQUE (" +KEY_URL+ "))";
        db.execSQL(CREATE_TABLE_REQUEST);
        db.execSQL(CREATE_TABLE_PREMIUM_REQUEST);
        db.execSQL(CREATE_TABLE_WALLPAPER);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        /*
         * Need to clear shared preferences with version 3.4.0
         */
        if (newVersion == 9) {
            Preferences.get(mContext).clearPreferences();
        }
        resetDatabase(db, oldVersion);
    }

    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        resetDatabase(db, oldVersion);
    }

    private void resetDatabase(SQLiteDatabase db, int oldVersion) {
        Cursor cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type=\'table\'", null);
        List<String> tables = new ArrayList<>();
        if (cursor.moveToFirst()) {
            do {
                tables.add(cursor.getString(0));
            } while (cursor.moveToNext());
        }
        cursor.close();

        List<Request> requests = getRequestedApps(db);
        List<Request> premiumRequest = getPremiumRequest(db);

        for (int i = 0; i < tables.size(); i++) {
            try {
                String dropQuery = "DROP TABLE IF EXISTS " + tables.get(i);
                if (!tables.get(i).equalsIgnoreCase("SQLITE_SEQUENCE"))
                    db.execSQL(dropQuery);
            } catch (Exception ignored) {}
        }
        onCreate(db);

        for (Request request : requests) {
            addRequest(db, request);
        }

        if (oldVersion <= 3) {
            return;
        }

        for (Request premium : premiumRequest) {
            Request r = Request.Builder()
                    .name(premium.getName())
                    .activity(premium.getActivity())
                    .orderId(premium.getOrderId())
                    .productId(premium.getProductId())
                    .requestedOn(premium.getRequestedOn())
                    .build();
            addPremiumRequest(db, r);
        }
    }

    public boolean openDatabase() {
        try {
            if (mDatabase == null || mDatabase.get() == null) {
                LogUtil.e("Database error: openDatabase() database instance is null");
                return false;
            }

            if (mDatabase.get().mSQLiteDatabase == null) {
                mDatabase.get().mSQLiteDatabase = mDatabase.get().getWritableDatabase();
            }

            if (!mDatabase.get().mSQLiteDatabase.isOpen()) {
                LogUtil.e("Database error: database openable false, trying to open the database again");
                mDatabase.get().mSQLiteDatabase = mDatabase.get().getWritableDatabase();
            }
            return mDatabase.get().mSQLiteDatabase.isOpen();
        } catch (SQLiteException | NullPointerException e) {
            LogUtil.e(Log.getStackTraceString(e));
            return false;
        }
    }

    public boolean closeDatabase() {
        try {
            if (mDatabase == null || mDatabase.get() == null) {
                LogUtil.e("Database error: closeDatabase() database instance is null");
                return false;
            }

            if (mDatabase.get().mSQLiteDatabase == null) {
                LogUtil.e("Database error: trying to close database which is not opened");
                return false;
            }
            mDatabase.get().mSQLiteDatabase.close();
            return true;
        } catch (SQLiteException | NullPointerException e) {
            LogUtil.e(Log.getStackTraceString(e));
            return false;
        }
    }

    public void addRequest(@Nullable SQLiteDatabase db, Request request) {
        SQLiteDatabase database = db;
        if (database == null) {
            if (!openDatabase()) {
                LogUtil.e("Database error: addRequest() failed to open database");
                return;
            }

            database = mDatabase.get().mSQLiteDatabase;
        }

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, request.getName());
        values.put(KEY_ACTIVITY, request.getActivity());

        String requestedOn = request.getRequestedOn();
        if (requestedOn == null) requestedOn = TimeHelper.getLongDateTime();
        values.put(KEY_REQUESTED_ON, requestedOn);

        database.insert(TABLE_REQUEST, null, values);
    }

    public boolean isRequested(String activity) {
        if (!openDatabase()) {
            LogUtil.e("Database error: isRequested() failed to open database");
            return false;
        }

        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_REQUEST, null, KEY_ACTIVITY + " = ?",
                new String[]{activity}, null, null, null, null);
        int rowCount = cursor.getCount();
        cursor.close();
        return rowCount > 0;
    }

    private List<Request> getRequestedApps(@Nullable SQLiteDatabase db) {
        SQLiteDatabase database = db;
        if (database == null) {
            if (!openDatabase()) {
                LogUtil.e("Database error: getRequestedApps() failed to open database");
                return new ArrayList<>();
            }

            database = mDatabase.get().mSQLiteDatabase;
        }

        List<Request> requests = new ArrayList<>();
        Cursor cursor = database.query(TABLE_REQUEST, null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                Request request = Request.Builder()
                        .name(cursor.getString(cursor.getColumnIndex(KEY_NAME)))
                        .activity(cursor.getString(cursor.getColumnIndex(KEY_ACTIVITY)))
                        .requestedOn(cursor.getString(cursor.getColumnIndex(KEY_REQUESTED_ON)))
                        .requested(true)
                        .build();

                requests.add(request);
            } while (cursor.moveToNext());
        }
        cursor.close();
        return requests;
    }

    public void addPremiumRequest(@Nullable SQLiteDatabase db, Request request) {
        SQLiteDatabase database = db;
        if (database == null) {
            if (!openDatabase()) {
                LogUtil.e("Database error: addPremiumRequest() failed to open database");
                return;
            }

            database = mDatabase.get().mSQLiteDatabase;
        }

        ContentValues values = new ContentValues();
        values.put(KEY_ORDER_ID, request.getOrderId());
        values.put(KEY_PRODUCT_ID, request.getProductId());
        values.put(KEY_NAME, request.getName());
        values.put(KEY_ACTIVITY, request.getActivity());

        String requestedOn = request.getRequestedOn();
        if (requestedOn == null) requestedOn = TimeHelper.getLongDateTime();
        values.put(KEY_REQUESTED_ON, requestedOn);

        database.insert(TABLE_PREMIUM_REQUEST, null, values);
    }

    public List<Request> getPremiumRequest(@Nullable SQLiteDatabase db) {
        SQLiteDatabase database = db;
        if (database == null) {
            if (!openDatabase()) {
                LogUtil.e("Database error: getPremiumRequest() failed to open database");
                return new ArrayList<>();
            }

            database = mDatabase.get().mSQLiteDatabase;
        }

        List<Request> requests = new ArrayList<>();

        Cursor cursor = database.query(TABLE_PREMIUM_REQUEST,
                null, null, null, null, null, null);
        if (cursor.moveToFirst()) {
            do {
                Request request = Request.Builder()
                        .name(cursor.getString(cursor.getColumnIndex(KEY_NAME)))
                        .activity(cursor.getString(cursor.getColumnIndex(KEY_ACTIVITY)))
                        .orderId(cursor.getString(cursor.getColumnIndex(KEY_ORDER_ID)))
                        .productId(cursor.getString(cursor.getColumnIndex(KEY_PRODUCT_ID)))
                        .build();
                requests.add(request);
            } while (cursor.moveToNext());
        }
        cursor.close();
        return requests;
    }

    public void addWallpapers(List<?> list) {
        if (!openDatabase()) {
            LogUtil.e("Database error: addWallpapers() failed to open database");
            return;
        }

        String query = "INSERT OR IGNORE INTO " +TABLE_WALLPAPERS+ " (" +KEY_NAME+ "," +KEY_AUTHOR+ "," +KEY_URL+ ","
                +KEY_THUMB_URL+ "," +KEY_ADDED_ON+ ") VALUES (?,?,?,?,?);";
        SQLiteStatement statement = mDatabase.get().mSQLiteDatabase.compileStatement(query);
        mDatabase.get().mSQLiteDatabase.beginTransaction();

        for (int i = 0; i < list.size(); i++) {
            statement.clearBindings();

            Wallpaper wallpaper;
            if (list.get(i) instanceof Wallpaper) {
                wallpaper = (Wallpaper) list.get(i);
            } else {
                wallpaper = JsonHelper.getWallpaper(list.get(i));
            }

            if (wallpaper != null) {
                if (wallpaper.getURL() != null) {
                    String name = wallpaper.getName();
                    if (name == null) name = "";

                    statement.bindString(1, name);

                    if (wallpaper.getAuthor() != null) {
                        statement.bindString(2, wallpaper.getAuthor());
                    } else {
                        statement.bindNull(2);
                    }

                    statement.bindString(3, wallpaper.getURL());
                    statement.bindString(4, wallpaper.getThumbUrl());
                    statement.bindString(5, TimeHelper.getLongDateTime());
                    statement.execute();
                }
            }
        }
        mDatabase.get().mSQLiteDatabase.setTransactionSuccessful();
        mDatabase.get().mSQLiteDatabase.endTransaction();
    }

    public void updateWallpaper(Wallpaper wallpaper) {
        if (!openDatabase()) {
            LogUtil.e("Database error: updateWallpaper() failed to open database");
            return;
        }

        if (wallpaper == null) return;

        ContentValues values = new ContentValues();
        if (wallpaper.getSize() > 0) {
            values.put(KEY_SIZE, wallpaper.getSize());
        }

        if (wallpaper.getMimeType() != null) {
            values.put(KEY_MIME_TYPE, wallpaper.getMimeType());
        }

        if (wallpaper.getDimensions() != null) {
            values.put(KEY_WIDTH, wallpaper.getDimensions().getWidth());
            values.put(KEY_HEIGHT, wallpaper.getDimensions().getHeight());
        }

        if (wallpaper.getColor() != 0) {
            values.put(KEY_COLOR, wallpaper.getColor());
        }

        if (values.size() > 0) {
            mDatabase.get().mSQLiteDatabase.update(TABLE_WALLPAPERS,
                    values, KEY_URL +" = ?", new String[]{wallpaper.getURL()});
        }
    }

    public int getWallpapersCount() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getWallpapersCount() failed to open database");
            return 0;
        }

        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS,
                null, null, null, null, null, null, null);
        int rowCount = cursor.getCount();
        cursor.close();
        return rowCount;
    }

    @Nullable
    public Wallpaper getWallpaper(String url) {
        if (!openDatabase()) {
            LogUtil.e("Database error: getWallpaper() failed to open database");
            return null;
        }

        Wallpaper wallpaper = null;
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS,
                null, KEY_URL +" = ?", new String[]{url}, null, null, null, "1");
        if (cursor.moveToFirst()) {
            do {
                int width = cursor.getInt(cursor.getColumnIndex(KEY_WIDTH));
                int height = cursor.getInt(cursor.getColumnIndex(KEY_HEIGHT));
                ImageSize dimensions = null;
                if (width  > 0 && height > 0) {
                    dimensions = new ImageSize(width, height);
                }

                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                wallpaper = Wallpaper.Builder()
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .dimensions(dimensions)
                        .mimeType(cursor.getString(cursor.getColumnIndex(KEY_MIME_TYPE)))
                        .size(cursor.getInt(cursor.getColumnIndex(KEY_SIZE)))
                        .color(cursor.getInt(cursor.getColumnIndex(KEY_COLOR)))
                        .build();
            } while (cursor.moveToNext());
        }
        cursor.close();
        return wallpaper;
    }

    public List<Wallpaper> getWallpapers() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getWallpapers() failed to open database");
            return new ArrayList<>();
        }

        List<Wallpaper> wallpapers = new ArrayList<>();
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS,
                null, null, null, null, null, KEY_ADDED_ON + " DESC, " +KEY_ID);
        if (cursor.moveToFirst()) {
            do {
                int width = cursor.getInt(cursor.getColumnIndex(KEY_WIDTH));
                int height = cursor.getInt(cursor.getColumnIndex(KEY_HEIGHT));
                ImageSize dimensions = null;
                if (width  > 0 && height > 0) {
                    dimensions = new ImageSize(width, height);
                }

                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                Wallpaper wallpaper = Wallpaper.Builder()
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .color(cursor.getInt(cursor.getColumnIndex(KEY_COLOR)))
                        .mimeType(cursor.getString(cursor.getColumnIndex(KEY_MIME_TYPE)))
                        .dimensions(dimensions)
                        .size(cursor.getInt(cursor.getColumnIndex(KEY_SIZE)))
                        .build();
                wallpapers.add(wallpaper);
            } while (cursor.moveToNext());
        }
        cursor.close();
        return wallpapers;
    }

    @Nullable
    public Wallpaper getRandomWallpaper() {
        if (!openDatabase()) {
            LogUtil.e("Database error: getRandomWallpaper() failed to open database");
            return null;
        }

        Wallpaper wallpaper = null;
        Cursor cursor = mDatabase.get().mSQLiteDatabase.query(TABLE_WALLPAPERS,
                null, null, null, null, null, "RANDOM()", "1");
        if (cursor.moveToFirst()) {
            do {
                int id = cursor.getInt(cursor.getColumnIndex(KEY_ID));
                String name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
                if (name.length() == 0) {
                    name = "Wallpaper "+ id;
                }

                wallpaper = Wallpaper.Builder()
                        .name(name)
                        .author(cursor.getString(cursor.getColumnIndex(KEY_AUTHOR)))
                        .url(cursor.getString(cursor.getColumnIndex(KEY_URL)))
                        .thumbUrl(cursor.getString(cursor.getColumnIndex(KEY_THUMB_URL)))
                        .build();
            } while (cursor.moveToNext());
        }
        cursor.close();
        return wallpaper;
    }

    public void deleteIconRequestData() {
        if (!openDatabase()) {
            LogUtil.e("Database error: deleteIconRequestData() failed to open database");
            return;
        }

        mDatabase.get().mSQLiteDatabase.delete("SQLITE_SEQUENCE", "NAME = ?", new String[]{TABLE_REQUEST});
        mDatabase.get().mSQLiteDatabase.delete(TABLE_REQUEST, null, null);
    }

    public void deleteWallpapers(List<Wallpaper> wallpapers) {
        if (!openDatabase()) {
            LogUtil.e("Database error: deleteWallpapers() failed to open database");
            return;
        }

        for (Wallpaper wallpaper : wallpapers) {
            mDatabase.get().mSQLiteDatabase.delete(TABLE_WALLPAPERS, KEY_URL +" = ?",
                    new String[]{wallpaper.getURL()});
        }
    }

    public void deleteWallpapers() {
        if (!openDatabase()) {
            LogUtil.e("Database error: deleteWallpapers() failed to open database");
            return;
        }

        mDatabase.get().mSQLiteDatabase.delete("SQLITE_SEQUENCE", "NAME = ?", new String[]{TABLE_WALLPAPERS});
        mDatabase.get().mSQLiteDatabase.delete(TABLE_WALLPAPERS, null, null);
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/utils/Extras.java
public abstract class Extras {

    public static final String TAG_HOME = "home";
    public static final String TAG_APPLY = "apply";
    public static final String TAG_ICONS = "icons";
    public static final String TAG_REQUEST = "request";
    public static final String TAG_WALLPAPERS = "wallpapers";
    public static final String TAG_SETTINGS = "settings";
    public static final String TAG_FAQS = "faqs";
    public static final String TAG_ABOUT = "about";

    public static final String EXTRA_POSITION = "position";
    public static final String EXTRA_SIZE = "size";
    public static final String EXTRA_URL = "url";
    public static final String EXTRA_IMAGE = "image";
    public static final String EXTRA_RESUMED = "resumed";

    public enum Error {
        APPFILTER_NULL,
        DATABASE_ERROR,
        INSTALLED_APPS_NULL,
        ICON_REQUEST_NULL,
        ICON_REQUEST_PROPERTY_NULL,
        ICON_REQUEST_PROPERTY_COMPONENT_NULL;

        public String getMessage() {
            switch (this) {
                case APPFILTER_NULL:
                    return "Error: Unable to read appfilter.xml";
                case DATABASE_ERROR:
                    return "Error: Unable to read database";
                case INSTALLED_APPS_NULL:
                    return "Error: Unable to collect installed apps";
                case ICON_REQUEST_NULL:
                    return "Error: Icon request is null";
                case ICON_REQUEST_PROPERTY_NULL:
                    return "Error: Icon request property is null";
                case ICON_REQUEST_PROPERTY_COMPONENT_NULL:
                    return "Error: Email client component is null";
                default:
                    return "Error: Unknown";
            }
        }

        public void showToast(Context context) {
            if (context == null) return;
            Toast.makeText(context, getMessage(), Toast.LENGTH_LONG).show();
        }
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/items/Request.java
public class Request {

    private String mName;
    private String mActivity;
    private String mPackageName;
    private String mOrderId;
    private String mProductId;
    private String mRequestedOn;
    private boolean mRequested;

    private Request(String name, String activity) {
        mName = name;
        mActivity = activity;
    }

    public String getName() {
        return mName;
    }

    @Nullable
    public String getPackageName() {
        if (mPackageName == null) {
            if (mActivity.length() > 0) {
                return mActivity.substring(0, mActivity.lastIndexOf("/"));
            }
        }
        return mPackageName;
    }

    public String getActivity() {
        return mActivity;
    }

    public boolean isRequested() {
        return mRequested;
    }

    public String getOrderId() {
        return mOrderId;
    }

    public String getProductId() {
        return mProductId;
    }

    public String getRequestedOn() {
        return mRequestedOn;
    }

    public void setPackageName(String packageName) {
        mPackageName = packageName;
    }

    public void setOrderId(String orderId) {
        mOrderId = orderId;
    }

    public void setProductId(String productId) {
        mProductId = productId;
    }

    public void setRequestedOn(String requestedOn) {
        mRequestedOn = requestedOn;
    }

    public void setRequested(boolean requested) {
        mRequested = requested;
    }

    public static Builder Builder() {
        return new Builder();
    }

    public static class Builder {

        private String mName;
        private String mActivity;
        private String mPackageName;
        private String mOrderId;
        private String mProductId;
        private String mRequestedOn;
        private boolean mRequested;

        private Builder() {
            mName = "";
            mActivity = "";
            mRequested = false;
        }

        public Builder name(String name) {
            mName = name;
            return this;
        }

        public Builder activity(String activity) {
            mActivity = activity;
            return this;
        }

        public Builder packageName(String packageName) {
            mPackageName = packageName;
            return this;
        }

        public Builder orderId(String orderId) {
            mOrderId = orderId;
            return this;
        }

        public Builder productId(String productId) {
            mProductId = productId;
            return this;
        }

        public Builder requestedOn(String requestedOn) {
            mRequestedOn = requestedOn;
            return this;
        }

        public Builder requested(boolean requested) {
            mRequested = requested;
            return this;
        }

        public Request build() {
            Request request = new Request(mName, mActivity);
            request.setPackageName(mPackageName);
            request.setRequestedOn(mRequestedOn);
            request.setRequested(mRequested);
            request.setOrderId(mOrderId);
            request.setProductId(mProductId);
            return request;
        }
    }

    public static class Property {

        private ComponentName componentName;
        private final String orderId;
        private final String productId;

        public Property(ComponentName componentName, String orderId, String productId){
            this.componentName = componentName;
            this.orderId = orderId;
            this.productId = productId;
        }

        @Nullable
        public ComponentName getComponentName() {
            return componentName;
        }

        public String getOrderId() {
            return orderId;
        }

        public String getProductId() {
            return productId;
        }

        public void setComponentName(ComponentName componentName) {
            this.componentName = componentName;
        }
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/fragments/dialog/IntentChooserFragment.java
public class IntentChooserFragment extends DialogFragment {

    private ListView mIntentList;
    private TextView mNoApp;

    private int mType;
    private IntentAdapter mAdapter;
    private AsyncTask mAsyncTask;

    public static final int ICON_REQUEST = 0;
    public static final int REBUILD_ICON_REQUEST = 1;

    public static final String TAG = "candybar.dialog.intent.chooser";
    private static final String TYPE = "type";

    private static IntentChooserFragment newInstance(int type) {
        IntentChooserFragment fragment = new IntentChooserFragment();
        Bundle bundle = new Bundle();
        bundle.putInt(TYPE, type);
        fragment.setArguments(bundle);
        return fragment;
    }

    public static void showIntentChooserDialog(@NonNull FragmentManager fm, int type) {
        FragmentTransaction ft = fm.beginTransaction();
        Fragment prev = fm.findFragmentByTag(TAG);
        if (prev != null) {
            ft.remove(prev);
        }

        try {
            DialogFragment dialog = IntentChooserFragment.newInstance(type);
            dialog.show(ft, TAG);
        } catch (IllegalArgumentException | IllegalStateException ignored) {}
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mType = getArguments().getInt(TYPE);
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        MaterialDialog.Builder builder = new MaterialDialog.Builder(getActivity());
        builder.customView(R.layout.fragment_intent_chooser, false);
        builder.typeface(
                TypefaceHelper.getMedium(getActivity()),
                TypefaceHelper.getRegular(getActivity()));
        builder.positiveText(android.R.string.cancel);

        MaterialDialog dialog = builder.build();
        dialog.getActionButton(DialogAction.POSITIVE).setOnClickListener(view -> {
            if (mAdapter == null || mAdapter.isAsyncTaskRunning()) return;

            if (CandyBarApplication.sZipPath != null) {
                File file = new File(CandyBarApplication.sZipPath);
                if (file.exists()) {
                    if (file.delete()) {
                        LogUtil.e(String.format("Intent chooser cancel: %s deleted", file.getName()));
                    }
                }
            }

            RequestFragment.sSelectedRequests = null;
            CandyBarApplication.sRequestProperty = null;
            CandyBarApplication.sZipPath = null;
            dialog.dismiss();
        });
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
        setCancelable(false);

        mIntentList = (ListView) dialog.findViewById(R.id.intent_list);
        mNoApp = (TextView) dialog.findViewById(R.id.intent_noapp);
        return dialog;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mAsyncTask = new IntentChooserLoader().execute();
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        if (mAsyncTask != null) {
            mAsyncTask.cancel(true);
        }
        super.onDismiss(dialog);
    }

    private class IntentChooserLoader extends AsyncTask<Void, Void, Boolean> {

        private List<IntentChooser> apps;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            apps = new ArrayList<>();
        }

        @Override
        protected Boolean doInBackground(Void... voids) {
            while(!isCancelled()) {
                try {
                    Thread.sleep(1);
                    Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
                            getResources().getString(R.string.dev_email),
                            null));
                    List<ResolveInfo> resolveInfos = getActivity().getPackageManager()
                            .queryIntentActivities(intent, 0);
                    try {
                        Collections.sort(resolveInfos, new ResolveInfo.DisplayNameComparator(
                                getActivity().getPackageManager()));
                    } catch (Exception ignored){}

                    for (ResolveInfo resolveInfo : resolveInfos) {
                        switch (resolveInfo.activityInfo.packageName) {
                            case "com.google.android.gm":
                                apps.add(new IntentChooser(resolveInfo, IntentChooser.TYPE_RECOMMENDED));
                                break;
                            case "com.google.android.apps.inbox":
                                try {
                                    ComponentName componentName = new ComponentName(resolveInfo.activityInfo.applicationInfo.packageName,
                                            "com.google.android.apps.bigtop.activities.MainActivity");
                                    Intent inbox = new Intent(Intent.ACTION_SEND);
                                    inbox.setComponent(componentName);

                                    List<ResolveInfo> list = getActivity().getPackageManager().queryIntentActivities(
                                            inbox, PackageManager.MATCH_DEFAULT_ONLY);
                                    if (list.size() > 0) {
                                        apps.add(new IntentChooser(resolveInfo, IntentChooser.TYPE_SUPPORTED));
                                        break;
                                    }
                                } catch (ActivityNotFoundException e) {
                                    LogUtil.e(Log.getStackTraceString(e));
                                }

                                apps.add(new IntentChooser(resolveInfo, IntentChooser.TYPE_NOT_SUPPORTED));
                                break;
                            case "com.android.fallback":
                            case "com.paypal.android.p2pmobile":
                            case "com.lonelycatgames.Xplore":
                                break;
                            default:
                                apps.add(new IntentChooser(resolveInfo, IntentChooser.TYPE_SUPPORTED));
                                break;
                        }
                    }
                    return true;
                } catch (Exception e) {
                    LogUtil.e(Log.getStackTraceString(e));
                    return false;
                }
            }
            return false;
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            if (getActivity() == null) return;
            if (getActivity().isFinishing()) return;

            mAsyncTask = null;
            if (aBoolean && apps != null) {
                mAdapter = new IntentAdapter(getActivity(), apps, mType);
                mIntentList.setAdapter(mAdapter);

                if (apps.size() == 0) {
                    mNoApp.setVisibility(View.VISIBLE);
                    setCancelable(true);
                }
            } else {
                dismiss();
                Toast.makeText(getActivity(), R.string.intent_email_failed,
                        Toast.LENGTH_LONG).show();
            }
        }
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/activities/CandyBarMainActivity.java
public abstract class CandyBarMainActivity extends AppCompatActivity implements
        ActivityCompat.OnRequestPermissionsResultCallback, RequestListener, InAppBillingListener,
        SearchListener, WallpapersListener, ActivityCallback {

    private TextView mToolbarTitle;
    private DrawerLayout mDrawerLayout;
    private NavigationView mNavigationView;

    private String mFragmentTag;
    private int mPosition, mLastPosition;
    private CandyBarBroadcastReceiver mReceiver;
    private ActionBarDrawerToggle mDrawerToggle;
    private FragmentManager mFragManager;
    private LicenseHelper mLicenseHelper;

    private boolean mIsMenuVisible = true;

    public static List<Request> sMissedApps;
    public static List<Icon> sSections;
    public static Home sHomeIcon;
    public static int sInstalledAppsCount;
    public static int sIconsCount;

    private ActivityConfiguration mConfig;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.setTheme(Preferences.get(this).isDarkTheme() ?
                R.style.AppThemeDark : R.style.AppTheme);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ColorHelper.setupStatusBarIconColor(this);
        ColorHelper.setNavigationBarColor(this, ContextCompat.getColor(this,
                Preferences.get(this).isDarkTheme() ?
                        R.color.navigationBarDark : R.color.navigationBar));
        registerBroadcastReceiver();
        startService(new Intent(this, CandyBarService.class));

        //Todo: wait until google fix the issue, then enable wallpaper crop again on API 26+
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Preferences.get(this).setCropWallpaper(false);
        }

        mConfig = onInit();
        InAppBillingProcessor.get(this).init(mConfig.getLicenseKey());

        mDrawerLayout = findViewById(R.id.drawer_layout);
        mNavigationView = findViewById(R.id.navigation_view);
        Toolbar toolbar = findViewById(R.id.toolbar);
        mToolbarTitle = findViewById(R.id.toolbar_title);

        toolbar.setPopupTheme(Preferences.get(this).isDarkTheme() ?
                R.style.AppThemeDark : R.style.AppTheme);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);

        mFragManager = getSupportFragmentManager();

        initNavigationView(toolbar);
        initNavigationViewHeader();

        mPosition = mLastPosition = 0;
        if (savedInstanceState != null) {
            mPosition = mLastPosition = savedInstanceState.getInt(Extras.EXTRA_POSITION, 0);
            onSearchExpanded(false);
        }

        IntentHelper.sAction = IntentHelper.getAction(getIntent());
        if (IntentHelper.sAction == IntentHelper.ACTION_DEFAULT) {
            setFragment(getFragment(mPosition));
        } else {
            setFragment(getActionFragment(IntentHelper.sAction));
        }

        checkWallpapers();
        IconRequestTask.start(this, AsyncTask.THREAD_POOL_EXECUTOR);
        IconsLoaderTask.start(this);

        if (Preferences.get(this).isFirstRun() && mConfig.isLicenseCheckerEnabled()) {
            mLicenseHelper = new LicenseHelper(this);
            mLicenseHelper.run(mConfig.getLicenseKey(), mConfig.getRandomString(), new LicenseCallbackHelper(this));
            return;
        }

        if (Preferences.get(this).isNewVersion())
            ChangelogFragment.showChangelog(mFragManager);

        if (mConfig.isLicenseCheckerEnabled() && !Preferences.get(this).isLicensed()) {
            finish();
        }
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        LocaleHelper.setLocale(this);
        if (mIsMenuVisible) mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        LocaleHelper.setLocale(newBase);
        super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
    }

    @Override
    protected void onNewIntent(Intent intent) {
        int action = IntentHelper.getAction(intent);
        if (action != IntentHelper.ACTION_DEFAULT)
            setFragment(getActionFragment(action));
        super.onNewIntent(intent);
    }

    @Override
    protected void onResume() {
        RequestHelper.checkPiracyApp(this);
        IntentHelper.sAction = IntentHelper.getAction(getIntent());
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        InAppBillingProcessor.get(this).destroy();

        if (mLicenseHelper != null) {
            mLicenseHelper.destroy();
        }

        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }

        CandyBarMainActivity.sMissedApps = null;
        CandyBarMainActivity.sHomeIcon = null;
        stopService(new Intent(this, CandyBarService.class));
        Database.get(this.getApplicationContext()).closeDatabase();
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putInt(Extras.EXTRA_POSITION, mPosition);
        Database.get(this.getApplicationContext()).closeDatabase();
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onBackPressed() {
        if (mFragManager.getBackStackEntryCount() > 0) {
            clearBackStack();
            return;
        }

        if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
            mDrawerLayout.closeDrawers();
            return;
        }

        if (!mFragmentTag.equals(Extras.TAG_HOME)) {
            mPosition = mLastPosition = 0;
            setFragment(getFragment(mPosition));
            return;
        }
        super.onBackPressed();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (!InAppBillingProcessor.get(this).handleActivityResult(requestCode, resultCode, data))
            super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PermissionCode.STORAGE) {
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                recreate();
                return;
            }
            Toast.makeText(this, R.string.permission_storage_denied, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onPiracyAppChecked(boolean isPiracyAppInstalled) {
        MenuItem menuItem = mNavigationView.getMenu().findItem(R.id.navigation_view_request);
        if (menuItem != null) {
            menuItem.setVisible(getResources().getBoolean(
                    R.bool.enable_icon_request) || !isPiracyAppInstalled);
        }
    }

    @Override
    public void onRequestSelected(int count) {
        if (mFragmentTag.equals(Extras.TAG_REQUEST)) {
            String title = getResources().getString(R.string.navigation_view_request);
            if (count > 0) title += " ("+ count +")";
            mToolbarTitle.setText(title);
        }
    }

    @Override
    public void onBuyPremiumRequest() {
        if (Preferences.get(this).isPremiumRequest()) {
            RequestHelper.showPremiumRequestStillAvailable(this);
            return;
        }

        if (InAppBillingProcessor.get(this.getApplicationContext())
                .getProcessor().loadOwnedPurchasesFromGoogle()) {
            List<String> products = InAppBillingProcessor.get(this).getProcessor().listOwnedProducts();
            if (products != null) {
                boolean isProductIdExist = false;
                for (String product : products) {
                    for (String premiumRequestProductId : mConfig.getPremiumRequestProductsId()) {
                        if (premiumRequestProductId.equals(product)) {
                            isProductIdExist = true;
                            break;
                        }
                    }
                }

                if (isProductIdExist) {
                    RequestHelper.showPremiumRequestExist(this);
                    return;
                }
            }
        }

        InAppBillingFragment.showInAppBillingDialog(getSupportFragmentManager(),
                InAppBilling.PREMIUM_REQUEST,
                mConfig.getLicenseKey(),
                mConfig.getPremiumRequestProductsId(),
                mConfig.getPremiumRequestProductsCount());
    }

    @Override
    public void onPremiumRequestBought() {
        if (mFragmentTag.equals(Extras.TAG_REQUEST)) {
            RequestFragment fragment = (RequestFragment) mFragManager.findFragmentByTag(Extras.TAG_REQUEST);
            if (fragment != null) fragment.refreshIconRequest();
        }
    }

    @Override
    public void onRequestBuilt(Intent intent, int type) {
        if (intent == null) {
            Toast.makeText(this, "Icon Request: Intent is null", Toast.LENGTH_LONG).show();
            return;
        }

        if (type == IntentChooserFragment.ICON_REQUEST) {
            if (RequestFragment.sSelectedRequests == null)
                return;

            if (getResources().getBoolean(R.bool.enable_icon_request_limit)) {
                int used = Preferences.get(this).getRegularRequestUsed();
                Preferences.get(this).setRegularRequestUsed((used + RequestFragment.sSelectedRequests.size()));
            }

            if (Preferences.get(this).isPremiumRequest()) {
                int count = Preferences.get(this).getPremiumRequestCount() - RequestFragment.sSelectedRequests.size();
                Preferences.get(this).setPremiumRequestCount(count);
                if (count == 0) {
                    if (InAppBillingProcessor.get(this).getProcessor().consumePurchase(Preferences
                            .get(this).getPremiumRequestProductId())) {
                        Preferences.get(this).setPremiumRequest(false);
                        Preferences.get(this).setPremiumRequestProductId("");
                    } else {
                        RequestHelper.showPremiumRequestConsumeFailed(this);
                        return;
                    }
                }
            }

            if (mFragmentTag.equals(Extras.TAG_REQUEST)) {
                RequestFragment fragment = (RequestFragment) mFragManager.findFragmentByTag(Extras.TAG_REQUEST);
                if (fragment != null) fragment.refreshIconRequest();
            }
        }

        try {
            startActivity(intent);
        } catch (IllegalArgumentException e) {
            startActivity(Intent.createChooser(intent,
                    getResources().getString(R.string.email_client)));
        }
        CandyBarApplication.sRequestProperty = null;
        CandyBarApplication.sZipPath = null;
    }

    @Override
    public void onRestorePurchases() {
        if (InAppBillingProcessor.get(this).getProcessor().loadOwnedPurchasesFromGoogle()) {
            List<String> productsId = InAppBillingProcessor.get(this).getProcessor().listOwnedProducts();
            if (productsId != null) {
                SettingsFragment fragment = (SettingsFragment) mFragManager.findFragmentByTag(Extras.TAG_SETTINGS);
                if (fragment != null) fragment.restorePurchases(productsId,
                        mConfig.getPremiumRequestProductsId(), mConfig.getPremiumRequestProductsCount());
            }
        }
    }

    @Override
    public void onInAppBillingSelected(int type, InAppBilling product) {
        Preferences.get(this).setInAppBillingType(type);
        if (type == InAppBilling.PREMIUM_REQUEST) {
            Preferences.get(this).setPremiumRequestCount(product.getProductCount());
            Preferences.get(this).setPremiumRequestTotal(product.getProductCount());
        }

        InAppBillingProcessor.get(this).getProcessor().purchase(this, product.getProductId());
    }

    @Override
    public void onInAppBillingConsume(int type, String productId) {
        if (InAppBillingProcessor.get(this).getProcessor().consumePurchase(productId)) {
            if (type == InAppBilling.DONATE) {
                new MaterialDialog.Builder(this)
                        .typeface(TypefaceHelper.getMedium(this),
                                TypefaceHelper.getRegular(this))
                        .title(R.string.navigation_view_donate)
                        .content(R.string.donation_success)
                        .positiveText(R.string.close)
                        .show();
            }
        }
    }

    @Override
    public void onInAppBillingRequest() {
        if (mFragmentTag.equals(Extras.TAG_REQUEST)) {
            RequestFragment fragment = (RequestFragment) mFragManager.findFragmentByTag(Extras.TAG_REQUEST);
            if (fragment != null) fragment.prepareRequest();
        }
    }

    @Override
    public void onWallpapersChecked(@Nullable Intent intent) {
        if (intent != null) {
            String packageName = intent.getStringExtra("packageName");
            LogUtil.d("Broadcast received from service with packageName: " +packageName);

            if (packageName == null)
                return;

            if (!packageName.equals(getPackageName())) {
                LogUtil.d("Received broadcast from different packageName, expected: " +getPackageName());
                return;
            }

            int size = intent.getIntExtra(Extras.EXTRA_SIZE, 0);
            int offlineSize = Database.get(this).getWallpapersCount();
            Preferences.get(this).setAvailableWallpapersCount(size);

            if (size > offlineSize) {
                if (mFragmentTag.equals(Extras.TAG_HOME)) {
                    HomeFragment fragment = (HomeFragment) mFragManager.findFragmentByTag(Extras.TAG_HOME);
                    if (fragment != null) fragment.resetWallpapersCount();
                }

                int accent = ColorHelper.getAttributeColor(this, R.attr.colorAccent);
                LinearLayout container = (LinearLayout) mNavigationView.getMenu().getItem(4).getActionView();
                if (container != null) {
                    TextView counter = container.findViewById(R.id.counter);
                    if (counter == null) return;

                    ViewCompat.setBackground(counter, DrawableHelper.getTintedDrawable(this,
                            R.drawable.ic_toolbar_circle, accent));
                    counter.setTextColor(ColorHelper.getTitleTextColor(accent));
                    int newItem = (size - offlineSize);
                    counter.setText(String.valueOf(newItem > 99 ? "99+" : newItem));
                    container.setVisibility(View.VISIBLE);
                    return;
                }
            }
        }

        LinearLayout container = (LinearLayout) mNavigationView.getMenu().getItem(4).getActionView();
        if (container != null) container.setVisibility(View.GONE);
    }

    @Override
    public void onSearchExpanded(boolean expand) {
        Toolbar toolbar = findViewById(R.id.toolbar);
        mIsMenuVisible = !expand;

        if (expand) {
            int color = ColorHelper.getAttributeColor(this, R.attr.toolbar_icon);
            toolbar.setNavigationIcon(DrawableHelper.getTintedDrawable(
                    this, R.drawable.ic_toolbar_back, color));
            toolbar.setNavigationOnClickListener(view -> onBackPressed());
        } else {
            SoftKeyboardHelper.closeKeyboard(this);
            ColorHelper.setStatusBarColor(this, Color.TRANSPARENT, true);
            if (CandyBarApplication.getConfiguration().getNavigationIcon() == CandyBarApplication.NavigationIcon.DEFAULT) {
                mDrawerToggle.setDrawerArrowDrawable(new DrawerArrowDrawable(this));
            } else {
                toolbar.setNavigationIcon(ConfigurationHelper.getNavigationIcon(this,
                        CandyBarApplication.getConfiguration().getNavigationIcon()));
            }

            toolbar.setNavigationOnClickListener(view ->
                    mDrawerLayout.openDrawer(GravityCompat.START));
        }

        mDrawerLayout.setDrawerLockMode(expand ? DrawerLayout.LOCK_MODE_LOCKED_CLOSED :
                DrawerLayout.LOCK_MODE_UNLOCKED);
        supportInvalidateOptionsMenu();
    }

    public void showSupportDevelopmentDialog() {
        InAppBillingFragment.showInAppBillingDialog(mFragManager,
                InAppBilling.DONATE,
                mConfig.getLicenseKey(),
                mConfig.getDonationProductsId(),
                null);
    }

    private void initNavigationView(Toolbar toolbar) {
        mDrawerToggle = new ActionBarDrawerToggle(
                this, mDrawerLayout, toolbar, R.string.txt_open, R.string.txt_close) {

            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                SoftKeyboardHelper.closeKeyboard(CandyBarMainActivity.this);
            }

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
                selectPosition(mPosition);
            }
        };
        mDrawerToggle.setDrawerIndicatorEnabled(false);
        toolbar.setNavigationIcon(ConfigurationHelper.getNavigationIcon(this,
                CandyBarApplication.getConfiguration().getNavigationIcon()));
        toolbar.setNavigationOnClickListener(view ->
                mDrawerLayout.openDrawer(GravityCompat.START));

        if (CandyBarApplication.getConfiguration().getNavigationIcon() == CandyBarApplication.NavigationIcon.DEFAULT) {
            DrawerArrowDrawable drawerArrowDrawable = new DrawerArrowDrawable(this);
            drawerArrowDrawable.setColor(ColorHelper.getAttributeColor(this, R.attr.toolbar_icon));
            drawerArrowDrawable.setSpinEnabled(true);
            mDrawerToggle.setDrawerArrowDrawable(drawerArrowDrawable);
            mDrawerToggle.setDrawerIndicatorEnabled(true);
        }

        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
        mDrawerLayout.addDrawerListener(mDrawerToggle);

        NavigationViewHelper.initApply(mNavigationView);
        NavigationViewHelper.initIconRequest(mNavigationView);
        NavigationViewHelper.initWallpapers(mNavigationView);

        ColorStateList itemStateList = ContextCompat.getColorStateList(this,
                Preferences.get(this).isDarkTheme() ?
                        R.color.navigation_view_item_highlight_dark :
                        R.color.navigation_view_item_highlight);
        mNavigationView.setItemTextColor(itemStateList);
        mNavigationView.setItemIconTintList(itemStateList);
        Drawable background = ContextCompat.getDrawable(this,
                Preferences.get(this).isDarkTheme() ?
                        R.drawable.navigation_view_item_background_dark :
                        R.drawable.navigation_view_item_background);
        mNavigationView.setItemBackground(background);
        mNavigationView.setNavigationItemSelectedListener(item -> {
            int id = item.getItemId();
            if (id == R.id.navigation_view_home) mPosition = 0;
            else if (id == R.id.navigation_view_apply) mPosition = 1;
            else if (id == R.id.navigation_view_icons) mPosition = 2;
            else if (id == R.id.navigation_view_request) mPosition = 3;
            else if (id == R.id.navigation_view_wallpapers) mPosition = 4;
            else if (id == R.id.navigation_view_settings) mPosition = 5;
            else if (id == R.id.navigation_view_faqs) mPosition = 6;
            else if (id == R.id.navigation_view_about) mPosition = 7;

            item.setChecked(true);
            mDrawerLayout.closeDrawers();
            return true;
        });

        NavigationViewHelper.hideScrollBar(mNavigationView);
    }

    private void initNavigationViewHeader() {
        if (CandyBarApplication.getConfiguration().getNavigationViewHeader() == CandyBarApplication.NavigationViewHeader.NONE) {
            mNavigationView.removeHeaderView(mNavigationView.getHeaderView(0));
            return;
        }

        String imageUrl = getResources().getString(R.string.navigation_view_header);
        String titleText = getResources().getString(R.string.navigation_view_header_title);
        View header = mNavigationView.getHeaderView(0);
        HeaderView image = header.findViewById(R.id.header_image);
        LinearLayout container = header.findViewById(R.id.header_title_container);
        TextView title = header.findViewById(R.id.header_title);
        TextView version = header.findViewById(R.id.header_version);

        if (CandyBarApplication.getConfiguration().getNavigationViewHeader() == CandyBarApplication.NavigationViewHeader.MINI) {
            image.setRatio(16, 9);
        }

        if (titleText.length() == 0) {
            container.setVisibility(View.GONE);
        } else {
            title.setText(titleText);
            try {
                String versionText = "v" + getPackageManager()
                        .getPackageInfo(getPackageName(), 0).versionName;
                version.setText(versionText);
            } catch (Exception ignored) {}
        }

        if (ColorHelper.isValidColor(imageUrl)) {
            image.setBackgroundColor(Color.parseColor(imageUrl));
            return;
        }

        if (!URLUtil.isValidUrl(imageUrl)) {
            imageUrl = "drawable://" + DrawableHelper.getResourceId(this, imageUrl);
        }

        ImageLoader.getInstance().displayImage(imageUrl, new ImageViewAware(image),
                ImageConfig.getDefaultImageOptions(true), new ImageSize(720, 720), null, null);
    }

    private void registerBroadcastReceiver() {
        IntentFilter filter = new IntentFilter(CandyBarBroadcastReceiver.PROCESS_RESPONSE);
        filter.addCategory(Intent.CATEGORY_DEFAULT);
        mReceiver = new CandyBarBroadcastReceiver();
        registerReceiver(mReceiver, filter);
    }

    private void checkWallpapers() {
        if (Preferences.get(this).isConnectedToNetwork()) {
            Intent intent = new Intent(this, CandyBarWallpapersService.class);
            startService(intent);
            return;
        }

        int size = Preferences.get(this).getAvailableWallpapersCount();
        if (size > 0) {
            onWallpapersChecked(new Intent()
                    .putExtra("size", size)
                    .putExtra("packageName", getPackageName()));
        }
    }

    private void clearBackStack() {
        if (mFragManager.getBackStackEntryCount() > 0) {
            mFragManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
            onSearchExpanded(false);
        }
    }

    public void selectPosition(int position) {
        if (position == 3) {
            if (!getResources().getBoolean(R.bool.enable_icon_request) &&
                    getResources().getBoolean(R.bool.enable_premium_request)) {
                if (!Preferences.get(this).isPremiumRequestEnabled())
                    return;

                if (!Preferences.get(this).isPremiumRequest()) {
                    mPosition = mLastPosition;
                    mNavigationView.getMenu().getItem(mPosition).setChecked(true);
                    onBuyPremiumRequest();
                    return;
                }
            }
        }

        if (position == 4) {
            if (WallpaperHelper.getWallpaperType(this)
                    == WallpaperHelper.EXTERNAL_APP) {
                mPosition = mLastPosition;
                mNavigationView.getMenu().getItem(mPosition).setChecked(true);
                WallpaperHelper.launchExternalApp(CandyBarMainActivity.this);
                return;
            }
        }

        if (position != mLastPosition) {
            mLastPosition = mPosition = position;
            setFragment(getFragment(position));
        }
    }

    private void setFragment(Fragment fragment) {
        clearBackStack();

        FragmentTransaction ft = mFragManager.beginTransaction()
                .replace(R.id.container, fragment, mFragmentTag);
        try {
            ft.commit();
        } catch (Exception e) {
            ft.commitAllowingStateLoss();
        }

        Menu menu = mNavigationView.getMenu();
        menu.getItem(mPosition).setChecked(true);
        mToolbarTitle.setText(menu.getItem(mPosition).getTitle());
    }

    private Fragment getFragment(int position) {
        mFragmentTag = Extras.TAG_HOME;
        if (position == 0) {
            mFragmentTag = Extras.TAG_HOME;
            return new HomeFragment();
        } else if (position == 1) {
            mFragmentTag = Extras.TAG_APPLY;
            return new ApplyFragment();
        } else if (position == 2) {
            mFragmentTag = Extras.TAG_ICONS;
            return new IconsBaseFragment();
        } else if (position == 3) {
            mFragmentTag = Extras.TAG_REQUEST;
            return new RequestFragment();
        } else if (position == 4) {
            mFragmentTag = Extras.TAG_WALLPAPERS;
            return new WallpapersFragment();
        } else if (position == 5) {
            mFragmentTag = Extras.TAG_SETTINGS;
            return new SettingsFragment();
        } else if (position == 6) {
            mFragmentTag = Extras.TAG_FAQS;
            return new FAQsFragment();
        } else if (position == 7) {
            mFragmentTag = Extras.TAG_ABOUT;
            return new AboutFragment();
        }
        return new HomeFragment();
    }

    private Fragment getActionFragment(int action) {
        switch (action) {
            case IntentHelper.ICON_PICKER :
            case IntentHelper.IMAGE_PICKER :
                mPosition = mLastPosition = 2;
                mFragmentTag = Extras.TAG_ICONS;
                return new IconsBaseFragment();
            case IntentHelper.WALLPAPER_PICKER :
                if (WallpaperHelper.getWallpaperType(this) == WallpaperHelper.CLOUD_WALLPAPERS) {
                    mPosition = mLastPosition = 4;
                    mFragmentTag = Extras.TAG_WALLPAPERS;
                    return new WallpapersFragment();
                }
            default :
                mPosition = mLastPosition = 0;
                mFragmentTag = Extras.TAG_HOME;
                return new HomeFragment();
        }
    }
}
core/src/main/java/com/dm/material/dashboard/candybar/fragments/RequestFragment.java
public class RequestFragment extends Fragment implements View.OnClickListener {

    private RecyclerView mRecyclerView;
    private FloatingActionButton mFab;
    private RecyclerFastScroller mFastScroll;
    private ProgressBar mProgress;

    private MenuItem mMenuItem;
    private RequestAdapter mAdapter;
    private StaggeredGridLayoutManager mManager;
    private AsyncTask mAsyncTask;

    public static List<Integer> sSelectedRequests;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_request, container, false);
        mRecyclerView = view.findViewById(R.id.request_list);
        mFab =  view.findViewById(R.id.fab);
        mFastScroll = view.findViewById(R.id.fastscroll);
        mProgress = view.findViewById(R.id.progress);

        if (!Preferences.get(getActivity()).isToolbarShadowEnabled()) {
            View shadow = view.findViewById(R.id.shadow);
            if (shadow != null) shadow.setVisibility(View.GONE);
        }
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(false);
        resetRecyclerViewPadding(getResources().getConfiguration().orientation);

        mProgress.getIndeterminateDrawable().setColorFilter(
                ColorHelper.getAttributeColor(getActivity(), R.attr.colorAccent),
                PorterDuff.Mode.SRC_IN);

        int color = ColorHelper.getTitleTextColor(ColorHelper
                .getAttributeColor(getActivity(), R.attr.colorAccent));
        mFab.setImageDrawable(DrawableHelper.getTintedDrawable(
                getActivity(), R.drawable.ic_fab_send, color));
        mFab.setOnClickListener(this);

        if (!Preferences.get(getActivity()).isFabShadowEnabled()) {
            mFab.setCompatElevation(0f);
        }

        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.getItemAnimator().setChangeDuration(0);
        mManager = new StaggeredGridLayoutManager(
                getActivity().getResources().getInteger(R.integer.request_column_count),
                StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(mManager);

        setFastScrollColor(mFastScroll);
        mFastScroll.attachRecyclerView(mRecyclerView);

        mAsyncTask = new MissingAppsLoader().execute();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        resetRecyclerViewPadding(newConfig.orientation);
        if (mAsyncTask != null) return;

        int[] positions = mManager.findFirstVisibleItemPositions(null);

        SparseBooleanArray selectedItems = mAdapter.getSelectedItemsArray();
        ViewHelper.resetSpanCount(mRecyclerView,
                getActivity().getResources().getInteger(R.integer.request_column_count));

        mAdapter = new RequestAdapter(getActivity(),
                CandyBarMainActivity.sMissedApps,
                mManager.getSpanCount());
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.setSelectedItemsArray(selectedItems);

        if (positions.length > 0)
            mRecyclerView.scrollToPosition(positions[0]);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_request, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public void onDestroy() {
        if (mAsyncTask != null) {
            mAsyncTask.cancel(true);
        }
        super.onDestroy();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.menu_select_all) {
            mMenuItem = item;
            if (mAdapter == null) return false;
            if (mAdapter.selectAll()) {
                item.setIcon(R.drawable.ic_toolbar_select_all_selected);
                return true;
            }

            item.setIcon(R.drawable.ic_toolbar_select_all);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.fab) {
            if (mAdapter == null) return;

            int selected = mAdapter.getSelectedItemsSize();
            if (selected > 0) {
                if (mAdapter.isContainsRequested()) {
                    RequestHelper.showAlreadyRequestedDialog(getActivity());
                    return;
                }

                boolean requestLimit = getResources().getBoolean(
                        R.bool.enable_icon_request_limit);
                boolean iconRequest = getResources().getBoolean(
                        R.bool.enable_icon_request);
                boolean premiumRequest =getResources().getBoolean(
                        R.bool.enable_premium_request);

                if (Preferences.get(getActivity()).isPremiumRequest()) {
                    int count = Preferences.get(getActivity()).getPremiumRequestCount();
                    if (selected > count) {
                        RequestHelper.showPremiumRequestLimitDialog(getActivity(), selected);
                        return;
                    }

                    if (!RequestHelper.isReadyToSendPremiumRequest(getActivity())) return;

                    try {
                        InAppBillingListener listener = (InAppBillingListener) getActivity();
                        listener.onInAppBillingRequest();
                    } catch (Exception ignored) {}
                    return;
                }

                if (!iconRequest && premiumRequest) {
                    RequestHelper.showPremiumRequestRequired(getActivity());
                    return;
                }

                if (requestLimit) {
                    int limit = getActivity().getResources().getInteger(R.integer.icon_request_limit);
                    int used = Preferences.get(getActivity()).getRegularRequestUsed();
                    if (selected > (limit - used)) {
                        RequestHelper.showIconRequestLimitDialog(getActivity());
                        return;
                    }
                }

                mAsyncTask = new RequestLoader().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            } else {
                Toast.makeText(getActivity(), R.string.request_not_selected,
                        Toast.LENGTH_LONG).show();
            }
        }
    }

    private void resetRecyclerViewPadding(int orientation) {
        if (mRecyclerView == null) return;

        int padding = 0;
        boolean tabletMode = getResources().getBoolean(R.bool.android_helpers_tablet_mode);
        if (tabletMode || orientation == Configuration.ORIENTATION_LANDSCAPE) {
            padding = getActivity().getResources().getDimensionPixelSize(R.dimen.content_padding);

            if (CandyBarApplication.getConfiguration().getRequestStyle() == CandyBarApplication.Style.PORTRAIT_FLAT_LANDSCAPE_FLAT) {
                padding = getActivity().getResources().getDimensionPixelSize(R.dimen.card_margin);
            }
        }

        int size = getActivity().getResources().getDimensionPixelSize(R.dimen.fab_size);
        int marginGlobal = getActivity().getResources().getDimensionPixelSize(R.dimen.fab_margin_global);

        mRecyclerView.setPadding(padding, padding, 0, size + (marginGlobal * 2));
    }

    public void prepareRequest() {
        if (mAsyncTask != null) return;

        mAsyncTask = new RequestLoader().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    public void refreshIconRequest() {
        if (mAdapter == null) {
            RequestFragment.sSelectedRequests = null;
            return;
        }

        if (RequestFragment.sSelectedRequests == null)
            mAdapter.notifyItemChanged(0);

        for (Integer integer : RequestFragment.sSelectedRequests) {
            mAdapter.setRequested(integer, true);
        }

        mAdapter.notifyDataSetChanged();
        RequestFragment.sSelectedRequests = null;
    }

    private class MissingAppsLoader extends AsyncTask<Void, Void, Boolean> {

        private List<Request> requests;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if (CandyBarMainActivity.sMissedApps == null) {
                mProgress.setVisibility(View.VISIBLE);
            }
        }

        @Override
        protected Boolean doInBackground(Void... voids) {
            while (!isCancelled()) {
                try {
                    Thread.sleep(1);
                    if (CandyBarMainActivity.sMissedApps == null) {
                        CandyBarMainActivity.sMissedApps = RequestHelper.getMissingApps(getActivity());
                    }

                    requests = CandyBarMainActivity.sMissedApps;
                    return true;
                } catch (Exception e) {
                    LogUtil.e(Log.getStackTraceString(e));
                    return false;
                }
            }
            return false;
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            if (getActivity() == null) return;
            if (getActivity().isFinishing()) return;

            mAsyncTask = null;
            mProgress.setVisibility(View.GONE);
            if (aBoolean) {
                setHasOptionsMenu(true);
                mAdapter = new RequestAdapter(getActivity(),
                        requests, mManager.getSpanCount());
                mRecyclerView.setAdapter(mAdapter);

                AnimationHelper.show(mFab)
                        .interpolator(new LinearOutSlowInInterpolator())
                        .start();

                TapIntroHelper.showRequestIntro(getActivity(), mRecyclerView);
            } else {
                mRecyclerView.setAdapter(null);
                Toast.makeText(getActivity(), R.string.request_appfilter_failed, Toast.LENGTH_LONG).show();
            }
        }
    }

    private class RequestLoader extends AsyncTask<Void, Void, Boolean> {

        private MaterialDialog dialog;
        private boolean noEmailClientError = false;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            MaterialDialog.Builder builder = new MaterialDialog.Builder(getActivity());
            builder.typeface(
                    TypefaceHelper.getMedium(getActivity()),
                    TypefaceHelper.getRegular(getActivity()));
            builder.content(R.string.request_building);
            builder.cancelable(false);
            builder.canceledOnTouchOutside(false);
            builder.progress(true, 0);
            builder.progressIndeterminateStyle(true);

            dialog = builder.build();
            dialog.show();
        }

        @Override
        protected Boolean doInBackground(Void... voids) {
            while (!isCancelled()) {
                try {
                    Thread.sleep(1);
                    Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
                            getResources().getString(R.string.dev_email),
                            null));
                    List<ResolveInfo> resolveInfos = getActivity().getPackageManager()
                            .queryIntentActivities(intent, 0);
                    if (resolveInfos.size() == 0) {
                        noEmailClientError = true;
                        return false;
                    }

                    if (Preferences.get(getActivity()).isPremiumRequest()) {
                        TransactionDetails details = InAppBillingProcessor.get(getActivity())
                                .getProcessor().getPurchaseTransactionDetails(
                                Preferences.get(getActivity()).getPremiumRequestProductId());
                        if (details == null) return false;

                        CandyBarApplication.sRequestProperty = new Request.Property(null,
                                details.purchaseInfo.purchaseData.orderId,
                                details.purchaseInfo.purchaseData.productId);
                    }

                    RequestFragment.sSelectedRequests = mAdapter.getSelectedItems();
                    List<Request> requests = mAdapter.getSelectedApps();
                    File appFilter = RequestHelper.buildXml(getActivity(), requests, RequestHelper.XmlType.APPFILTER);
                    File appMap = RequestHelper.buildXml(getActivity(), requests, RequestHelper.XmlType.APPMAP);
                    File themeResources = RequestHelper.buildXml(getActivity(), requests, RequestHelper.XmlType.THEME_RESOURCES);

                    File directory = getActivity().getCacheDir();
                    List<String> files = new ArrayList<>();

                    for (Request request : requests) {
                        Drawable drawable = getHighQualityIcon(getActivity(), request.getPackageName());
                        String icon = IconsHelper.saveIcon(files, directory, drawable, request.getName());
                        if (icon != null) files.add(icon);
                    }

                    if (appFilter != null) {
                        files.add(appFilter.toString());
                    }

                    if (appMap != null) {
                        files.add(appMap.toString());
                    }

                    if (themeResources != null) {
                        files.add(themeResources.toString());
                    }

                    CandyBarApplication.sZipPath = FileHelper.createZip(files, new File(directory.toString(),
                            RequestHelper.getGeneratedZipName(RequestHelper.ZIP)));
                    return true;
                } catch (Exception e) {
                    LogUtil.e(Log.getStackTraceString(e));
                    return false;
                }
            }
            return false;
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            if (getActivity() == null) return;
            if (getActivity().isFinishing()) return;

            mAsyncTask = null;
            dialog.dismiss();
            if (aBoolean) {
                IntentChooserFragment.showIntentChooserDialog(getActivity().getSupportFragmentManager(),
                        IntentChooserFragment.ICON_REQUEST);

                mAdapter.resetSelectedItems();
                if (mMenuItem != null) mMenuItem.setIcon(R.drawable.ic_toolbar_select_all);
            } else {
                if (noEmailClientError) {
                    Toast.makeText(getActivity(), R.string.no_email_app,
                            Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getActivity(), R.string.request_build_failed,
                            Toast.LENGTH_LONG).show();
                }
            }
        }
    }
}


Question: package com.dm.material.dashboard.candybar.tasks;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.danimahardhika.android.helpers.core.FileHelper;
import com.dm.material.dashboard.candybar.R;
import com.dm.material.dashboard.candybar.activities.CandyBarMainActivity;
import com.dm.material.dashboard.candybar.applications.CandyBarApplication;
import com.dm.material.dashboard.candybar.databases.Database;
import com.dm.material.dashboard.candybar.fragments.RequestFragment;
import com.dm.material.dashboard.candybar.fragments.dialog.IntentChooserFragment;
import com.dm.material.dashboard.candybar.helpers.DeviceHelper;
import com.dm.material.dashboard.candybar.items.Request;
import com.dm.material.dashboard.candybar.preferences.Preferences;
import com.danimahardhika.android.helpers.core.utils.LogUtil;
import com.dm.material.dashboard.candybar.utils.Extras;
import com.dm.material.dashboard.candybar.utils.listeners.RequestListener;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.concurrent.Executor;




/*
 * CandyBar - Material Dashboard
 *
 * Copyright (c) 2014-2016 Dani Mahardhika
 *
 * 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.
 */

public class IconRequestBuilderTask extends AsyncTask<Void, Void, Boolean> {

    private WeakReference<Context> mContext;
    private WeakReference<IconRequestBuilderCallback> mCallback;
    private String mEmailBody;
    private Extras.Error mError;

    private IconRequestBuilderTask(Context context) {
        mContext = new WeakReference<>(context);
    }

    public IconRequestBuilderTask callback(IconRequestBuilderCallback callback) {
        mCallback = new WeakReference<>(callback);
        return this;
    }

    public AsyncTask start() {
        return start(SERIAL_EXECUTOR);
    }

    public AsyncTask start(@NonNull Executor executor) {
        return executeOnExecutor(executor);
    }

    public static IconRequestBuilderTask prepare(@NonNull Context context) {
        return new IconRequestBuilderTask(context);
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        while (!isCancelled()) {
            try {
                Thread.sleep(1);
                if (RequestFragment.sSelectedRequests == null) {
                    mError = Extras.Error.ICON_REQUEST_NULL;
                    return false;
                }

                if (CandyBarApplication.sRequestProperty == null) {
                    mError = Extras.Error.ICON_REQUEST_PROPERTY_NULL;
                    return false;
                }

                if (CandyBarApplication.sRequestProperty.getComponentName() == null) {
                    mError = Extras.Error.ICON_REQUEST_PROPERTY_COMPONENT_NULL;
                    return false;
                }

                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(DeviceHelper.getDeviceInfo(mContext.get()));

                if (Preferences.get(mContext.get()).isPremiumRequest()) {
                    if (CandyBarApplication.sRequestProperty.getOrderId() != null) {
                        stringBuilder.append("Order Id: ")
                                .append(CandyBarApplication.sRequestProperty.getOrderId());
                    }

                    if (CandyBarApplication.sRequestProperty.getProductId() != null) {
                        stringBuilder.append("\nProduct Id: ")
                                .append(CandyBarApplication.sRequestProperty.getProductId());
                    }
                }

                for (int i = 0; i < RequestFragment.sSelectedRequests.size(); i++) {
Answer:                     Request request = CandyBarMainActivity.sMissedApps.get(RequestFragment.sSelectedRequests.get(i));