ads

a simple Click-A-Tell SendSMS HTTP POST API library

Click-a-tell is a simple web service that allows you to integrate sms sending capability into your web application. Its simplicity and wide range of API available is very attractive to small to medium web application developers. Among the API supported by Clickatell are :

  • HTTP POST
  • HTTP GET
  • FTP API
  • SOAP
  • EMAIL-to-SMS
  • COM Object

Clickatell website offers examples of how to use their API in several programming language including but not limited to : VB.net, PHP, ASP, ASP.NET,PERL, Python, Coldfusion, etc.

However I found that the example written for PHP is a little bit outdated and it uses the file() function to initiate HTTP GET request which is generally restricted on webservers as it pose a huge security risk. The other Clickatell class found through PHPClasses website are either too cumbersome for my project or supported other protocol than I intended to use.

As a result I wrote my own Clickatell SMS (clickatell_sendsms_0.5.zip) class specifically for my own use.

Here are a sample code using the SendSMS 0.5 class

PHP:
  1. <?php
  2. require('SendSMS.php');
  3.  
  4.  
  5. $sendsms = new SendSMS("username","password","HTTP POST API key");
  6.  
  7.  
  8. /* if the login return 0, means that login failed, you cant send sms after this */
  9. if  (  ($sendsms->login()) == 0  ) {
  10.     die( "failed");
  11. }
  12.  
  13. /*other wise, you can send sms using the simple send() call*/
  14.  
  15. $sendsms->send("0132073011","testing send sms - camna? boleh dpt ? - mr hafiz");
  16.  
  17. ?>

You can download the clickatell_sendsms_0.5.zip">SendSMS 0.5 PHP class from this website, note that the class is licensed under the terms of the GNU General Public License version 2, and the class is only meant to be use with Click-A-Tell HTTP POST API.

The class can also be use with the libcurlemu library whenever applicable.

JavaME JSR-179 Example Code : Detect Location via TinyGeocoder

I've completed the JSR-179 Location API code for reverse geocoding in JavaME. This code essentially is an expansion of the previous JSR-179 example that i've posted in the blog before, plus the Reverse-Geocoding feature, thanks to TinyGeocoder service.

J2ME GPS Reverse Geocoding mypapit

What this sample MIDlet does?
It obtain coordinates via the mobile phone JSR-179 Location API and subsequently display the name of the location using TinyGeocoder reverse geocoding service.

