All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vorlonsoft.android.rate.DefaultDialogManager Maven / Gradle / Ivy

Go to download

Library to help you promote your Android app by prompting users to rate the app after using it for a few days.

The newest version!
/*
 * Copyright 2017 - 2018 Vorlonsoft LLC
 *
 * Licensed under The MIT License (MIT)
 */

package com.vorlonsoft.android.rate;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

import java.lang.ref.WeakReference;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import static com.vorlonsoft.android.rate.Constants.Utils.TAG;
import static com.vorlonsoft.android.rate.IntentHelper.createIntentsForStore;
import static com.vorlonsoft.android.rate.PreferenceHelper.getDialogFirstLaunchTime;
import static com.vorlonsoft.android.rate.PreferenceHelper.increment365DayPeriodDialogLaunchTimes;
import static com.vorlonsoft.android.rate.PreferenceHelper.setDialogFirstLaunchTime;
import static com.vorlonsoft.android.rate.PreferenceHelper.setIsAgreeShowDialog;
import static com.vorlonsoft.android.rate.PreferenceHelper.setRemindInterval;
import static com.vorlonsoft.android.rate.PreferenceHelper.setRemindLaunchesNumber;
import static com.vorlonsoft.android.rate.StoreType.AMAZON;
import static com.vorlonsoft.android.rate.StoreType.APPLE;
import static com.vorlonsoft.android.rate.StoreType.BAZAAR;
import static com.vorlonsoft.android.rate.StoreType.BLACKBERRY;
import static com.vorlonsoft.android.rate.StoreType.CHINESESTORES;
import static com.vorlonsoft.android.rate.StoreType.GOOGLEPLAY;
import static com.vorlonsoft.android.rate.StoreType.INTENT;
import static com.vorlonsoft.android.rate.StoreType.MI;
import static com.vorlonsoft.android.rate.StoreType.OTHER;
import static com.vorlonsoft.android.rate.StoreType.SAMSUNG;
import static com.vorlonsoft.android.rate.StoreType.SLIDEME;
import static com.vorlonsoft.android.rate.StoreType.TENCENT;
import static com.vorlonsoft.android.rate.StoreType.YANDEX;
import static com.vorlonsoft.android.rate.Utils.isLollipop;

