String assertion in android build

I’m trying to compile my app with a lower minSdkVersion. (from 24 down to 19, to support an older device).

I got it to build eventually after android studio lost the plot with shedloads of unresolved symbols…

APK installs but app errors out and does not run. So I ran it thru the debugger…

It’s hitting a JUCE String assertion

    "If you get an assertion here, then you're trying to create a string from 8-bit data
    that contains values greater than 127. These can NOT be correctly converted to unicode
    because there's no way for the String class to know what encoding was used to
    create them. The source data could be UTF-8, ASCII or one of many local code-pages.

    To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
    string to the String class - so for example if your source data is actually UTF-8,
    you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
    correctly convert the multi-byte characters to unicode. It's *highly* recommended that
    you use UTF-8 with escape characters in your source code to represent extended characters,
    because there's no other way to represent these strings in a way that isn't dependent on
    the compiler, source code editor and platform.

    Note that the Projucer has a handy string literal generator utility that will convert
    any unicode string to a valid C++ string literal, creating ascii escape sequences that will
    work in any compiler."

Fair enough, but the triggering call is not from my code. It’s from juce_android_JNIHelpers.cpp line 109…

    String path (cls->getClassPath());

If I throw in a cheeky wee cast on that line…

 String path ((CharPointer_UTF8)cls->getClassPath());

then the assertion is not hit until later on, same JNIHelpers file, line 158…

      LocalRef<jstring> classNameAndPackage (javaString (String (classPath).replaceCharacter (L'/', L'.')));

Now I don’t feel that following the debugger and casting every string that throws is particularly clever! I don’t want to be messing about with JUCE code. Don’t even know if that cast is correct thing.

Any ideas? (Ideally I’d rather not be targeting sdk 19 / 4.4.1 but I don’t even know if that’s the issue. )

2 Likes

I have exactly the same issue. Did you find a workaround?

[Update]
I just find out that JUCE_PUSH_NOTIFICATIONS_ACTIVITY is defined to something really weird in CMakeList.txt.

Any idea about possible cause?

add_definitions("-DJUCE_ANDROID=1" “-DJUCE_ANDROID_API_VERSION=16” “-DJUCE_PUSH_NOTIFICATIONS=1” “-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY=“潣⽭潲楬樯捵⽥畊散捁楴楶祴�ɭ”” “-DJUCER_ANDROIDSTUDIO_7F0E4A25=1” “-DJUCE_APP_VERSION=1.2.054” “-DJUCE_APP_VERSION_HEX=0x10236”)

Trying to work it out by going backwards:

Do you have anything specified in the “Custom Android Activity” field of the Android exporter in Projucer?

No, I just have the empty default value. But I ran the Producer in Visual Studio to trace the issue, and I discovered that the following line is not working properly (juce_ProjectExport_Android.h, line 1145)

defines.set (“JUCE_PUSH_NOTIFICATIONS_ACTIVITY”, String::formatted(""%s"", getJNIActivityClassName().toUTF8()));

getJNIActivityClassName returns the right text, but the result of String::formatted is the chinese character string you can see in my previous message.

String::formatted is quite broken (because not actually cross-platform) and its documentation says not to use it:

@ed95 @jules @t0m Could you please consider (again) eliminating this broken function? Could you at least please make sure that it is not used in Projucer and any other JUCE code that should be cross-platform? Thanks!

@Pca you can apply the following diff to fix Projucer:

--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
@@ -1442,7 +1442,7 @@ private:
         if (arePushNotificationsEnabled())
         {
             defines.set ("JUCE_PUSH_NOTIFICATIONS", "1");
-            defines.set ("JUCE_PUSH_NOTIFICATIONS_ACTIVITY", String::formatted("\"%s\"", getJNIActivityClassName().toUTF8()));
+            defines.set ("JUCE_PUSH_NOTIFICATIONS_ACTIVITY", getJNIActivityClassName().quoted());
         }

         if (androidInAppBillingPermission.get())
1 Like

Yep I reached the same conclusion when I saw this format string, and already fixed it the same way in my local copy :smiley:

Thanks! :+1:

1 Like

Ouch! Thanks for the heads-up, yes, we’ll definitely fix that very nasty bit of code!

Like the comment says, I’d love to get rid of that method but last time I tried, the moaning was unbearable!

1 Like