How to read Text on any view of any application using AccessibilityInfo? - android

I am trying to read every item inside a ListView of any application by using AccessibilityInfo class. The problem is that i am getting the total number of items inside the ListView by using the following piece of code:
if(event.getClassName().equals("android.widget.ListView")) {
String className= TextView.class.getName();
AccessibilityNodeInfo nodeInfo= event.getSource();
int i= nodeInfo.getChildCount(); }
But i am not getting the names of items inside the ListView , for example let there are 5 textviews inside one ListView then i want to get the text from that TextViews. I tried to further break the nodeInfo object by using:
for(int j=0; j<nodeInfo.getChildCount() ;j++){
AccessibilityNodeInfo subChild = nodeInfo.getChild(j);
CharSequence subText = subChild.getText();
Log.e("MyService: ","ListView child name: "+subText);
}
So what i am doing wrong in getting the values of TextView's inside ListView ,
or
it is not possible to do so?

I have found the solution by myself and the solution is:
event.getSource() method returns instance of AccessibilityNodeInfo and by converting that instance value to String format we can easily get the results. Just we need is to break the string and get the required result out, in my case the way i did is:
String get_cord= String.valueOf(event.getSource());
String[] first_split= get_cord.split("[;]");
for(int i=0; i<first_split.length; i++){
if(first_split[i].contains("text")){
String[] second_split= first_split[i].split(":");
user= second_split[1].trim();
System.out.println(user);
Log.e("MyService: ","username is: "+user);
break;
}
}`

Related

Looping out JSON Array using ArrayList

I am trying to learn retrofit and I have made successful attempts at posting data and now I am trying to retrieve JSON array which looks as follows:
{
"result": "success",
"message": "All Questions Have Been Selected",
"question": {
"all_question_ids": ["1","2","3"]
}
}
I am using the following getter
public ArrayList getAll_question_ids(){
return all_question_ids;
}
I am retrieving using Retrofit as follows
if (resp.getResult().equals(Constants.SUCCESS)) {
SharedPreferences.Editor editor = pref.edit();
Log.d("Question_IDs", "getAllQuestionID() = " + response.body().getQuestion().getAll_question_ids() );
editor.putString(Constants.All_QUESTION_IDS,((resp.getQuestion().getAll_question_ids().toString())));
editor.apply();
}
progress.setVisibility(View.INVISIBLE);
It is here that I am stuck, as I am retrieving the array ok but I am unsure how to loop out the Array which is now stored in Shared Preferences.
When I place a toast to show me how the IDs are coming across, my toast confirms the data as [1,2,3]
The goal is to add a dynamic button and the individual ID, i.e button 1, button 2 etc every-time the loop is iterated.
I have tried the following:
String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");
for (int i =0; i < questionNumber.length(); i++) {
try {
/*Dynamically create new Button which includes the question name
*/
AppCompatButton btn_question = new AppCompatButton(getActivity());
/*LayoutParams (int width, int height,float weight)
As LayoutParams is defaulted in px, I have called a method called dpToPX to make sure
the dynamically added EditText is the same size on all devices.
*/
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(280), dpToPx(45), 1);
btn_question.setBackgroundColor(Color.parseColor("#3B5998"));
btn_question.setTextColor(Color.WHITE);
// btn_question.setText(String.valueOf(x));
btn_question.setText("Question "+ pref.getString(Constants.All_QUESTION_IDS,""));
btn_question.setGravity(Gravity.CENTER);
//generate unique ID for each new EditText dynamically created
View.generateViewId();
//Log.d("TEST VALUE", "Question1 generated ID = " + btn_question.generateViewId());
params.setMargins(0, dpToPx(10), 0, dpToPx(10));
btn_question.setPadding(0, 0, 0, 0);
btn_question.setLayoutParams(params);
allEds.add(btn_question);
mLayout.addView(btn_question);
} catch (Exception e) {
Log.d(TAG, "Failed to create new edit text");
}
}
However the above is adding the value as it appears in the array e.g [1,2,3] which is obviously not what I want.
I have added a photo in case my explanation isn't clear. I want a button with 1 number added to it each time the loop iterates but I am unable to figure this out.
I have looked through lots of resource but cannot find an answer that is relevant to my problem, although, if there is, I am not familiar enough to recognise a similar issue.
If someone can offer some assistance, I would appreciate it!
When you call editor.putString(Constants.All_QUESTION_IDS,((SOMETHING.toString())));, what is actually stored depends on the implementation of the toString method in the type of SOMETHING (in this case String[]). So avoid doing that. Instead, since you're already using Gson or Jackson (or others), store the question_idsas JSON:
final String jsonIds = gson.toJson (resp.getQuestion().getAll_question_ids());
editor.putString(Constants.All_QUESTION_IDS, jsonIds);
Your actual stored value no longer depends on the implementation of something that you don't control (String[].toString). It is a valid JSON array and regardless of what tool/library you use to read it back, it's valid.
Now, to read back the stored data:
final String storedJson = pref.getString(Constants.All_QUESTION_IDS, null);
if (null == storedJson) {
// TODO: No question ids found
}
final String[] ids = gson.fromJson (storedJson, String[].class);
for (int i = 0; i < ids.length; i++) {
// make your buttons
}
This is a problem of saving and then reading out a List of items (in this case, String instances).
You've chosen to save the list by calling editor.putString() with a value of getAll_question_ids().toString(). That toString() call is going to return a string representation of your list, or, in other words, a String instance with the value [1, 2, 3]. At this point, you no longer have a List proper, but a String that looks like a list.
This is all technically fine, but it means you have to take this into account when you're trying to read out that list.
You've written this to read the list back out:
String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");
Once this line executes, questionNumber will be a String instance with the value [1, 2, 3]. Again, this is fine, but now we come to the key point: we have to convert this String back into a List.
If you know for sure that the values in this list won't have commas in them, you can do it easily:
Trim the braces off the string using substring()
Create a String[] using split()
Convert your array to a list using Arrays.asList() (you could even skip this step since iterating over an array is just as easy as iterating over a list)
Put that together and you get:
String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");
questionNumber = questionNumber.substring(1, questionNumber.length() - 1);
String[] array = questionNumber.split(", ");
List list = Arrays.asList(array);
At this point, you can iterate over your array or list:
for (String value : list) {
...
btn_question.setText("Question " + value);
...
}

how to clear the ArrayList after adding that ArrayList to HashMap in Android?

Am doing one small android app. In that i have Expandable listview and am trying to populate data's from SQLite. So that i used HashMap to store parent(String) and child(ArrayList).
For eg I have four integer no's in parent(1, 2, 3, 4) i get this and stored in ListArray. Now i need to get child(ListArray) for that particular parent. Parent 1 contain (aa, bb), parent 2 contain (cc).. etc, now see this code
try
{
header = new ArrayList<String>();
footer = new ArrayList<String>();
child= new HashMap<String, List<String>>();
String date = null;
int count=0, countchild=0;
Cursor c = db.rawQuery("SELECT Date FROM Table", null);
if (c.moveToFirst())
{
do
{
date=c.getString(c.getColumnIndex("Date"));
header.add(date);
count=count+1;
} while (c.moveToNext());
}
for (int i = 0; i < count; i++)
{
String temp=header.get(i);
Cursor cc=db.rawQuery("SELECT Id FROM Table WHERE Date ='"+ temp +"' ", null);
if(cc.moveToFirst())
{
do
{
countchild=countchild+1;
String id=cc.getString(cc.getColumnIndex("Id"));
//footer.clear(); // it clear all data's on child
footer.add(id);
Log.d("Footer date count", "" + countchild);
child.put(temp, footer);
}
while (cc.moveToNext());
//footer.clear(); // it clear all data's on child
}
footer.clear(); // it clear all data's on child
}
}
I want to clear footer here after adding it to child then only i will get proper Expandable listview. If i remove/comment this footer.clear() line then all child's are added to all parents. eg parent 1 contain (aa, bb, cc, etc) and parent 2 contain (aa, bb, cc, etc). If i leave this footer.clear() line then all child's are cleared and display only parent like this eg Parent 1(), Parent 2()... etc
How to clear this footer(ListArray) after adding it to HashMap ?? or tell me some suggestion to modify this code.
Thank you. Srihari
When you put the ArrayList to the HashMap, the HashMap actually saves a reference to your array, not a copy.
That's why you must use different arrays for each group:
for (int i = 0; i < count; i++)
{
List<String> children = new ArrayList<String>();
String temp = header.get(i);
Cursor cc = db.rawQuery("SELECT Id FROM Table WHERE Date ='"+ temp +"' ", null);
if(cc.moveToFirst())
{
countChild += cc.getCount();
Log.d("Footer date count", "" + countchild);
do
{
String id = cc.getString(cc.getColumnIndex("Id"));
children.add(id);
child.put(temp, children);
}
while (cc.moveToNext());
}
}
As you can see a new children ArrayList here is created for each group and it's never cleared as that would clear the values from HashMap also.
Furthermore I've let myself fix a few other things like using Cursor's getCount method, to get the count instead of looping. Also I'm not using the footer array as it's unnecessary in the code you've shown.
Lastly, please use understandable and meaningful names for your variables as it can help you as well as others who read your code.
Remember Java is OO so if you clear an instance of an object, in this case an ArrayList, every other object referencing to it will get that new value.
What I recommend is you create a new instance of your footer variable everytime you need to fill a new group of your expandable list view, that way every footer list instance you create will be "associated" with one group in your list.
Hope this helps. :)

how to remove a string from arraylist of strings, ANDROID

I created an arraylist of strings
List<String> textArray = new ArrayList<String>();
and then I added the strings(which I am getting from edittext) to textArray as follows
String text = editText1.getText().toString();
textArray.add(text);
Now I created a button and need to remove the string from the array when the button is clicked.But i dont know what to do.
I know for arrays of bitmaps we clear a bitmap from array using recycle but Please suggest me how to remove or clear the string from arraylist.
You can call one of:
to remove all entries
textArray.clear();
to remove from a specific position (e.g. first item)
textArray.remove(0);
to remove a specific string (that equals yours)
textArray.remove("myString");
Try this..
Getting position from the textArray array list
int pos = textArray.indexOf(text);
and then remove from the string position
textArray.remove(pos);
because we cannot directly remove the string. we can remove the string contains position.
You can do it with more then one way as per your need.
textArray.clear();
It will clear whole ArrayList.
If you want to remove only some specifis data from index then,
textArray.remove(INDEX TO REMOVE);
Try This
String text = editText1.getText().toString();
textArray.add(text);
to remove
textArray.remove(text);

Store multiple dynamic EditText value

I have a code adding multiple EditText. How can i store them into a array. This number 10 is just example, the number may bigger than that. How can i store it after click a button
for(int i=0; i<10; i++) {
String store[] = new String[10];
EditText addAnsMCQ = new EditText(this);
AnswerRG.addView(addAnsMCQ, 1);
addAnsMCQ.setWidth(200);
addAnsMCQ.setId(1000);
}
In your example the store variable isn't actually being used, did you intend do use it for storing the EditTexts?
Instead of using an array of String, just use an array of EditText and store a reference to them:
EditText store[] = new EditText[10];
for(int i=0; i<10; i++) {
EditText addAnsMCQ = new EditText(this);
AnswerRG.addView(addAnsMCQ, 1);
addAnsMCQ.setWidth(200);
addAnsMCQ.setId(1000);
store[i] = addAnsMCQ; //store a reference in the array to the EditText created
}
Then outside of the for loop, you can access the reference to each EditText, e.g.
store[0].setWidth(300);
You need to keep/get a reference to each of your EditText's then you can look up its value with .getText().toString() which you can store in whatever manner you like.
However if as you say
This number 10 is just example, the number may bigger than that.
If the number is going to be larger you should be using an Adapter and a ListView or something to hold your View objects. That will make it easier to get everything on to the screen. And will give you the benefit of view recycling.

can't get the text from an autocomplete

I have to create an app in android with a database.In that database I have a predefined list of products.
Now,the thing is that my ap has to offer to the user the posibility to introduce in that list some other products which are not in the list.
To this end, I've created an autocomplete text view in which I introduce a new product and I take the text fro autocomplete and I have to write it in the database
Now,my problem is that when I display the products that I've introduced in the database,the toast text that I use to display what I have in the database it shows me nothing next to "product......".
Now,that may be because when I try to get the text from the autocomplete I get nothing in return?
This is how I read from autocomplete:
mItem = (AutoCompleteTextView) findViewById(R.id.todo_edit_item);
String nou=mItem.getText().toString();
And then I compare nou(which is what I wrote in the autocomplete) with what I have predefnied in the list,so if it is a new product(which was not in the list already) the I add it in the database:
for(int i = 0; i < l; i++)
{
if (nou!=fruits[i])
t=true;
else t=false;
}
if (t==true)
{
db.insertTitle(nou);
fruits=db.getAllfromDB("Fruits","fruit");
l=l+1;
}
Anyone any ideas of what I'm doing wrong in here cause I can't figure out.I'lll be here for further details.Thank u in advance:)
You compare strings using != instead of using !nou.equals(fruits[i]). also you compare to all elements in array each time, since you so t is always the value of the comparison to the last element in the array whether a match was found or not.
It should be written like that:
t = true;
for(int i = 0; i < l; i++)
{
if (nou.equals(fruits[i]))
{
t=false;
break;
}
}
if (t==true)
{
db.insertTitle(nou);
fruits=db.getAllfromDB("Fruits","fruit");
l=l+1;
}

Categories

Resources