Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

Stefan Bols
Stefan Bols
2,515 Points

String replace method error

Hello. I don't if it's okay that I'm posting this post in this forum. It's is not related to the Treehouse videos. But I'm am working on a little Android App. When the users logs into the app, the user will see the name and the balance registered to the account.

My code (the comments on the right is the value of the variable:

    // get user data from session
    HashMap<String, String> user = session.getUserDetails();

    // name
    String name = user.get(SessionManager.KEY_NAME); // "Stefan Bols"
    String balance = user.get(SessionManager.KEY_BALANCE); // "466"

    String newLblName = getString(R.string.welcomeReplaceName_sentence); // "Din saldo er: {{BALANCE}} kr."
    String newLblBalance = getString(R.string.yourBalanceIs_sentence); // "Velkommen {{NAME}}!"

    newLblName = newLblName.replace("{{NAME}}", name);
    newLblBalance = newLblBalance.replace("{{BALANCE}}", balance);

    lblName.setText(newLblName);
    lblBalance.setText(newLblBalance);

The thing I wanna do is in my string resources I've declared these:

    <string name="yourBalanceIs_sentence">Din saldo er: {{BALANCE}} kr.</string>
    <string name="welcomeReplaceName_sentence">Velkommen {{NAME}}!</string>

And the code, pasted in the top should replace {{BALANCE}} and {{NAME}} with the given variables:

            newLblName = newLblName.replace("{{NAME}}", name);
            newLblBalance = newLblBalance.replace("{{BALANCE}}", balance);

But the problem is that it works for some time, and then with no change in the code or the external data the app simply just crashes all the time. In the LogCat I can see that it's the .replace method there causes the crash... but I can't find out what I've done wrong?

If anyone can help, I would really appreciate it!

  • Best, Stefan

LogCat: 08-30 12:30:01.105: D/dalvikvm(8625): GC_FOR_ALLOC freed 43K, 8% free 12272K/13251K, paused 21ms, total 21ms

08-30 12:30:01.145: D/dalvikvm(8625): GC_CONCURRENT freed 90K, 8% free 12644K/13639K, paused 3ms+2ms, total 27ms

08-30 12:30:01.145: D/dalvikvm(8625): WAIT_FOR_CONCURRENT_GC blocked 14ms

08-30 12:30:01.185: D/AndroidRuntime(8625): Shutting down VM

08-30 12:30:01.185: W/dalvikvm(8625): threadid=1: thread exiting with uncaught exception (group=0x41f142a0)

08-30 12:30:01.190: E/AndroidRuntime(8625): FATAL EXCEPTION: main

08-30 12:30:01.190: E/AndroidRuntime(8625): java.lang.RuntimeException: Unable to start activity ComponentInfo{net.imbols.omnihuset.saldotjek/net.imbols.omnihuset.saldotjek.MainActivity}: java.lang.NullPointerException: replacement == null

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.ActivityThread.access$600(ActivityThread.java:140)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.os.Handler.dispatchMessage(Handler.java:99)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.os.Looper.loop(Looper.java:137)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.ActivityThread.main(ActivityThread.java:4898)

08-30 12:30:01.190: E/AndroidRuntime(8625): at java.lang.reflect.Method.invokeNative(Native Method)

08-30 12:30:01.190: E/AndroidRuntime(8625): at java.lang.reflect.Method.invoke(Method.java:511)

08-30 12:30:01.190: E/AndroidRuntime(8625): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)

08-30 12:30:01.190: E/AndroidRuntime(8625): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)

08-30 12:30:01.190: E/AndroidRuntime(8625): at dalvik.system.NativeStart.main(Native Method)

08-30 12:30:01.190: E/AndroidRuntime(8625): Caused by: java.lang.NullPointerException: replacement == null

08-30 12:30:01.190: E/AndroidRuntime(8625): at java.lang.String.replace(String.java:1358)

08-30 12:30:01.190: E/AndroidRuntime(8625): at net.imbols.omnihuset.saldotjek.MainActivity.onCreate(MainActivity.java:56)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.Activity.performCreate(Activity.java:5206)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1083)

08-30 12:30:01.190: E/AndroidRuntime(8625): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)

08-30 12:30:01.190: E/AndroidRuntime(8625): ... 11 more

3 Answers

