Related
I developed an android app for auto replying to Whatsapp. My app is perfect working for replying with text. But I am unable to send images in auto reply in background.
This activity is for managing notifications.
NotificationService.java
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.provider.ContactsContract;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.text.SpannableString;
import android.util.Log;
import android.widget.TextView;
import androidx.core.app.NotificationCompat;
import com.templatemela.whatsbot.model.Action;
import com.templatemela.whatsbot.model.AutoReply;
import com.templatemela.whatsbot.model.StatisticsReplyMsgListModel;
import com.templatemela.whatsbot.utilities.Const;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
public class NotificationService extends NotificationListenerService {
public static final String TAG = "Auto Reply";
private String autoReplyText;
private List<String> cntList;
private String contactType;
private long count = 0;
private List<String> getUserList;
private String headerText;
private String noMatch = "";
private SharedPreference preference;
private int replyTime;
private String sendMessage;
private TextView text;
private Uri string;
private Bitmap bitmap;
#Override
public void onListenerConnected() {
super.onListenerConnected();
Log.e(TAG, "Notification Listener Connected");
}
#Override
public void onCreate() {
super.onCreate();
preference = new SharedPreference(this);
count = preference.getFromPref_Long("Counter");
getUserList = new ArrayList();
cntList = new ArrayList();
Const.staticsReplyList = new ArrayList();
Const.contactList = new ArrayList();
}
#Override
public int onStartCommand(Intent intent, int i, int i2) {
Log.e("Service Class", "Service is started-----");
return Service.START_STICKY;
}
#Override
public void onNotificationRemoved(StatusBarNotification statusBarNotification) {
super.onNotificationRemoved(statusBarNotification);
Log.e("AUTO REPLY", "Notificationremoved");
}
#Override
public void onNotificationPosted(StatusBarNotification statusBarNotification) {
if (preference.getFromPref_Boolean("CheckedState")) {
boolean fromPref_Boolean = preference.getFromPref_Boolean("ScheduleTime");
Log.e("scheduleTime", fromPref_Boolean + ":::");
contactType = preference.getFromPref_String("ContactType");
Const.contactList = preference.getContactList("ContactList");
try {
if (Const.contactList.isEmpty()) {
Const.contactList = new ArrayList();
}
} catch (Exception unused) {
Const.contactList = new ArrayList();
}
Const.replyList = preference.getList("MessageList");
try {
if (Const.replyList.isEmpty()) {
Const.replyList = new ArrayList();
}
} catch (Exception unused2) {
Const.replyList = new ArrayList();
}
Const.staticsReplyList = preference.getReplyList("StaticsReplyList");
try {
if (Const.staticsReplyList.isEmpty()) {
Const.staticsReplyList = new ArrayList();
}
} catch (Exception e) {
Const.staticsReplyList = new ArrayList();
Log.e("StaticsList", e.getMessage());
}
String fromPref_String = preference.getFromPref_String("BoldHeaderText");
if (fromPref_String.isEmpty()) {
headerText = "*Auto Reply*\n\n";
} else if (fromPref_String.equals(" ")) {
headerText = fromPref_String;
} else {
headerText = "*" + fromPref_String + "*\n\n";
}
autoReplyText = headerText + preference.getFromPref_String("autoReplyText");
if (isScheduleTime(fromPref_Boolean)) {
Log.e("IS SCHEDULE TIME", isScheduleTime(fromPref_Boolean) + "::::");
cancelNotification(statusBarNotification.getKey());
final Action quickReplyAction = NotificationUtils.getQuickReplyAction(statusBarNotification.getNotification(), getPackageName());
Log.e("Action", quickReplyAction + "::Action:");
if (quickReplyAction == null) {
return;
}
if (statusBarNotification.getPackageName().equalsIgnoreCase("com.whatsapp")||statusBarNotification.getPackageName().equalsIgnoreCase("com.whatsapp.w4b"))
{
if (statusBarNotification.getPackageName().equalsIgnoreCase("com.whatsapp")&&preference.getFromPref_Boolean("WAState") ){
final String string = statusBarNotification.getNotification().extras.getString(NotificationCompat.EXTRA_TITLE);
Log.e("USERNAME", string + ":::");
final String string2 = statusBarNotification.getNotification().extras.getString(NotificationCompat.EXTRA_TEXT);
if (EveryOne(contactType) || ContactList(contactType, string) || ExceptContactList(contactType, string) || ExceptPhoneList(contactType, string)) {
Log.e("CONTACT TYPE", contactType + "::::");
if (string2 != null && !string2.equalsIgnoreCase("📷 Photo") && isGroupMessageAndReplyAllowed(statusBarNotification) && NotificationUtils.isNewNotification(statusBarNotification) && selfName(statusBarNotification)) {
if (preference.getFromPref_Boolean("Immediately")) {
Log.e("Immediately", "True");
sendMsg(quickReplyAction, string2, string, string, bitmap);
} else if (preference.getFromPref_Boolean("Time")) {
Log.e("Time", "True");
String fromPref_String2 = preference.getFromPref_String("TimeofMsg");
String fromPref_String3 = preference.getFromPref_String("SpinTime");
if (fromPref_String3.equals("Minutes")) {
replyTime = Integer.valueOf(fromPref_String2).intValue() * 1000 * 60;
} else if (fromPref_String3.equals("Seconds")) {
replyTime = Integer.valueOf(fromPref_String2).intValue() * 1000;
}
Log.e("REPLY TIME", replyTime + ":::::");
new Handler().postDelayed(new Runnable() {
public void run() {
sendMsg(quickReplyAction, string2, string, string, bitmap);
}
}, (long) replyTime);
} else if (preference.getFromPref_Boolean("Once")) {
Log.e("Once", "True");
List<String> userList = preference.getUserList("UserList");
getUserList = userList;
try {
if (userList.isEmpty()) {
getUserList = new ArrayList();
}
} catch (Exception e2) {
Log.e("ONCE", e2.getMessage());
getUserList = new ArrayList();
}
if (getUserList.contains(string)) {
stopService(new Intent(getApplicationContext(), getClass()));
} else {
sendMsg(quickReplyAction, string2, string, string, bitmap);
}
} else {
Log.e("ELse", "True");
sendMsg(quickReplyAction, string2, string, string, bitmap);
}
}
}
}
if (statusBarNotification.getPackageName().equalsIgnoreCase("com.whatsapp.w4b")&&preference.getFromPref_Boolean("WBState")){
final String string = statusBarNotification.getNotification().extras.getString(NotificationCompat.EXTRA_TITLE);
Log.e("USERNAME", string + ":::");
final String string2 = statusBarNotification.getNotification().extras.getString(NotificationCompat.EXTRA_TEXT);
if (EveryOne(contactType) || ContactList(contactType, string) || ExceptContactList(contactType, string) || ExceptPhoneList(contactType, string)) {
Log.e("CONTACT TYPE", contactType + "::::");
if (string2 != null && !string2.equalsIgnoreCase("📷 Photo") && isGroupMessageAndReplyAllowed(statusBarNotification) && NotificationUtils.isNewNotification(statusBarNotification) && selfName(statusBarNotification)) {
if (preference.getFromPref_Boolean("Immediately")) {
Log.e("Immediately", "True");
sendMsg(quickReplyAction, string2, string, string, bitmap);
} else if (preference.getFromPref_Boolean("Time")) {
Log.e("Time", "True");
String fromPref_String2 = preference.getFromPref_String("TimeofMsg");
String fromPref_String3 = preference.getFromPref_String("SpinTime");
if (fromPref_String3.equals("Minutes")) {
replyTime = Integer.valueOf(fromPref_String2).intValue() * 1000 * 60;
} else if (fromPref_String3.equals("Seconds")) {
replyTime = Integer.valueOf(fromPref_String2).intValue() * 1000;
}
Log.e("REPLY TIME", replyTime + ":::::");
new Handler().postDelayed(new Runnable() {
public void run() {
sendMsg(quickReplyAction, string2, string, string, bitmap);
}
}, (long) replyTime);
} else if (preference.getFromPref_Boolean("Once")) {
Log.e("Once", "True");
List<String> userList = preference.getUserList("UserList");
getUserList = userList;
try {
if (userList.isEmpty()) {
getUserList = new ArrayList();
}
} catch (Exception e2) {
Log.e("ONCE", e2.getMessage());
getUserList = new ArrayList();
}
if (getUserList.contains(string)) {
stopService(new Intent(getApplicationContext(), getClass()));
} else {
sendMsg(quickReplyAction, string2, string, string, bitmap);
}
} else {
Log.e("ELse", "True");
sendMsg(quickReplyAction, string2, string, string, bitmap);
}
}
}
}
}
else {
Log.e(TAG, "not success");
}
}
}
}
#Override
public void onTaskRemoved(Intent intent) {
super.onTaskRemoved(intent);
Intent intent2 = new Intent(getApplicationContext(), getClass());
intent2.setPackage(getPackageName());
startService(intent2);
}
public void sendMsg(Action action, String str, String str2, String tetStr, Bitmap image4) {
String str3;
String str4;
Intent phonebookIntent = new Intent();
image4 = BitmapFactory.decodeResource(getResources(), R.drawable.msg_vector);
boolean z;
try {
Log.e("RECEIVE MSG", str);
Const.replyList.isEmpty();
boolean z2 = false;
boolean isContain=preference.getFromPref_Boolean("contain");
boolean isExtra=preference.getFromPref_Boolean("exact");
Log.e("rules","contain=="+String.valueOf(isContain)+" "+"exact==="+String.valueOf(isExtra));
boolean fromPref_Boolean = preference.getFromPref_Boolean("customAutoReplySwitch");
Log.e("CustomReply", fromPref_Boolean + ":::");
Iterator<AutoReply> it = Const.replyList.iterator();
while (true) {
if (!it.hasNext()) {
str3 = "autoReplyText";
str4 = "Counter";
z = true;
break;
}
AutoReply next = it.next();
if (isContain?next.getReceiveMsg().equalsIgnoreCase(str)||str.contains(next.getReceiveMsg()):next.getReceiveMsg().equalsIgnoreCase(str)) {
if (fromPref_Boolean) {
long currentTimeMillis = System.currentTimeMillis();
Context applicationContext = getApplicationContext();
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.msg_vector);
action.sendReply(applicationContext, headerText + next.getSendMsg(), "okay kar", bitmap);
stopService(new Intent(getApplicationContext(), getClass()));
long j = count + 1;
count = j;
preference .addToPref_Long("Counter", j);
sendMessage = next.getSendMsg();
List<StatisticsReplyMsgListModel> list = Const.staticsReplyList;
str3 = "autoReplyText";
str4 = "Counter";
z = true;
StatisticsReplyMsgListModel statisticsReplyMsgListModel = new StatisticsReplyMsgListModel((int) count, next.getSendMsg(), str2, currentTimeMillis);
list.add(statisticsReplyMsgListModel);
preference.setReplyList("StaticsReplyList", Const.staticsReplyList);
if (preference.getFromPref_Boolean("Once") && !Const.userList.contains(str2)) {
Const.userList.add(str2);
preference.setUserList("UserList", Const.userList);
}
} else {
str3 = "autoReplyText";
str4 = "Counter";
z = true;
stopService(new Intent(getApplicationContext(), getClass()));
}
z2 = true;
}
}
if (!z2 && preference.getFromPref_Boolean("autoReplyTextSwitch") == z) {
Log.e(TAG, "Else");
if (autoReplyText.equals(str)) {
Log.e("Equal", "Message");
stopService(new Intent(getApplicationContext(), getClass()));
}
long currentTimeMillis2 = System.currentTimeMillis();
action.sendReply(getApplicationContext(), autoReplyText, "okay kar bhai", bitmap );
stopService(new Intent(getApplicationContext(), getClass()));
String str7 = str3;
sendMessage = preference.getFromPref_String(str7);
long j2 = count + 1;
count = j2;
preference.addToPref_Long(str4, j2);
Const.staticsReplyList.add(new StatisticsReplyMsgListModel((int) count, preference.getFromPref_String(str7), str2, currentTimeMillis2));
preference.setReplyList("StaticsReplyList", Const.staticsReplyList);
if (preference.getFromPref_Boolean("Once") == z && !Const.userList.contains(str2)) {
Const.userList.add(str2);
preference.setUserList("UserList", Const.userList);
}
}
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
Log.e("Replied Message Error", e.getMessage());
}
}
private Intent getIntent() {
return null;
}
private boolean selfName(StatusBarNotification statusBarNotification) {
String title = NotificationUtils.getTitle(statusBarNotification);
return title == null || !title.equalsIgnoreCase(statusBarNotification.getNotification().extras.getString(NotificationCompat.EXTRA_SELF_DISPLAY_NAME));
}
private boolean isGroupMessageAndReplyAllowed(StatusBarNotification statusBarNotification) {
String titleRaw = NotificationUtils.getTitleRaw(statusBarNotification);
SpannableString valueOf = SpannableString.valueOf("" + statusBarNotification.getNotification().extras.get(NotificationCompat.EXTRA_TEXT));
boolean z = titleRaw != null && (": ".contains(titleRaw) || "# ".contains(titleRaw)) && valueOf != null && valueOf.toString().contains("📷");
if (!statusBarNotification.getNotification().extras.getBoolean(NotificationCompat.EXTRA_IS_GROUP_CONVERSATION)) {
return !z;
}
boolean fromPref_Boolean = preference.getFromPref_Boolean("GroupEnable");
Log.e("Group Message", "Return" + fromPref_Boolean);
return fromPref_Boolean;
}
private boolean EveryOne(String str) {
return str.equals("Everyone") || str.equals("");
}
private boolean ContactList(String str, String str2) {
return str.equals("ContactList") && Const.contactList.contains(str2);
}
private boolean ExceptContactList(String str, String str2) {
return str.equals("ExceptContList") && !Const.contactList.contains(str2);
}
#SuppressLint("Range")
private boolean ExceptPhoneList(String str, String str2) {
if (!str.equals("ExceptPhoneList")) {
return false;
}
Cursor query = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, (String[]) null, (String) null, (String[]) null, "display_name ASC");
while (query.moveToNext()) {
cntList.add(query.getString(query.getColumnIndex("display_name")));
}
query.close();
return !cntList.contains(str2);
}
private boolean isScheduleTime(boolean z) {
if (z) {
try {
Calendar instance = Calendar.getInstance();
String fromPref_String = preference.getFromPref_String("StartTime");
String fromPref_String2 = preference.getFromPref_String("EndTime");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm a");
Date parse = simpleDateFormat.parse(simpleDateFormat.format(instance.getTime()));
Date parse2 = simpleDateFormat.parse(fromPref_String);
Date parse3 = simpleDateFormat.parse(fromPref_String2);
if (!parse.after(parse2) || !parse.before(parse3)) {
return false;
}
return true;
} catch (ParseException e) {
e.printStackTrace();
Log.e("CURRENTTIME", e.getMessage());
}
}
return true;
}
}
This is action activity that is sending reply in background.
Action.java
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.core.app.RemoteInput;
import com.templatemela.whatsbot.NotificationService;
import com.templatemela.whatsbot.R;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.Iterator;
public class Action implements Parcelable {
public static final Creator CREATOR = new Creator() {
public Action createFromParcel(Parcel parcel) {
return new Action(parcel);
}
public Action[] newArray(int i) {
return new Action[i];
}
};
private final boolean isQuickReply;
private final PendingIntent p;
private final String packageName;
private final ArrayList<RemoteInputParcel> remoteInputs;
private final String text;
private final Uri imageUri = Uri.parse(Environment.getExternalStorageDirectory().toString() + "/AwakiFolder/" + "aifile" + ".jpeg");
public int describeContents() {
return 0;
}
public Action(Parcel parcel) {
ArrayList<RemoteInputParcel> arrayList = new ArrayList<>();
remoteInputs = arrayList;
text = parcel.readString();
packageName = parcel.readString();
p = (PendingIntent) parcel.readParcelable(PendingIntent.class.getClassLoader());
isQuickReply = parcel.readByte() != 0;
parcel.readTypedList(arrayList, RemoteInputParcel.CREATOR);
}
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(text);
parcel.writeString(packageName);
parcel.writeParcelable(p, i);
parcel.writeByte(isQuickReply ? (byte) 1 : 0);
parcel.writeTypedList(remoteInputs);
}
public Action(String str, String str2, PendingIntent pendingIntent, RemoteInput remoteInput, boolean z) {
ArrayList<RemoteInputParcel> arrayList = new ArrayList<>();
remoteInputs = arrayList;
text = str;
packageName = str2;
p = pendingIntent;
isQuickReply = z;
arrayList.add(new RemoteInputParcel(remoteInput));
}
public Action(NotificationCompat.Action action, String str, boolean z) {
remoteInputs = new ArrayList<>();
text = action.title.toString();
packageName = str;
p = action.actionIntent;
if (action.getRemoteInputs() != null) {
for (RemoteInput remoteInputParcel : action.getRemoteInputs()) {
remoteInputs.add(new RemoteInputParcel(remoteInputParcel));
}
}
isQuickReply = z;
}
public void sendReply(Context context, String str, String tetStr, Bitmap bitmap) throws PendingIntent.CanceledException {
Log.e("AutoReply", "inside sendReply");
Intent intent = new Intent();
Bundle bundle = new Bundle();
Bitmap image4 = BitmapFactory.decodeResource(getResources(), R.drawable.msg_vector);
bundle.putParcelable( "image/png", image4);
String both = imageUri+ str + tetStr;
ArrayList arrayList = new ArrayList();
Iterator<RemoteInputParcel> it = remoteInputs.iterator();
while (it.hasNext()) {
RemoteInputParcel next = it.next();
Log.e("", "RemoteInput: " + next.getLabel());
intent.setAction(Intent.ACTION_SEND);
intent.setPackage("com.whatsapp");
intent.putExtra(Intent.EXTRA_STREAM, imageUri);
intent.setType("");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
bundle.putCharSequence(next.getResultKey(), both);
RemoteInput.Builder builder = new RemoteInput.Builder(next.getResultKey());
builder.setLabel(next.getLabel());
builder.setChoices(next.getChoices());
builder.setAllowFreeFormInput(next.isAllowFreeFormInput());
builder.addExtras(next.getExtras());
arrayList.add(builder.build());
}
RemoteInput.addResultsToIntent((RemoteInput[]) arrayList.toArray(new RemoteInput[arrayList.size()]), intent, bundle);
p.send(context, 0, intent);
context.stopService(new Intent(context, NotificationService.class));
}
private Resources getResources() {
return null;
}
public ArrayList<RemoteInputParcel> getRemoteInputs() {
return remoteInputs;
}
public boolean isQuickReply() {
return isQuickReply;
}
public String getText() {
return text;
}
public PendingIntent getQuickReplyIntent() {
if (isQuickReply) {
return p;
}
return null;
}
public String getPackageName() {
return packageName;
}
}
I am using this TextWatcher for .addtextOnChangeListener, the output of the string is ex: "123,456,77" i want it to be "123.456,77" if i use the replace method on "et" in the "afterTextChanged" method, the number isn't even formatting. With the code below the listener works and everything, i just don't know how to replace the "," with "." until the decimals.
If you think to just change the pattern ("###,##0,00") it doesn't work
This is the TextWatcher I have for the EditText
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Locale;
public class NumberTextWatcher implements TextWatcher {
private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText et;
public NumberTextWatcher(EditText et)
{
df = new DecimalFormat("###,##0,00");
df.setDecimalSeparatorAlwaysShown(true);
dfnd = new DecimalFormat("###,##0,00");
this.et = et;
hasFractionalPart = false;
}
#SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";
#Override
public void afterTextChanged(Editable s)
{
et.removeTextChangedListener(this);
try {
int inilen, endlen;
inilen = et.getText().length();
String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
Number n = df.parse(v);
int cp = et.getSelectionStart();
if (hasFractionalPart) {
et.setText(df.format(n));
} else {
et.setText(dfnd.format(n));
}
endlen = et.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= et.getText().length()) {
et.setSelection(sel);
} else {
// place cursor at the end?
et.setSelection(et.getText().length() - 1);
}
} catch (NumberFormatException nfe) {
// do nothing?
} catch (ParseException e) {
// do nothing?
}
et.addTextChangedListener(this);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int index = s.toString().indexOf(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator()));
int trailingZeroCount = 0;
if (index > -1)
{
for (index++; index < s.length(); index++) {
if (s.charAt(index) == '0')
trailingZeroCount++;
else {
trailingZeroCount = 0;
}
}
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
{
if (s.toString().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator())))
{
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
}
}
}
Use this:
DecimalFormat decimalFormat=new DecimalFormat();
DecimalFormatSymbols decimalFormatSymbols=DecimalFormatSymbols.getInstance();
decimalFormatSymbols.setDecimalSeparator(',');
decimalFormatSymbols.setGroupingSeparator('.');
decimalFormat.setDecimalFormatSymbols(decimalFormatSymbols);
String formattedNumber=decimalFormat.format(123456.78);// prints 123.456,78
I'm trying make a serial IEC communication for Android and there I need check if a device send some data. I started a timer on the begin of communication a reset it when some data comes. Reset on incoming data is working, but cancelling before data is saved not working. I can't understand why.
Here is my MainActivity.java code
package cz.trisko.jan.amr;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbDeviceConnection;
import com.felhr.usbserial.UsbSerialDevice;
import com.felhr.usbserial.UsbSerialInterface;
import static java.lang.Integer.parseInt;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "AMR";
private UsbManager usbManager;
private UsbDevice device;
private UsbDeviceConnection connection;
private UsbSerialDevice serialDevice;
private String handshake = "/?!\r\n";
MediaPlayer errSnd; // chyba
MediaPlayer bdSnd; // registry
MediaPlayer lpSnd; // profil
MediaPlayer infoSnd; // info
ProgressBar progressBar;
RadioGroup rg;
RadioButton rb;
TextView registryNam; // textview pro nazev registru
TextView registryVal; // textview pro hodnotu registru a stavova hlaseni
String regName; // nazev registru
String regValue; // hodnota registru
boolean readRegs; // typy odectu
boolean readLastMonth;
boolean readThisMonth;
Calendar calendar = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat("yyMMdd");
int currentMonth;
int currentYear;
Date today;
Date tomorrow;
String tomorrowAsString;
String lastMonthInterval;
String thisMonthInterval;
String lpInterval;
int startMonth;
int startYear;
int endMonth;
int endYear;
private static final Pattern communicationSpeedIndexPattern
= Pattern.compile("^.*(/)(\\w{3})(\\d{1})(.*)$"); // [0] - komplet, [1] - /, [2] - vyrobce, [3] - baudrate, [4] - model
private static final Pattern CRpat = Pattern.compile("^(\r)$"); // CR
private static final Pattern LFpat = Pattern.compile("^(\n)$"); // LF
private static final Pattern STXpat = Pattern.compile("^(\\x02)$"); // STX
private static final Pattern ETXpat = Pattern.compile("^(\\x03)$"); // ETX
private static final Pattern DLEpat = Pattern.compile("^(\\x10)$"); // DLE
private static final Pattern ETBpat = Pattern.compile("^(\\x17)$"); // ETB
private static final Pattern regNameValuePattern
= Pattern.compile("([^\\(\\)]*)\\(([^\\(\\)]*)\\)"); // [0] - komplet, [1] - Registr, [2] - hodnota
boolean CRLF; // konec radku prijimanych dat
boolean isCR;
boolean isLF;
boolean firstLine;
boolean isETX;
String data; // prichozi data na USB
String dataLine; // radek s prichozimi daty
String tmpDataLine; // radek prichozich dat, ktery je zpracovavan po znacich
//String tmpDataLine2; // radek prichozich dat, ktery je zpracovavan po znacich
String buffer; // buffer pro vystup do souboru
//String tmpBuffer = "";
int dataLength;
private int[] baudrateList = {300, 600, 1200, 2400, 4800, 9600, 19200};
String meterId;
Pattern meterIdPattern = Pattern.compile("0\\.0\\.0|0\\.0|0|C\\.1|C\\.1\\.0|0\\.0\\.1|0\\.0\\.2|0\\.0\\.3|C\\.1\\.1|C\\.90\\.1");
int speed; // komunikacni rychlost seriove link - pocatek 300 Bd
int readedSpeed; // maximalni komunikacni rychlost v zarizeni
String askData; // retezec pro odeslani pozadavku dat
char valueSOHchar = 0x01; // SOH
String SOH = String.valueOf(valueSOHchar);
char valueSTXchar = 0x02; // STX
String STX = String.valueOf(valueSTXchar);
char valueETXchar = 0x03; // ETX
String ETX = String.valueOf(valueETXchar);
char valueACKchar = 0x06; // ACK
String ACK = String.valueOf(valueACKchar);
char valueDLEchar = 0x10; // DLE
String DLE = String.valueOf(valueDLEchar);
char valueNAKchar = 0x15; // NAK
String NAK = String.valueOf(valueNAKchar);
char valueETBchar = 0x17; // ETB
String ETB = String.valueOf(valueETBchar);
int etxIndex; // pocet prichozich ETX
boolean registryReceived;
String filename;
String filepath;
File myExternalFile;
boolean successCreateDir;
boolean outputDirOk;
boolean meterEchoes;
//String debugStringValue = "";
long startTime;
long currentTime;
long timeLeft;
MyTimer responseTimeCounter;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "-------------- APP START --------------");
setDates(); // nastavime intervaly odectu
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progressBar);
errSnd = MediaPlayer.create(this, R.raw.wrong);
bdSnd = MediaPlayer.create(this, R.raw.case_closed);
lpSnd = MediaPlayer.create(this, R.raw.beep_beep_beep);
infoSnd = MediaPlayer.create(this, R.raw.smack_that_bitch);
rg = findViewById(R.id.readoutType);
registryNam = findViewById(R.id.registryNames);
registryVal = findViewById(R.id.registryValues);
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
// casovac pro prodlevu na vstupu
responseTimeCounter = new MyTimer(5000,1);
}
public void setDefaultValues() {
// nastaveni vychozich polozek pro odecet
regName = "";
regValue = "";
readRegs = false;
readLastMonth = false;
readThisMonth = false;
CRLF = false; // konec radku prijimanych dat
isCR = false;
isLF = false;
firstLine = true; // nacitani prvniho radku dat
isETX = false;
data = null; // prichozi data na USB
dataLine = ""; // radek s prichozimi daty
tmpDataLine = ""; // radek prichozich dat, ktery je zpracovavan po znacich
buffer = ""; // buffer pro vystup do souboru
dataLength = 0;
meterId = "";
speed = 300; // komunikacni rychlost - pocatek 300 Bd
readedSpeed = 0; // index komunikacni rychlosti nacteny ze zarizeni
askData = ""; // retezec pro odeslani pozadavku dat
tvSetContent(registryNam, "");
tvSetContent(registryVal, "");
meterEchoes = false;
registryReceived = false;
etxIndex = 0;
}
public String toHex(String arg) {
return String.format("%012x", new BigInteger(1, arg.getBytes()));
}
public void setDates() {
// vypocet dat pro interval odectu
String leadingStartMonthZero = "";
String leadingEndMonthZero = "";
String startDate;
String endDate;
currentMonth = calendar.get(Calendar.MONTH) + 1;
currentYear = calendar.get(Calendar.YEAR) % 100;
// dnes / today
today = calendar.getTime();
// zitra / tomorrow
calendar.add(Calendar.DAY_OF_YEAR, 1);
tomorrow = calendar.getTime();
dateFormat = new SimpleDateFormat("yyMMdd");
tomorrowAsString = dateFormat.format(tomorrow);
// interval pro odecet pri vymene - od 1. tohoto mesice do zitra / this month
if (currentMonth < 10) {
leadingStartMonthZero = "0";
}
startDate = "0" + currentYear + leadingStartMonthZero + currentMonth + "010000";
endDate = "0" + tomorrowAsString + "0000";
thisMonthInterval = startDate + ";" + endDate;
// interval pro std odecet - od 1. minuleho mesice do 1. tohoto mesice / last month
startYear = currentYear;
endYear = currentYear;
startMonth = currentMonth - 1;
endMonth = currentMonth;
if (currentMonth == 1) {
startYear = currentYear - 1;
startMonth = 12;
endYear = currentYear;
endMonth = currentMonth;
}
if (endMonth < 10) {
leadingEndMonthZero = "0";
}
if (startMonth < 10) {
leadingStartMonthZero = "0";
}
startDate = "0" + startYear + leadingStartMonthZero + startMonth + "010000";
endDate = "0" + endYear + leadingEndMonthZero + endMonth + "010000";
lastMonthInterval = startDate + ";" + endDate;
}
private boolean checkUSBdevice() {
boolean pass = false;
Map<String, UsbDevice> deviceList = usbManager.getDeviceList();
if (deviceList.isEmpty()) {
pass = false;
} else {
for (Map.Entry<String, UsbDevice> entry : deviceList.entrySet()) {
device = entry.getValue();
if (usbManager.hasPermission(device)) {
Log.d(TAG, "USB has permission");
pass = true;
} else {
Toast.makeText(getApplicationContext(), "Není oprávnění pro přístup k USB zařízení", Toast.LENGTH_LONG).show();
errSnd.start(); // chck OK
Log.d(TAG, "USB have not permission");
pass = false;
}
}
}
if (pass) {
return true;
} else {
return false;
}
}
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
} else {
return false;
}
}
public void getReadoutType() {
String selectedtext = (String) rb.getText();
int radioButtonID = rg.getCheckedRadioButtonId();
View radioButton = rg.findViewById(radioButtonID);
int rbIndex = rg.indexOfChild(radioButton);
switch (rbIndex) {
case 0: // odecet jen registru
readRegs = true;
readLastMonth = false;
readThisMonth = false;
break;
case 1: // odecet registru a LP za minuly mesic
readRegs = true;
readLastMonth = true;
readThisMonth = false;
break;
case 2: // odecet registru a LP za tent mesic
readRegs = true;
readLastMonth = false;
readThisMonth = true;
break;
}
Log.d(TAG, "Index radiobuttonu: " + rbIndex + " - " + selectedtext);
Log.d(TAG, "readRegs = " + readRegs);
Log.d(TAG, "readLastMonth = " + readLastMonth);
Log.d(TAG, "readThisMonth = " + readThisMonth);
}
private void tvSetContent(TextView tv, CharSequence text) {
final TextView ftv = tv;
final CharSequence ftext = text;
runOnUiThread(new Runnable() {
#Override public void run() {
ftv.setText(ftext);
}
});
}
public void getSpeed() throws InterruptedException {
// nacteni rychlostniho indexu z identifikacniho retezce / get device max speed
Matcher speedIndex = communicationSpeedIndexPattern.matcher(tmpDataLine);
Log.d(TAG, "getSpeed processing");
if (speedIndex.find()) {
readedSpeed = parseInt(speedIndex.group(3));
Log.d(TAG, "Speed index " + readedSpeed);
speed = baudrateList[readedSpeed];
Log.d(TAG, "New speed will be " + speed + " Bd");
tvSetContent(registryVal, "Komunikace na " + speed + " Bd");
if (readThisMonth || readLastMonth) {
askData = ACK + "0" + readedSpeed + "1\r\n";
Log.d(TAG, "Profile ACK");
} else {
askData = ACK + "0" + readedSpeed + "0\r\n";
Log.d(TAG, "Registry ACK");
}
Log.d(TAG, "Waiting 300 ms");
Thread.sleep(300);
Log.d(TAG, "Send to serial " + askData + "|" + toHex(askData));
serialDevice.write(askData.getBytes());
Log.d(TAG, "Waiting 300 ms");
Thread.sleep(300);
Log.d(TAG, "Serial line switching to " + speed + " Bd");
serialDevice.setBaudRate(speed);
Log.d(TAG, "Speed switched");
} else {
Log.d(TAG, "No speed index found");
}
}
public void showValues() {
// rozlozeni na nazev a hodnotu registru / show registry name and value
Matcher regNamVal = regNameValuePattern.matcher(tmpDataLine);
if (regNamVal.find()) {
regName = regNamVal.group(1).toString();
regValue = regNamVal.group(2).toString();
tvSetContent(registryNam, regName);
tvSetContent(registryVal, regValue);
if (meterId == "") {
// hledame cislo elektromeru / looking for meter ID
Matcher metId = meterIdPattern.matcher(regName);
if (metId.matches()) {
meterId = regValue;
Log.d(TAG, "meterId = " + meterId);
}
}
} else {
tvSetContent(registryVal, tmpDataLine);
Log.d(TAG, "Pickup registry and value fail");
tvSetContent(registryNam, "");
tvSetContent(registryVal, "");
}
}
public void chkDirectories() {
// kontrola/vytvoreni adresaru pro vystup a konfiguraci / chck output dir
outputDirOk = false;
File dirDocuments = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
String dirDocumentsPath = dirDocuments.getPath();
File dirAmr = new File(dirDocumentsPath+"/AMR");
filepath = dirAmr.getAbsolutePath();
if (!dirAmr.exists()) {
// adresar pro vystup neexistuje, vytvorime ho
successCreateDir = dirAmr.mkdir();
if (successCreateDir) {
Log.d(TAG,"Directory " + filepath + " created successfully");
} else {
Log.d(TAG,"Creating od directory " + filepath + " FAILED!");
}
} else {
Log.d(TAG,"AMR directory OK");
File dirReadouts = new File(filepath + "/Readouts");
filepath = dirReadouts.getAbsolutePath();
if (!dirReadouts.exists()) {
successCreateDir = dirReadouts.mkdir();
if (successCreateDir) {
outputDirOk = true;
Log.d(TAG,"Directory " + filepath + " created successfully");
} else {
Log.d(TAG,"Creating od directory " + filepath + " FAILED!");
}
} else {
outputDirOk = true;
Log.d(TAG,"Readouts directory OK");
}
}
Log.d(TAG,"Readouts output directory: " + filepath);
}
public void saveFile() {
// ukladame na SD kartu / saving to SD
try {
tvSetContent(registryVal, "Ukládám data" + filename);
Log.d(TAG, "Timer pred ukladanim: " + timeLeft);
responseTimeCounter.cancel(); // zastavime casovac odezvy elektromeru / cancel timer
/* THIS CANCEL DID NOT WORKING - WHY???????????????????????? */
Log.d(TAG, "Timer po jeho preruseni: " + timeLeft);
filename = meterId.trim() + ".rd";
myExternalFile = new File(filepath, filename);
Log.d(TAG,"Output stream start " + myExternalFile.getAbsolutePath());
FileOutputStream fos = new FileOutputStream(myExternalFile);
Log.d(TAG, "Start writting data");
fos.write(buffer.getBytes());
Log.d(TAG, "Closing file - saved to " + myExternalFile.getAbsolutePath());
fos.close();
tvSetContent(registryVal, "Uloženo do " + filename);
Log.d(TAG, "Closing serial communication");
connection.close();
bdSnd.start();
} catch (IOException e) {
e.printStackTrace();
}
// ukladame do interniho uloziste / saving in to internal storage
/*
try {
filename = meterId.trim() + ".rd";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new
File(getFilesDir()+File.separator+filename)));
bufferedWriter.write(buffer);
bufferedWriter.close();
tvSetContent(registryVal, "Uloženo do " + filename);
//setDefaultValues();
bdSnd.start();
} catch (IOException e) {
e.printStackTrace();
}
*/
}
public void processData() throws InterruptedException {
// prochazeni prichozich dat po znacich
for (dataLength = 0; dataLength < data.length(); dataLength++) {
//Process char
char c = data.charAt(dataLength);
String charToString = c + "";
Log.d(TAG, "R <- " + charToString + " hex:" + toHex(charToString));
Matcher incomingOneChar = STXpat.matcher(charToString);
if (incomingOneChar.matches()) {
Log.d(TAG, "\n\nSTX found - dropping it\n\n");
charToString = ""; // drop STX char
}
Matcher nextIncomingOneChar = ETXpat.matcher(charToString);
if (nextIncomingOneChar.matches()) {
Log.d(TAG, "\n\nETX found - dropping it and next data\n\n");
charToString = ""; // drop ETX char a vsechno za tim
isETX = true;
etxIndex += 1;
dataLength = data.length(); // ukonci cyklus driv
registryReceived = true;
responseTimeCounter.cancel();
saveFile();
}
// je prichozi znak CR?
Matcher incomingCharCR = CRpat.matcher(charToString);
if (incomingCharCR.matches()) {
//tvAppend(textView, "CR");
isCR = true;
//Log.d(TAG, "CR");
} else {
// je prichozi znak LF?
Matcher incomingCharLF = LFpat.matcher(charToString);
if (incomingCharLF.matches()) {
//tvAppend(textView, "LF");
isLF = true;
//Log.d(TAG, "LF");
}
}
tmpDataLine += charToString; // pridame nacteny znak do radku
// reset casovace na vstupu
responseTimeCounter.cancel();
responseTimeCounter.start();
/* THIS TIMER RESET WORKING */
if (isCR && isLF) {
// je konec radku?
CRLF = true;
}
if (CRLF) {
// mame cely radek, zpracujeme jej / processing completed data row
//Log.d(TAG, "CRLF");
if (firstLine) {
// v prvnim radku je identifikace s indexem rychlosti
Log.d(TAG, "First line completed - " + tmpDataLine);
if (tmpDataLine.equals(handshake)) {
// test na echo
meterEchoes = true;
tmpDataLine = ""; // drop radku s echem
Log.d(TAG, "Meter send echo");
} else {
getSpeed();
firstLine = false;
Log.d(TAG, "First line operated");
}
}
if (meterEchoes && tmpDataLine.equals(askData)) {
// pokud elektromer vraci echo, drop data
tmpDataLine = "";
}
buffer += tmpDataLine;
Log.d(TAG, "tmpDataLine: " + tmpDataLine);
if (!tmpDataLine.equals("")) {
// pokud nejaka data jsou, zobraz je
showValues();
}
dataLine = ""; // vymazeme obsah radku
CRLF = false;
isCR = false;
isLF = false;
tmpDataLine = "";
}
}
}
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
//Defining a Callback which triggers whenever data is read.
//#TargetApi(Build.VERSION_CODES.KITKAT)
//#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onReceivedData(byte[] arg0) {
//String data = null;
try {
data = new String(arg0);
//Log.d(TAG, "R <- " + data);
Log.d(TAG, "Timer pri vstupu dat na USB: " + timeLeft);
processData();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
private void startSerialConnection(UsbDevice device) {
Log.i(TAG, "Ready to open USB device connection");
connection = usbManager.openDevice(device);
serialDevice = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialDevice != null) {
if (serialDevice.open()) {
serialDevice.setBaudRate(speed);
serialDevice.setDataBits(UsbSerialInterface.DATA_BITS_7);
serialDevice.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialDevice.setParity(UsbSerialInterface.PARITY_EVEN);
serialDevice.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
Log.d(TAG, "mCallback Called");
serialDevice.read(mCallback);
Log.d(TAG, "Serial connection opened at " + speed + " Bd");
} else {
Log.d(TAG, "Cannot open serial connection");
tvSetContent(registryVal, "Nefunguje COM port");
Toast.makeText(getApplicationContext(), "Nefunguje COM port", Toast.LENGTH_LONG).show();
infoSnd.start();
}
} else {
Log.d(TAG, "Could not create USB Serial Device");
}
}
public class MyTimer extends CountDownTimer {
public MyTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
tvSetContent(registryNam, String.valueOf(millisUntilFinished));
}
#Override
public void onFinish() {
errSnd.start();
tvSetContent(registryVal, "Elektroměr neodpovídá"); // device did not respond
connection.close();
}
}
public void doReadout(View view) {
setDefaultValues();
chkDirectories();
int radioButtonId = rg.getCheckedRadioButtonId();
rb = findViewById(radioButtonId);
Log.d(TAG, "Do Readout pressed");
if (!isExternalStorageWritable()) {
Toast.makeText(getApplicationContext(), "Externí úložiště není k dispozici.", Toast.LENGTH_LONG).show();
errSnd.start();
}
// pro zapis na SD kartu
if (!outputDirOk) {
Toast.makeText(getApplicationContext(), "Adresář pro výstup není k dispozici.", Toast.LENGTH_LONG).show();
errSnd.start();
}
if (checkUSBdevice() && isExternalStorageWritable() && outputDirOk) {
startSerialConnection(device);
if (device != null) {
//tvSetContent(registryVal, "Sériová komunikace spuštěna");
Log.d(TAG, "Serial communication opened");
} else {
Log.d(TAG, "Serial communication opening FAIL");
}
if (rb == null) {
Toast.makeText(getApplicationContext(), "Není vybrán typ odečtu!", Toast.LENGTH_LONG).show();
Log.d(TAG, "No readout type selected");
errSnd.start();
} else {
getReadoutType();
tvSetContent(registryVal, "Posílam handshake");
serialDevice.write(handshake.getBytes());
Log.d(TAG, "Handshake sent " + toHex(handshake));
responseTimeCounter.start();
Log.d(TAG, "Response timer started");
}
} else {
// nepripojene USB nedelame nic
errSnd.start();
Toast.makeText(getApplicationContext(), "Není připojena USB optická sonda." ,Toast.LENGTH_LONG).show();
Log.d(TAG, "No USB device connected");
}
}
}
It depends whether you want your override of onFinish() to be called - generally it is not called on cancel() (but might be called on start()) so if you want the connection closed, call onFinish() after cancel()
I found the reason, why a timer did not want to be cancelled. There is .cancel() and .start() called in wrong place. They are called in cycle where is input processed char by char and there is too many cancels and starts in short time and that probably confused the timer. Moving timer restart out of this cycle solved my problem.
I have a DecimalFormat with the following pattern "#,###.###"
But when I want to type for example 50.05 it does not allow to, as I parse the string to number every time a text changes and when I call
df.parse("50.0");
it returns 50. and cuts the 0
Any ideas what can I do to be able to type numbers like 50.05 ?
The full code of my class is presented below. Sorry if it is too verbose:
private class NumberTextWatcher implements TextWatcher {
#SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";
private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText et;
NumberTextWatcher(EditText et) {
df = (DecimalFormat) DecimalFormat.getInstance(Locale.ENGLISH);
df.applyLocalizedPattern(hasThousandSeparator ? "#,###.###" : "####.###");
df.setDecimalSeparatorAlwaysShown(true);
df.setMaximumFractionDigits(maxDecimal);
dfnd = (DecimalFormat) DecimalFormat.getInstance(Locale.ENGLISH);
dfnd.applyLocalizedPattern(hasThousandSeparator ? "#,###" : "####");
dfnd.setMaximumFractionDigits(maxDecimal);
this.et = et;
hasFractionalPart = false;
}
#Override
public void afterTextChanged(Editable s) {
et.removeTextChangedListener(this);
try {
int inilen, endlen;
inilen = et.getText().length();
String sign = hasSign ? s.toString().startsWith("-") ? "-" : "+" : null;
String sStr = hasSignAttached(s) ? s.toString().substring(1) : s.toString();
String v = sStr.replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
if(v.length() == 0){
return;
}
if(hasFractionalPart){
String[] vSplit = v.split("\\.");
String intStr = vSplit[0];
String decStr = vSplit.length > 1 ? vSplit[1] : "";
if(intStr.length() > maxNumbers)
intStr = intStr.substring(0, maxNumbers);
if(decStr.length() > maxDecimal)
decStr = decStr.substring(0, maxDecimal);
v = String.format("%s.%s", intStr, decStr);
} else {
if(v.length() > maxNumbers)
v = v.substring(0, maxNumbers);
}
Number n = df.parse(v);
int cp = et.getSelectionStart();
String formatted;
if (hasFractionalPart) {
formatted = df.format(n);
} else {
formatted = dfnd.format(n);
}
et.setText(hasSign ? String.format("%s%s", sign, formatted) : formatted);
endlen = et.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= et.getText().length()) {
et.setSelection(sel);
} else {
// place cursor at the end?
et.setSelection(et.getText().length() - 1);
}
} catch (Exception e) {
ExceptionTracker.trackException(e);
} finally {
et.addTextChangedListener(this);
}
}
private boolean hasSignAttached(Editable s){
return s.toString().startsWith("+") || s.toString().startsWith("-");
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if(hasSign && start == 1 && count == 1){
et.setText("");
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasFractionalPart = s.toString().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator()));
}
}
this code solves the problem:
import java.text.DecimalFormat;
public class DecimalFormatExample {
public static void main(String[] args) {
DecimalFormat dformat = new DecimalFormat("#,###.###");
dformat.setMinimumFractionDigits(1);
String someNumber = "50.05";
Double someNumberDouble = Double.valueOf(someNumber);
System.out.println(dformat.format(someNumberDouble)); // 50.05
someNumber = "50.0";
someNumberDouble = Double.valueOf(someNumber);
System.out.println(dformat.format(someNumberDouble)); // 50.0
}
}
Ok, I have done a small hack to fix this. May be it will help someone in the future, or someone will suggest a better solution.
So I added the following checks:
boolean decHasZeroAtEnd = false;
.......
if(decStr.endsWith("0")){
decHasZeroAtEnd = true;
}
.......
if(decHasZeroAtEnd){
decHasZeroAtEnd = false;
formatted = String.format("%s0", formatted);
}
And the whole code is the following:
private class NumberTextWatcher implements TextWatcher {
#SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";
private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText et;
NumberTextWatcher(EditText et) {
df = (DecimalFormat) DecimalFormat.getInstance(Locale.ENGLISH);
df.applyLocalizedPattern(hasThousandSeparator ? "#,###.###" : "####.###");
df.setDecimalSeparatorAlwaysShown(true);
df.setMaximumFractionDigits(maxDecimal);
dfnd = (DecimalFormat) DecimalFormat.getInstance(Locale.ENGLISH);
dfnd.applyLocalizedPattern(hasThousandSeparator ? "#,###" : "####");
dfnd.setMaximumFractionDigits(maxDecimal);
this.et = et;
hasFractionalPart = false;
}
#Override
public void afterTextChanged(Editable s) {
et.removeTextChangedListener(this);
try {
int inilen, endlen;
inilen = et.getText().length();
String sign = hasSign ? s.toString().startsWith("-") ? "-" : "+" : null;
String sStr = hasSignAttached(s) ? s.toString().substring(1) : s.toString();
String v = sStr.replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
if(v.length() == 0){
return;
}
boolean decHasZeroAtEnd = false;
if(hasFractionalPart){
String[] vSplit = v.split("\\.");
String intStr = vSplit[0];
String decStr = vSplit.length > 1 ? vSplit[1] : "";
if(intStr.length() > maxNumbers)
intStr = intStr.substring(0, maxNumbers);
if(decStr.length() > maxDecimal)
decStr = decStr.substring(0, maxDecimal);
if(decStr.endsWith("0")){
decHasZeroAtEnd = true;
}
v = String.format("%s.%s", intStr, decStr);
} else {
if(v.length() > maxNumbers)
v = v.substring(0, maxNumbers);
}
Number n = df.parse(v);
int cp = et.getSelectionStart();
String formatted;
if (hasFractionalPart) {
formatted = df.format(n);
} else {
formatted = dfnd.format(n);
}
if(decHasZeroAtEnd){
decHasZeroAtEnd = false;
formatted = String.format("%s0", formatted);
}
Log.d("testt", "formatted " + formatted);
et.setText(hasSign ? String.format("%s%s", sign, formatted) : formatted);
endlen = et.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= et.getText().length()) {
et.setSelection(sel);
} else {
// place cursor at the end?
et.setSelection(et.getText().length() - 1);
}
} catch (Exception e) {
ExceptionTracker.trackException(e);
} finally {
et.addTextChangedListener(this);
}
}
private boolean hasSignAttached(Editable s){
return s.toString().startsWith("+") || s.toString().startsWith("-");
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if(hasSign && start == 1 && count == 1){
et.setText("");
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
hasFractionalPart = s.toString().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator()));
}
}
I'm trying to format the input value of an EditText in Android, I want to format the input in currency value, I' ve tried the following:
EditText minimo = (EditText) view.findViewById(R.id.minimo);
Locale locale = new Locale("en", "UK");
NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
Locale locale = new Locale("en", "UK");
NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
minimo.setText("", TextView.BufferType.valueOf(String.valueOf(fmt.format(TextView.BufferType.EDITABLE))));
Log:
java.lang.IllegalArgumentException: Bad class: class android.widget.TextView$BufferType
try this :
set TextChangedListner as :
minimo.addTextChangedListener(new NumberTextWatcher(minimo));
create custom TextWatcher as:
class NumberTextWatcher implements TextWatcher {
private DecimalFormat df;
private DecimalFormat dfnd;
private boolean hasFractionalPart;
private EditText et;
public NumberTextWatcher(EditText et)
{
df = new DecimalFormat("#,###.##");
df.setDecimalSeparatorAlwaysShown(true);
dfnd = new DecimalFormat("#,###");
this.et = et;
hasFractionalPart = false;
}
#SuppressWarnings("unused")
private static final String TAG = "NumberTextWatcher";
public void afterTextChanged(Editable s)
{
et.removeTextChangedListener(this);
try {
int inilen, endlen;
inilen = et.getText().length();
String v = s.toString().replace(String.valueOf(df.getDecimalFormatSymbols().getGroupingSeparator()), "");
Number n = df.parse(v);
int cp = et.getSelectionStart();
if (hasFractionalPart) {
et.setText(df.format(n));
} else {
et.setText(dfnd.format(n));
}
endlen = et.getText().length();
int sel = (cp + (endlen - inilen));
if (sel > 0 && sel <= et.getText().length()) {
et.setSelection(sel);
} else {
// place cursor at the end?
et.setSelection(et.getText().length() - 1);
}
} catch (NumberFormatException nfe) {
// do nothing?
} catch (ParseException e) {
// do nothing?
}
et.addTextChangedListener(this);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if (s.toString().contains(String.valueOf(df.getDecimalFormatSymbols().getDecimalSeparator())))
{
hasFractionalPart = true;
} else {
hasFractionalPart = false;
}
}
}