Determine if two resource id's point to same layout - android

I have an Android setup that has a resource file that refers to a single layout from a choice of two.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<resources>
<item name="another_resource_id" type="layout">#layout/some_layout</item>
</resources>
or
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<resources>
<item name="another_resource_id" type="layout">#layout/some_layout2</item>
</resources>
This produces the R.layout
public static final class layout {
...
public static final int another_resource_id=0x7f030000;
public static final int some_layout=0x7f030001;
public static final int some_layout2=0x7f030002;
...
}
So the issue is that from the code I want to be able to tell which layout the another_resource_id resource identifier refers to.

I'll answer my question: Seems there is no straight forward way to tell the root view for a layout EXCEPT to dig down and get the original XML for the layout. Comparing the two is how I am able to tell if they are the same view. Kind of the long way around, but there it is. The following code just compares the addition of the resouce id for the underlying elements. Obviously you could put a lot more complex logic in.
try {
XmlResourceParser xrp = ctx.getResources().getLayout(id);
int eventType;
xrp.next();
String resourceIds = "";
do {
eventType = xrp.nextToken();
if (eventType == XmlPullParser.START_TAG) {
int attrs = xrp.getAttributeCount();
if (attrs > 0) {
for (int i = 0; i < attrs; i++) {
if (xrp.getAttributeName(i).compareTo("id") == 0) {
resourceIds += xrp.getAttributeValue(i);
}
}
}
}
} while (eventType != XmlPullParser.END_DOCUMENT);
returnVal = resourceIds.hashCode();
} catch (XmlPullParserException e) {
// e.printStackTrace();
} catch (FileNotFoundException e) {
// e.printStackTrace();
} catch (IOException e) {
// e.printStackTrace();
} catch (Resources.NotFoundException e) {
// e.printStackTrace();
}

Related

Retrieve String Resource From Another App

