pa3: whats new in resources

Previous notes: anroid.r

Previous notes: understanding R.java


res/layout //default
res/layout-land //alternative resources

"-land" // configuration qualifier


mccAAA - where AAA is the mobile country code
mncAAA - where AAA is the carrier/network code
en-rUS - language and region
small,large,normal - screen size
long, notlong - screen type
port, land - portrait or landscape
car, desk - type of docking
night, notnight - night or day
ldpi, mdpi, hdpi, nodpi - screend density
notouch, stylus, finger - what kind of a screen
keysexposed, keyssoft, keyshidden - what kind of a keyboard
nokeys, qwerty, 12key - how many keys
navexposed, navhidden - navigation keys hidden or exposed
nonav, dpad, trackball, wheel
v3, v4, v7 - api level

multiple qualifiers separated by a "-"

if specified the qualifiers must be in the same order

directory names are case insensitive

You cannot specify the same resource for two types of similar qualifiers.

Use the link below to define resource aliases

Types of resources

Supporting multiple screens

Seems like a hefty topic worth consideration


home
list of applications
custom locale

You will see here current locale setting such as "en_US". You can change it to another locale by "long-clicking" on the available locales.

eclipse adt xml resource problem null pointer exception

Search for: eclipse adt xml resource problem null pointer exception

Here is a bug report


<resources xmlns:android="http://schemas.android.com/apk/res/android" >

eclipse adt xmlns values null pointer exception

Search for: eclipse adt xmlns values null pointer exception


<resources xmlns="default namespace">
or
<resources xmlns="http://....etc">

xmlns:android doesn't seem to work


plurals
arrays

values_en
values_en_US // this is error
values_en_rUS // this works

<resources>    
  <plurals name="numberOfSongsAvailable">        
      <item quantity="one">One song found.</item>        
      <item quantity="other">%d songs found.</item>    
  </plurals>
</resources>

android plurals quantity

Search for: android plurals quantity


abstract class PluralRules {

    static final int QUANTITY_OTHER = 0x0000;
    static final int QUANTITY_ZERO  = 0x0001;
    static final int QUANTITY_ONE   = 0x0002;
    static final int QUANTITY_TWO   = 0x0004;
    static final int QUANTITY_FEW   = 0x0008;
    static final int QUANTITY_MANY  = 0x0010;

    static final int ID_OTHER = 0x01000004;

    abstract int quantityForNumber(int n);

    final int attrForNumber(int n) {
        return PluralRules.attrForQuantity(quantityForNumber(n));
    }

    static final int attrForQuantity(int quantity) {
        // see include/utils/ResourceTypes.h
        switch (quantity) {
            case QUANTITY_ZERO: return 0x01000005;
            case QUANTITY_ONE:  return 0x01000006;
            case QUANTITY_TWO:  return 0x01000007;
            case QUANTITY_FEW:  return 0x01000008;
            case QUANTITY_MANY: return 0x01000009;
            default:            return ID_OTHER;
        }
    }

    static final String stringForQuantity(int quantity) {
        switch (quantity) {
            case QUANTITY_ZERO:
                return "zero";
            case QUANTITY_ONE:
                return "one";
            case QUANTITY_TWO:
                return "two";
            case QUANTITY_FEW:
                return "few";
            case QUANTITY_MANY:
                return "many";
            default:
                return "other";
        }
    }

    static final PluralRules ruleForLocale(Locale locale) {
        String lang = locale.getLanguage();
        if ("cs".equals(lang)) {
            if (cs == null) cs = new cs();
            return cs;
        }
        else {
            if (en == null) en = new en();
            return en;
        }
    }

    private static PluralRules cs;
    private static class cs extends PluralRules {
        int quantityForNumber(int n) {
            if (n == 1) {
                return QUANTITY_ONE;
            }
            else if (n >= 2 && n <= 4) {
                return QUANTITY_FEW;
            }
            else {
                return QUANTITY_OTHER;
            }
        }
    }

