Source code snippets (examples)

This is a list of Alvin Alexander's source code snippets (simple source code examples).

Android setDisplayHomeAsUpEnabled not needed to enable Up/Home/Back ActionBar button

When you want to provide Up/Back/Home navigation in an Android sub-activity, this Java code doesn’t seem to be needed:

getActionBar().setDisplayHomeAsUpEnabled(true);

The “Add Up Action” docs on this Android.com page state that is needed, but as of some (unknown) Android version it is not needed. All you need to do is specify the “Up/Parent” activity in your AndroidManifest.xml file, like this:

<activity
    android:name="com.alvinalexander.motify.NewQuoteActivity"
    android:label="@string/title_add_quote"
    android:theme="@style/ActionBarWithHomeArrowTheme"
    android:parentActivityName=".QuotesListActivity" />

I’m not sure about Android version specifics, but I’m developing my app with a minSdkVersion of 16 and my Up/Back buttons work fine without the Java code.

Android centering example: ImageButton in a Toolbar

As a quick Android “centering” tip, I found that by adding this snippet to the ImageButton below:

android:layout_gravity="center"

I was able to get the ImageButton to center itself in the Toolbar. Here’s the layout code for the Toolbar and the ImageButton:

<android.support.v7.widget.Toolbar
    android:id="@+id/bottomToolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="#ffffa302"
    android:minHeight="@android:dimen/notification_large_icon_height">

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/pinButton"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:drawable="@drawable/pinterest_pin"
        android:clickable="true"/>

</android.support.v7.widget.Toolbar>

I don’t think I needed this line in the ImageButton:

android:layout_centerHorizontal="true"

but I could be wrong. Once I got this Toolbar floated down to the bottom of the display I decided I didn’t like the look of it after all, so I deleted this code before getting a screenshot. But I do know that the android:layout_gravity setting was the one that centered my ImageButton. (Also, a lot of that other layout configuration code is unnecessary. I was experimenting with several different things when I was working on this button centering problem.)

Android: How to add a click listener to a Button (action listener)

As another quick Android example, this Java source code shows how to add a “click listener” to an Android Button:

public class MyActivity extends Activity {

     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         setContentView(R.layout.my_layout_id);

         final Button button = (Button) findViewById(R.id.my_cool_button);
         button.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 // your handler code here
             }
         });
     }

}

Important things to know are a) you need to add a listener to the Button, b) the listener you need is called an OnClickListener (not an ActionListener or ButtonClickListener, etc.), c) you add the listener with the setOnClickListener method, and d) that you need to implement the onClick method.

If you needed to see how to add a listener to an Android Button, I hope this example code is helpful.

How to set an image on an Android ImageButton

To set an image on an Android ImageButton, you basically just need to put your image in the “res/drawable” directories, and then add this tag to your ImageButton XML definition:

android:src="@drawable/my_image"

That assumes the image file is named my_image.png.

Here’s a full ImageButton example to demonstrate this:

<ImageButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/landingPagePinButton"
    android:layout_centerHorizontal="true"
    android:layout_gravity="center"
    android:src="@drawable/my_image"
    android:clickable="true"
    android:minHeight="36dp"
    android:minWidth="36dp"
    android:background="@android:color/darker_gray"/>

There is even more you can do with images on ImageButton’s. See the Android ImageButton docs for more information.

Android - How to access a String resource from Java code

To access a String resource that you’ve defined in an XML file from your Android/Java code, use the Android getString method, like this:

String prefsKeyTimeBetweenNotifications = getString(R.string.prefsKeyTimeBetweenNotifications);

In this example I’ve defined prefsKeyTimeBetweenNotifications as a string resource key in a res/values/strings.xml file, like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="prefsKeyTimeBetweenNotifications">timeBetweenNotifications</string>

</resources>

If you don’t use the getString method you’ll end up retrieving a long value.

Android: SQLite: SQLiteOpenHelper/SQLiteDatabase insert method doesn't throw exception

Android SQLite FAQ: I’m trying to catch an exception when my SQLiteOpenHelper/SQLiteDatabase insert method fails (typically because of a unique/duplicate constraint); why can’t I catch the exception?

Solution: The SQLiteOpenHelper insert method (SQLiteDatabase, actually) doesn’t throw an exception. The insert method returns the ID of the newly inserted row if it succeeds, or -1 if it fails. If you want an exception when the insert method fails, use the insertOrThrow method instead, as shown in this Java code:

/**
 * @throws java.sql.SQLException if the insert fails (typically because of a
 * "duplicate/unique" constraint.
 */
public long insert(String quote) {
    ContentValues cv = new ContentValues();
    cv.put(COL_QUOTES_QUOTE, quote);
    return getWritableDatabase().insertOrThrow(TABLE_QUOTES, null, cv);
}

The signature for insertOrThrow is the same as the insert method, so this is a simple change, assuming you want an exception. As my documentation shows, the insertOrThrow method throws a standard Java SQLException if the SQL INSERT fails.

For more information, see the SQLiteDatabase javadoc.

How to show an Android Toast message from a fragment

This is how you can show an Android Toast message from a Fragment:

Toast.makeText(getActivity(), "Click!", Toast.LENGTH_SHORT).show();

As shown, don’t forget to call .show() at the end of the makeText method. Forgetting to call show() is a common mistake.

If it helps to see this in more context, this is a complete onListItemClick method from a ListFragment subclass I’m currently working on:

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    Crime c = (Crime)(getListAdapter()).getItem(position);
    Log.d(TAG, c.getTitle() + " was clicked");
    Toast.makeText(getActivity(), "Click!", Toast.LENGTH_SHORT).show();
}

 

Using the Android Holo Light Theme in an Android app