JAVA:
  1. import javax.microedition.midlet.*;
  2. import javax.microedition.lcdui.*;
  3. import javax.microedition.location.*;
  4. import javax.microedition.io.*;
  5. import javax.microedition.location.*;
  6. import java.io.*;
  7.  
  8. public class Geocoder extends MIDlet implements CommandListener
  9. {
  10.     public Display display;
  11.     public Form form;
  12.     private Command cmdExit,cmdOK;
  13.     public StringItem si, sili;
  14.  
  15.     public Geocoder()
  16.     {
  17.  
  18.         display =Display.getDisplay(this);
  19.         form = new Form("Location Api test");
  20.         cmdExit = new Command("Exit",Command.EXIT,5);
  21.         cmdOK = new Command("OK",Command.OK,1);
  22.         si = new StringItem("Coordinates", "Press OK");
  23.         sili = new StringItem("Location", "");
  24.         form.append(si);
  25.         form.append(sili);
  26.         form.addCommand(cmdOK);
  27.         form.addCommand(cmdExit);
  28.         form.setCommandListener(this);
  29.     }
  30.  
  31.     public void startApp()
  32.     {
  33.         display.setCurrent(form);
  34.     }
  35.  
  36.  
  37.     public void pauseApp()
  38.     {}
  39.  
  40.     public void destroyApp(boolean flag) {
  41.         notifyDestroyed();
  42.     }
  43.  
  44.     public void commandAction(Command c, Displayable d)
  45.     {
  46.         if (c == cmdOK){
  47.             Retriever ret = new Retriever(this);
  48.             ret.start();
  49.  
  50.         } else if (c == cmdExit) {
  51.             destroyApp(false);
  52.         }
  53.     }
  54.  
  55.     public void displayString(String string)
  56.     {
  57.         si.setText(string);
  58.     }
  59.  
  60.     public void showAlert(String message) {
  61.         Alert alert = new Alert("Alert",message,null,AlertType.WARNING);
  62.         display.setCurrent(alert,form);
  63.     }
  64.  
  65.  
  66.  
  67.  
  68. }
  69.  
  70. class Retriever extends Thread {
  71.  
  72.     private Geocoder midlet;
  73.     Form formRunning;
  74.     Gauge gauge;
  75.  
  76.  
  77.  
  78.     public Retriever(Geocoder midlet)
  79.         {
  80.             /**
  81.               * Constructor
  82.               *
  83.               * EFFECTS: Initialise the server and store midlet information
  84.               *
  85.               * @param midlet The main application midlet
  86.               * @param server Forecast Server URL
  87.               *
  88.               */
  89.             this.midlet = midlet;
  90.             formRunning = new Form("Retrieving Info");
  91.             formRunning.append(new Gauge("Processing",false,Gauge.INDEFINITE,Gauge.CONTINUOUS_RUNNING));
  92.             midlet.display.setCurrent(formRunning);
  93.  
  94.     }
  95.  
  96.     public void run()
  97.         {
  98.             /**
  99.             * Entry point of the thread
  100.             *
  101.             * EFFECTS: call to connect() method
  102.             */
  103.             try {
  104.                             checkLocation();
  105.                         } catch (Exception ex)
  106.                         {
  107.                             ex.printStackTrace();
  108.                             midlet.displayString(ex.toString());
  109.             } finally {
  110.  
  111.             }
  112.  
  113.  
  114.         }
  115.  
  116.     public void checkLocation() throws Exception
  117.     {
  118.         String string;
  119.         Location l;
  120.         LocationProvider lp;
  121.         Coordinates c;
  122.         // Set criteria for selecting a location provider:
  123.         // accurate to 500 meters horizontally
  124.         Criteria cr= new Criteria();
  125.         cr.setHorizontalAccuracy(5000);
  126.         cr.setVerticalAccuracy(5000);
  127.  
  128.         // Get an instance of the provider
  129.         lp= LocationProvider.getInstance(cr);
  130.  
  131.         // Request the location, setting a one-minute timeout
  132.         l = lp.getLocation(120);
  133.         c = l.getQualifiedCoordinates();
  134.  
  135.         if(c != null ) {
  136.           // Use coordinate information
  137.           double lat = c.getLatitude();
  138.           double lon = c.getLongitude();
  139.           string = "\nLatitude : " + lat + "\nLongitude : " + lon;
  140.           new GetData(midlet,lat,lon).start();
  141.  
  142.         } else {
  143.             string ="Location API failed";
  144.         }
  145.  
  146.         formRunning.append("Obtained coordinates...");
  147.         midlet.displayString(string);
  148.     }
  149. }
  150.  
  151. class GetData implements Runnable,CommandListener {
  152.  
  153. Geocoder midlet;
  154. double lat, lon;
  155.  
  156. public GetData (Geocoder midlet, double lat, double lon) {
  157.  
  158.     this.lat = lat;
  159.     this.lon = lon;
  160.     this.midlet = midlet;
  161.  
  162.  
  163. }
  164.  
  165. public void commandAction (Command cmd,Displayable disp)
  166. {
  167.  
  168. }
  169.  
  170. public void start() {
  171.        Thread t = new Thread(this);
  172.        t.start();
  173. }
  174.  
  175.  
  176. public void run() {
  177.     HttpConnection conn=null;
  178.     InputStream is=null;
  179.     String sb;
  180.  
  181.     try {
  182.             String sUrl = "http://tinygeocoder.com/create-api.php?g="+""+lat+","+""+lon;
  183.             conn = (HttpConnection) Connector.open(sUrl,Connector.READ);
  184.             if (conn.getResponseCode() == HttpConnection.HTTP_OK) {
  185.                     is = conn.openInputStream();
  186.                     byte buf[] = new byte[128];
  187.                     int total =0;
  188.                     while (total <128) {
  189.                         int count = is.read(buf,total,128-total);
  190.                         if (count<0) {
  191.                             break;
  192.                         }
  193.                         total += count;
  194.                     }
  195.  
  196.                     sb = new String(buf,0,total);
  197.  
  198.                     if (sb.length() <10) {
  199.                             midlet.showAlert("Connection error, please try again");
  200.                             is.close();
  201.                             conn.close();
  202.  
  203.                             return;
  204.                     }
  205.  
  206.                       midlet.sili.setText(sb);
  207.                     //midlet.form.append(sb);
  208.                     //vectorized();
  209.                     //midlet.saveCurrency(false,midlet.vector);
  210.                     //midlet.display.setCurrent(midlet.form);
  211.             } else if (conn.getResponseCode() == HttpConnection.HTTP_NOT_FOUND) {
  212.                     midlet.showAlert("URL not found");
  213.  
  214.             } else {
  215.                 midlet.showAlert("Server busy or unavailable. Please try again later");
  216.             }
  217.  
  218.     } catch (SecurityException sex) {
  219.         midlet.showAlert("Connection failed. You need to authorize this application to access network");
  220.     } catch (IOException ioex) {
  221.             midlet.showAlert("Connection failed. Please try again later.");
  222.     } catch (Exception e){
  223.         midlet.showAlert(e.toString());
  224.         e.printStackTrace();
  225.         //midlet.display.setCurrent(midlet.form);
  226.     } finally {
  227.         try {
  228.             if (is != null) {
  229.                 is.close();
  230.             }
  231.  
  232.             if (conn != null) {
  233.                 conn.close();
  234.             }
  235.         } catch (IOException ioexception) {}
  236.             is =null;
  237.             conn =null;
  238.             midlet.display.setCurrent(midlet.form);
  239.  
  240.  
  241.     }
  242. }
  243.  
  244.  
  245. public String URLEncode(String s)
  246. {
  247.         if (s!=null) {
  248.             StringBuffer tmp = new StringBuffer();
  249.             int i=0;
  250.             try {
  251.                 while (true) {
  252.                     int b = (int)s.charAt(i++);
  253.                     if ((b>=0x30 && b<=0x39) || (b>=0x41 && b<=0x5A) || (b>=0x61 && b<=0x7A)) {
  254.                         tmp.append((char)b);
  255.                     }
  256.                     else {
  257.                         tmp.append("%");
  258.                         if (b <= 0xf) tmp.append("0");
  259.                         tmp.append(Integer.toHexString(b));
  260.                     }
  261.                 }
  262.             }
  263.             catch (Exception e) {}
  264.             return tmp.toString();
  265.         }
  266.         return null;
  267. }
  268. }

