Android string decimal value passed to BigDecimal not always works - android

I have such code:
private static final BigDecimal STEP = new BigDecimal("0.01");
private BigDecimal minValue = BigDecimal.ZERO;
private BigDecimal maxValue = BigDecimal.TEN;
private ImageView addImageView;
private ImageView subImageView;
private ESB_EditText esbEditText;
(...)
addImageView.setOnClickListener(v -> {
BigDecimal value = new BigDecimal(esbEditText.getEditableText().toString());
if (value.compareTo(maxValue) < 0) {
value = value.add(STEP);
esbEditText.setText(NumberUtils.formatBigDecimal(value));
}
});
subImageView.setOnClickListener(v -> {
BigDecimal value = new BigDecimal(esbEditText.getEditableText().toString());
if (value.compareTo(minValue) > 0) {
value = value.subtract(STEP);
esbEditText.setText(NumberUtils.formatBigDecimal(value));
}
});
where the ESB_EditText is just simple class that extends AppCompatEditText without any big magic.
The problem is when I click either first or second ImageView such error appears when I declare value variable:
java.lang.NumberFormatException: For input string: "0,00"
and what's interesting this error appears only on real phone but not on emulator. Why this error appears?
Thanks in advance!

Related

Running a tensorflow model in Android

I'm trying to run a simple iris classifier in an Android app. I created a MLP in keras, converted it into .pb format and put it into an assets folder. The keras model:
data = sklearn.datasets.load_iris()
x=data.data
y=data.target
x=np.array(x)
y=np.array(y)
x_train, x_test, y_train, y_test= train_test_split(x, y, test_size = 0.25)
inputs=Input(shape=(4,))
x=Dense(10,activation="relu",name="input_layer")(inputs)
x=Dense(10,activation="relu")(x)
x=Dense(15,activation="relu")(x)
x=Dense(3,activation="softmax",name="output_layer")(x)
model=Model(inputs,x)
sgd = SGD(lr=0.05, momentum=0.9, decay=0.0001, nesterov=False)
model.compile(optimizer=sgd, loss="sparse_categorical_crossentropy", metrics=["accuracy"])
model.fit(x_train,y_train,batch_size=20, epochs=100, verbose=0)
The code in AndroidStudio(I have 4 fields for input numbers,1 output field and 1 Button. The predictClick method gets called when the button gets clicked):
static{
System.loadLibrary("tensorflow_inference");
}
String model_name ="file:///android_asset/iris_model.pb";
String output_name = "output_layer";
String input_name = "input_data";
TensorFlowInferenceInterface tfinterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tfinterface = new TensorFlowInferenceInterface(getAssets(),model_name);
}
public void predictClick(View v){
TextView antwort = (TextView)findViewById(R.id.antwort);
EditText number1 = (EditText)findViewById(R.id.number1);
EditText number2 = (EditText)findViewById(R.id.number2);
EditText number3 = (EditText)findViewById(R.id.number3);
EditText number4 = (EditText)findViewById(R.id.number4);
Button predict = (Button)findViewById(R.id.button);
float[] result = {};
String zahl1 = number1.getText().toString();
String zahl2 = number2.getText().toString();
String zahl3 = number3.getText().toString();
String zahl4 = number4.getText().toString();
float n1 = Float.parseFloat(zahl1);
float n2 = Float.parseFloat(zahl2);
float n3 = Float.parseFloat(zahl3);
float n4 = Float.parseFloat(zahl4);
float[] inputs={n1,n2,n3,n4};
//im pretty sure these lines cause the error
tfinterface.feed(input_name,inputs,4,1);
tfinterface.run(new String[]{output_name});
tfinterface.fetch(output_name,result);
antwort.setText(Float.toString(result[0]));
}
The build runs without error, but when I hit the predict button the app chrashes. When I leave the the lines
tfinterface.feed(input_name,inputs,4,1);
tfinterface.run(new String[]{output_name});
tfinterface.fetch(output_name,result);
out the app runs correctly, so I think that's were the error comes from.
Your model's input layer is named "input_layer" in the python code, but "input_data" in the Java code.
Also check your logcat output. You should get an error message stating, that the model doesn't have the input layer you're searching for.

Android, Reading blank values

