Posts in the “android” category

How to programmatically set the font size and style of an Android TextView

Android FAQ: How do I programmatically set the font size (and/or font style) for an Android TextView?

Solution: Setting the Android TextView font size programmatically is a simple two-step process. First, define everything about the font that you want to use in a resources file. For example, I put this code in a file named res/values/styles.xml:

Android Room, database I/O, and Java 8 threads

I just started working with the Android Room database persistence library, and since you’re not supposed to run things like database queries on the main thread (the UI thread), I was looking at other ways to run them.

In general, you probably won’t want to run database queries using a Thread, but just to see how Room works, I wrote this Java Thread code, and confirmed that it works as expected:

// works (pre-java8)
Thread t = new Thread() {
    public void run() {
        mAppDatabase.userDao().insert(u);
    }
};
t.start();

Since that code runs in a separate thread, it runs fine even if I enable Android’s StrictMode.

Java 8 Thread syntax

Then I thought, “Hey, if I use the Android Studio 3 Canary Preview, I can use Android’s Java 8 features,” and when I did that I was able to use this Java 8 Thread syntax for the same purpose:

// works (java8)
new Thread(() -> {
    mAppDatabase.userDao().insert(u);
}).start();

That also works, and it’s much easier to read than the old Java Thread syntax.

As a quick summary, if you want to use a Java 8 Thread with Android, I hope that last example is helpful. I don’t often interact with a database without calling back to update the UI, but when I’m writing a little test app, or testing new features like the Android Room persistence library, this is a simple approach to keep database I/O code off the main thread.

Android: How to send a message from a Thread to a Handler

As a quick example of how to use a Thread with a basic Handler in an Android application, the following code creates a view where the text in the TextView is updated to show the current date and time when the Button is tapped.

Java source code

First, here’s the Java source code for a file class named ThreadHandlerActivity:

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.os.Handler;
import android.os.Message;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import com.alvinalexander.todo.R;

public class ThreadHandlerActivity extends Activity {

    private static final String MSG_KEY = "yo";

    /**
     * perform the action in `handleMessage` when the thread calls
     * `mHandler.sendMessage(msg)`
     */
    @SuppressLint("HandlerLeak")
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Bundle bundle = msg.getData();
            String string = bundle.getString(MSG_KEY);
            final TextView myTextView = (TextView)findViewById(R.id.myTextView);
            myTextView.setText(string);
        }
    };

    private final Runnable mMessageSender = new Runnable() {
        public void run() {
            Message msg = mHandler.obtainMessage();
            Bundle bundle = new Bundle();
            bundle.putString(MSG_KEY, getCurrentTime());
            msg.setData(bundle);
            mHandler.sendMessage(msg);
        }
    };

    private String getCurrentTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss MM/dd/yyyy", Locale.US);
        return dateFormat.format(new Date());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_thread_example);
        final Button button = (Button) findViewById(R.id.myButton);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                handleButtonClick(v);
            }
        });
    }

    public void handleButtonClick(View view) {
        new Thread(mMessageSender).start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        //TODO not sure if this is needed for this use case
        mHandler.removeCallbacks(mMessageSender);
    }

}

XML layout file

Next, here’s the layout XML for the view, from a file named activitythreadexample.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/myTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:height="32dp"
        android:text="TextView" />

    <Button
        android:id="@+id/myButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>

The app

Here’s what this little app looks like in an Android emulator:

Android thread, runnabler, and handler example

Discussion

Please note that this source code is heavily based on the now-old book, Android 4.4 App Development. I was just looking into threads and handlers in Android last night, and this is a relatively simple example of how to send a message from a thread/runnable to a handler.

Note that I had to add the @SuppressLint annotation to this code. I don’t know much about handlers yet, so I need to look into why that is needed. I do know that Android Studio is telling me that the handler should be declared as a static field. (Adding the annotation isn’t 100% necessary, but it’s a nice reminder that there’s a potential problem here.)

The “Unfortunately your Android app has stopped” error message

Android error FAQ: Help, I'm developing an Android app, and I'm getting a "Unfortunately your Android app has stopped error message"; how do I fix it?

If you're getting an Android error message that looks like this:

"Unfortunately your Android app has stopped error message"

It's probably because you forgot to put a new Activity in the AndroidManifest.xml file (or at least that's been the #1 cause of this error message in my experience).

An Android method to center text when using Canvas drawText

I’m not an expert on this subject just yet, but if you want the source code for an Android method to center text that you want to use with the drawText method of the Canvas class, I know that this code works in two places in my current Android app:

Android ActionBar example: How to create an options menu item

As Android programming goes, creating an options menu item/button in the Android ActionBar is fairly straightforward. In this brief tutorial I’ll demonstrate all of the steps needed to add a new menu item to the action bar.

1) Define the view/layout

The first step is to declare what the menu “view” is going to look like. This is very similar to defining other Android views, you do it with an XML layout file.

A Java method to log Android memory use

As a quick note today, here’s a little Java method that I use to log Android memory use (RAM use) from an Activity or Fragment:

