HowFarNow App

UPDATE (February 12, 2019): I have unpublished the HowFarNow app on the Google Play Store because the permission to send SMS messages automatically is no longer available to apps that do not serve as the main SMS Messages app and do not fit into other narrow categories defined by Google. Google changed this policy recently in order to eliminate malware apps that scanned one’s SMS messages looking for sensitive security codes, etc. (My app does not do that and never did, but because permission to send SMS messages is no longer available to apps like mine, the HowFarNow app’s ability to automatically deliver text messages in a hands free manner has, in effect, been removed by Google. I did try to convince Google that my app was using the permission in accordance with one of their predefined categories, but did not succeed. I also tried to convince them to create a new category for apps such as mine, but failed there too. I’m sorry for any inconvenience this may have caused.)

HowFarNow is an app I wrote. As you drive, it automatically sends text updates of your distance from a specific destination to a recipient from your contacts list.


READ_CONTACTS Permission Before and After Marshmallow

The READ_CONTACTS permission is required if you look up a contact (using the code below) on a pre-Marshmallow device (API 23). But, on Marshmallow or above, you don’t seem to need READ_CONTACTS even though READ_CONTACTS is a dangerous permission.

I don’t see why these two cases should be different.

In particular, if you launch the user’s contacts app with this:

val intent = Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI)
startActivityForResult(intent, RC_CONTACT_LOOKUP)

and then read the contact’s phone number with this in onActivityResult:

RC_CONTACT_LOOKUP -> if (resultCode == RESULT_OK) {
    lateinit var cursor: Cursor
    if (data != null) {
        try {
            cursor =  applicationContext.contentResolver.query(,
                    null, null, null, null)
            val column = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
            val phoneNumber = cursor.getString(column)
            contactButton.text = phoneNumber
            errorTextView.text = ""
        } catch (exception: Exception) {
            Log.e(tag, "Could not query column db", exception)
        } finally {

it won’t work in the pre-Marshmallow case unless you’ve required the READ_CONTACTS permission in the manifest. But, for the Marshmallow case, you don’t need to request it (which you would do, of course, at runtime on an as-needed basis because it’s Marshmallow).


ConstraintLayout Guidelines Want Percentages Expressed as Decimal Value

I find it easy to forget that the “Guideline” element in a ConstraintLayout requires a value from 0 to 1 for its “layout_constraintGuide_percent” attribute:

  app:layout_constraintGuide_percent="0.50" />

Don’t people usually think of numbers between 0 and 100 when they hear the word “percent”?

Android Studio 3.1.2’s layout designer does not seem to warn or complain if you use a value above 1 (e.g. “50”). But when I did that, the layout behaved unexpectedly.


And the Winner for Best Screenplay in an Android Bug Report is …

“People are implementing IPv6 only networks with DHCPv6. Please implement RFC 3315.” by someone named Tyler.


TextUtils.isDigitsOnly Returns True if Given an Empty String

I happened across this problem while using the Android SDK’s TextUtils.isDigitsOnly() method recently.

This is the body of that method from the API 27 source:

    public static boolean isDigitsOnly(CharSequence str) {
        final int len = str.length();
        for (int cp, i = 0; i &lt; len; i += Character.charCount(cp)) {
            cp = Character.codePointAt(str, i);
            if (!Character.isDigit(cp)) {
                return false;
        return true;

Someone filed a bug report against it in January 2012. It seems no progress toward a fix has been made.

The app I’m coding is in Kotlin, and my first thought was to try to create my own local fix by creating my own local TextUtils.isDigitsOnly implementation in an extension function.

But this is not (yet) possible for a static method whose original definition is in a Java class (as opposed to a Kotlin class). Someone has filed a feature request to make it possible though. (It seems like a sensible request to me because there’s an asymmetry between Kotlin and Java with respect to extension functions: with Kotlin-defined classes you can reimplement both instance and companion object methods, but with Java-defined classes you can only reimplement instance methods.)

Anyway, in the mean time I replaced this expression:


with this expression:

!TextUtils.isEmpty(myString) && TextUtils.isDigitsOnly(myString)

Being a Good Android Citizen

From Previewing Android P:

In Android P we continue to refine Doze, App Standby, and Background Limits to further improve battery life; please be sure to try your apps with these and send feedback.

They don’t point to any specific improvements for Doze, App Standby and Background Limits. Maybe they didn’t quite reach their goals for these features. Or maybe developers and apps are not using these “good citizen” types of features enough to make the overall android experience better.


Flutter’s Hot Reload is Extremely Fast

Trying out Flutter’s “hot reload” feature, I have to say: it’s really fast.

Hot reload looks like a big step forward in productivity, even compared to conventional Android’s “Instant Run” feature.

Great job, Team Flutter.


Android Studio 3.0 Released. Woo Hoo.

Took me 4 days to realize it, but they have officially released a stable version of Android Studio 3. Woo hoo.

I’m officially looking forward to the stable release of Android Studio 3.1 now.


To Change the Option Menu’s Text Color and Typeface, I Got Rid of the Whole Thing

For a Halloween mapping app I was working on recently, I wanted to change the color and typeface of items in the standard options menu.

After trying some obvious things, like experimenting with text/color/font related attributes on the ‘item’ tag and monkeying around with the app’s theme, I found that I do not know how to do this.

So, I looked at this, this, this, and this. But, I never quite managed to change both the color and the typeface on the individual menu items. (Maybe I could have created a custom class that merges the features of a ForegroundColorSpan and a TypefaceSpan and a SpannableString or something, but I ran out of patience.) It started to look like more work than I wanted to do. And I’m not a big fan of the options menu anyway.

So I gave up on the options menu and started to look for something else. Eventually, I found Nightonke’s Boom Menu. Compared to most free android libraries hosted on GitHub, Boom Menu is awesome. Changing the text color and typeface are EASY. And the documentation is solid.

It was easy to change a Boom Menu button’s text color and typeface. I read the doc pages. Then I was like, Boom:

TextInsideCircleButton.Builder builder = new TextInsideCircleButton.Builder();
builder.typeface(ResourcesCompat.getFont(this, R.font.my_custom_font));

Thank you, Nightonke!


Problems with the new GPS Automatic License Notice Generator

Following up on my previous post, here’s a screenshot of the OSS license item for the popular Glide library as generated by version 11.2.2 of the new GPS OSS tools. There are two distinct OSS licenses for the Glide library and the GPS OSS tools finds both of them. But it concatenates the two URLs without a space or line break in between. They’re just stuck together:

To fix that, I added a gradle hack which runs after the app’s preBuild gradle task. The code block, placed at the bottom of build.gradle, carries out a specific edit within third_party_licenses (a text file generated by the OSS gradle plugin):

    String thirdPartyLicenseFilePath = 'app/src/main/res/raw/third_party_licenses'
    File thirdPartyLicenses = new File(thirdPartyLicenseFilePath)
    if (thirdPartyLicenses.exists()) {
        String contents = thirdPartyLicenses.getText('UTF-8')
        contents = contents.replace("licensehttp://", "license http://")
        thirdPartyLicenses.setText(contents, 'UTF-8')
    } else {
        println "cannot find " + thirdPartyLicenseFilePath

Sure enough, the hack adds a space between the two urls:

But there’s a new problem: the ‘t’ at the very end of the second url is no longer present. (Look closely. The url points to a ‘.tx’ file instead of a ‘.txt’ file).

On one of my android devices, it appears that there’s a 92 character length limit on that string. Or something. I have yet to discover where that limit is set.