I want to add layout with controls dynamically and in the future I want to save this data to DB.
public void onClickAdd(View view) {
LayoutInflater ltInflater = getLayoutInflater();
final LinearLayout subLayoutFields = (LinearLayout) findViewById(R.id.subLayoutFields);
LinearLayout subLayoutFields1;
final View view1 = ltInflater.inflate(R.layout.sub_fields, subLayoutFields, true);
subLayoutFields.setId(countID);
countID++;
}
And compiler did not finish successful.What's wrong with this?I get error on the
subLayoutFields.setId(countID);
The error is a:
Reports two types of problems: Supplying the wrong type of resource
identifier. For example, when calling Resources.getString(int id), you
should be passing R.string.something, not R.drawable.something.
Passing the wrong constant to a method which expects one of a specific
set of constants. For example, when calling View#setLayoutDirection,
the parameter must be android.view.View.LAYOUT_DIRECTION_LTR or
android.view.View.LAYOUT_DIRECTION_RTL
Thank you...
Like this
someView.setId(GenerateViewId.generateId());
This is the UTIL you need
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
import java.util.concurrent.atomic.AtomicInteger;
public class GenerateViewId {
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
/**
* Generate a value suitable for use in setId(int}.
* This value will not collide with ID values generated at build time by aapt for R.id.
*
* #return a generated ID value
*/
private static int generateViewId() {
for (; ; ) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) {
newValue = 1; // Roll over to 1, not 0.
}
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
}
#SuppressLint("NewApi")
public static int generateId() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return generateViewId();
}
else {
return View.generateViewId();
}
}
}
Related
Hy
my professor asked how you can print the contents of the variables within a class
he provided us with an apk to be launched and analyzed with frida:
package com.test_uni_apk.lib.proftest;
public class ProfApi{
public static class StateReady
extends ProfApi.CallState
{
public CallStateReady() {}
public CallStateReady(ProfApi.CallProc paramCallProc,
ProfApi.CallConnection[] paramArrayOfCallConnection, String
paramString, byte[] paramArrayOfByte, String[] paramArrayOfString)
{
this.printthis = paramArrayOfCallConnection;
}
}
}
I read that with frida you can hook a class but I do not understand how to print the value of printthis.
I will assume CallStateReady is an inner class of com.test_uni_apk.lib.proftest.ProfApi and you want to hook the c'tor and print the second parameter #PleaseSubmitElegantCode
function printParamArrayOfCallConnection() {
var ArrayList = Java.use("java.util.ArrayList");
var CallConnection = Java.use("com.test_uni_apk.lib.proftest.ProfApi$CallConnection");
Java.use("com.test_uni_apk.lib.proftest.ProfApi$CallStateReady") // dollar sign for inner class
.$init // init represent the constructor
// list of arguments are passed in byte code style, [B represents byte array
// when you try to hook Frida will provide an informative error with all the possible arguments for overloading
// copy & paste the right one which will look like this:
.overload("Lcom..ProfApi.CallProc;", "Lcom...ProfApi.CallConnection;", "java.lang.String", "[B", "Ljava.lang.String;")
.implementation = function(paramCallProc, paramArrayOfCallConnection, paramString, paramArrayOfByte, paramArrayOfString) {
// first we cast to list
var list = Java.cast(paramArrayOfCallConnection, ArrayList);
// iterating the list
for (var i = 0, l = list.size(); i < l; i++) {
// casting each element to the object we created earlier
var currentElement = Java.cast(list.get(i), CallConnection);
// printing to terminal
console.log(i, currentElement);
}
// executing original c'tor
this.$init(paramCallProc, paramArrayOfCallConnection, paramString, paramArrayOfByte, paramArrayOfString);
}
}
Java.perform(printParamArrayOfCallConnection);
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}
}
I have two arrays :
String []myExpressions = {"20+10","50+50","25+25","10+15"};
String []answers = {"30#","100#","50#","25#"};
When the user clicks the generate button it generates an expression from the array myExpressions and displays it in text-field. Then I require the user to enter the answer using the buttons provided. The answer is displayed in a EditText. When the user enters an answer they should enter a #(like a submit button) and if is the correct answer it should display correct in a text-field. So if the position in the expression array is 1, the correct answer is in the answer array in the same position. How would i check if they are in the same position?
For example: myExpressions[1] correct answer to this is answers[1].
Here is my code:
package com.gamesup.braingame;
import java.util.Random;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class Easy extends Activity implements OnClickListener{
EditText display;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.easy);
display = (EditText)findViewById(R.id.displayText);
display.setText("?");
final String []myExpressions = {"20+10","50+50","25+25","10+15"};
final String []answers = {"30#","100#","50#","25#"};
final TextView displayExpression = (TextView) findViewById(R.id.expression);
Button generate = (Button) findViewById(R.id.random_gen);
generate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Random ranGenerate = new Random ();
int random = ranGenerate.nextInt(4) ;
displayExpression.setText(myExpressions[random]);
}
});
}
static boolean isEmpty = true;
public void num_Clicked(View v){
Button btn = (Button) findViewById(v.getId());
//getting the button object and using a view to get the id of the buttons
if (v.getId()== R.id.del_button){
String s = display.getText().toString();
s = s.substring(0, s.length() - 1);
display.setText(s);
return;
}
if(isEmpty){
display.setText(btn.getText());
isEmpty = false;
}
else{
display.append(btn.getText().toString());
// storing the existing number into editText and current text is set
//to current button value
//display.setText(number+btn.getText().toString());
//the total in the editText
}
if (v.getId()== R.id.hash_button){
String userAns = display.getText().toString();
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
For starters arrays in Java Begin at Index 0 so therefore , to compare the first items of the Array you should be using something like this to check if things are equal:
EditText myAnswer = (EditText) findViewById(R.id.myAnswer);
String answer = myAnswer.getText().toString();
// Notice my loop starts at 0 because the first index of an array is 0
for(int i = 0 ; i < answers.length; i++)
{
if(answers[i].equals(answer))
{
// Congratulate the User for getting it Right
}
}
It seems as though you have a little bit of a shaky logic. IMHO you should be using a multidimensional Array.
With a multidimensional Array you can essentially set up keys and values.
This is how I think your application should be configures
// This Array says , I am an array that holds arrays
String [][] multiArray = {{"4 + 5", "9"},
{"20 * 3","60"},
{"99 - 9","90"}};
// Fetch your random question, since we know our questions are the first item in out Array we can use the index [x][0] depending on the index you pull from
String question = multiArray[0][0];
// To do this randomly
Random ranGenerate = new Random ();
int random = ranGenerate.nextInt(4) ;
String question = multiArray[random][0];
// Get the Answer from yout EditText
String answer = myAnswer.getText().toString();
// Using a for loop iterate on the base index
for(int i = 0; i < multiArray.length ; i++)
{
// if the answer is in position 1 of Array [i]
if(answer.equals(mutliArray[i][1])
{
// We have found the answer, Congratulate the User
}else{
// Tell them how bad they are since they can't solve simple equations!
// ....joking obviously we would be nice and let them know its not the answer
}
}
In this line
int random = ranGenerate.nextInt(4) ;
why don't you make random an instance variable inside your class? This way you would preserve the index, and you would know which index to use to compare the answer.
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.
I am trying to make an ordered list from XML in a textview. This list would be bulleted and properly justified with subheadings. Unfortunately, it seems that the support for this in the xml is minimal. I have tried the following in strings.xml:
<ol>
<li> item 1\n
<li>sub-item1\n</li>
<li>sub-item2\n</li>
<li>item2\n</li>
<li>item3</li>
</ol>
with various permutations having ol around each item etc etc. The result typically shows subitem2 and item 2 being indented away from the bullet. I have been really scratching my head on this one. Any guidance on this would be great.
First, create a Custom Tag handler class:
package com.thecitybank.myca.ui;
import android.text.Editable;
import android.text.Html;
import android.text.Spanned;
import android.text.style.BulletSpan;
import android.text.style.LeadingMarginSpan;
import android.util.Log;
import org.xml.sax.XMLReader;
import java.util.Stack;
public class MyTagHandler implements Html.TagHandler {
private static final String OL_TAG = "ol";
private static final String UL_TAG = "ul";
private static final String LI_TAG = "li";
private static final int INDENT_PX = 10;
private static final int LIST_ITEM_INDENT_PX = INDENT_PX * 2;
private static final BulletSpan BULLET_SPAN = new BulletSpan(INDENT_PX);
private final Stack<ListTag> lists = new Stack<ListTag>();
#Override
public void handleTag(final boolean opening, final String tag, final Editable output, final XMLReader xmlReader) {
if (UL_TAG.equalsIgnoreCase(tag)) {
if (opening) { // handle <ul>
lists.push(new Ul());
} else { // handle </ul>
lists.pop();
}
} else if (OL_TAG.equalsIgnoreCase(tag)) {
if (opening) { // handle <ol>
lists.push(new Ol()); // use default start index of 1
} else { // handle </ol>
lists.pop();
}
} else if (LI_TAG.equalsIgnoreCase(tag)) {
if (opening) { // handle <li>
lists.peek().openItem(output);
} else { // handle </li>
lists.peek().closeItem(output, lists.size());
}
} else {
Log.d("TagHandler", "Found an unsupported tag " + tag);
}
}
/**
* Abstract super class for {#link Ul} and {#link Ol}.
*/
private abstract static class ListTag {
/**
* Opens a new list item.
*
* #param text
*/
public void openItem(final Editable text) {
if (text.length() > 0 && text.charAt(text.length() - 1) != '\n') {
text.append("\n");
}
final int len = text.length();
text.setSpan(this, len, len, Spanned.SPAN_MARK_MARK);
}
/**
* Closes a list item.
*
* #param text
* #param indentation
*/
public final void closeItem(final Editable text, final int indentation) {
if (text.length() > 0 && text.charAt(text.length() - 1) != '\n') {
text.append("\n");
}
final Object[] replaces = getReplaces(text, indentation);
final int len = text.length();
final ListTag listTag = getLast(text);
final int where = text.getSpanStart(listTag);
text.removeSpan(listTag);
if (where != len) {
for (Object replace : replaces) {
text.setSpan(replace, where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
protected abstract Object[] getReplaces(final Editable text, final int indentation);
/**
* Note: This knows that the last returned object from getSpans() will be the most recently added.
*
* #see Html
*/
private ListTag getLast(final Spanned text) {
final ListTag[] listTags = text.getSpans(0, text.length(), ListTag.class);
if (listTags.length == 0) {
return null;
}
return listTags[listTags.length - 1];
}
}
/**
* Class representing the unordered list ({#code <ul>}) HTML tag.
*/
private static class Ul extends ListTag {
#Override
protected Object[] getReplaces(final Editable text, final int indentation) {
// Nested BulletSpans increases distance between BULLET_SPAN and text, so we must prevent it.
int bulletMargin = INDENT_PX;
if (indentation > 1) {
bulletMargin = INDENT_PX - BULLET_SPAN.getLeadingMargin(true);
if (indentation > 2) {
// This get's more complicated when we add a LeadingMarginSpan into the same line:
// we have also counter it's effect to BulletSpan
bulletMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX;
}
}
return new Object[]{
new LeadingMarginSpan.Standard(LIST_ITEM_INDENT_PX * (indentation - 1)),
new BulletSpan(bulletMargin)
};
}
}
/**
* Class representing the ordered list ({#code <ol>}) HTML tag.
*/
private static class Ol extends ListTag {
private int nextIdx;
/**
* Creates a new {#code <ul>} with start index of 1.
*/
public Ol() {
this(1); // default start index
}
/**
* Creates a new {#code <ul>} with given start index.
*
* #param startIdx
*/
public Ol(final int startIdx) {
this.nextIdx = startIdx;
}
#Override
public void openItem(final Editable text) {
super.openItem(text);
text.append(Integer.toString(nextIdx++)).append(". ");
}
#Override
protected Object[] getReplaces(final Editable text, final int indentation) {
int numberMargin = LIST_ITEM_INDENT_PX * (indentation - 1);
if (indentation > 2) {
// Same as in ordered lists: counter the effect of nested Spans
numberMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX;
}
return new Object[]{new LeadingMarginSpan.Standard(numberMargin)};
}
}
}
Then add a string in your string.xml as done below:
<string name="change_password_note"><![CDATA[<ol><li>Your password should contain at least one character of a-z, A-Z and 0-9. No special character is allowed.</li> <li>Please do not use any of your last three passwords.</li> <li>Please do not enter your User ID as password.</li> <li>Password minimum of 8 and maximum of 20 characters.</li></ol>]]></string>
Lastly, set text into your TextView as below:
txtNotesDescription.setText(Html.fromHtml(getString(R.string.change_password_note),null,new MyTagHandler()));
This worked for me. You can use un-ordered list by using the (ul) tag.
<string name="accessibility_service_instructions">
1. Enable TalkBack (Settings -> Accessibility -> TalkBack).
\n\n2. Enable Explore-by-Touch (Settings -> Accessibility -> Explore by Touch).
\n\n3. Touch explore the Clock application and the home screen.
\n\n4. Go to the Clock application and change the time of an alarm.
\n\n5. Enable ClockBack (Settings -> Accessibility -> ClockBack).
\n\n6. Go to the Clock application and change an alarm.
\n\n7. Set the ringer to vibration mode and change an alarm.
\n\n8. Set the ringer to muted mode and change an alarm.
</string>