Wednesday, January 20, 2010

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

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

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

How to get Nokia Battery Level in JavaME

Nokia Symbian 3rd Edition phone introduces "com.nokia.mid.batterylevel" properties which you can get the current battery charge level by calling System.getProperty("com.nokia.mid.batterylevel") from within your midlet application. Its up to your imagination for you to do the rest.

Sample source code (displaying battery charge level on gauge):

JAVA:
  1. /**********
  2. /*
  3. /* Nokia Battery Level midlet
  4. /* Copyright 2008 Mohammad Hafiz bin Ismail (info@mypapit.net)
  5. /* http://mobilepit.com
  6. /*
  7. /* May be use freely
  8. **********/
  9. import javax.microedition.midlet.*;
  10. import javax.microedition.lcdui.*;
  11. public class NokiaBattery extends MIDlet implements CommandListener {
  12. int value;
  13. Display display;
  14. Form form;
  15. Gauge gauge;
  16. Command cmdExit;
  17. public NokiaBattery() {
  18. display = Display.getDisplay(this);
  19. form = new Form("Nokia Battery");
  20. cmdExit = new Command("Exit",Command.EXIT,1);
  21. form.addCommand(cmdExit);
  22. value=Integer.parseInt(System.getProperty("com.nokia.mid.batterylevel"));
  23. gauge = new Gauge("Level",false,100,value);
  24. form.append(gauge);
  25. form.append("Value :"+value);
  26. StringItem item = new StringItem("Network Signal",System.getProperty("com.nokia.mid.networksignal"));
  27. form.append(item);
  28. form.setCommandListener(this);
  29. }
  30. public void startApp(){
  31. display.setCurrent(form);
  32. }
  33. public void pauseApp() {}
  34. public void destroyApp(boolean flags) {
  35. notifyDestroyed();
  36. }
  37. public void commandAction (Command cmd, Displayable disp)
  38. {
  39. if (cmd == cmdExit) {
  40. destroyApp(false);
  41. }
  42. }
  43. }

Download source code and sample midlet : NokiaBattery_midlet.zip

Create PC Bluetooth application easily with pybluez

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. p = pyosd.osd()
  5. p.set_pos(pyosd.POS_MID)
  6. p.set_align(pyosd.ALIGN_CENTER)
  7. p.set_colour("green")
  8. p.display( "Scanning for bluetooth device")
  9. nearby_devices = bluetooth.discover_devices(duration=20, lookup_names = True)
  10. str= "found %d devices" % len(nearby_devices)
  11. print str
  12. p.display(str)
  13. sleep(2)
  14. for name, addr in nearby_devices:
  15. p.display( " %s - %s" % (addr, name))
  16. print (" %s - %s" % (addr,name))
  17. 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]


How to generate Random Numbers in J2ME application

One of the popular question asked in this blog is ways to generate random numbers in J2ME application.

As most people probably realized, the JavaME CLDC does not include the Math.Random class to generate random numbers. However one can generate a series of random numbers in JavaME/J2ME application by using the included java.util.Random class.

Here's a sample usage

JAVA:
  1. import java.util.Random;
  2. ...
  3. Random generator = new Random();
  4. generator.setSeed(System.currentTimeMillis());
  5. float f = generator.nextFloat();
  6. System.out.println(""+(f*100.0f)%100);
  7. ...

The sample code above will produce a random floating-point number between 0..100 (exclusive)

Here's the source code for the full Random Number Demo application : RandomDemo.java,

Presentation Slides for 10 Sept UUM Sintok Class Talk (AP Hatim)

Here is the presentation slides of the 10 Sept 2007 Network Content & Applications in Mobile Devices - Assoc Prof. Hatim Mohamad Tahir class at UUM Sintok.

[tags]sintok,malaysia,uum,presentation,slides,mobile,j2me,javame,webservice,web service,xmlrpc,xml-rpc,soap[/tags]


The best J2ME MIDlet icon size settings

Although not required, It is nice to include icon in your MIDlet distribution as it give a unique feeling to your mobile application. The only problem is different device seems to have different icon sizes requirements for tJ2ME MIDlet.

The Ideal Icon size guidelines for different mobile device
Here is the icon size guideline for different devices

Nokia

  • Series 40 - 128x160=24x24, 208x208=46x46, 240x320=46x48
  • S60 1st and 2nd - 176x208=42x29, 352x416=76x76
  • S60 3rd - 176x208=31x31, 208x176=37x37, 352x416=76x76, 240x320=53x53/55x55, 320x240=52x52/54x54, 208x208=37x37
  • N90/N95 : 84x58

Samsung & Sony Ericsson
Most Samsung phone accept 16x16, 32x32 icon size

Motorola
15x15, 16x16, 32x32

Most phone seems to accept 8bit-depth color for MIDlet icons, except Nokia S60 3rd edition which seems display 24bit icon quite well.

Note that most of this figure are based on experiments and observation on different phone models.

[tags]midlet,java,j2me,javame,midp,midp2,symbian,nokia,motorola,sony ericsson[/tags]




Post a Comment

Template by : kendhin x-template.blogspot.com by :