/**
 * 

DefaultDialogManager Class - default dialog manager class implements {@link DialogManager} * interface of the AndroidRate library.

*

You can extend DefaultDialogManager Class and use * {@link AppRate#setDialogManagerFactory(DialogManager.Factory)} if you want to use fully custom * dialog (from v7 AppCompat library etc.). DefaultDialogManager Class is thread-safe and a fast * singleton implementation inside library, not outside (protected, not private constructor).

* * @since 1.0.2 * @version 1.2.1 * @author Alexander Savin * @author Antoine Vianey * @see DefaultDialogManager.Factory * @see DialogManager */ public class DefaultDialogManager implements DialogManager { /**

The WeakReference to the {@link DefaultDialogManager} singleton object.

*/ private static volatile WeakReference singleton = null; private final StoreOptions storeOptions; private final OnClickButtonListener listener; @SuppressWarnings("WeakerAccess") protected final DialogOptions dialogOptions; @SuppressWarnings({"WeakerAccess", "UnusedAssignment"}) protected Context context = null; @SuppressWarnings("WeakerAccess") protected final DialogInterface.OnShowListener showListener = dialog -> { if (getDialogFirstLaunchTime(context) == 0L) { setDialogFirstLaunchTime(context); } increment365DayPeriodDialogLaunchTimes(context); if (isLollipop()) { try { final Button positiveButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE); if (positiveButton != null) { final LinearLayout linearLayout = (LinearLayout) positiveButton.getParent(); if ((linearLayout != null) && (positiveButton.getLeft() + positiveButton.getWidth() > linearLayout.getWidth())) { final Button neutralButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_NEUTRAL); final Button negativeButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_NEGATIVE); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setGravity(Gravity.END); if (neutralButton != null) { linearLayout.removeView(neutralButton); if (negativeButton != null) { linearLayout.removeView(negativeButton); linearLayout.addView(negativeButton); } linearLayout.addView(neutralButton); } else if (negativeButton != null) { linearLayout.removeView(negativeButton); linearLayout.addView(negativeButton); } } } } catch (Exception e) { Log.i(TAG, "Positive button may not fits in the window, can't change layout orientation to vertical"); } } }; @SuppressWarnings("WeakerAccess") protected final DialogInterface.OnDismissListener dismissListener = dialog -> AppRate.with(context).clearRateDialog(); @SuppressWarnings("WeakerAccess") protected final DialogInterface.OnClickListener positiveListener = new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { final Intent[] intentsToAppStores; final String packageName = AppInformation.getInstance(context).getAppPackageName(); if ((packageName != null) && (packageName.hashCode() != "".hashCode())) { switch (storeOptions.getStoreType()) { case AMAZON: intentsToAppStores = createIntentsForStore(context, AMAZON, packageName); break; case APPLE: intentsToAppStores = createIntentsForStore(context, APPLE, storeOptions.getApplicationId()); break; case BAZAAR: intentsToAppStores = createIntentsForStore(context, BAZAAR, packageName); break; case BLACKBERRY: intentsToAppStores = createIntentsForStore(context, BLACKBERRY, storeOptions.getApplicationId()); break; case CHINESESTORES: intentsToAppStores = createIntentsForStore(context, CHINESESTORES, packageName); break; case MI: intentsToAppStores = createIntentsForStore(context, MI, packageName); break; case SAMSUNG: intentsToAppStores = createIntentsForStore(context, SAMSUNG, packageName); break; case SLIDEME: intentsToAppStores = createIntentsForStore(context, SLIDEME, packageName); break; case TENCENT: intentsToAppStores = createIntentsForStore(context, TENCENT, packageName); break; case YANDEX: intentsToAppStores = createIntentsForStore(context, YANDEX, packageName); break; case INTENT: case OTHER: intentsToAppStores = storeOptions.getIntents(); break; default: intentsToAppStores = createIntentsForStore(context, GOOGLEPLAY, packageName); } if (intentsToAppStores == null) { Log.w(TAG, "Failed to rate app, can't create intents for store"); } } else { Log.w(TAG, "Failed to rate app, can't get app package name"); intentsToAppStores = null; } try { if (intentsToAppStores != null) { if (intentsToAppStores.length == 0) { Log.w(TAG, "Failed to rate app, no intent found for startActivity (intentsToAppStores.length == 0)"); } else if (intentsToAppStores[0] == null) { throw new ActivityNotFoundException("Failed to rate app, no intent found for startActivity (intentsToAppStores[0] == null)"); } else { context.startActivity(intentsToAppStores[0]); } } } catch (ActivityNotFoundException e) { Log.w(TAG, "Failed to rate app, no activity found for " + intentsToAppStores[0], e); byte intentsToAppStoresNumber = (byte) intentsToAppStores.length; if (intentsToAppStoresNumber > 1) { boolean isCatch; for (byte b = 1; b < intentsToAppStoresNumber; b++) { // intentsToAppStores[1] - second intent in the array try { if (intentsToAppStores[b] == null) { throw new ActivityNotFoundException("Failed to rate app, no intent found for startActivity (intentsToAppStores[" + b + "] == null)"); } else { context.startActivity(intentsToAppStores[b]); } isCatch = false; } catch (ActivityNotFoundException ex) { Log.w(TAG, "Failed to rate app, no activity found for " + intentsToAppStores[b], ex); isCatch = true; } if (!isCatch) { break; } } } } setIsAgreeShowDialog(context, false); if (listener != null) listener.onClickButton((byte) which); } }; @SuppressWarnings("WeakerAccess") protected final DialogInterface.OnClickListener negativeListener = new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { setIsAgreeShowDialog(context, false); if (listener != null) listener.onClickButton((byte) which); } }; @SuppressWarnings("WeakerAccess") protected final DialogInterface.OnClickListener neutralListener = new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { setRemindInterval(context); setRemindLaunchesNumber(context); if (listener != null) listener.onClickButton((byte) which); } }; @SuppressWarnings("WeakerAccess") protected DefaultDialogManager(final Context context, final DialogOptions dialogOptions, final StoreOptions storeOptions) { this.context = context; this.dialogOptions = dialogOptions; this.storeOptions = storeOptions; this.listener = dialogOptions.getListener(); } @SuppressWarnings("WeakerAccess") protected void setContext(Context context){ this.context = context; } /** *

Creates {@link android.app.AlertDialog.Builder}.

* * @param context activity context * @param themeResId theme resource ID * @return created {@link android.app.AlertDialog.Builder} object */ @SuppressWarnings("WeakerAccess") @Nullable protected AlertDialog.Builder getDialogBuilder(@NonNull final Context context, final int themeResId) { return Utils.getDialogBuilder(context, themeResId); } /** *

Creates Rate Dialog.

* * @return created dialog */ @Nullable @Override public Dialog createDialog() { AlertDialog.Builder builder = getDialogBuilder(context, dialogOptions.getThemeResId()); if (builder == null) { return null; } builder.setMessage(dialogOptions.getMessageText(context)); if (dialogOptions.shouldShowTitle()) { builder.setTitle(dialogOptions.getTitleText(context)); } builder.setCancelable(dialogOptions.getCancelable()); View view = dialogOptions.getView(); if (view != null) { builder.setView(view); } builder.setPositiveButton(dialogOptions.getPositiveText(context), positiveListener); if (dialogOptions.shouldShowNeutralButton()) { builder.setNeutralButton(dialogOptions.getNeutralText(context), neutralListener); } if (dialogOptions.shouldShowNegativeButton()) { builder.setNegativeButton(dialogOptions.getNegativeText(context), negativeListener); } final AlertDialog alertDialog = builder.create(); if (alertDialog != null) { alertDialog.setOnShowListener(showListener); alertDialog.setOnDismissListener(dismissListener); } return alertDialog; } /** *

DefaultDialogManager.Factory Class - default dialog manager factory class implements * {@link DialogManager.Factory} interface of the AndroidRate library.

*

You can extend DefaultDialogManager.Factory Class and use * {@link AppRate#setDialogManagerFactory(DialogManager.Factory)} if you want to use fully * custom dialog (from v7 AppCompat library etc.).

* * @since 1.0.2 * @version 1.2.1 * @author Alexander Savin * @author Antoine Vianey * @see DialogManager.Factory */ static class Factory implements DialogManager.Factory { Factory() { if (singleton != null) { singleton.clear(); } } /** Clear {@link DefaultDialogManager} singleton */ @Override public void clearDialogManager() { if (singleton != null) { singleton.clear(); } } /** *

Creates {@link DefaultDialogManager} singleton object.

* * @param context context * @param dialogOptions Rate Dialog options * @param storeOptions App store options * @return {@link DefaultDialogManager} singleton object */ @Override public DialogManager createDialogManager(final Context context, final DialogOptions dialogOptions, final StoreOptions storeOptions) { if ((singleton == null) || (singleton.get() == null)) { synchronized (DefaultDialogManager.class) { if ((singleton == null) || (singleton.get() == null)) { if (singleton != null) { singleton.clear(); } singleton = new WeakReference<>(new DefaultDialogManager(context, dialogOptions, storeOptions)); } else { singleton.get().setContext(context); } } } else { singleton.get().setContext(context); } return singleton.get(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy