diff --git a/CHANGELOG.md b/CHANGELOG.md index 495c7ac..c49ae54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changes +- Migrates to AndroidX [RNMT-6236](https://outsystemsrd.atlassian.net/browse/RNMT-6236) + +### Removals +- **BREAKING:** Drops support for apps targeting SDK 28 (Android 9) or lower [RNMT-6236](https://outsystemsrd.atlassian.net/browse/RNMT-6236) + ## [2.6.0] ### Additions - Adds granular media permissions for Android 13 [RNMT-5590](https://outsystemsrd.atlassian.net/browse/RNMT-5590) diff --git a/plugin.xml b/plugin.xml index bd536f9..c2187d7 100755 --- a/plugin.xml +++ b/plugin.xml @@ -36,8 +36,6 @@ - - diff --git a/src/android/MobileECT/MobileECT.aar b/src/android/MobileECT/MobileECT.aar index bc5fd75..bfba564 100644 Binary files a/src/android/MobileECT/MobileECT.aar and b/src/android/MobileECT/MobileECT.aar differ diff --git a/src/android/OSAppFeedback.java b/src/android/OSAppFeedback.java index a24cb7e..9ab2556 100755 --- a/src/android/OSAppFeedback.java +++ b/src/android/OSAppFeedback.java @@ -1,21 +1,20 @@ package com.outsystems.plugins.appfeedback; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v4.view.MotionEventCompat; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; import android.widget.LinearLayout; import android.widget.RelativeLayout; -import com.outsystems.android.mobileect.api.interfaces.OSECTProviderAPIHandler; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + import com.outsystems.plugins.broadcaster.interfaces.Event; import org.apache.cordova.CallbackContext; @@ -25,10 +24,7 @@ import org.json.JSONArray; import org.json.JSONException; -import java.lang.ref.WeakReference; import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; public class OSAppFeedback extends CordovaPlugin { @@ -48,71 +44,56 @@ public class OSAppFeedback extends CordovaPlugin { private static final String GESTURE_THREE_FINGERS = "3"; private OSAppFeedbackListener appFeedbackListener; - private ViewGroup mainViewGroup; private ViewGroup ectViewGroup; private BroadcastReceiver broadcastReceiver; private boolean inBackground; private String defaultHostname; - protected ViewGroup getMainViewGroup() { - return mainViewGroup; - } - protected void setMainViewGroup(ViewGroup mainViewGroup) { this.mainViewGroup = mainViewGroup; } - protected ViewGroup getEctViewGroup() { - return ectViewGroup; - } - protected void setEctViewGroup(ViewGroup ectViewGroup) { this.ectViewGroup = ectViewGroup; } - + @SuppressLint("ResourceType") @Override protected void pluginInitialize() { - this.defaultHostname = preferences.getString(DEFAULT_HOSTNAME,null); - final boolean defautHandler = preferences.getBoolean(DEFAULT_HANDLER,true); + this.defaultHostname = preferences.getString(DEFAULT_HOSTNAME, null); + final boolean defautHandler = preferences.getBoolean(DEFAULT_HANDLER, true); - cordova.getActivity().runOnUiThread(new Runnable() { - @SuppressWarnings("ResourceType") - @Override - public void run() { + cordova.getActivity().runOnUiThread(() -> { - final CordovaActivity cordovaActivity = (CordovaActivity) cordova.getActivity(); + final CordovaActivity cordovaActivity = (CordovaActivity) cordova.getActivity(); - ViewGroup mainViewGroup = (ViewGroup) webView.getView().getParent(); + ViewGroup mainViewGroup = (ViewGroup) webView.getView().getParent(); + ViewGroup rootView = (ViewGroup) mainViewGroup.getParent(); - ViewGroup rootView = (ViewGroup) mainViewGroup.getParent(); - - if (rootView instanceof LinearLayout) { - LinearLayout linearLayout = (LinearLayout) rootView; - linearLayout.setOrientation(LinearLayout.VERTICAL); - } + if (rootView instanceof LinearLayout) { + LinearLayout linearLayout = (LinearLayout) rootView; + linearLayout.setOrientation(LinearLayout.VERTICAL); + } - RelativeLayout ectViewGroup = new RelativeLayout(cordovaActivity); - RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); - ectViewGroup.setLayoutParams(params); - ectViewGroup.setId(2001); - ectViewGroup.setFitsSystemWindows(true); - ectViewGroup.setVisibility(View.GONE); + RelativeLayout ectViewGroup = new RelativeLayout(cordovaActivity); + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); + ectViewGroup.setLayoutParams(params); + ectViewGroup.setId(2001); + ectViewGroup.setFitsSystemWindows(true); + ectViewGroup.setVisibility(View.GONE); - rootView.addView(ectViewGroup); - rootView.invalidate(); + rootView.addView(ectViewGroup); + rootView.invalidate(); - setMainViewGroup(mainViewGroup); - setEctViewGroup(ectViewGroup); + setMainViewGroup(mainViewGroup); + setEctViewGroup(ectViewGroup); - if(defautHandler){ - registerGestureHandler(); - } + if (defautHandler) { + registerGestureHandler(); } }); - } @Override @@ -125,9 +106,7 @@ public void onResume(boolean multitasking) { public void onStart() { super.onStart(); final Activity activity = this.cordova.getActivity(); - if(activity.getApplicationInfo().targetSdkVersion >= 29) { - LocalBroadcastManager.getInstance(activity.getApplicationContext()).registerReceiver(this.broadcastReceiver, new IntentFilter(GESTURE_EVENT)); - } + LocalBroadcastManager.getInstance(activity.getApplicationContext()).registerReceiver(this.broadcastReceiver, new IntentFilter(GESTURE_EVENT)); } @Override @@ -139,210 +118,89 @@ public void onPause(boolean multitasking) { @Override public void onStop() { final Activity activity = this.cordova.getActivity(); - if(activity.getApplicationInfo().targetSdkVersion >= 29) { - LocalBroadcastManager.getInstance(activity.getApplicationContext()).unregisterReceiver(this.broadcastReceiver); - } + LocalBroadcastManager.getInstance(activity.getApplicationContext()).unregisterReceiver(this.broadcastReceiver); super.onStop(); } @Override public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException { - if (!inBackground) { - if (action.equals("deviceready")) { + if (inBackground) { + callbackContext.error("Can't open ECT while in background."); + return false; + } - if(defaultHostname == null || defaultHostname.isEmpty()){ + switch (action) { + case "deviceready": + if (defaultHostname == null || defaultHostname.isEmpty()) { defaultHostname = args.getString(0); } - handleDeviceReady(defaultHostname); - - return true; - } else { - if (action.equals("isAvailable")) { - handleIsECTAvailable(callbackContext); - - return true; - } else { - if (action.equals("openECT")) { - handleOpenECT(callbackContext); - - return true; - } - } - } - - callbackContext.error("Invalid plugin action."); - return false; - } else { - callbackContext.error("Can't open ECT while in background."); - return false; + break; + case "isAvailable": + handleIsECTAvailable(callbackContext); + break; + case "openECT": + handleOpenECT(callbackContext); + break; + default: + callbackContext.error("Invalid plugin action."); + return false; } + return true; } - private void handleDeviceReady(String hostname) { SystemWebViewEngine webViewEngine = (SystemWebViewEngine) webView.getEngine(); WebView currentWebView = (WebView) webViewEngine.getView(); appFeedbackListener = new OSAppFeedbackListener(cordova.getActivity(), mainViewGroup, ectViewGroup, currentWebView, hostname); - - cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - appFeedbackListener.handleDeviceReady(); - } - }); - + cordova.getActivity().runOnUiThread(() -> appFeedbackListener.handleDeviceReady()); } private void handleIsECTAvailable(final CallbackContext callbackContext) { - cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - appFeedbackListener.handleECTAvailable(new OSECTProviderAPIHandler() { - @Override - public void execute(boolean result) { - if (result) { - callbackContext.success(1); - } else { - callbackContext.error("App Feedback is not available."); - } - } - }); + cordova.getActivity().runOnUiThread(() -> appFeedbackListener.handleECTAvailable(result -> { + if (result) { + callbackContext.success(1); + } else { + callbackContext.error("App Feedback is not available."); } - }); + })); } private void handleOpenECT(final CallbackContext callbackContext) { - cordova.getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - appFeedbackListener.handleOpenECT(new OSECTProviderAPIHandler() { - @Override - public void execute(boolean result) { - if (result) { - callbackContext.success(1); - } else { - callbackContext.error("App Feedback is not available."); - } - } - }); + cordova.getActivity().runOnUiThread(() -> appFeedbackListener.handleOpenECT(result -> { + if (result) { + callbackContext.success(1); + } else { + callbackContext.error("App Feedback is not available."); } - }); + })); } - /** - * Gesture Detector - */ - - private long mSecondFingerTimeDown = 0; - private Timer mGestureRecognizerTimer; - private int INTERVAL_TO_SHOW_MENU = 600; - - private class GestureRecognizerTimedTask extends TimerTask { - - WeakReference hRef; - - public GestureRecognizerTimedTask(CordovaActivity activity) { - hRef = new WeakReference(activity); - } - - @Override - public void run() { - - final CordovaActivity activity = hRef.get(); - - if (activity == null) - return; - - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - appFeedbackListener.handleECTAvailable(new OSECTProviderAPIHandler() { - @Override - public void execute(boolean result) { - if(result) { - appFeedbackListener.handleOpenECT(null); - } - } - }); - } - }); - - } - } - - private void registerGestureHandler(){ + private void registerGestureHandler() { final CordovaActivity cordovaActivity = (CordovaActivity) cordova.getActivity(); - if(cordovaActivity.getApplicationInfo().targetSdkVersion >= 29) { - this.broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Bundle extras = intent.getExtras(); - if(extras != null) { - Event gestureEvent = extras.getParcelable(GESTURE_EVENT); - if(gestureEvent != null) { - Map eventData = gestureEvent.getData(); - if(eventData != null) { - if(GESTURE_LONG_PRESS.equals(eventData.get(GESTURE_TYPE)) && - GESTURE_TWO_FINGERS.equals(eventData.get(GESTURE_NUMBER_FINGERS))) { - cordovaActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - appFeedbackListener.handleECTAvailable(new OSECTProviderAPIHandler() { - @Override - public void execute(boolean result) { - if(result) { - appFeedbackListener.handleOpenECT(null); - } - } - }); - } - }); - } + this.broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Bundle extras = intent.getExtras(); + if (extras != null) { + Event gestureEvent = extras.getParcelable(GESTURE_EVENT); + if (gestureEvent != null) { + Map eventData = gestureEvent.getData(); + if (eventData != null) { + if (GESTURE_LONG_PRESS.equals(eventData.get(GESTURE_TYPE)) && + GESTURE_TWO_FINGERS.equals(eventData.get(GESTURE_NUMBER_FINGERS))) { + cordovaActivity.runOnUiThread(() -> appFeedbackListener.handleECTAvailable(result -> { + if (result) { + appFeedbackListener.handleOpenECT(null); + } + })); } } } } - }; - } - else { - webView.getView().setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - int action = MotionEventCompat.getActionMasked(event); - - if(event.getPointerCount() == 2) { - switch (action) { - case MotionEvent.ACTION_POINTER_DOWN: - mSecondFingerTimeDown = System.currentTimeMillis(); - mGestureRecognizerTimer = new Timer(); - mGestureRecognizerTimer.schedule(new GestureRecognizerTimedTask(cordovaActivity), INTERVAL_TO_SHOW_MENU); - break; - case MotionEvent.ACTION_POINTER_UP: - if ((System.currentTimeMillis() - mSecondFingerTimeDown) <= INTERVAL_TO_SHOW_MENU) { - mGestureRecognizerTimer.cancel(); - } - if ((System.currentTimeMillis() - mSecondFingerTimeDown) >= INTERVAL_TO_SHOW_MENU) { - mSecondFingerTimeDown = 0; - } - break; - } - - } - else{ - if(mGestureRecognizerTimer != null){ - mGestureRecognizerTimer.cancel(); - } - mSecondFingerTimeDown = 0; - } - - return webView.getView().onTouchEvent(event); - } - }); - } - + } + }; } - -} \ No newline at end of file +} diff --git a/src/android/OSAppFeedbackListener.java b/src/android/OSAppFeedbackListener.java index 26dbcb0..bb68814 100755 --- a/src/android/OSAppFeedbackListener.java +++ b/src/android/OSAppFeedbackListener.java @@ -3,32 +3,30 @@ import android.app.Activity; import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.util.Log; import android.view.ViewGroup; import android.webkit.WebView; +import androidx.appcompat.app.AppCompatActivity; + import com.outsystems.android.mobileect.MobileECTController; import com.outsystems.android.mobileect.api.interfaces.OSECTProviderAPIHandler; import com.outsystems.android.mobileect.interfaces.OSECTContainerListener; -import org.apache.cordova.CallbackContext; - public class OSAppFeedbackListener implements OSECTContainerListener { private final String SHAREDPREF_NAME = "com.outsystems.plugins.appfeedback.preferences"; private final String SHAREDPREF_KEY_SKIP_HELP = "com.outsystems.plugins.appfeedback.key.skiphelp"; - private MobileECTController mobileECTController; + private final MobileECTController mobileECTController; + private final Context context; private boolean appFeedbackAvailable; - private Context context; - public OSAppFeedbackListener(Activity activity, ViewGroup mainViewGroup, ViewGroup ectViewGroup, WebView currentWebView, String hostname) { + public OSAppFeedbackListener(AppCompatActivity activity, ViewGroup mainViewGroup, ViewGroup ectViewGroup, WebView currentWebView, String hostname) { this.context = activity; @@ -77,13 +75,8 @@ public void openECT() { * Public API for Plugin */ - public void handleDeviceReady(){ - this.mobileECTController.prepareECTData(new OSECTProviderAPIHandler() { - @Override - public void execute(boolean result) { - // Do Nothing - } - }); + public void handleDeviceReady() { + this.mobileECTController.prepareECTData(result -> { /* Do Nothing */ }); } private boolean isNetworkAvailable(Context context) { @@ -93,40 +86,28 @@ private boolean isNetworkAvailable(Context context) { } public void handleECTAvailable(final OSECTProviderAPIHandler apiHandler) { - if(isNetworkAvailable(context)) { - mobileECTController.checkECTAvailability(new OSECTProviderAPIHandler() { - @Override - public void execute(boolean result) { - appFeedbackAvailable = result; - if(apiHandler != null) - apiHandler.execute(result); - } + if (isNetworkAvailable(context)) { + mobileECTController.checkECTAvailability(result -> { + appFeedbackAvailable = result; + if (apiHandler != null) + apiHandler.execute(result); }); } else { AlertDialog.Builder alert = new AlertDialog.Builder(context); alert.setTitle("Can't send feedback"); alert.setMessage("Make sure your device has internet connection and try again."); - alert.setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - + alert.setPositiveButton("OK", (dialog, which) -> dialog.dismiss()); alert.show(); } } public void handleOpenECT(final OSECTProviderAPIHandler apiHandler) { - if (this.isAppFeedbackAvailable()) { + boolean isAppFeedbackAvailable = this.isAppFeedbackAvailable(); + if (isAppFeedbackAvailable) { this.openECT(); - if(apiHandler != null) { - apiHandler.execute(true); - } - } else { - if(apiHandler != null) { - apiHandler.execute(false); - } + } + if (apiHandler != null) { + apiHandler.execute(isAppFeedbackAvailable); } } diff --git a/src/android/osappfeedback.gradle b/src/android/osappfeedback.gradle index 6eaadc7..0fcba82 100755 --- a/src/android/osappfeedback.gradle +++ b/src/android/osappfeedback.gradle @@ -1,20 +1,21 @@ -repositories{ - jcenter() - flatDir{ - dirs 'libs','src/main/libs' - } +repositories { + google() + mavenCentral() + flatDir { + dirs 'libs', 'src/main/libs' + } } dependencies { - implementation 'com.loopj.android:android-async-http:1.4.9' - implementation 'com.google.code.gson:gson:2.6.2' - implementation 'commons-io:commons-io:1.3.2' - implementation(name:'MobileECT', ext:'aar') + implementation 'com.loopj.android:android-async-http:1.4.11' + implementation 'com.google.code.gson:gson:2.10.1' + implementation 'commons-io:commons-io:1.3.2' + implementation(name: 'MobileECT', ext: 'aar') } android { - packagingOptions { - exclude 'META-INF/NOTICE' - exclude 'META-INF/LICENSE' - } + packagingOptions { + exclude 'META-INF/NOTICE' + exclude 'META-INF/LICENSE' + } } \ No newline at end of file