So I want to retrieve a string resource from another app. The app is the Android PackageInstaller (most probably a System app) and the String I want to retrieve has multiple language versions (Source Code here > Link). So Package Installer's resource directory looks like this:
I want to retrieve the String permission_warning_template from the values folder (I realize that Android will automatically determine the current language and will fetch me that language's value, but I may be wrong).
These are the 2 methods I wrote (Minimal, Complete, and Verifiable example) and neither works. Is it even possible? How to get it done?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//First Try
testUseAndroidString();
//Second Try
Resources res = null;
try {
res = getPackageManager().getResourcesForApplication("com.android.packageinstaller");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if(null != res) {
int sId = res.getIdentifier("com.android.packageinstaller:string/permission_warning_template", null, null);
if(0 != sId) {
Log.d("TagLet", res.getString(sId));
}
}
}
public void testUseAndroidString() {
Context context = this;
Resources res;
try {
res = context.getPackageManager().getResourcesForApplication("com.android.packageinstaller");
int resourceId = res.getIdentifier("com.android.packageinstaller:string/permission_warning_template", null, null);
if(0 != resourceId) {
CharSequence s = context.getPackageManager().getText("com.android.packageinstaller:string/permission_warning_template", resourceId, null);
Log.d("TagLet", "resource=" + s);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Log.d("TagLet", "FAIL");
}
}
Thanks.
So you actually almost solved your problem. As you have the resources of another application retreived, you just have to call get{Something} on this res object, and you will get the exact resource.
So I tried this method:
public void testUseAndroidString() {
Context context = this;
Resources res;
try {
res = context.getPackageManager().getResourcesForApplication("com.android.packageinstaller");
int resourceId = res.getIdentifier("com.android.packageinstaller:string/permission_warning_template", null, null);
if(0 != resourceId) {
String s = res.getString(resourceId);
Log.d("TagLet", "resource=" + s);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
And got
Allow %1$s to %2$s?
Which I guess is exactly what you're looking for.

Set different text colors to different options in NumberPicker (android)

I would like to create a NumberPicker for the four suits of playing cards (as unicode) with 2 of the suits displaying with red font and the other 2 with black font.
All the solutions regarding NumberPicker and text-color change the color of all the elements of the picker.
Right now, I have made it so that when the value changes, the color also changes. This allows the suit selected to be in the correct color but will also change the adajacent suits to be the wrong color.
Is there any way to have alternating colors in NumberPicker?
Thanks in advance:)
String[] suits = {
"\u2665", "\u2660", "\u2666", "\u2663"
};
suitPicker.setMaxValue(suits.length - 1);
suitPicker.setMinValue(0);
suitPicker.setDisplayedValues(suits);
suitPicker.setWrapSelectorWheel(true);
suitPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
setNumberPickerTextColor(suitPicker, getResources().getColor(R.color.GreyDark));
suitPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {#
Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
if (newVal % 2 == 0) {
setNumberPickerTextColor(suitPicker, getResources().getColor(R.color.Red));
} else {
setNumberPickerTextColor(suitPicker, getResources().getColor(R.color.GreyDark));
}
}
});
.....
public boolean setNumberPickerTextColor(NumberPicker numberPicker, int color) {
int count = numberPicker.getChildCount();
for (int i = 0; i < count; i++) {
View child = numberPicker.getChildAt(i);
if (child instanceof EditText) {
try {
Field selectorWheelPaintField = numberPicker.getClass()
.getDeclaredField("mSelectorWheelPaint");
selectorWheelPaintField.setAccessible(true);
selectorWheelPaintField.setAccessible(true);
((Paint) selectorWheelPaintField.get(numberPicker)).setColor(color);
((EditText) child).setTextColor(color);
numberPicker.invalidate();
return true;
} catch (NoSuchFieldException e) {
Log.w("setNumberPickerTextColor", e);
} catch (IllegalAccessException e) {
Log.w("setNumberPickerTextColor", e);
} catch (IllegalArgumentException e) {
Log.w("setNumberPickerTextColor", e);
}
}
}
return false;
}

Android - Parsing XML into an ArrayList

I'm having trouble parsing and showing information from a very simple xml file.
First of all, I'm storing the xml file in the res/xml folder. In the folder I have an xml file named jokes.xml, the content of the file is the following:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<joke>This is a good joke.</joke>
<joke>This is a very nice good great joke.</joke>
<joke>Oh Yeah!</joke>
</resources>
I want to parse this file, store all the jokes into an arraylist and the get a random one to show. My code is the following:
public class MainActivity extends Activity {
private TextView texto;
private int i = 0;
private String[] arrayJokes;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
texto = (TextView) findViewById(R.id.textView1);
XmlResourceParser joke = getResources().getXml(R.xml.jokes);
try {
while( joke.getEventType() != XmlResourceParser.END_DOCUMENT ){
if( joke.getEventType() == XmlResourceParser.START_TAG ){
String s = joke.getName();
if( s.equals("joke")){
arrayJokes[i] = joke.getAttributeValue(null, "joke");
i++;
}
}
}
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//takes random id from the array
Random generator = new Random();
int rnd = generator.nextInt(arrayJokes.length);
String j = arrayJokes[rnd];
texto.setText(j);
}
}
The problem is that I only get a blank page. Any idea on what I'm doing wrong?
Thanks in advance,
Cláudio
you can parse your joke items like this:
private ArrayList<String> parseJokes() {
ArrayList<String> jokes = new ArrayList<String>();
XmlResourceParser parser = getResources().getXml(R.xml.jokes);
try {
int eventType=parser.getEventType();
while (eventType!=XmlPullParser.END_DOCUMENT) {
if(eventType==XmlPullParser.START_TAG){
if (parser.getName().equals("joke")) {
jokes.add(parser.nextText());
}
}
eventType= parser.next();
}
} catch (XmlPullParserException | IOException e) {
Log.e("XmlPullParserException", e.toString());
}
parser.close();
return jokes;
}
the main idea is to advance the parser across the document using the next() method.

Getting data from xml in android

I am working on android application. In my app I got the xml data response from server and stored it in a string. Now I need to get each value of that xml and display in a dropdown. How can I do that. Please help me with this. Will be really thankful.
My xml data:
<?xml version="1.0" encoding="utf-8"?>
<root>
<status>first<status>
<description>very good</description>
<Firstnames>
<name>CoderzHeaven</name>
<name>Android</name>
<name>iphone</name>
</Firstnames>
<SecondNames>
<name>Google</name>
<name>Android</name>
</SecondNames>
</root>
I am getting the above mentioned xml data from server. Now I need to display that in listview. How can I get those values using xmlparser. I tried with different examples but it didnt work for me.
You will need to create an extra class and parametrize your adapter with objects of this class, an example data model would look like:
public class DataClass {
private String status, description;
private ArrayList<String> fnames, lnames;
public DataClass() {
fnames = new ArrayList<String>();
lnames = new ArrayList<String>();
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public ArrayList<String> getFnames() {
return fnames;
}
public ArrayList<String> getLnames() {
return lnames;
}
}
As for the XML parser, there are literally tons of examples, you're definitely in advantage if you can use search. Just to give you a staring point, tutorials one, two, three, four.
If you experience problems, post your efforts and the code that didn't work, what have you tried and so on. Then you'll get help, otherwise nobody on SO is going to write code for you. https://stackoverflow.com/help/how-to-ask
Here's how you can do it if the xml is inside of your apps assets folder.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InputStream input = null;
try {
input = getApplicationContext().getAssets().open("data.xml");
} catch (IOException e) {
e.printStackTrace();
}
DocumentBuilder builder = null;
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = null;
if (builder == null) {
Log.e("TAG", "Builder is empty.");
return;
}
try {
doc = builder.parse(input);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (doc == null) {
Log.e("TAG", "Document is empty.");
return;
}
// Get Firstnames element
Element firstNames = (Element) doc.getElementsByTagName("Firstnames").item(0);
// Get name nodes from Firstnames
NodeList nameNodes = firstNames.getElementsByTagName("name");
// Get count of names inside of Firstnames
int cChildren = nameNodes.getLength();
List<String> names = new ArrayList<String>(cChildren);
for (int i=0; i<cChildren; i++) {
names.add(nameNodes.item(i).getTextContent());
Log.d("TAG","Name: "+names.get(i));
}
// Do same with SecondNames
}

Change Divider Color Android DatePicker Dialog

I´m tying to change the divider color of the DatePicker Dialog.
I create the style:
<style name="dialog_custom" parent="#android:style/Widget.DatePicker">
<item name="android:divider">#drawable/dialog_divider</item>
</style>
And create the drawable like this
And the result is this
The divider no change color and the dialog take the content size..
This is my solution to change divider colors in NumberPickers, TimePickers, DatePickers and the TimePickerDialog. For DatePickerDialog you can call DatePickerDialog.getDatePicker()
public class NumberPickerStylingUtils {
private static final Drawable PICKER_DIVIDER_DRAWABLE = //Place your drawable here
private NumberPickerStylingUtils() {}
public static void applyStyling(TimePickerDialog timePickerDialog) {
try {
Field field = TimePickerDialog.class.getDeclaredField("mTimePicker");
field.setAccessible(true);
applyStyling((TimePicker) field.get(timePickerDialog));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static void applyStyling(TimePicker timePicker) {
try {
Field fields[] = TimePicker.class.getDeclaredFields();
for (Field field : fields) {
if (field.getType().equals(NumberPicker.class)) {
field.setAccessible(true);
applyStyling((NumberPicker) field.get(timePicker));
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static void applyStyling(DatePicker datePicker) {
try {
Field fields[] = DatePicker.class.getDeclaredFields();
for (Field field : fields) {
if (field.getType().equals(NumberPicker.class)) {
field.setAccessible(true);
applyStyling((NumberPicker) field.get(datePicker));
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public static void applyStyling(NumberPicker numberPicker) {
try {
Field field = NumberPicker.class.getDeclaredField("mSelectionDivider");
field.setAccessible(true);
field.set(numberPicker, PICKER_DIVIDER_DRAWABLE));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
You can do this using theme. Check accepted answer on this question. i think it will helpful to you.
UPDATES
Expand res folder in your application and expand values folder. Then create themes.xml file on values folder. then replace all code in themes.xml file with below code.
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="MYTheme" parent="#android:style/Theme">
<item name="android:divider">#drawable/dialog_divider</item>
</style>
</resources>
Then open your AndroidManifest.xml file. and find android:theme and replcae with android:theme="#style/MYTheme"

Categories

Resources