diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eaa44fff..10ecfe4bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ ## XX.XX.XX +* The feedback widgets now have transparent backgrounds for a cleaner look. + * Mitigated an issue where visibility could have been wrongly assigned if a view was closed while going to background. (Experimental!) +* Deprecated "presentFeedbackWidget(widgetInfo, context, closeButtonText, devCallback)", replaced with "presentFeedbackWidget(widgetInfo, context, devCallback)" in the feedbacks. + ## 24.7.5 * ! Minor breaking change ! All active views will now automatically stop when consent for "views" is revoked. diff --git a/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java b/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java index b6a91a1cf..784ebfa2e 100644 --- a/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java +++ b/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java @@ -2,7 +2,6 @@ import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; import android.os.Handler; import android.os.Looper; import android.webkit.WebSettings; @@ -173,7 +172,7 @@ static List parseFeedbackList(JSONObject requestResponse) return parsedRes; } - void presentFeedbackWidgetInternal(@Nullable final CountlyFeedbackWidget widgetInfo, @Nullable final Context context, @Nullable final String closeButtonText, @Nullable final FeedbackCallback devCallback) { + void presentFeedbackWidgetInternal(@Nullable final CountlyFeedbackWidget widgetInfo, @Nullable final Context context, @Nullable final FeedbackCallback devCallback) { if (widgetInfo == null) { L.e("[ModuleFeedback] Can't present widget with null widget info"); @@ -245,6 +244,8 @@ void presentFeedbackWidgetInternal(@Nullable final CountlyFeedbackWidget widgetI JSONObject customObjectToSendWithTheWidget = new JSONObject(); try { customObjectToSendWithTheWidget.put("tc", 1); + customObjectToSendWithTheWidget.put("rw", 1); + customObjectToSendWithTheWidget.put("xb", 1); } catch (JSONException e) { throw new RuntimeException(e); } @@ -257,8 +258,6 @@ void presentFeedbackWidgetInternal(@Nullable final CountlyFeedbackWidget widgetI //enable for chrome debugging //WebView.setWebContentsDebuggingEnabled(true); - - final boolean useAlertDialog = true; Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { public void run() { @@ -267,27 +266,46 @@ public void run() { try { ModuleRatings.RatingDialogWebView webView = new ModuleRatings.RatingDialogWebView(context); + webView.getSettings().setJavaScriptEnabled(true); webView.clearCache(true); webView.clearHistory(); webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); - webView.setWebViewClient(new ModuleRatings.FeedbackDialogWebViewClient()); + ModuleRatings.FeedbackDialogWebViewClient webViewClient = new ModuleRatings.FeedbackDialogWebViewClient(); + webView.setWebViewClient(webViewClient); webView.loadUrl(preparedWidgetUrl); webView.requestFocus(); - AlertDialog.Builder builder = prepareAlertDialog(context, webView, closeButtonText, widgetInfo, devCallback); + AlertDialog alert = new AlertDialog.Builder(context).setView(webView).setCancelable(false).create(); + alert.getWindow().setBackgroundDrawableResource(android.R.color.transparent); + alert.getWindow().setDimAmount(0f); - if (useAlertDialog) { - // use alert dialog to host the webView - L.d("[ModuleFeedback] Creating standalone Alert dialog"); - builder.show(); - } else { - // use dialog fragment to host the webView - L.d("[ModuleFeedback] Creating Alert dialog in dialogFragment"); + webViewClient.listener = new WebViewUrlListener() { + @Override + public boolean onUrl(String url, WebView webView) { + if (!url.startsWith(Utils.COMM_URL)) { + return false; + } - //CountlyDialogFragment newFragment = CountlyDialogFragment.newInstance(builder); - //newFragment.show(fragmentManager, "CountlyFragmentDialog"); - } + Map params = Utils.splitIntoParams(url, L); + String widgetCommand = params.get("cly_widget_command"); + + if ("1".equals(widgetCommand)) { + String close = params.get("close"); + if ("1".equals(close)) { + if (devCallback != null) { + devCallback.onFinished(null); + } + reportFeedbackWidgetCancelButton(widgetInfo, cachedAppVersion); + alert.cancel(); + return true; + } + } + + return false; + } + }; + alert.show(); if (devCallback != null) { devCallback.onFinished(null); @@ -302,27 +320,6 @@ public void run() { }); } - AlertDialog.Builder prepareAlertDialog(@NonNull final Context context, @NonNull WebView webView, @Nullable String closeButtonText, @NonNull final CountlyFeedbackWidget widgetInfo, @Nullable final FeedbackCallback devCallback) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setView(webView); - builder.setCancelable(false); - String usedCloseButtonText = closeButtonText; - if (closeButtonText == null || closeButtonText.isEmpty()) { - usedCloseButtonText = "Close"; - } - builder.setNeutralButton(usedCloseButtonText, new DialogInterface.OnClickListener() { - @Override public void onClick(DialogInterface dialogInterface, int i) { - L.d("[ModuleFeedback] Cancel button clicked for the feedback widget"); - reportFeedbackWidgetCancelButton(widgetInfo, deviceInfo.mp.getAppVersion(context)); - - if (devCallback != null) { - devCallback.onClosed(); - } - } - }); - return builder; - } - void reportFeedbackWidgetCancelButton(@NonNull CountlyFeedbackWidget widgetInfo, @NonNull String appVersion) { L.d("[reportFeedbackWidgetCancelButton] Cancel button event"); if (consentProvider.getConsent(Countly.CountlyFeatureNames.feedback)) { @@ -643,7 +640,7 @@ private void presentFeedbackWidgetNameIDorTag(@NonNull Context context, @NonNull return; } - presentFeedbackWidgetInternal(selectedWidget, context, null, devCallback); + presentFeedbackWidgetInternal(selectedWidget, context, devCallback); } }); } @@ -679,12 +676,28 @@ public void getAvailableFeedbackWidgets(@Nullable RetrieveFeedbackWidgets callba * @param context * @param closeButtonText if this is null, no "close" button will be shown * @param devCallback + * @deprecated use {@link #presentFeedbackWidget(CountlyFeedbackWidget, Context, FeedbackCallback)} instead */ public void presentFeedbackWidget(@Nullable CountlyFeedbackWidget widgetInfo, @Nullable Context context, @Nullable String closeButtonText, @Nullable FeedbackCallback devCallback) { synchronized (_cly) { L.i("[Feedback] Trying to present feedback widget in an alert dialog"); - presentFeedbackWidgetInternal(widgetInfo, context, closeButtonText, devCallback); + presentFeedbackWidget(widgetInfo, context, devCallback); + } + } + + /** + * Present a chosen feedback widget in an alert dialog + * + * @param widgetInfo the widget to present + * @param context the context to use for displaying the feedback widget + * @param devCallback callback to be called when the feedback widget is closed + */ + public void presentFeedbackWidget(@Nullable CountlyFeedbackWidget widgetInfo, @Nullable Context context, @Nullable FeedbackCallback devCallback) { + synchronized (_cly) { + L.i("[Feedback] Trying to present feedback widget in an alert dialog"); + + presentFeedbackWidgetInternal(widgetInfo, context, devCallback); } } diff --git a/sdk/src/main/java/ly/count/android/sdk/ModuleRatings.java b/sdk/src/main/java/ly/count/android/sdk/ModuleRatings.java index 414398324..67d2f8e8d 100644 --- a/sdk/src/main/java/ly/count/android/sdk/ModuleRatings.java +++ b/sdk/src/main/java/ly/count/android/sdk/ModuleRatings.java @@ -564,10 +564,19 @@ public boolean onCheckIsTextEditor() { } static class FeedbackDialogWebViewClient extends WebViewClient { + + WebViewUrlListener listener; + @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); + if (listener != null) { + if (listener.onUrl(url, view)) { + return true; + } + } + // Filter out outgoing calls if (url.endsWith("cly_x_int=1")) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); diff --git a/sdk/src/main/java/ly/count/android/sdk/TransparentActivity.java b/sdk/src/main/java/ly/count/android/sdk/TransparentActivity.java index 4dcb87591..cdf2ca498 100644 --- a/sdk/src/main/java/ly/count/android/sdk/TransparentActivity.java +++ b/sdk/src/main/java/ly/count/android/sdk/TransparentActivity.java @@ -29,7 +29,6 @@ public class TransparentActivity extends Activity { static final String CONFIGURATION_LANDSCAPE = "Landscape"; static final String CONFIGURATION_PORTRAIT = "Portrait"; static final String ORIENTATION = "orientation"; - private static final String URL_START = "https://countly_action_event"; int currentOrientation = 0; TransparentActivityConfig configLandscape = null; TransparentActivityConfig configPortrait = null; @@ -64,14 +63,14 @@ protected void onCreate(Bundle savedInstanceState) { int height = config.height; configLandscape.listeners.add((url, webView) -> { - if (url.startsWith(URL_START)) { + if (url.startsWith(Utils.COMM_URL)) { return contentUrlAction(url, configLandscape, webView); } return false; }); configPortrait.listeners.add((url, webView) -> { - if (url.startsWith(URL_START)) { + if (url.startsWith(Utils.COMM_URL)) { return contentUrlAction(url, configPortrait, webView); } return false; diff --git a/sdk/src/main/java/ly/count/android/sdk/Utils.java b/sdk/src/main/java/ly/count/android/sdk/Utils.java index 20ca4e089..506ed2c63 100644 --- a/sdk/src/main/java/ly/count/android/sdk/Utils.java +++ b/sdk/src/main/java/ly/count/android/sdk/Utils.java @@ -24,6 +24,10 @@ import static android.content.Context.UI_MODE_SERVICE; public class Utils { + /** + * This is a communication url between web views and the SDK + */ + protected static final String COMM_URL = "https://countly_action_event"; private static final ExecutorService bg = Executors.newSingleThreadExecutor(); public static Future runInBackground(Runnable runnable) {