    private static PluralRules en;
    private static class en extends PluralRules {
        int quantityForNumber(int n) {
            if (n == 1) {
                return QUANTITY_ONE;
            }
            else {
                return QUANTITY_OTHER;
            }
        }
    }
}

plural rules en cs other languages

Search for: plural rules en cs other languages

xliff

Search for: xliff: What on the island is it??


public CharSequence getQuantityText(int id, int quantity) throws NotFoundException {
        PluralRules rule = getPluralRule();
        CharSequence res = mAssets.getResourceBagText(id, rule.attrForNumber(quantity));
        if (res != null) {
            return res;
        }
        res = mAssets.getResourceBagText(id, PluralRules.ID_OTHER);
        if (res != null) {
            return res;
        }
        throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
                + " quantity=" + quantity
                + " item=" + PluralRules.stringForQuantity(rule.quantityForNumber(quantity)));
    }

    private PluralRules getPluralRule() {
        synchronized (mSync) {
            if (mPluralRule == null) {
                mPluralRule = PluralRules.ruleForLocale(mConfiguration.locale);
            }
            return mPluralRule;
        }
    }

locale codes cs en

Search for: locale codes cs en

here is one list from google

cs: Czech en: English

if the locale is Czech then we get the terms "one" "few" and "other". Otherwise we get english rules "one" and "other".

It is not clear how one will accomodate the other locales. Probably not at the moment or one has to write their own I suppose. Not sure what xliff is and seems unlikely it will play a role. May be there is a way to supply additional PluralRules implementations.


<resources xmlns="http://schemas.android.com/apk/res/android">
<item type="id" name="menu_da_clear"/>

<string name="teststring_all">teststring in root</string>
<string name="t1_enport">t1 in root</string>
<string name="t1_1_en_port">t1_1 in root</string>
<string name="t2">t2 in root</string>

<string name="testport_port">testport in root</string>

<plurals name="test_plurals">
    <item quantity='one'>You are one</item>
    <item quantity='other'>You are many</item>
</plurals>

</resources>

public static final class plurals {
        public static final int test_plurals=0x7f060000;
    }

    reportPlural(R.plurals.test_plurals,0);
    reportPlural(R.plurals.test_plurals,1);
    reportPlural(R.plurals.test_plurals,2);
    reportPlural(R.plurals.test_plurals,3);
}
private void reportPlural(int plural_id, int amount)
{
    Resources res = this.mContext.getResources();
    String s = res.getQuantityString(plural_id, amount);
    this.mReportTo.reportBack(tag, s);
}

<string-array name="test_array">
	<item>one</item>
	<item>two</item>
	<item>three</item>
</string-array>

public static final class array {
        public static final int test_array=0x7f070000;
    }

private void reportArray(int arrayId)
{
    Resources res = this.mContext.getResources();
    String strings[] = res.getStringArray(arrayId);
    for (String s: strings)
    {
        this.mReportTo.reportBack(tag, s);
    }
}

Once you have a function like that you can do


reportArray(R.array.test_array);

Undestanding the precedence of configuration qualifiers


<string name="teststring_all">teststring in root</string>
<string name="t1_enport">t1 in root</string>
<string name="t1_1_en_port">t1_1 in root</string>
<string name="t2">t2 in root</string>

The goal is each of these strings ids are present in the root values directory. Then some of them will be redefined in configuration specific values directory.

Here is an example


<resources xmlns="http://schemas.android.com/apk/res/android">
	<string name="teststring_all">teststring-en</string>
	<string name="t1_enport">t1_en</string>
	<string name="t1_1_en_port">t1_1_en</string>
</resources>

This is a resource file that is meant for the english language. The id "teststring_all" is going to be there in all of the variations for our testing purposes.

"t1_enport" is going to be there in the english variation and also the portrait variation. However it is not going to be there in the "en_port" variation.

