A chat app that receives SMS and sends HTTP messages (A Xamarin Android App Preview)

MySMSWebChat02A while back, I delved into Android development using Android Studio and Java (in this article).  It was a little bit difficult for me as I need to familiarize myself with Android Studio and relearn Java.  But with Xamarin now part of Visual Studio, it became easier.  All I need to concern myself is the Android development itself.  So in just a few days, I created my first usable Android mobile application.  This app can now receive SMS messages but the sending of HTTP messages is still in the works (which is why it’s still in a preview).

Anyways, what did I do to make this SMS work?  The app registers a broadcast receiver for SMS messages.  This broadcast receiver then sends an ordered broadcast to the app where it has 2 more broadcast receivers: one broadcast receiver to update the UI with the SMS message received when the app is running, and another one to display a notification when the app is not running.  When the notification is clicked, the app will launch and the chat will start.

I see a potential in this mobile development space for me, and for this app which I will continually build on.  There are still a lot of work in progress here.  One takeaway for me on this is that Xamarin does really help you develop Android apps using your favorite language C# and your favorite IDE Visual Studio.

Resources and Tools:

Advertisements

Testing an HTML Page on the Android Emulator Browser

HTMLonAndroidAlthough you can easily test your HTML page’s responsive design using Chrome’s Mobile Emulation feature, you can also do it, albeit the harder way, by loading the page on the Android emulator’s browser.

First you must run the Android Virtual Device (AVD) Manager to launch your Android emulator.  You don’t necessarily have to run the IDE that came with your Android emulator (e.g. Eclipse or Android Studio).  You can use the batch file android.bat which you can find under sdk/tools of your Android installation folder.  In the command prompt, just type in “android.bat avd”.

Once you have the AVD manager running, select the device you want to emulate.  But before starting the device, make sure you have specified a size for the SD card, as we will be using this to store the HTML page.  2GB should be OK.

Next, you need to copy the HTML page from the computer to the Android emulator’s SD card storage using the Android Debug Bridge program or adb.exe, which you can find under sdk/platform-tools.  Using a command prompt, run adb with the following options:

  • “adb devices” which will list the devices attached including the emulator ones.  To connect to the emulator you just started, you need to get the device number assigned to the emulator from the device list.  Or you can get the number from the emulator window bar.
  • “adb connect localhost:5554” which will connect you to the device emulator.   The number 5554 should be replaced with the device number for your emulator.
  • “adb push C:\YourFolder\YourHTMLPage.html sdcard/.”  which will copy your HTML page from your computer’s local folder to the Android emulator’s sdcard folder.  Note that the Android OS is based on Linux kernel which is why the destination path follows the Linux syntax.
  • “adb shell” which will bring you to the Android emulator file system.  You can go to the SD card folder to check if your HTML page was copied successfully by entering “cd sdcard” and then “ls –al”.  It’s exactly a Linux file system at your fingertip.  If you want to create a folder under the SD card folder you can use mkdir.  To get out of the shell, just type in exit.

You can also copy any accompanying CSS and JavaScript files for the HTML page you just copied.

Now you are ready to view the HTML page on the Android emulator browser.  On the emulator, open up the browser and type in the URL file:///sdcard/YourHTMLPage.html on the address window.

Note that by default, these mobile browsers will automatically shrink the page to fit the mobile device width.  The following meta tag should be used to override this and display the page at 100 percent.

<meta name="viewport" content="width=device-width,initial-scale=1.0"/>

 

Android Development: main() Method, Application Lifecycle, and Event Handling

AndroidDevImg02So, I was going through some tutorials in Android development and along the way created my first applications that just demonstrate the programming features that are available in Android.  It does not seem to me a far fetch programming paradigm as this is mostly familiar to someone with a windows or web development background, but with some subtle differences of course.  My purpose for this post and future posts as well is to list these nuances.

The first thing that a windows or web developer will ask, who is just beginning Android development, is how an Android application is started, thus the following question.

Is there a main() method in Android?  There is no main() method but there is one similar to it, the main activity’s onCreate() method.

Main activity is the first activity that is run by the Android OS when launching an android app.  The main activity is defined in the AndroidManifest.xml file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.app" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.app.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

