From c953dd738b3f35b38432732e229e14af58c2d833 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Thu, 24 Oct 2024 17:04:24 +0300 Subject: [PATCH 1/6] feat: basic fw comm --- .../ly/count/android/sdk/ModuleFeedback.java | 28 ++++++++++--------- .../ly/count/android/sdk/ModuleRatings.java | 9 ++++++ 2 files changed, 24 insertions(+), 13 deletions(-) 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 da06bfdcb..172f5d81e 100644 --- a/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java +++ b/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java @@ -245,6 +245,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); } @@ -271,23 +273,24 @@ public void run() { 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 = builder.create(); + webViewClient.listener = new WebViewUrlListener() { + @Override public boolean onUrl(String url, WebView webView) { + if (url.equals("https://countly_action_event/?cly_widget_command&close=1")) { + alert.cancel(); + return true; + } - 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"); - - //CountlyDialogFragment newFragment = CountlyDialogFragment.newInstance(builder); - //newFragment.show(fragmentManager, "CountlyFragmentDialog"); - } + return false; + } + }; + alert.show(); if (devCallback != null) { devCallback.onFinished(null); @@ -314,7 +317,6 @@ AlertDialog.Builder prepareAlertDialog(@NonNull final Context context, @NonNull @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(); } 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)); From c8ba60a11fc5facc12b6e3453bb8ad32ec3ad493 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Fri, 25 Oct 2024 08:49:33 +0300 Subject: [PATCH 2/6] fix: basic check --- sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 172f5d81e..4a48391c7 100644 --- a/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java +++ b/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java @@ -281,7 +281,11 @@ public void run() { AlertDialog.Builder builder = prepareAlertDialog(context, webView, closeButtonText, widgetInfo, devCallback); AlertDialog alert = builder.create(); webViewClient.listener = new WebViewUrlListener() { - @Override public boolean onUrl(String url, WebView webView) { + @Override + public boolean onUrl(String url, WebView webView) { + if (devCallback != null) { + devCallback.onFinished(null); + } if (url.equals("https://countly_action_event/?cly_widget_command&close=1")) { alert.cancel(); return true; From 2fbc9f86d851a787c2b10f101063241f0a249965 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Fri, 25 Oct 2024 08:53:31 +0300 Subject: [PATCH 3/6] fix: basic check --- sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4a48391c7..18a47c387 100644 --- a/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java +++ b/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java @@ -283,10 +283,10 @@ public void run() { webViewClient.listener = new WebViewUrlListener() { @Override public boolean onUrl(String url, WebView webView) { + if (url.equals("https://countly_action_event/?cly_widget_command&close=1")) { if (devCallback != null) { devCallback.onFinished(null); } - if (url.equals("https://countly_action_event/?cly_widget_command&close=1")) { alert.cancel(); return true; } From df97478c2e8b0d00095abe2fd7e06cc80b0956c3 Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Fri, 1 Nov 2024 10:38:09 +0300 Subject: [PATCH 4/6] refactor: comm --- .../ly/count/android/sdk/ModuleFeedback.java | 20 ++++++++++++++----- .../android/sdk/TransparentActivity.java | 5 ++--- .../main/java/ly/count/android/sdk/Utils.java | 4 ++++ 3 files changed, 21 insertions(+), 8 deletions(-) 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 18a47c387..91c9a1992 100644 --- a/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java +++ b/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java @@ -283,12 +283,22 @@ public void run() { webViewClient.listener = new WebViewUrlListener() { @Override public boolean onUrl(String url, WebView webView) { - if (url.equals("https://countly_action_event/?cly_widget_command&close=1")) { - if (devCallback != null) { - devCallback.onFinished(null); + if (!url.startsWith(Utils.COMM_URL)) { + return false; + } + + 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); + } + alert.cancel(); + return true; } - alert.cancel(); - return true; } return false; 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 9889bda2d..23c2e2949 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) { From d6a4d71ecf49089aad39ca6bfaed2492ae81247c Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Tue, 12 Nov 2024 18:00:58 +0300 Subject: [PATCH 5/6] feat: made transparent the alert dialog --- .../ly/count/android/sdk/ModuleFeedback.java | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) 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 91c9a1992..c65dde56b 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; @@ -259,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() { @@ -269,6 +266,7 @@ public void run() { try { ModuleRatings.RatingDialogWebView webView = new ModuleRatings.RatingDialogWebView(context); + webView.getSettings().setJavaScriptEnabled(true); webView.clearCache(true); webView.clearHistory(); @@ -278,8 +276,10 @@ public void run() { webView.loadUrl(preparedWidgetUrl); webView.requestFocus(); - AlertDialog.Builder builder = prepareAlertDialog(context, webView, closeButtonText, widgetInfo, devCallback); - AlertDialog alert = builder.create(); + AlertDialog alert = new AlertDialog.Builder(context).setView(webView).setCancelable(false).create(); + alert.getWindow().setBackgroundDrawableResource(android.R.color.transparent); + alert.getWindow().setDimAmount(0f); + webViewClient.listener = new WebViewUrlListener() { @Override public boolean onUrl(String url, WebView webView) { @@ -319,26 +319,6 @@ public boolean onUrl(String url, WebView webView) { }); } - 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)) { From c0e097686b286551bf85d6cedfda723055c6c7bf Mon Sep 17 00:00:00 2001 From: Arif Burak Demiray Date: Tue, 12 Nov 2024 18:09:42 +0300 Subject: [PATCH 6/6] feat: add changelog and add event on close --- CHANGELOG.md | 4 ++++ .../ly/count/android/sdk/ModuleFeedback.java | 23 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) 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 e4578380b..784ebfa2e 100644 --- a/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java +++ b/sdk/src/main/java/ly/count/android/sdk/ModuleFeedback.java @@ -172,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"); @@ -296,6 +296,7 @@ public boolean onUrl(String url, WebView webView) { if (devCallback != null) { devCallback.onFinished(null); } + reportFeedbackWidgetCancelButton(widgetInfo, cachedAppVersion); alert.cancel(); return true; } @@ -639,7 +640,7 @@ private void presentFeedbackWidgetNameIDorTag(@NonNull Context context, @NonNull return; } - presentFeedbackWidgetInternal(selectedWidget, context, null, devCallback); + presentFeedbackWidgetInternal(selectedWidget, context, devCallback); } }); } @@ -675,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); } }