8

Background

I would like to get all of the strings of the Android OS (including all of them) programmatically, including those that are considered private.

For example, I would like to get those of the packageManager app, as found here .

The problem

Using android.R.string only returns a small portion of the strings.

What I've tried

I've found this link, which shows the next code, but I'm not sure what to put into the parameters:

private String GetAttributeStringValue(Context context, AttributeSet attrs, String namespace, String name, String defaultValue) 
    {
        //Get a reference to the Resources
        Resources res = context.getResources();
        //Obtain a  String from the attribute
        String stringValue = attrs.getAttributeValue(namespace, name);
        //If the String is null 
        if(stringValue == null)
        {
            //set the return String to the default value, passed as a parameter
            stringValue = defaultValue;
        }
        //The String isn't null, so check if it starts with '@' and contains '@string/'
        else if( stringValue.length() > 1 && 
                 stringValue.charAt(0) == '@' && 
                 stringValue.contains("@string/") ) 
        {
            //Get the integer identifier to the String resource
            final int id = res.getIdentifier(context.getPackageName() + ":" + stringValue.substring(1), null, null);
            //Decode the string from the obtained resource ID
            stringValue = res.getString(id);
        } 
        //Return the string value
        return stringValue;
    }

I've seen some apps in the past that can list various resources of other apps, including of the system itself (example here).

Later I've found how to get a string from any app you wish, but it assumes you know the name of the identifier, and doesn't offer you to list them:

fun getStringFromApp(context: Context, packageName: String, resourceIdStr: String, vararg formatArgs: Any): String? {
    try {
        val resources = context.packageManager.getResourcesForApplication(packageName)
        val stringResId = resources.getIdentifier(resourceIdStr, "string", packageName)
        if (stringResId == 0)
            return null
        return resources.getString(stringResId, *formatArgs)
    } catch (e: Exception) {
        return null
    }
}

For example, if you want to get the string of "more" (key is "more_item_label"), you can use :

val moreString = getStringFromApp(this,"android", "more_item_label")

The question

Is such a thing possible? If not, is it possible to do it with root?

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • I don't think you can do that. The private resources are designed this way because they are not guaranteed to be present in the latter version of android. – Quanturium Mar 26 '13 at 11:14
  • @Quanturium I know that they are protected and that you can't assume the existence of all of them. I only wish to query them. If I ever assume an existence of one string, I would have a fallback to my own strings. – android developer Mar 26 '13 at 11:18
  • What about that http://stackoverflow.com/questions/8077795/how-to-get-the-private-drawable-to-use-in-activity-in-android ? – Quanturium Mar 26 '13 at 11:21
  • @Quanturium I need to query the current resources, and not to download them all of a specific version. The way this link talks about, I need to add more and more resources each time there is a new android version. Not to mention that there are some roms that might change the resources themselves. – android developer Mar 26 '13 at 11:24
  • The link to "Android resources" doesn't work. Also look at [Resource Viewer](https://play.google.com/store/apps/details?id=jp.miotti.AndroidViewer). I am fairly certain that the Android system is, in itself, an APK, so getting any string value seems doable. You can use APKTool to decode an Android APK to see that this is doable. I think the doc for APKTool describes where to find the system APK. (No, actually drag the system APK into Android Studio to see the resources.) – Cheticamp Nov 30 '20 at 01:52
  • @Cheticamp I'm talking about getting it as an Android app. The app you've mentioned doesn't seem like it's open sourced, and is the same as the example app I've mentioned (just that what I had is now gone) . I've updated the question and removed the link. – android developer Nov 30 '20 at 09:33
  • To demonstrate where the attributes you want reside, you can do the following: In an emulator, double click " /system/framework/framework-res.apk" using the Android Studio Device File Explorer. This should bring up a window showing all the attributes of the system loaded on the emulator. I believe that "^attr-private" may have some of the components you want. You can peruse this display to determine if what you want is available in the framework APK file On Android itself, you may need to parse resources directly to see and get a list of everything. Isn't this something that APK Parser can do? – Cheticamp Nov 30 '20 at 12:49
  • You will also need to click on "resources.arsc" to see the resources in the framework APK. – Cheticamp Nov 30 '20 at 13:02
  • @Cheticamp So you say the Android framework doesn't offer some API for this? – android developer Nov 30 '20 at 14:17
  • Other than what you have already stated, no framework API call that I know of. Do you have a private string that you know you can't get? – Cheticamp Nov 30 '20 at 14:44
  • @Cheticamp Too bad. The question wasn't about me not being able to get a specific string. It was about listing them all. The parameter "resourceIdStr" shows you need to know what to put there. Seeing that some very old apps could list them all, I thought maybe they use the official API. – android developer Dec 01 '20 at 11:41
  • The "nnnn" of the resource id format ("ppttnnnn") is just an offset into a string table for strings (tt = 0x04 for Android,) If you know the size of the string table, you could just iterate from 0x01040000 to 0x0104xxxx where "xxxx" is the size of the table less 1. Android will return info on strings even if they are "private." The problem with this scheme, is that some resources don't have a default value, so you'll just get a "Resource Not Found" even though the resource exists for some non-default configurations unless, of course, your configuration happens to match one that is defined. – Cheticamp Dec 03 '20 at 20:02
  • @Cheticamp I've found another very-old app that could do it: https://play.google.com/store/apps/details?id=com.gmail.heagoo.apkeditor.parser . Are you sure there is no official way to do it? It sounds weird that such old apps could parse APK files so easily. – android developer Dec 05 '20 at 19:49
  • There may be a way, but I don't know what the use case would be to have that in the system and accessible through an API. My opinion is that these apps you find read the APK and interpret it according to its structure which is available. I took a quick look at the asset manager, ApkAsset.java, and a couple of other classes (heavy API usage restrictions and native calls) and see just the common things such as retrieving a resource name by id, etc. - nothing that asks for a dump of the system strings. APKReader does have most of the code you would need, but you would need to piece it together. – Cheticamp Dec 05 '20 at 23:29

1 Answers1

1

Your link show how get resources from preferences screen and say :

 The goal of this example was to show how to obtain the correct String resource outside the Android XML namespace

Link describe that you can get resources by alternative way ,not only by R.string.

I create a demo project with another custom namespace and custom button Label,but unfortunately i cannot show string resources from one project to another.

Yahor10
  • 2,123
  • 1
  • 13
  • 13