Saturday, December 17, 2011

Simple SMS Scheduler

Few weeks ago, I attended a seminar in a university. It was about gathering student resources to start a business. The club provides information about how to get fundings, mentors, etc. It also have a section about creating mobile apps. One of the guys there was talking about an SMS scheduler to send messages to his girlfriend. I found it simple and interesting.

I built the following part time:

App Name: Simple SMS Scheduler
Market Link: https://market.android.com/details?id=com.ignitesms.android

Description:

Simple SMS Scheduler is a clean and simple tool for sending automatic messages at a chosen time. 
Features:
  • Can choose recipients from contact list
  • Sent SMS shows up on default android messaging app
  • Optional delivery and sent reporting via status bar notification
  • Delivery and error history

Screenshots:





Feel free to try it out at https://market.android.com/details?id=com.ignitesms.android.

Feel free to let me know what you think. Feedback, criticisms are always welcomed.

Friday, December 16, 2011

Using javascript in webview to call native code

We will define two js functions in android

  • goToHome
  • showToast

for javacript calls from the webview.

You would call the functions like
<script type="text/javascript">
  window.jsinterface.goToHome()
  window.jsinterface.showToast()
</script>
Define the following in your android activity as an inner class.
public class JSInterface {
public void goToHome() {
Intent i = new Intent(getApplicationContext(), Home.class);
startActivity(i);
}
public void showToast(final String msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
}
In your onCreate function, intialize the webview similar to below:
WebView mWebView = (WebView) findViewById(R.id.webview);
mWebView.setVisibility(View.GONE);
mWebView.addJavascriptInterface(new JSInterface(), "jsinterface");
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int progress) {
Logger.v("webview", String.format("progress changed: %d", progress));
if (progress == 100) {
// webpage loaded completely
} else {
// webpage is loading
}
}
//@Override
public boolean onJsAlert(WebView view, String url,
String message, JsResult result) {
// if you do js alerts, this will show them as toast
Toast.makeText(getBaseContext(), message, Toast.LENGTH_SHORT).show();
result.confirm();
return true;
}
});

Basicly, that's it!

Android soft keyboard not showing on webview

Sometimes your webview may not show the soft keyboard.  This has to do with the focus and the timing that the webview is rendered.

If the soft keyboard does not show up, try to add the following to your webview:

mWebView.requestFocus(View.FOCUS_DOWN);
mWebView.setOnTouchListener(new View.OnTouchListener() {
       @Override
       public boolean onTouch(View v, MotionEvent event) {
           switch (event.getAction()) {
               case MotionEvent.ACTION_DOWN:
               case MotionEvent.ACTION_UP:
                   if (!v.hasFocus()) {
                       v.requestFocus();
                   }
                   break;
           }
           return false;
       }
   });

Thursday, November 24, 2011

Android how to schedule multiple alarms

The Android alarm service is very useful if for scheduling tasks to be done at future dates.  A common use is passing a PendingIntent to the AlarmManager.  When the alarm wakes up the phone, a broadcastReceiver is used to perform the desired actions:

Intent intent = new Intent(a, AlarmReceiver.class);
intent.putExtra("row_id", rowId);
final int alarmId = (int) System.currentTimeMillis();
PendingIntent sender = PendingIntent.getBroadcast(a, alarmId, intent,
    PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) a.getSystemService(a.ALARM_SERVICE);
    am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), sender);

Notice the "alarmId" above.  By setting different private request codes as an argument for the getBroadcast function, you can schedule multiple alarms.  If you use the same id, the previous alarms scheduled will be cancelled.

How to call Android contact list

1) Add the following to your AndroidManifest:

<uses-permission android:name="android.permission.READ_CONTACTS">

2) Call the Contact Picker from your activity by using the following intent:

Intent i = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(i, CHOOSE_CONTACT);

