We left off working on our Android client for the URL Shortener able to display all of the URL slugs that were saved on the server.  Today we’re going to continue on by giving the user the ability to tap into a slug and see the details on that shortened URL.  You can download the code that we left of from here.

If you run the app right now, you’ll see that you can tap on an individual item in our list view and it will highlight when you do, but nothing else will happen.  We want to show a new Activity when the user taps those with the URL information.  Let’s start by adding a new class to your project.  Let’s name the class UrlDetailsActivity and make it extend android.app.Activity.  Before we can set up the onCreate method for our new Activity, we need to create a new layout for it as well.  In your layout folder, add a new Android XML File named activity_url_details.  You can leave it with a root element of a LinearLayout.  Now we can go back to UrlDetailsActivity.java and implement the onCreate method:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_url_details);
    }

Nothing fancy here yet, just setting the content view.  Now, let’s go back to MainActivity.java and create an onClickListener for our list view:

    getListView().setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {                
        }
    });

Now, inside of the listener, we need to create an Intent to represent our UrlDetailsActivity and start it:

  getListView().setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view,
        int position, long id) {
      //Convert the tapped view into a TextView
          TextView tv = (TextView) view;        
          //Load the details intent for this specific slug
          Intent urlDetailsIntent = new Intent(getApplicationContext(),
              UrlDetailsActivity.class);
          urlDetailsIntent.putExtra("UrlSlug", tv.getText().toString());
          //We need to get the Full URL somehow and send it as an extra
          startActivity(urlDetailsIntent);
    }
  });

Here we’re casting the View sent into the listener as a TextView so we can pull out the text of the item tapped, creating an Intent, adding some extras, and then starting the Activity.  The one problem we have here is that we don’t have the Full URL to send as an extra.  We could do another post to the server and say “what’s the Full URL for this slug” but that wouldn’t be very efficient since we’re already pulling that data down.  If you recall from the last article, when our service finishes pulling down all of the shortened URLs, it sends that data back to the MainActivity as an extra.  When MainActivity get’s that data back, it just uses it to fill the list view.  Let’s change that to save the data.  First, add a new private member variable to the class to store the HashMap:

    private ServiceResultReceiver mReceiver;
    private HashMap<String, String> mUrlMap;

Now, in your onResultReceived method, when you pull out the HashMap from the Bundle, store it into mUrlMap:

    ...
    case UrlFetchService.STATUS_SUCCESS:
        boolean wasSuccess = resultBundle
                .getBoolean(UrlFetchService.SERVICE_WAS_SUCCESS_KEY);
        if (wasSuccess) {
          //Success, update the ListView
          mUrlMap = (HashMap<String, String>) 
              resultBundle.getSerializable("urlMap");
            showUrlsInListView(mUrlMap);
        } else {
        ...

Now we can go back to the click listener and send the full URL data over as an extra:

    ...
    //We need to get the Full URL somehow and send it as an extra
    urlDetailsIntent.putExtra("FullUrl",
            mUrlMap.get(tv.getText().toString()));
    ...

Now the last thing we need to do before testing, is add the UrlDetailsActivity to our AndroidManifest.xml file.  So open that and add this in side your application block:

    <activity android:name="UrlDetailsActivity"/>

Now, when you run your app and tap on an item in the list, you’ll see a new activity come up.  It doesn’t actually show anything yet though, so let’s fix that.  Go into your activity_url_details.xml.  We want to be able to show the user the URL slug, full URL, shortified URL, and a button to go to that short URL.  So we’re going to need a label for each of those, edit texts for the first three, and a button for the last.  When we’re done, our XML looks like this:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
        <TextView
            android:id="@+id/lblHeader"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="URL Details"
            android:textAppearance="?android:attr/textAppearanceLarge" />
        <TextView
            android:id="@+id/lblUrlSlug"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="URL Slug" />
        <EditText
            android:id="@+id/txtUrlSlug"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:ems="10">
            <requestFocus />
        </EditText>
        <TextView
            android:id="@+id/lblFulLUrl"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Full URL" />
        <EditText
            android:id="@+id/txtFullUrl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:ems="10"/>
        <TextView
            android:id="@+id/lblShortyUrl"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Shorty URL" />
        <EditText
            android:id="@+id/txtShortyUrl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:ems="10" />
        <TextView
            android:id="@+id/lblGoToUrl"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Go To URL" />
        <Button
            android:id="@+id/btnGoToUrl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Go To URL" />
    </LinearLayout>

Now we need to wire things up in the backend.  Let’s start by adding some private variables to our UrlDetailsActivity class:

    private EditText mTxtUrlSlug;
    private EditText mTxtFullUrl;
    private EditText mTxtShortyUrl;
    private Button mBtnGoToUrl;

We’ll use these in our onCreate method to hold references to our UI controls.  After we set the content view in onCreate let’s get those references as well as pulling the extras out of the intent that starts our activity:

    // Get controls we'll need regardless of whether we're adding or viewing
    mTxtUrlSlug = (EditText) findViewById(R.id.txtUrlSlug);
    mTxtFullUrl = (EditText) findViewById(R.id.txtFullUrl);
    mTxtShortyUrl = (EditText) findViewById(R.id.txtShortyUrl);
    mBtnGoToUrl = (Button) findViewById(R.id.btnGoToUrl);
    
    //Get extra data from intent
    Intent intent = getIntent();
    final String urlSlug = intent.getStringExtra("UrlSlug");
    final String fullUrl = intent.getStringExtra("FullUrl");

After that, we just need to wire up our controls to our data and set a click listener on our button:

    //Set our text fields and disable them
    mTxtUrlSlug.setText(urlSlug);
    mTxtUrlSlug.setFocusable(false);
    mTxtFullUrl.setText(fullUrl);
    mTxtFullUrl.setFocusable(false);
    mTxtShortyUrl.setText("http://urlshortener.azurewebsites.net/" + urlSlug);
    mTxtShortyUrl.setFocusable(false);
    
    mBtnGoToUrl.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            //Fire intent to view URL in web browser
            Intent webIntent = new Intent(Intent.ACTION_VIEW);
            webIntent.setData(Uri.parse
                    ("http://urlshortener.azurewebsites.net/" + urlSlug));
            startActivity(webIntent);
        }
    });

Notice we’re setting the Focusable property to be false for the EditTexts.  This is to that users can’t go in and edit any of the fields (they’re read only).  When the user clicks the button, we’re creating an ACTION_VIEW intent and firing that of with the shorty URL as the data on it.  This will bring up the browser at that URL.  Now when we run our app and tap on an item in the list view we get our details:

URL Details in Android

That concludes the work on the Android client for this article.  Next time we’ll detail how to give the user the ability to add new shortened URLs.  You can grab the completed source code from today here.

For a free trial for Windows Azure Websites, sign up here.


Chris Risner