Ben Jakuben
STAFF
Ben Jakuben
Treehouse Teacher

We're happy to have you post in here! We want this to be a supportive community for Treehouse students whether working on Treehouse or personal projects. :smile:

I'm not much of a troubleshooter without full code that I can debug. Just one thought...Where is your session variable being declared? The fact that the error says "replacement == null" makes me think that name or balance are not getting set properly. Since they both come from that session variable, maybe something is causing that to be destroyed or reset? This could be a lifecycle problem, like if the Activity is destroyed because the system is low on memory. Depending on how you handle that, maybe the session variable isn't being recreated properly?

Can you post the full Activity code in here? I can't promise a solution, but I (and hopefully others) can take a look!

Stefan Bols
Stefan Bols
2,515 Points

It's is maybe a lifecycle problem, because I've not been able to recreate the problem deliberately. But I'm gonna post the code after I've tried to locate the problem within the SessionManager class by trying out with the lifecycle in mind. Thanks allot, I'll get back to you!

Stefan Bols
Stefan Bols
2,515 Points

Hi Ben. I can't see how I did miss the "replacement == null". But I tried a new way to fix my problem, the first idea was to try to recreate the problem without the app crashing. With this code:

    String name = user.get(SessionManager.KEY_NAME); // "Stefan Bols"
    String balance = user.get(SessionManager.KEY_BALANCE); // "466"
    Boolean err = false;

    if (name==""||name==null||balance==""||balance==null) {
        Log.e("Tis","Pis lort!");
        err = true;
    }


    String newLblName = getString(R.string.welcomeReplaceName_sentence);
    String newLblBalance = getString(R.string.yourBalanceIs_sentence);

    if (!err) {
        newLblName = newLblName.replace("{{NAME}}", name);
        newLblBalance = newLblBalance.replace("{{BALANCE}}", balance);
    }

    lblName.setText(newLblName);
    lblBalance.setText(newLblBalance);

This brick of code, almost does the same as it did before. But if the name or balance is equal to nothing or is "null", then the replacement methods will not be called and the lblName and lblBalance will be set to the standard String from Strings.xml.

Now I thought I could recreate this ugly app-crash... but no, I simply can't get the app to crash - neither to write the standard string.

The whole app seems to work just fine. I've simulated texts, incoming calls, killing the process and so on... nothing crashes the app or forces it not to call replace methods.

I should be happy, but I'm a bit scared to publish the app - what if the users experiences the crash? I can't force the crash/error, but I don't trust my work to be perfect enough to publish? What can I do? I'll be happy to post the whole code if you want that?

(I hope that you can understand my english)

Best, Stefan

Ben Jakuben
Ben Jakuben
Treehouse Teacher

The good thing about Google Play is that users can report crashes and you can respond to any bad reviews. You can also update the code right away if you need to. Can you possibly have other people help you test before you publish? The good thing is that the way you have written your code should totally prevent crashes in the future (at least from this section of code). So I would recommend publishing once you feel comfortable knowing that at least the app wouldn't crash like it was before.

If it was in fact a lifecycle/memory problem, it may be hard to reproduce. One thing you could try is to simulate low memory on an emulator with something like this: http://stackoverflow.com/questions/1483047/how-do-you-simulate-low-memory-in-the-android-emulator

Stefan Bols
Stefan Bols
2,515 Points

After I took a look at the lifecycle, I realized that when it's creating the session it writes it down on a "file" and keeps it. So if I kill the process/forces stop or anything - and then opening the app again, the session is still active and the login screen will not be displayed. Which is perfect for my solution. With this, no onResume is necessary :-)

It seems to work fine, I've spend my day trying to get some errors. Now I'll select a handfull of test users to use the app in debug mode to see if the problem comes up. If not, publish stage :) !

And now a off-topic question! Do you any idea of where I can learn to design some good looking apps?

Thanks for all your help and guidance. You are a great teacher!

Ben Jakuben
Ben Jakuben
Treehouse Teacher

For your design question, why don't you post a new thread in the Forum? I don't have much design advice myself, but you might get some great responses from the community and other teachers. :)

Stefan Bols
Stefan Bols
2,515 Points

I'll try that, thanks... and now another thing, I can se an edit label at your reply - and I can edit it... but getting an error message when doing it. Maybe you have to change that :) ?

Again, thanks for all you help :)