Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Fix for API 30 / Android 11 by removing deprecated API calls. #139

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 38 additions & 105 deletions src/android/nl/xservices/plugins/Toast.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
package nl.xservices.plugins;

import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.CountDownTimer;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.AlignmentSpan;
import android.text.Html;
import android.text.Spanned;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
Expand All @@ -36,7 +29,6 @@ public class Toast extends CordovaPlugin {
private ViewGroup viewGroup;

private static final boolean IS_AT_LEAST_LOLLIPOP = Build.VERSION.SDK_INT >= 21;
private static final boolean IS_AT_LEAST_PIE = Build.VERSION.SDK_INT >= 28;

// note that webView.isPaused() is not Xwalk compatible, so tracking it poor-man style
private boolean isPaused;
Expand All @@ -59,23 +51,31 @@ public boolean execute(String action, JSONArray args, final CallbackContext call
}

final JSONObject options = args.getJSONObject(0);
final String msg = options.getString("message");
final Spannable message = new SpannableString(msg);
message.setSpan(
new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
0,
msg.length() - 1,
Spannable.SPAN_INCLUSIVE_INCLUSIVE);

final String duration = options.getString("duration");
final String position = options.getString("position");
final int addPixelsY = options.has("addPixelsY") ? options.getInt("addPixelsY") : 0;
final JSONObject data = options.has("data") ? options.getJSONObject("data") : null;
final JSONObject styling = options.optJSONObject("styling");

JSONObject styling = options.optJSONObject("styling");
final String msg = options.getString("message");
currentMessage = msg;
currentData = data;

String _msg = msg;
if(styling != null){
final String textColor = styling.optString("textColor", "#000000");
_msg = "<font color='"+textColor+"' ><b>" + _msg + "</b></font>";

final String backgroundColor = styling.optString("backgroundColor", "#333333");
final Double textSize = styling.optDouble("textSize", -1);
final double opacity = styling.optDouble("opacity", 0.8);
final int cornerRadius = styling.optInt("cornerRadius", 100);
final int horizontalPadding = styling.optInt("horizontalPadding", 50);
final int verticalPadding = styling.optInt("verticalPadding", 30);
}
final String html = _msg;


cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
int hideAfterMs;
Expand All @@ -87,12 +87,31 @@ public void run() {
// assuming a number of ms
hideAfterMs = Integer.parseInt(duration);
}

Spanned message;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// FROM_HTML_MODE_LEGACY is the behaviour that was used for versions below android N
// we are using this flag to give a consistent behaviour
message = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
} else {
message = Html.fromHtml(html);
}
final android.widget.Toast toast = android.widget.Toast.makeText(
IS_AT_LEAST_LOLLIPOP ? cordova.getActivity().getWindow().getContext() : cordova.getActivity().getApplicationContext(),
message,
"short".equalsIgnoreCase(duration) ? android.widget.Toast.LENGTH_SHORT : android.widget.Toast.LENGTH_LONG
);

toast.addCallback(new android.widget.Toast.Callback(){
public void onToastShown() {

}

public void onToastHidden() {
returnTapEvent("hide", msg, data, callbackContext);
}
});

if ("top".equals(position)) {
toast.setGravity(GRAVITY_TOP, 0, BASE_TOP_BOTTOM_OFFSET + addPixelsY);
} else if ("bottom".equals(position)) {
Expand All @@ -104,93 +123,7 @@ public void run() {
return;
}

// if one of the custom layout options have been passed in, draw our own shape
if (styling != null && Build.VERSION.SDK_INT >= 16) {

// the defaults mimic the default toast as close as possible
final String backgroundColor = styling.optString("backgroundColor", "#333333");
final String textColor = styling.optString("textColor", "#ffffff");
final Double textSize = styling.optDouble("textSize", -1);
final double opacity = styling.optDouble("opacity", 0.8);
final int cornerRadius = styling.optInt("cornerRadius", 100);
final int horizontalPadding = styling.optInt("horizontalPadding", 50);
final int verticalPadding = styling.optInt("verticalPadding", 30);

GradientDrawable shape = new GradientDrawable();
shape.setCornerRadius(cornerRadius);
shape.setAlpha((int)(opacity * 255)); // 0-255, where 0 is an invisible background
shape.setColor(Color.parseColor(backgroundColor));
toast.getView().setBackground(shape);

final TextView toastTextView;
toastTextView = (TextView) toast.getView().findViewById(android.R.id.message);
toastTextView.setTextColor(Color.parseColor(textColor));
if (textSize > -1) {
toastTextView.setTextSize(textSize.floatValue());
}

toast.getView().setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);

// this gives the toast a very subtle shadow on newer devices
if (Build.VERSION.SDK_INT >= 21) {
toast.getView().setElevation(6);
}
}

// On Android >= 5 you can no longer rely on the 'toast.getView().setOnTouchListener',
// so created something funky that compares the Toast position to the tap coordinates.
if (IS_AT_LEAST_LOLLIPOP) {
getViewGroup().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
if (mostRecentToast == null || !mostRecentToast.getView().isShown()) {
getViewGroup().setOnTouchListener(null);
return false;
}

float w = mostRecentToast.getView().getWidth();
float startX = (view.getWidth() / 2) - (w / 2);
float endX = (view.getWidth() / 2) + (w / 2);

float startY;
float endY;

float g = mostRecentToast.getGravity();
float y = mostRecentToast.getYOffset();
float h = mostRecentToast.getView().getHeight();

if (g == GRAVITY_BOTTOM) {
startY = view.getHeight() - y - h;
endY = view.getHeight() - y;
} else if (g == GRAVITY_CENTER) {
startY = (view.getHeight() / 2) + y - (h / 2);
endY = (view.getHeight() / 2) + y + (h / 2);
} else {
// top
startY = y;
endY = y + h;
}

float tapX = motionEvent.getX();
float tapY = motionEvent.getY();

final boolean tapped = tapX >= startX && tapX <= endX &&
tapY >= startY && tapY <= endY;

return tapped && returnTapEvent("touch", msg, data, callbackContext);
}
});
} else {
toast.getView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return motionEvent.getAction() == MotionEvent.ACTION_DOWN && returnTapEvent("touch", msg, data, callbackContext);
}
});
}
// trigger show every 2500 ms for as long as the requested duration
_timer = new CountDownTimer(hideAfterMs, 2500) {
public void onTick(long millisUntilFinished) {
Expand Down