Month: April 2014

  • How to make Html Links in Android Text View work

    The task itself is easy: You have a TextView which should show a clickable link to open a WebPage. As ususal, there are several ways to achieve the goal. The nasty thing is: if you mix them, they might no longer work. And also, some sometimes work, sometimes they don’t.

    As it took me a little while to figure my final settings, I’ll note them here. A StackOverflow Post was a hint into a very good direction.

    First, display the links as clickable links in the textview:

    textView.setText(Html.fromHtml("Here is a <a href=\"http://www.Locked.de\">link</a>"));

    Now there are two options:
    Either make the link clickable programmatically by adding the following code:

    textView.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());

    or add android:autoLink="web" to the according XML-element:

    <TextView
    android:id="@+id/myId"
    android:autoLink="web"/>

    If one of the options doesn’t work, try the other one, but don’t mix them. In one of my apps there are TextViews in two different activities with very similar setup. Yet, the android:autoLink="web" solution didn’t work in both TextViews whereas the setMovementMethod works in both. In the StackOverflow Post, some users also mention that both solutions didn’t work, and that android:linksClickable="true" was a solution.

    My learning was: there are multiple ways to achieve the goal, but test it on each component separately as I do not yet completely trust the setMovementMethod way.

  • IllegalStateException: Content has been consumed

    When working with Android or (to be more general) Apache HttpComponents, one should keep in mind that it depends on the HttpResponses (Api: Apache, Android) if they can be consumed multiple times or not. And if the response is not, then better triple check your code, what you’re doing.

    I experiences the (very ugly) issue during the apparently simple task of reading the content of the response. )For ease of simplicity, I also use Apache commons-io, to read buffers etc.)

    HttpResponse response = ...;
    String content = IOUtils.toString(response.getEntity().entity.getContent());

    Okay, how many possible Nullpointer Exceptions do you see? I didn’t care until I experienced the first one, so I made the code NPE safe:

    HttpEntity entity = response.getEntity();
    // entity can be null according to the docs!
    if (entity != null) { 
        // The interface doesn't say that getContent() MUST return non-null
        InputStream stream = entity.getContent(); 
            if (stream != null) {
                tempContent = IOUtils.toString(entity.getContent());
            }
    }

    And suddenly I was faced with IllegalStateException: Content has been consumed. As I also did changes somewhere else, I assumed the error in some toString()-Methods that would read the content of the response during debugging. But as the error also showed up without debugging, I had a closer look to my “improvement”.

    Well, the error was the call IOUtils.toString(entity.getContent()); which tried to re-aquire the Input Stream. But as I just aquired it two lines above for the null check, the content was already marked as consumed. So the (now hopefully) correct and robust code is:

    HttpEntity entity = response.getEntity();
    // entity can be null according to the docs!
    if (entity != null) { 
        // The interface doesn't say that getContent() MUST return non-null
        InputStream stream = entity.getContent(); 
            if (stream != null) {
                tempContent = IOUtils.toString(<strong>stream</strong>);
            }
    }

    And the moral of the story

    Be very carefull when reading HttpResponses! Also avoid pretty-printing the content in toString() – this might suddenly also consume your content. And good luck finding the point where you consume the content in such cases.

    But .. why?! Please avoid returning null!

    Yet I still wonder, why so many methods are allowed to return null instead of just an empty stream or something. All the Null-checks don’t make the code more readable. Some programmers might even be tempted to simply put an catch(NullPointerException e) around the part of

    response.getEntity().entity.getContent()

    . Nothing I’d really recommend but I could also understand if I’d see something in other code.