3) get the phone through the contact id; you will need to query the contentResolver twice

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);

  switch (requestCode) {
    case (CHOOSE_CONTACT):
    if (resultCode == Activity.RESULT_OK) {
        Uri contactInfo = data.getData();
        Cursor c = managedQuery(contactInfo, null, null, null, null);
        if (c.moveToFirst()) {
                String contactId = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID));
                String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                String hasPhone = c.getString(c.getColumnIndex(
                        ContactsContract.Contacts.HAS_PHONE_NUMBER));
                String phoneNumber = "";
                if (hasPhone != null &amp;&amp; hasPhone.equalsIgnoreCase("1")) {
                        Cursor phones = getContentResolver()
                                .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,                                                            
                                           ContactsContract.CommonDataKinds.Phone.CONTACT_ID
                                           + " = " + contactId, null, null);

                               while (phones.moveToNext()) {
                                        phoneNumber = phones.getString(phones
                                                .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                               }
                       phones.close();
               }

               // do something with the name and phone; you can also accesss other information such as photo
        }
    }
    break;
  }
}

Saturday, November 19, 2011

Passing data between activities or context objects

You can pass data between activities, broadcastReceivers, etc, by using Intent and Bundle Objects as follows:
Intent intent = new Intent(FROM_ACTIVITY, TO_ACTIVITY);
Bundle bundle = new Bundle();
bundle.putString("data", "Hello World!");
intent.putExtras(bundle);
Similarly, retreiving an object:
Bundle bundle = intent.getExtras();
String data = b.getInt("data", "");
The second argument is the default value. Notice that the bundle object is an argument of the onCreate method for every activity.

Thursday, November 17, 2011

Android sending a sms

1) Add the following permissions in the AndroidManifest.xml:

<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>


2) Import the SMSManager library:

import android.telephony.SmsManager;


3) The simplest way to send a sms is as follows:

public static void sendSMS(String context, String phoneNumber, String message) {      
    PendingIntent pi = PendingIntent.getActivity(this, 0,
            new Intent(context, YOUR_ACTIVITY), 0);              
    SmsManager sms = SmsManager.getDefault();
    sms.sendTextMessage(phoneNumber, null, message, pi, null);      
}


4) To test the sending, start two emulators. The top left corner of the windows is the port number (ex. 5554). Use the port number as the phone number and try to send a message.


5) To get the status about the message after you send it, you can create the sending intent and delivery intent as the broadcastReciever.

public static void sendSMS(Context context, String phoneNumber, String message)
{
        PendingIntent sentPi = PendingIntent.getBroadcast(context, 0,
                new Intent(SENT), 0);
   
        PendingIntent deliveredPi = PendingIntent.getBroadcast(context, 0,
                new Intent(DELIVERED), 0);
   
            registerReceiver(new BroadcastReceiver(){
                @Override
                public void onReceive(Context arg0, Intent arg1) {
                    switch (getResultCode())
                    {
                        case Activity.RESULT_OK:
                            Toast.makeText(context, "SMS sent",
                                    Toast.LENGTH_SHORT).show();
                            break;
                        case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                            Toast.makeText(context, "Generic failure",
                                    Toast.LENGTH_SHORT).show();
                            break;
                        case SmsManager.RESULT_ERROR_NO_SERVICE:
                            Toast.makeText(context, "No service",
                                    Toast.LENGTH_SHORT).show();
                            break;
                        case SmsManager.RESULT_ERROR_NULL_PDU:
                            Toast.makeText(context, "Null PDU",
                                    Toast.LENGTH_SHORT).show();
                            break;
                        case SmsManager.RESULT_ERROR_RADIO_OFF:
                            Toast.makeText(context, "Radio off",
                                    Toast.LENGTH_SHORT).show();
                            break;
                    }
                }
            }, new IntentFilter(SENT));
   
            registerReceiver(new BroadcastReceiver(){
                @Override
                public void onReceive(Context arg0, Intent arg1) {
                    switch (getResultCode())
                    {
                        case Activity.RESULT_OK:
                            Toast.makeText(context, "SMS delivered",
                                    Toast.LENGTH_SHORT).show();
                            break;
                        case Activity.RESULT_CANCELED:
                            Toast.makeText(context, "SMS not delivered",
                                    Toast.LENGTH_SHORT).show();
                            break;                      
                    }
                }
            }, new IntentFilter(DELIVERED));
           
        SmsManager sms = SmsManager.getDefault();
        sms.sendTextMessage(phoneNumber, null, message, sentPi, deliveredPi);      
}


That's it for sending a sms on Android.