private void logMemoryInfo(Context context, String TAG) {
   ActivityManager activityManager = (ActivityManager) context.getSystemService(getActivity().ACTIVITY_SERVICE);
   int memoryClass = activityManager.getMemoryClass();
   ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
   activityManager.getMemoryInfo(memoryInfo);

   Log.i(TAG, "\n------------ RAM -------------");
   Log.i(TAG, "mem class: " + memoryClass);
   Log.i(TAG, "mem avail: " + memoryInfo.availMem);
   Log.i(TAG, "low mem:   " + memoryInfo.lowMemory);
   Log.i(TAG, "threshold: " + memoryInfo.threshold);

   long mb = 1024*1024;
   Runtime runtime = Runtime.getRuntime();
   Log.i(TAG, "Used Memory:  " + (runtime.totalMemory() - runtime.freeMemory()) / mb);
   Log.i(TAG, "Free Memory:  " + runtime.freeMemory()  / mb);
   Log.i(TAG, "Total Memory: " + runtime.totalMemory() / mb);
   Log.i(TAG, "Max Memory:   " + runtime.maxMemory()   / mb);
}

Android: How to go back to Google App stories after closing the Now card

I like the “Google” app on Android — the thing you see if you swipe right on the Android home screen. But a weakness of it is that you can’t get back to a story easily. For instance, this morning I followed a Google Now card to see a story about Tom Ricketts and the Cubs, closed the story, then thought, “Wait, I meant to look at XYZ in that web page.” Once you close a story like this the Now card disappears, and you can’t get back to it easily (which is the weakness).

Solution 1: Going back to Google Now app stories on Android 7

I don’t know if this is the only way to do it, but as a solution, one way to get back to the story on Android 7 is to follow these steps:

How to make a phone call from your Android app

I came across this Android phone dialer tip yesterday. If you want to make a phone call from an Android application, all you have to do is create a new Intent, either an Intent.ACTION_DIAL (to start the call) or Intent.ACTION_CALL (to place the call).

Here are the three lines of source code you need to get started:

Intent dialIntent = new Intent();
dialIntent.setAction(Intent.ACTION_DIAL);
dialIntent.setData(Uri.parse("tel:8675309"));

How to transfer very large files to an Android device with adb

Today I learned that the Android File Transfer tool has a 4GB data transfer limit, but I was able to get around that by using the adb (Android Debug Bridge) command. The short story is that I used this adb command to transfer a 6GB file to my Android system, an old Nexus 9:

adb push ABigMovie.iso /sdcard/Movies

The bad news is that VNC choked and died when trying to play the movie, but the good news is that I found a good way to transfer very large files to an Android device. (I wasn’t really trying to go too far down the road trying to upload DVD images to my Nexus 9, I just wanted to see if I could upload very large files to an Android device. (You can’t fit many ISO images on an old Android device.))

In a related note, I found the Android /sdcard/Movies path through a little trial and error. For future reference, I found that this command lists all of the directories on an Android device:

adb ls /sdcard

The output of that command looks like this:

$ adb ls /sdcard

000041f9 00001000 5a31ec5e .
000041c9 00001000 58c58c32 ..
000041f9 00001000 58c58c57 Android
000041f9 00001000 58dc6424 Music
000041f9 00001000 58c58c3e Podcasts
000041f9 00001000 58c58c3e Ringtones
000041f9 00001000 58c58c3e Alarms
000041f9 00001000 58c5d2d4 Notifications
000041f9 00001000 58c5d902 Pictures
000041f9 00001000 5a31ecc6 Movies
000041f9 00001000 5a01e0fe Download
000041f9 00001000 5998ecef DCIM
000081b0 00000010 58dc6301 Music:.pos
000041f9 00001000 59b28d95 Temp
000041f9 00001000 59866d57 kindle
000041f9 00001000 592cf85d Books
000041f9 00001000 59b28d15 .RecycleBin

You can also learn a little more about the Android filesystem reality with a few more commands. After running adb shell, I poked around the filesystem a little, like this:

flounder:/ $ ls -al /sdcard
lrwxrwxrwx 1 root root 21 1969-12-31 17:00 /sdcard -> /storage/self/primary

flounder:/ $ ls -a /storage/self/primary
.  .RecycleBin Android DCIM     Movies Music:.pos    Pictures Ringtones kindle 
.. Alarms      Books   Download Music  Notifications Podcasts Temp    

Finally, here are two good ADB resources I found whilst poking around the interwebs:

How to enable a physical Android device (phone or tablet) for development and debugging

To enable a physical Android hardware device (phone or tablet) for developing and debugging your apps with Android Studio, follow these steps.

1) Enable “Developer Options”

The first thing you have to do with a new Android device is to enable the developer options in the Settings app. To do this:

  • Open Settings
  • Scroll down to “About phone” or “About tablet”
  • Tap that item (“About phone” or “About tablet”)
  • Tap the “Build number” field seven times

In Android 7, as you tap “Build number,” you’ll see it count down, which is a nice touch. When you finish with this you’ll see a message that says something like, “You’re now a developer.”

2) Developer options > USB debugging

Next:

  • Go back to the main Settings menu, where you’ll see a new “Developer options” menu item. Tap that.
  • Scroll down to the “USB debugging” setting, and enable it. This needs to be enabled so you can upload your Android apps to your physical hardware device.

Your Android device should be ready to use

At this point your device should show up in the “Select Deployment Target” window when you click “Run app” in Android Studio. If it doesn’t show up, there is one more step you need to take on your device.

The short version of this goes like this:

  • Pull down the Android settings window on your physical device.
  • There should be an “Android System” notification there. Tap it.
  • Select the “Transfer files” option on that notification setting.

(I describe this solution more in my Android File Transfer error: Can’t access device storage (solved) tutorial.)

Summary: How to enable a physical Android device for development and debugging

At the time of this writing this android.com article, Configure On-Device Developer Options, wasn’t 100% clear about this process, so I wrote this article to save me some time in the future. I hope it helps you as well.