4

In an Android application, all of the strings values are hard coded (labels, dialog titles, buttons, etc). My task is to extract all these strings into a resource file. Without manually going through the code and making a lot of c/p, is there a way I can extract all the Strings from the application? Using regexes? I was thinking of writing a Pattern with someting like ".*" Or somehow parsing through the code?

Edit: I am aware of the externalize strings for Eclipse, but it creates .properties file and what I need is an .xml file. So, it would take some effort again to convert it to an .xml file.

I was thinking of writing a simple program that would extract all the strings with the names of the classes they were found in.

Matt
  • 74,352
  • 26
  • 153
  • 180
Maggie
  • 7,823
  • 7
  • 45
  • 66

2 Answers2

3

Eclipse provides an externalize strings wizard. For Android-specific solutions: Externalize strings for Android project.

Hope it helps.

Community
  • 1
  • 1
Savino Sguera
  • 3,522
  • 21
  • 20
  • Thanx, I am aware of this. But it creates .properties file, and it is not quite what I need. Android uses xml file for string resource. So, I would somehow need to convert .properties file to an .xml file, which is also a trouble. – Maggie Oct 05 '11 at 16:01
  • I can't find it in my Eclipse, but it in the comment it says I need to upgrade my adt version. Thanks, you are the best :) – Maggie Oct 05 '11 at 17:10
1

I wrote a short program to help me achieve this. I had a file with over hundred Strings in it, so just pressing Ctrl+1 --> Enter in each line would be too much of a hassle.

The little program takes the file location of your .java file as input and puts the info to your console for C&P. One could image improving it to crawl through the file system and do it for all .java files, but it was sufficient for my purpose...

package de.panschk.androidutil;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Set;

public class ExtractStringHelper {

public static void main (String[] args) throws IOException {
    String fileName = "LOCATION OF .JAVA FILE";
    FileInputStream fis = new FileInputStream(fileName);
    streamToStringReplaceEntities(fis);
    fis.close();

}

private static Set<String> varNames= new HashSet<String>();
public static void streamToStringReplaceEntities(InputStream is)
        throws IOException {
    BufferedInputStream bis = new BufferedInputStream(is);
    ByteArrayOutputStream codeOut = new ByteArrayOutputStream();
    StringBuffer xmlOut = new StringBuffer();
    boolean inLineComment = false;
    boolean inMultilineComment = false;
    boolean inQuotes = false;
    char lastChar = ' ';
    ByteArrayOutputStream stringContent = new ByteArrayOutputStream();
    int result = bis.read();
    while (result != -1) {
        boolean inComment = inLineComment || inMultilineComment;
        byte b = (byte) result;
        // read next byte
        result = bis.read();
        boolean copyCharToBuffer = true;
        if (!inQuotes && !inComment && b == '"') {
            stringContent = new ByteArrayOutputStream();
            inQuotes = true;
            copyCharToBuffer = false;
        } else if (inQuotes && b == '"') {
            String content = stringContent.toString("UTF-8");
            String varName = makeVariableName(content);
            inQuotes = false;
            addXMLContent(varName, content, xmlOut);
            addCodeContent(varName, codeOut);
            copyCharToBuffer = false;

        } else if (inQuotes) {
            copyCharToBuffer = false;
            stringContent.write(b);

        } else if (!inComment && !inQuotes && lastChar == '/' && b == '/') {
            inLineComment = true;
        } else if (!inComment && !inQuotes && lastChar == '/' && b == '*') {
            inMultilineComment = true;
        } else if (inLineComment && b == '\n') {
            inLineComment = false;
        } else if (inMultilineComment && lastChar == '*' && b == '/') {
            inMultilineComment = false;
        }

        if (copyCharToBuffer) {
            codeOut.write(b);
        }
        lastChar = (char) b;
    }

    System.out.println(codeOut.toString("UTF-8"));
    System.out.println(xmlOut.toString());

}

private static void addCodeContent(String varName,
        ByteArrayOutputStream codeOut) throws IOException {
    String contentToAdd = "getResources().getString(R.string."+varName+")";
    byte[] bytes;
    try {
        bytes = contentToAdd.getBytes("UTF-8");
        codeOut.write(bytes);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

}

private static void addXMLContent(String varName, String content,
        StringBuffer xmlOut) {
    if (!varNames.contains(varName)) {
        content = content.replace("'", "\\'");
        xmlOut.append("    <string name=\"").append(varName).append("\">").append(content).append("</string>\n");
        varNames.add(varName);
    }

}

static String makeVariableName(String s) {
    s = s.replace(' ', '_');
    s = s.replaceAll("[^A-Za-z0-9_]", "").toLowerCase();
    return s;
}

}

panschk
  • 3,228
  • 3
  • 24
  • 20