I'm new to android development, I trying to create a simply Pythagorean Calculator, I need help with reading if a lines blank, but still calculates instead of failing.
Here is my code
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText sideAObj;
private EditText sideBObj;
private EditText sideCObj;
private EditText outputObj;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sideAObj = (EditText) findViewById(R.id.SideAInput);
sideBObj = (EditText) findViewById(R.id.SideBInput);
sideCObj = (EditText) findViewById(R.id.SideCInput);
outputObj = (EditText) findViewById(R.id.OutputText);
}
public void calculateClick(View v){
try {
double sideA = Double.parseDouble(sideAObj.getText().toString());
double sideB = Double.parseDouble(sideBObj.getText().toString());
double sideC = Double.parseDouble(sideCObj.getText().toString());
if (sideAObj.getText().toString().equalsIgnoreCase("0")) {
double pt = Math.sqrt((sideC * sideC) - (sideB * sideB));
outputObj.setText(String.format("%.2f", pt));
}
}
catch (NumberFormatException ex){
Toast errMess = Toast.makeText(getApplicationContext(),"Enter Numbers Only",Toast.LENGTH_SHORT);
errMess.show();
outputObj.setText(String.format("%2.f",0.00));
return;
}
}
public void clearClick(View v){
sideAObj.setText("");
sideBObj.setText("");
sideCObj.setText("");
outputObj.setText("");
sideAObj.requestFocus();
}
}
My program will calculate if their is a Zero on 1 line, but if I leave it blank the program fails entirely, whats the best way to prevent that.
It will obviously fail as it doesn't know how to parse a blank value into a double. Just use something like this during instantiation itself:
double sideB = (sideBObj.getText().toString() == "") ? 0 : (Double.parseDouble(sideBObj.getText().toString()));
double sideC = (sideCObj.getText().toString() == "") ? 0 : (Double.parseDouble(sideCObj.getText().toString()));
Basically, you will be assigning the value 0 if the edit text field is 0 else, you will parse the value entered to a double.
Assuming you want to consider a 0 if there is a blank edit text field.
========================================================================
UPDATE
if(sideAObj.getText().toString() != ""){
double sideA = Double.parseDouble(sideAObj.getText().toString());
}
The simple solution for this problem would be to check each edittext whether they are blank or not and then perform the task.
Get the value of each Edittext to a int variable and then use loop and with the help of edittext.length() method verify if it is equal to 0, if yes, then assign a value to 0 to a new global variable, else assign the exact value to global variable.
and then perform the calculation with the new variables.
Sample code for better understanding :-
String a = et.getText().toString();
int l = a.length();
if (l == 0){
// set the value of global variable = 0;
} else {
// set the value of global variable = a {Actual Digit}
}

replace (,) in place of (.) in textview in android

I am using this code to add two number after (. in my number. For example: I have string 14.3, so I want to get 14.30, when get 14 I want to get 14.00. This is code:
NumberFormat format = NumberFormat.getNumberInstance();
format.setMinimumFractionDigits(2);
format.setMaximumFractionDigits(2);
tvPrice.setText(addDolar(format.format(Double.parseDouble(alerts.getPrice()))));
private String addDolar(String amount) {
if(amount.startsWith("-")) {
return "-$ "+amount.substring(1, amount.length());
}
else
return "$ "+amount;
}
problem is that I want to get '.' and now i get ','.
You can replace it:
someDouble.toString().replace(",", "."))
If you want to add two precisions only, then try this code
DecimalFormat format = new DecimalFormat("##.##");
String formatted = format.format(your_value);
editText.setText(formatted);
Use this function :
public double round(double unrounded)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
return rounded.doubleValue();
}
Try following
NumberFormat format = NumberFormat.getNumberInstance();
format.setMinimumFractionDigits(2);
format.setMaximumFractionDigits(2);
tvPrice.setText(addDolar(format.format(Double.parseDouble(alerts.getPrice()))));
private String addDolar(String amount)
{
amount = amount.replace ( ",","." ); // Add this line
if(amount.startsWith("-"))
{
return "-$ "+amount.substring(1, amount.length());
}
else
return "$ "+amount;
}

Prevent line-break in TextView