All android apps contain at least one activity.  An activity is much like a web page, in that it defines the screen layout and the behavior.  The activity’s screen layout is defined in an XML markup file.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.example.app.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click me!!!"
        android:id="@+id/button"
        android:layout_marginTop="30dp"
        android:onClick="buttonOnClick"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="No text..."
        android:id="@+id/textView"
        android:layout_below="@+id/button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="22dp" />
</RelativeLayout>

The activity’s behavior is defined in a Java class.

public class MainActivity extends Activity {
    //
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    //
    public void buttonOnClick(View v) {
        Button b = (Button) v;
        b.setText("I've Been Clicked!");
        //
        TextView t = (TextView) findViewById(R.id.textView);
        t.setText("You Clicked Me!");
    }
}

So for every screen that your android app will need, you usually create an activity.  The main activity’s onCreate() method is called by the Android OS when the app is launched.

So what’s in the app’s lifecycle?  Well, an android app goes through different states in its lifecycle as a user navigates through, out of, and back to it, such as, when the user receives a phone call or switches to another app, when the user is not actively using it, when the user leaves your app and return to it a later time; and when the screen rotates between landscape and portrait orientation.

Knowing the different states in the lifecycle, how to take advantage of them by making sure your app does not crash, does not consume valuable system resource, and does not lose the user’s progress, will make you a good android app developer.

The figure below describes the states an android app goes through and the different lifecycle callbacks that the system calls and that the app can implement.

So when the app is launched, it is created, started, and resumed, and stays in the resumed state until it is paused, and stays in the paused state until it is resumed, or stopped and stays in a stopped state until it is restarted or destroyed.

Key points to remember here are:

  • Created and Started are transient states, meaning the app does not stay in these states for long.  So basically the app is created, then quickly started, and immediately goes into a resumed state and stays there for some time.
  • Resumed, Paused, and Stopped are static states, meaning these are the possible states that the app maybe currently in at any given time.  The difference between these 3 states are:
    • Resumed or “running” state is when the activity is in the foreground and the user can interact with it.
    • Paused state is when the activity is partially obscured by another activity, usually a dialog window.  The other activity that is in the foreground is semi-transparent or does not cover the entire screen.  The paused activity does not receive input and cannot execute code.
    • Stopped state is when the activity is completely hidden and not visible to the user, thus it is in the background.  The activity instance and all its state information is retained, but it cannot execute any code.
  • Destroyed state is when the activity is completely removed from the system memory.
  • An activity is destroyed when the user presses the back button, or when it terminates itself, or when the system terminates it if it’s currently stopped and hasn’t been used in a long time or the other activity that is in the foreground requires more resources that the system must shut down background processes to recover memory.
  • If the system terminates an activity due to system constraints, the system retains the state of the activity such that when the user navigates back to it, it creates a new activity instance and brings it back to the state it was in when it was destroyed using the saved data.

Managing the Activity Lifecycle from the Android Developer website explains it in more detail including when to implement the different lifecycle callbacks.

What’s different then in handling events in Android?  Similar to how you handle events on windows, you do the same in Android but with some caveat.  You should know that the easiest way to handle event is to create a function, an event handler function, and assign this function to the object’s event through the properties windows.  You can still do this in Android but only with the onClick event unfortunately.

public void onButtonClick(View v) {
    // process event
}

For other events, you need to code them by hand.  There are 3 ways to hookup to an object’s event using code:

  • Creating a subclass of the object’s event listener and creating an instance of it.
@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...
    Button button = (Button) findViewById(R.id.button);
    MyOnClickListener Listener = new MyOnClickListener();
    button.setOnClickListener(Listener);
}
//
public class MyOnClickListener 
        implements View.OnClickListener { 
    public void onClick(View v) {
        // process event
    }
}
  • Implementing the object’s event listener interface in the activity class.
public class MainActivity extends Activity
        implements TextView.OnEditorActionListener {
    //
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        EditText et = (EditText) findViewById(R.id.editText);
        et.setOnEditorActionListener(this);
    }
    //
    @Override
    public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
        TextView t = (TextView) findViewById(R.id.textView2);
        t.setText(textView.getText());
        return true;
    }
}
  • Using an anonymous class
Button b = (Button) findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        TextView t = (TextView) findViewById(R.id.textView2);
        t.setText("Regular button");
    }
});