Search code examples
javaandroidstringstring-formattingformat-string

Is it possible to have %n newlines in strings.xml format strings with parameters?


I'm having an issue with having a %n newline in an android format string.

This is the intended output:

Address Line 1
City, State

So I created a format string like this:

%s%n%s, %s

But I got this error:

Error: Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?

My string is formatted, so that second solution doesn't seem to make sense, so I made the %s's positional:

%1$s%n%2$s, %3$s

But I still got the same error.

So I tried making the %n positional too, just to see if that'd fix the issue:

%1$s%4$n%2$s, %3$s

And then I got a runtime error (!!!) by java.util.Formatter:

E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.example.app, PID: 27843
        java.util.IllegalFormatFlagsException: %n doesn't take an argument
            at java.util.Formatter$FormatToken.checkFlags(Formatter.java:1373)
            at java.util.Formatter.transform(Formatter.java:1442)
            at java.util.Formatter.doFormat(Formatter.java:1081)
            at java.util.Formatter.format(Formatter.java:1042)
            at java.util.Formatter.format(Formatter.java:1011)
            at java.lang.String.format(String.java:1554)
            at android.content.res.Resources.getString(Resources.java:431)
            ... // omitting project specific files
            at android.support.v4.app.Fragment.performCreateView(Fragment.java:2080)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677)
            at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:536)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:152)
            at android.app.ActivityThread.main(ActivityThread.java:5497)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

How can have a %n newline in a strings.xml format string with other format parameters? Is it possible? If not, what's the best way to display a newline?

Android documentation or api guide references would be appreciated.


Solution

  • It might be a bug.

    Look at the AAPT sources -- specifically at the hasSubstitutionErrors method. It counts the number of arguments in the string to check if they should be positional. It makes sure to skip the literal percent sign (%%) but it doesn't skip the platform-specific newline symbol (%n).

    I have raised this problem in the issue tracker.

    At this point I don't see a solution other than using \n.

    EDIT: the issue has been marked as fixed in the tracker.