In my Android app I have a text view that displays text containing special characters. The TextView somehow automatically breaks strings at the characters '/' and '-'.
For example, the string "aaaaaaa/bbb-ccccc/ddd" is displayed as
aaaaaaa/
bbb-
ccccc/
ddd
However, I would like to display it without any linebreaks except the one at the boundaries of the view, i.e., like this:
aaaaaaa/bb
bb-ccccc/d
dd
Is there any way to deactivate the automatic line-breaks or to escape these characters? I already tried escaping with \uFEFF without success.
Keep your textview attribute
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Define Your string in string.xml
<string name="Username"> aaaaaaa\/bb\nbb\-ccccc\/d\ndd</string>
Maybe this is a solution: https://stackoverflow.com/a/22337074/3472905
I've added the slash as mentioned:
public class WordBreakTransformationMethod extends ReplacementTransformationMethod {
private static WordBreakTransformationMethod instance;
private WordBreakTransformationMethod() {}
public static WordBreakTransformationMethod getInstance() {
if (instance == null) {
instance = new WordBreakTransformationMethod();
}
return instance;
}
private static char[] dash = new char[]{'-', '\u2011'};
private static char[] space = new char[]{' ', '\u00A0'};
private static char[] slash = new char[]{'/', '\u2215'};
private static char[] original = new char[]{dash[0], space[0], slash[0]};
private static char[] replacement = new char[]{dash[1], space[1], slash[1]};
#Override
protected char[] getOriginal() {
return original;
}
#Override
protected char[] getReplacement() {
return replacement;
}
}
Its is a new thing in Android 6.
Try adding this to your TextView xml layout
android:hyphenationFrequency="none"
Android TextView follows the standard Unicode line break algorithm: http://www.unicode.org/reports/tr14/tr14-45.html
Excerpt: / Prevent a break before, and allow a break after
You can work around this by placing the 'word joiner' character (U+2060) after the slashes.
Example from strings.xml:
aaaaaaa/\u2060bbb-ccccc/\u2060ddd
You can also try using android:breakStrategy="balanced" to keep the lines roughly the same length.
this is work's for me in kotlin
object WordBreakTransformationMethod : ReplacementTransformationMethod() {
private val dash = charArrayOf('-', '\u2011')
private val space = charArrayOf(' ', '\u00A0')
private val slash = charArrayOf('/', '\u2215')
private val original = charArrayOf(dash[0], space[0], slash[0])
private val replacement = charArrayOf(dash[1], space[1], slash[1])
override fun getOriginal() = original
override fun getReplacement() = replacement
}
//tv_text is TextView
tv_text.apply {
transformationMethod = WordBreakTransformationMethod
text = item.text
}
There no ready solution and no such thing as "wrap text by letters in TextView" the only way to do it in a good way is to extend TextView and modify Paint's breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth) function.
Also, you can calculate TextView size in pixels, calculate width of one letter in pixels, then find number of letters (X) that will fit in one line and then insert linebreak after each X letters
you probably can use the Lines attribute or its counter-part method setLines(int)
I have tested the following code. You can even convert it into a function:
String specialString = "a/b/-c/d-d";
String[] specialArray = specialString.split("/");
String str = "";
for(int i = 0; i < specialArray.length - 1; i++){
str = str + specialArray[i] + Character.toString((char) 47);
}
str = str + specialArray[specialArray.length - 1];
specialArray = str.split("-");
str = "";
for(int i = 0; i < specialArray.length - 1; i++){
str = str + specialArray[i] + Character.toString((char) 45);
}
str = str + specialArray[specialArray.length - 1];
textView.setText(str);
Now the text does not escape
You can calculate the size of a text this way:
String text = "This is my text";
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(14.0f);
Rect bounds = new Rect();
textPaint.getTextBounds(text, 0, text.length(), bounds);
bounds.width() // width in pixels
bounds.height() // height in pixels
Based on these values you could break up the text in pieces and insert newline characters.

How to do a findViewById (R.id.>> StringVarHere << )?

