Mobility

Jelly Bean's ConnectivityManager has a new goodie

Android developer William J. Francis demonstrates how to determine if a connection is metered, as well as some other handy information that can be gleaned from the ConnectivityManager.

Android Chief Andy Rubin was quoted in April 2012 as saying there are 15 million lines of source code that make up Google's operating system. While the statement was made in the context of Google's highly publicized legal troubles with Oracle, considering that Android just celebrated its 5th birthday, 15 million lines of code is an impressive feat by any standard.

When a new version of the Android operating system is released, I tend to dive right in and try the most touted features for myself. With Jelly Bean (Android 4.1), that meant the new and improved "butter" user interface, the much-talked-about fancy notifications, and the new whiz-bang beam interface. But 15 million lines of source code means there are also some incremental changes that, while not necessarily headline worthy, are nothing to sneeze at.

I came across one such digital pearl last week; it's a simple boolean query that allows an application to determine if the active connection is "metered." In simplest terms, a metered connection is one that costs the user money, in most cases, a mobile data plan (3/4G).

The short tutorial that follows demonstrates how to determine if a connection is metered, as well as some other handy information that can be gleaned from the ConnectivityManager. You may follow along or download the source code and import it directly into Eclipse.

1. Create a new Android project in Eclipse. To use the new Jelly Bean-specific API call, you must target SDK 16 or higher. Be sure to rename the startup file to Main.java and the corresponding layout file to main.xml so you can easily follow along with the example.

2. Open the AndroidManifest.xml file and add the read network status permission.

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.network_info"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="16" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".Main"
            android:label="@string/title_activity_main" >
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
       </activity>
   </application>
</manifest>

3. Go to the /res/layout folder and modify main.xml. Our layout will be a simple linear layout with one text view and one edit text.

main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="#000000">
    <TextView
        android:layout_margin="10dip"
        android:textColor="#00ff00"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Details" />
    <EditText
        android:layout_margin="10dip"
        android:gravity="top|left"
        android:textColor="#ffffff"
        android:background="#000000"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Querying device, please wait..."
        android:maxLines="8"
        android:minLines="8"
        android:editable="false"
        android:enabled="false"
        android:scrollbars="vertical"
        android:id="@+id/console"/>
</LinearLayout>

4. The final step is to add code to our /src/Main.java file. The private function getNetworkStatus() is where the magic happens. It's a straight-forward matter of obtaining an instance of the ConnectivityManager and then making a few queries against it.

Main.java

package com.example.network_info;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.widget.EditText;
import android.app.Activity;
import android.content.Context;
public class Main extends Activity {
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      getNetworkStatus();
   }

private void getNetworkStatus() {
      ConnectivityManager manager = (ConnectivityManager)
getBaseContext().getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkInfo network = manager.getActiveNetworkInfo();
      String text = "Is available? " + (network.isAvailable() ? "yes" : "no") +"\n";
      text += "Is connected? " + (network.isConnected() ? "yes" : "no") +"\n";
      text += "Network type: " + network.getTypeName() +"\n";
      text += "Is metered? " + (manager.isActiveNetworkMetered() ? "yes" : "no") +"\n";
      ((EditText)findViewById(R.id.console)).setText(text);
   }
}
The resulting code can be executed on the emulator or a physical device (Figure A). If you use an actual device, you can switch between Wi-Fi and your mobile data plan and observe the difference reported. Figure A

When you have the ability to know if the active connection is available, as well as if that connection might rack up a big bill for the user, you can add controls and data ceilings to your applications. In my opinion, it's a lot of bang for your buck — a feature that, thanks to Jelly Bean, is easy to implement and one that your users can surely appreciate.

About William J. Francis

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

Editor's Picks

Free Newsletters, In your Inbox