The code requires mobile device which implements JSR-179 Location API and has been tested on Nokia E71 and 6210 Navigator.

Google Android Phone Kogan Agora delayed?

February 1st, 2009 No Comments   Posted in Android, Open Source

Probably a stale news for most of you, the touted second Google Android Phone on the market, Kogan Agora product has been canceled despite having received huge pre-orders. The official statement from Kogan Technologies website states that the Kogan Agora release is delayed indefinitely citing technical issues regarding is screen size and resolution.

Kogan Agora, estimated to be available by Christmas 2008, might not even be ready by this year (2009). Customer who pre-ordered Kogan is being refunded as this article were written.

Kogan Agora fakaped

Its a pity to see such affordable Google Android phone to be delayed indefinitely, while there are a lot of phone manufacturers behind Open Handset Alliance (OHA, the organization that backed Android), we have yet to see other Google Android phone surfaces besides HTC manufactured T-Mobile G1.

As for my personal opinion, I don't think Android platform is worth investing in right now since the only supported Android phone in the market is the SIM-locked T-Mobile, and although there has been news that Motorola, Huawei and Sony Ericsson are preparing to release Android phone, I don't think I will give in much hope for Android until I've seen on the shelf of my local mobile phone store (SIM-unlocked, just like normal phones that is)