Searched and working on this a long while - no luck. ( It must be simple ? Thanks for the assist. )
Trying to get / set a screen full of EditTexts' text, but not with the usual, more hard-coded way:
... findViewById (R.id.SomeTextWidgetId) ;
Instead, I'm trying to figure out a reusable way via a variable holding the (String) name_of_widget.
In psuedo code:
findViewById (R.id.>> StringVarHere << ); // how to do that ?
I tried also this findViewById method, but it didn't work (!?)
//// given:
static final String FIELD_TV_FEE = "TextViewFee" ;
static final String FIELD_TV_FOO = "TextViewFoo" ;
static final String FIELD_TV_FUM = "TextViewFum" ;
//// and some arbitrary number more of similar fields
static final String [] ALL_FIELDS = {
FIELD_TV_FEE ,
FIELD_TV_FOO ,
FIELD_TV_FUM // ...
} ;
//// ...
//// this part works
int ResourceID;
String stringVarHere = FIELD_TV_FEE;
//// outputs a correct id, say '0x7f05000f' as in R.id.xxx below
ResourceID = context
.getResources()
.getIdentifier ( stringVarHere,
"id",
context
.getApplicationInfo()
.packageName
) ;
Log.d ("MyClass" , "RESID = " + Integer.toHexString(ResourceID) ) ;
/*
* that's where I'm stuck ^^^ ... how do I do:
*/
String field_name ;
for ( field_name : ALL_FIELDS ) {
(EditText) SomethingLike_a_findViewById(field_name).setText ("Hello Wurld") ;
}
I've tried .setId ...
//// details
<!-- excerpt from working xml layout -->
<EditText
android:id="#+id/TextViewFee"
android:inputType="text"
android:layout ... etc ...
/>
<EditText
android:id="#+id/TextViewFoo"
android:inputType="text"
android:layout ... etc ...
/>
<EditText
android:id="#+id/TextViewFum"
android:inputType="text"
android:layout ... etc ...
/>
As expected, the gen'ed R file has something like this:
// ...
public static final class id {
public static final int TextViewFee=0x7f05000f;
public static final int TextViewFum=0x7f05001c;
public static final int TextViewFoo=0x7f05001d;
// ... etc
Yes, thanks - it makes sense to do it in the activity. I was trying to keep it from getting too code bulky. Here's what I'm doing now, based on your and A-C's helpful suggestions. The intention is to get all the text of fields of a form back in one String[]. (I know I could brute force all the fields too.)
What do you all think about this below - seems very similar to your suggestion, madlymad ? I am wondering if this is a poor design approach ?
public class FoodBar {
private Activity activity;
private Context ctx;
public FoodBar ( Activity _activity ) {
this.activity = _activity;
this.ctx = this.activity.getApplicationContext() ;
}
public String[] getTextFromAllEditTexts () { // the UI views
int res_id = 0;
int i = 0;
String [] retValues = new String [MyClassName.ALL_FIELDS_LENGTH] ;
for (String field : MyClassName.ALL_FIELDS_ALL_VEHICLES) {
res_id = this.ctx.getResources()
.getIdentifier ( field, "id", this.ctx.getPackageName() );
((EditText) this.activity
.findViewById (res_id))
.setText( "Meat and Potatoes" ) ;
// redundant - get it right back to make sure it really went in !
retVal[i++] = ((EditText) this.activity
.findViewById (res_id))
.getText().toString() ;
}
return retVal;
} // end func
} // end class
Then from the Activity class, it's just:
String [] theFields = null;
FoodBar = new FoodBar (this);
try {
theFields = FoodBar.getTextFromAllEditTexts ();
} catch (Exception e) {
Log.d ("OOPS", "There's a big mess in the Foodbar: " + e.toString() );
}
The way you could do it is (as I understand the way you are trying):
This can be in non-Activity (YourClassname.java):
public static int getMyId(Context context, String field) {
return context.getResources().getIdentifier (field, "id", context.getPackageName());
}
in Activity-class:
for ( String field_name : YourClassname.ALL_FIELDS ) {
int resid = YourClassname.getMyId(context, field_name);
if(resid != 0) { // 0 = not found
EditText et = (EditText) findViewById(resid);
if (et != null) {
et .setText ("Hello Wurld") ;
}
}
}
But I think it's better to code in the activity class like:
String packageName = getPackageName();
Resources res = getResources();
for ( String field_name : YourClassname.ALL_FIELDS ) {
int resid = res.getIdentifier (field_name, "id", packageName);
if(resid != 0) {// 0 = not found
EditText et = (EditText) findViewById(resid);
if (et != null) {
et .setText ("Hello Wurld") ;
}
}
}
A-C suggested something along the lines of:
res_id = getResources().getIdentifier (field, "id", getPackageName());
((EditText)findViewById (res_id)).setText("NoLongerFubar");
this DOES work - when I tried it standalone in a test rig. Thanks ! Still not sure what was blowing up, but I suspect it was Context or Resource items not being accessible.
Note that variable names (such as R.id.some_id) are only available at compile time and cannot be accessed from a String value at run time. Since these ids are declared as ints, you might consider using an int[] or List<Integer> to store the ids. Depending on how dynamic your layout is and what you are doing with the Views in it, you might even want to simply create the Views at run time and store an array or List of them without using any ids at all.

Categories

Resources