14

To reference string foo in strings.xml (in res\values) of an app project, one can simply use

getString(R.string.foo)

getString is a method of Context.

Suppose an Android library has a string foo in its strings.xml. How can it be used in a method of the library?

Edited: It has been suggested to pass a reference of Context to the library method so getString() can be used. Since it is a context of an app's project, there is potential conflict that can be illustrated as following:

Suppose: The library has a string foo with value = "library foo". An app project has a string foo with value = "app foo"

The following code

Log.d("Debug", "App foo ID: " + R.string.foo);  
Log.d("Debug", "App: foo value: " + getString(R.string.foo));

generates:

03-22 05:53:55.590: D/Debug(16719): App foo ID: 2131230723
03-22 05:53:55.590: D/Debug(16719): App foo value: app foo

In a library method, the following code

Log.d("Debug", "Library foo ID: " + R.string.foo); 
Log.d("Debug", "Library foo value: " + context.getString(com.my.library.R.string.foo));

generates:

03-22 05:55:03.680: D/Debug(16719): Library foo ID: 2131230723
03-22 05:55:03.680: D/Debug(16719): Library foo value: app foo

The above shows the ID conflict hence erroneous string value.

3 Answers 3

8

As you indicated to reference a string resource defined in your library you can use getString() method, you only need a Context, but in your example the conflict is generated by the same name of the strings.

When you define a resource in your library you have a conflict if you use the same name of a resource in the application module. To avoid conflicts you have to use unique names, for example using a common prefix for resource names in the library, it is not sufficient the different package name.

To resolve you can use the following names:

  • mylib_foo in your library
  • foo in your application

Source from android documentation: http://developer.android.com/tools/projects/index.html#considerations

As you develop your library modules and dependent applications, keep the points listed below in mind:

  • Resource conflicts

    Since the tools merge the resources of a library module with those of a dependent application module, a given resource ID might be defined in both modules. In this case, the tools select the resource from the application, or the library with highest priority, and discard the other resource. As you develop your applications, be aware that common resource IDs are likely to be defined in more than one project and will be merged, with the resource from the application or highest-priority library taking precedence.

  • Use prefixes to avoid resource conflicts

    To avoid resource conflicts for common resource IDs, consider using a prefix or other consistent naming scheme that is unique to the module (or is unique across all project modules).

Sign up to request clarification or add additional context in comments.

Comments

5

A library project should be able to reference it's resources in exactly the same way.

Is there a specific use case / code sample that illustrates this not working?

Any strings defined in the parent project will overwrite the library. Even actionbarsherlock uses a prefix ex. abs__action_bar_home_description

6 Comments

The method does not have a Context reference, how can getString() be used?
The only way is with a context. Usually I just set up my method to accept a context from the calling application.
you must pass a Context parameter to your method. Note that View has a getContext() method, if you already have a parameter of this type
I was thinking about passing a Context, but the library can be used by unlimited number of apps. I am very unclear how the resources of the library are incorporated into each app without causing any potential string ID conflicts. When I use getString(R.string.foo) now in an app, I know it goes to the app's strings.xml to fetch it. How does an activity's context know to go to the library's resources to get a string. I must be missing something fundamental here.
When you import the R package you specify the parent domain. So in your library you import com.example.test.libraryname.R; While your app might use import com.example.test.app.R;
|
2
//For boolean values
    int resId = context.getResources().getIdentifier("bool_ID", "bool", context.getPackageName());
    if(resId != 0){
       System.out.println(context.getResources().getBoolean(resId));
    }

    //For String values
    int resStringId = context.getResources().getIdentifier("string_ID", "string", context.getPackageName());
    if(resStringId != 0){
        System.out.println(context.getResources().getString(resStringId));
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.