I'm not an Android expert, but I wanted to use the Android Holo Light theme, and changing my <application> tag in my Android application manifest file to look like this definitely switched my Android app from having a dark background to a light background:

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" 
    android:theme="@style/android:Theme.Holo.Light">

That last line of code where I set the "theme" is what did the trick for me.

If only I could take a screenshot on my Android tablet, I'd be glad to show you the before and after pictures, but without this tag my application -- which primarily uses ListActivity's and Fragments -- had light text on a dark background, but with this setting, it now has dark text on a light background.

Update: I have learned that you can't do this for all Android apps. In particular, you can't use this when you're using an ActionBarActivity; it requires that you use some "compatibility" themes.

Android - How to attach an extra to an Intent/PendingIntent in a Notification (solution)

I’m working on a very small Android “notifications” app where I a) display a notification using a background service, b) the user taps the notification, which c) takes them to a view that shows the full text of the notification. To get this to work, I need to send the full text along with the notification. However, this didn’t work easily. The text that was shown by my full view would be updated once, then never again.

After a lot of googling and trial and error, I finally got this approach in my sendNotification method working:

public void sendNotification() {
    String randomQuote = getRandomQuote();

    Intent showFullQuoteIntent = new Intent(this, ShowFullQuoteActivity.class);
    showFullQuoteIntent.putExtra(INTENT_KEY, randomQuote);

    // both of these approaches now work: FLAG_CANCEL, FLAG_UPDATE; the uniqueInt may be the real solution.
    //PendingIntent pendingIntent = PendingIntent.getActivity(this, uniqueInt, showFullQuoteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    int uniqueInt = (int) (System.currentTimeMillis() & 0xfffffff);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, uniqueInt, showFullQuoteIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Notification notification = new NotificationCompat.Builder(this)
            .setTicker(randomQuote)
            .setSmallIcon(android.R.drawable.ic_menu_view)
            .setContentTitle(randomQuote)
            .setContentText(randomQuote)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .build();

    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    notificationManager.notify(0, notification);
}

Honestly, at the moment I don’t know why these approaches are working. As noted in the comments, this code works properly when I use any of the flags shown on the PendingIntent.getActivity method call. One thing I can say for sure: that method call is where the problem was.

The Android PendingIntent.getActivity method (API)

FWIW, yes, I have read the PendingIntent API documentation. As you can see from this image, the requestCode could probably be documented better (IMHO):

Complete source code

If it helps to see the full source code for my IntentService, here it is, all comments included:

package com.alvinalexander.motify;

import java.util.Random;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class PollingService extends IntentService {

    private static final String TAG = "PollingService";
    private static final Random random = new Random();
    public static final String INTENT_KEY = "THE_QUOTE";
    public static final String INTENT_KEY_2 = "INTENT_KEY_2";

    public PollingService() {
        super(TAG);
    }

    @Override
    public void onHandleIntent(Intent intent) {
        Log.i(TAG, "ENTERED onHandleIntent");
        sendNotification();
    }

    public void sendNotification() {
        Log.i(TAG, "ENTERED sendNotification");

        String randomQuote = getRandomQuote();
        Log.i(TAG, "QUOTE: " + randomQuote);

        Intent showFullQuoteIntent = new Intent(this, ShowFullQuoteActivity.class);
        showFullQuoteIntent.putExtra(INTENT_KEY, randomQuote);

        // from stackoverflow.com/questions/11551195/intent-from-notification-does-not-have-extras
        //showFullQuoteIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

        // stackoverflow.com/questions/7370324/notification-passes-old-intent-extras/9330144
        // @see http://developer.android.com/reference/android/app/PendingIntent.html#FL...

        // both of these approaches now work: FLAG_CANCEL, FLAG_UPDATE; the uniqueInt may be the real solution.
        //PendingIntent pendingIntent = PendingIntent.getActivity(this, uniqueInt, showFullQuoteIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        int uniqueInt = (int) (System.currentTimeMillis() & 0xfffffff);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, uniqueInt, showFullQuoteIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification notification = new NotificationCompat.Builder(this)
                .setTicker(randomQuote)
                .setSmallIcon(android.R.drawable.ic_menu_view)
                .setContentTitle(randomQuote)
                .setContentText(randomQuote)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .build();

        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        notificationManager.notify(0, notification);
    }

    private String getRandomQuote() {
        Resources res = getResources();
        String[] quotes = res.getStringArray(R.array.motivational_quotes);
        int randomIndex = random.nextInt(quotes.length);
        String randomQuote = quotes[randomIndex];
        return randomQuote;
    }

}

The receiving Activity/Fragment

I’ll update this article when I learn for sure why the current code is working, but as mentioned, my “extras” string is now properly being passed through the Intent and PendingIntent, and I’m able to retrieve the intent extra in my fragment on the receiving end like this:

public static class ShowFullQuoteFragment extends Fragment {

    private static final String PF_TAG = "ShowFullQuoteFragment";

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container,
                             Bundle savedInstanceState) {
        Log.i(PF_TAG, "ENTERED onCreateView");

        // get the 'extra' from the intent
        String quote = (String)getActivity().getIntent().getStringExtra(PollingService.INTENT_KEY);
        Log.i(PF_TAG, "QUOTE: " + quote);

        View rootView = inflater.inflate(R.layout.fragment_show_full_quote, container, false);
        TextView quoteLabel = (TextView)rootView.findViewById(R.id.put_quote_here);
        quoteLabel.setText(quote);
        return rootView;
    }
}

Android - How to view LogCat output from the command line

Like my last note, this isn't a "source code snippet", but just something I want to remember. In short, if you want to see Android LogCat output from the command line, just run this adb command from your Unix/Linux command line:

adb logcat

When you're developing an Android app, it's a good idea to keep this command open and running in a separate window, though of course you can also see this output in the Eclipse or Android Studio LogCat view.