The "t1_1_en_port" is a variation of "t1" that is going to be there along with "t1" but also in the "en_port" variation.

t2 is going to be there only in the root.


<resources xmlns="http://schemas.android.com/apk/res/android">
   <string name="teststring_all">test-en-us</string>
</resources>

<resources xmlns="http://schemas.android.com/apk/res/android">
	<string name="teststring_all">test-en-us-port</string>
	<string name="testport_port">testport-port</string>
	<string name="t1_enport">t1_port</string>
	<string name="t1_1_en_port">t1_1_port</string>
</resources>

<resources xmlns="http://schemas.android.com/apk/res/android">
	<string name="teststring_all">test-en-port</string>
	<string name="t1_1_en_port">t1_1_en_port</string>
</resources>

public static final class string {
    public static final int t1_1_en_port=0x7f050002;
    public static final int t1_enport=0x7f050001;
    public static final int t2=0x7f050003;
    public static final int testport_port=0x7f050004;
    public static final int teststring_all=0x7f050000;
}

public class ResourceTester extends BaseTester 
{
    private static String tag = "ResourceTester";
    ResourceTester(Context ctx, IReportBack target)
    {
        super(ctx, target);
    }
    public void testEnStrings()
    {
        
        String msg = "available in all en/us/root/port/en_port: test_en_us";
        reportString(msg, R.string.teststring_all);
        //The one in file _port is not picked up
        //The precedence is given to the en_us over _port and also over en_port

        msg = "available in only root/en and port: t1_enport";
        reportString(msg, R.string.t1_enport);
        //t1 is in en and port at a parallel level
        //The one in file _port is not picked up
        //The precedence is given to the file in en
        //if you have "t1" in values_en_port, then that will be picked up
        
        msg = "available in only root/en/port: t1_en_port";
        reportString(msg, R.string.t1_1_en_port);
        //Value from _en_port will be picked up
        //value from _port ignored
        //value from _en ignored
        
        msg = "available in only root: t2";
        reportString(msg, R.string.t2);

        msg = "available in only port/root: testport_port";
        reportString(msg, R.string.testport_port);
        //this shows that the _port directory is considered
        //even though there are other directories with a
        //higher precedence
        
        reportPlural(R.plurals.test_plurals,0);
        reportPlural(R.plurals.test_plurals,1);
        reportPlural(R.plurals.test_plurals,2);
        reportPlural(R.plurals.test_plurals,3);
        
        reportArray(R.array.test_array);
        
    }
    private void reportPlural(int plural_id, int amount)
    {
        Resources res = this.mContext.getResources();
        String s = res.getQuantityString(plural_id, amount);
        this.mReportTo.reportBack(tag, s);
    }
    private void reportArray(int arrayId)
    {
        Resources res = this.mContext.getResources();
        String strings[] = res.getStringArray(arrayId);
        for (String s: strings)
        {
            this.mReportTo.reportBack(tag, s);
        }
    }
    private void report(int stringid)
    {
        this.mReportTo.reportBack(tag,this.mContext.getString(stringid));
    }
    private void reportString(String s)
    {
        this.mReportTo.reportBack(tag,s);
    }
    private void reportString(String s, int stringid)
    {
        this.mReportTo.reportBack(tag,s);
        report(stringid);
    }
}

Click here to download: ProAndroid3_Ch03_TestResources.zip

Eclipse 3.6 compatibility issue Options

This thread indicates a bug in eclipse 3.6 surrounding xml editors

android resource ? question mark id

Search for: android resource ? question mark id


<EditText id="text"    
  android:layout_width="fill_parent"    
  android:layout_height="wrap_content"    
  android:textColor="?android:textColorSecondary"
  android:text="@string/hello_world" />

The "?" is used instead of "@" to refer to a style attribute, and use that value to honor the theme that is in place.

standard android style theme attribute names

Search for: standard android style theme attribute names

How to design for multiple screen sizes

resource qualifiers link