Primosync: Synchronize Google Calendar with Mobile Phone

Primosync Google Calendar

This week, I've tried Primosync, a JavaME application which allows you to synchronize your Calendar, Events and activities with Google Calendar.

Primosync is compatible with mobile phone which supports JavaME JSR-75 PIM API, a feature that becoming common in latest modern phones.

Advantages of syncing phone calendar with Google Calendar :

  • You will be able to access your event, activities and reminders anywhere with internet connection
  • Your events and reminder will be more portable across various phone models as you can sync it with Google Calendar to update your Calendar
  • Easier to keep track of your reminder and events
  • As a backup measure in case if your mobile phone is stolen or lost

You can download it from Primosync Google Code project website (yes it is open source!) or from Primosync.mobi download site (mobile phone friendly). Available in 3 versions (Blackberry, JavaME Signed, JavaME Unsigned), for some reasons, I was unable to install the Signed version of Primosync in my E71. So I figure the Unsigned version might work in more phones.

So lets start syncing!

Create PC Bluetooth application easily with pybluez

October 23rd, 2007 No Comments   Posted in Open Source, PDA, PocketPC, Tips, Tricks, Guide

pybluez is a python bindings for the bluez application which enables you to interface with bluetooth devices on your computer.

Combined with the power of python dynamic typing, you will be able to do Rapid Application Development and test mobile bluetooth application quickly on your computer

Here's a snippets which combines pyosd and pybluez which scans for nearby bluetooth devices and display the result on screen :

PYTHON:
  1. import bluetooth
  2. import pyosd
  3. from time import sleep
  4.  
  5. p = pyosd.osd()
  6.  
  7. p.set_pos(pyosd.POS_MID)
  8. p.set_align(pyosd.ALIGN_CENTER)
  9. p.set_colour("green")
  10.  
  11. p.display( "Scanning for bluetooth device")
  12.  
  13. nearby_devices = bluetooth.discover_devices(duration=20, lookup_names = True)
  14.  
  15. str= "found %d devices" % len(nearby_devices)
  16. print str
  17. p.display(str)
  18. sleep(2)
  19.  
  20. for name, addr in nearby_devices:
  21.    p.display( "  %s - %s" % (addr, name))
  22.    print (" %s - %s" % (addr,name))
  23.    sleep(2)

Python enables Rapid Application Development on your computer without much fuss. Coupled with pygtk and wxPython acting as GUI, you can create a lot of bluetooth application to interface with your mobile devices, limited only by your imagination.

[tags]python,pybluez,bluetooth,gtk,gnome,linux,mobile,pda,programming,development,RAD[/tags]


iPhoneCanvas – Fancy List component class for J2ME

October 1st, 2007 No Comments   Posted in J2ME / JavaME, Open Source

I found a really nice but simple to use fancy list chooser class that emulates an iPhone display. The class requires MIDP 2.0 supported phones and can replace the default and boring List chooser class into a stunning, smooth scrolling graphical menu (includes reflections) for your users to see

Here's example screenshot of iPhoneCanvas demo in action :

These menu icons are generated from flat and boring thumbnails like these :

Download
iPhoneCanvas is licensed under the GNU General Public License and can be downloaded from listchooser Google Code project page

Demo
The iPhoneCanvas demo featured in above screenshot can be downloaded here - fancylist.jar, fancylist.zip (demo source code)

Please submit bug reports or suggestions at Google Code listchooser page

Foxrate – Open Source J2ME Currency Converter Mobile Application

September 28th, 2007 7 Comments   Posted in J2ME / JavaME, Mobile Software, Open Source, PDA
open source j2me currency converter

Foxrate mobile is a currency converter application for mobile devices. It is a relatively small application which supports converting from/to 35 different currencies used around the world.

Foxrate lifts you from the burden of updating currency rate by automatically retrieving latest currency information from remote server. The best part about foxrate is -- it is available for free and open source!

Download Foxrate Mobile Currency Converter
Foxrate can downloaded from- Google Code's Foxrate page and Getjar.com