<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">

<channel>
	<title>MIDP Adventures</title>
	
	<link>http://sergioestevao.com/blogs/midp</link>
	<description>Java ME tips and tricks for the adventurous coder</description>
	<pubDate>Wed, 10 Sep 2008 16:40:37 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/MidpAdventures" type="application/rss+xml" /><item>
		<title>Developing in Mac OSx</title>
		<link>http://sergioestevao.com/blogs/midp/2008/09/08/developing-in-mac-osx/</link>
		<comments>http://sergioestevao.com/blogs/midp/2008/09/08/developing-in-mac-osx/#comments</comments>
		<pubDate>Mon, 08 Sep 2008 17:49:49 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/blogs/midp/?p=31</guid>
		<description><![CDATA[In the last months I have being busy building a application for the iPhone using the offical Apple iPhone SDK.
I think this new plataform and the bussiness model associated is one step in the right direction. It still has some issues, like the impossibility to create  background applications, but is way ahead of what have [...]]]></description>
			<content:encoded><![CDATA[<p>In the last months I have being busy building a application for the iPhone using the offical Apple iPhone SDK.</p>
<p>I think this new plataform and the bussiness model associated is one step in the right direction. It still has some issues, like the impossibility to create  background applications, but is way ahead of what have available in the Java ME plataform. You can check some tip and tricks in this sister site <a href="http://sergioestevao.com/blogs/iphone/">iPhone Adventures</a>.</p>
<p>Meanwhile because i was assigned a Mac to create applications for the iPhone, I decided to try to develop for MIDP using the Mac OSx. My first idea was to replicate my Windows developing enviroment using Eclipse and EclipseME plug-in, after I had all these  installed I had my first (big) surprise, the Sun-WTK isn&#8217;t available for Mac OSx, then I also discovered that the NetBeans mobility version isn&#8217;t available, becouse is mobile module is based on the Sun WTK SDK.</p>
<p>After some googling around i found an alternative, <a href="http://www.microemu.org/">MicroEmulator</a>, is an open source LGPL Java implementation of J2ME in J2SE. The problem is that it doesn&#8217;t implement all the libraries the WTK supports, so you need to add some extra libraries to have full compability with WTK. Check out the ones below:</p>
<ul>
<li><a href="http://www.bluecove.org/">BlueCove</a> , a open source Bluetooth JSR-82 implementation</li>
<li><a href="http://code.google.com/p/openlapi/">OpenLApi</a>, a open source Location JSR-179 implementation.</li>
</ul>
<p>I also found out that Eclipse Me was adopted as the official tool for mobile development in Eclipse, you can check out the new features being developed <a href="http://eclipseme.org/">here</a> and download a RC version in <a href="http://download.eclipse.org/dsdp/mtj/downloads/index.php">here</a>. I tested it with my projects and it works great.</p>
<p>Update:</p>
<p>After some more trials i discovered that my setup wasn&#8217;t 100 percent, i couldn&#8217;t built jar/jad packages because I didn&#8217;t have a working preverifier. After some more googling around i found the solution for this:</p>
<ul>
<li>Download the Sun WTK for Linux, install it in some folder in your machine.</li>
<li>Rename the folder /wtklib/Linux to /wtklib/Mac</li>
<li>Donwload and install <a href="http://mpowerplayer.com/?cat=6">MPowerPlayer</a> SDK. The official page is crashed but you can use this direct <a href="http://mpowerplayer.com/mpp-sdk-1185.zip">link</a>.</li>
<li>Install the MPowerPlayer and go inside the folder osx/preverify and copy the file preverify to you WTK folder inside the bin folder ( it&#8217;s a good idea to backup the existing file).</li>
<li>After this you can configure you EclipseME/MJT  to use the WTK folder.  This way you can build your project and create the packages.</li>
<li>To emulate the application you will use the MicroEmulator, just create a run configuration and specify this emulator.</li>
</ul>
<p>See you soon</p>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2008/09/08/developing-in-mac-osx/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Log</title>
		<link>http://sergioestevao.com/blogs/midp/2008/06/25/log/</link>
		<comments>http://sergioestevao.com/blogs/midp/2008/06/25/log/#comments</comments>
		<pubDate>Wed, 25 Jun 2008 22:36:54 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[How to]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=54</guid>
		<description><![CDATA[One of the problems of developing for mobile phones is that functionalities that work in the emulators don&#8217;t work in the real devices. Some devices manufacturers offer on device debug functionality for their SDKs but the majority don&#8217;t.
On regular Java development  programmers normally use the &#8220;System.out.println&#8221; to print variables, state information or even exceptions. [...]]]></description>
			<content:encoded><![CDATA[<p>One of the problems of developing for mobile phones is that functionalities that work in the emulators don&#8217;t work in the real devices. Some devices manufacturers offer on device debug functionality for their SDKs but the majority don&#8217;t.</p>
<p>On regular Java development  programmers normally use the &#8220;System.out.println&#8221; to print variables, state information or even exceptions. The problem with this approach is that it doesn&#8217;t help on the actual devices because there isn&#8217;t any console to print on.</p>
<p>After trying different methods on several projects I finally ended up creating a small static class called Log. This simple class as one main method:</p>
<pre>
  public static void log(String text) {
    if (logText == null) {
      logText = new String();
    }
    Date date = new Date();
    logText = date.toString() + ":" + text + "\n" + logText;
    // also print to console in simulators
    System.out.println(text);
  }
</pre>
<p>So now in my projects instead of using the &#8220;System.out.println&#8221; i always use the Log.log method.<br />
But now you ask how can i see this information in the device? for that i added a new method that creates a form and shows it on the screen.</p>
<pre>
public static Displayable showConsole(){
    if (formLogConsole == null) {
      formLogConsole = new Form("Log");
      itemLog = new StringItem("Log:", "");
      formLogConsole.append(itemLog);
      formLogConsole.addCommand(new Command("Back", Command.BACK, 1));
      formLogConsole.addCommand(new Command("Clear", Command.ITEM, 1));
      formLogConsole.setCommandListener(instance());
    }
    current = Display.getDisplay(midlet).getCurrent();
    itemLog.setText(Log.logText);
    return formLogConsole;
  }
</pre>
<p>So whenever i need to check the console i just call the method Log.showConsole() and there it&#8217;s a form with all my logging info. I normally associate this action to a key event.<br />
After you check the log you just press back option and return to your previous &#8220;Displayable&#8221;.</p>
<p>In order to use this functionality you just need to set the midlet variable of the log once in your project. I normally do this in the constructor of the project Midlet.</p>
<p>I also created some helper methods for handling logging of exceptions, you can check them out in the full code.</p>
<p>Happy logging and see you soon.</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2008/06/log.java'>Log.java</a></li>
<ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2008/06/25/log/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Lesson 7 - Network</title>
		<link>http://sergioestevao.com/blogs/midp/2008/02/10/lesson-7-network/</link>
		<comments>http://sergioestevao.com/blogs/midp/2008/02/10/lesson-7-network/#comments</comments>
		<pubDate>Sun, 10 Feb 2008 21:52:32 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=48</guid>
		<description><![CDATA[Now that we have our Arkanoid single player experience complete is time to connect to rest of the world. After all better than show off our high-scores to our friends is to show them to everybody in the Internet!
One of the main features of mobile devices is the ability to be connected almost everywhere anytime. [...]]]></description>
			<content:encoded><![CDATA[<p>Now that we have our Arkanoid single player experience complete is time to connect to rest of the world. After all better than show off our high-scores to our friends is to show them to everybody in the Internet!</p>
<p>One of the main features of mobile devices is the ability to be connected almost everywhere anytime. Java ME allows easy access to these communications features of your device:</p>
<ul>
<li>HTTP</li>
<li>Socket</li>
<li>SMS</li>
<li>Bluetooth</li>
</ul>
<p>During this lesson we are going to learn to use a HTTP connection to send our highscores data to a central server and  to use the SMS functionality to invite other friends to play our Arkanoid game.<br />
<span id="more-26"></span></p>
<h3>Connector and Connections</h3>
<p>The main entry point for network functionality is the factory class Connector. This class allows the creation of Connection objects trough the following static methods:</p>
<ul>
<li>open(String name)</li>
<li>open(String name, int mode)</li>
</ul>
<p>The name parameter is a URL string that identifies the connection you want to make. Depending of the protocol in the URL, a different kind of Connection object is returned. Here is a list of URL and the correspondent Connection objects:</p>
<ul>
<li>&#8220;http://www.server.com&#8221;, returns a http connection, using the class HttpConnection</li>
<li>&#8220;socket://server.com:8080&#8243;, returns a TCP/IP connection</li>
<li>&#8220;btsp://2343434d3434&#8243;, returns a bluetooth connection</li>
<li>&#8220;sms://+351910000000&#8243;, returns a SMS connection to the phone +351910000000</li>
</ul>
<p>Of those protocols only HTTP is mandatory on all Java ME phones, all the others are device dependent, however the majority of new phones support all these protocols.</p>
<p>One thing you must be aware is that when you try to open any kind of connection, the user of your application is notified by the Application Management System. He then has the option to accept or deny your connection, if he denies your application will receive a SecurityException and no communication will happen.</p>
<h3>HTTP</h3>
<p>Let&#8217;s start with HTTP connections, one of the most common type of connections used. To create an HTTP connection you just need to do the following:</p>
<pre>

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

public class Network {

  public byte[] httpConnection(String url, byte[] dataToSend)
    throws IOException
  {
    HttpConnection hc = null;
    // Prepare Connection
    hc = (HttpConnection) Connector.open(url, Connector.READ_WRITE);
    [...]
  }
}
</pre>
<p>The HTTP connections are represented by the HttpConnection class, this class has three states:</p>
<ul>
<li><strong>Setup</strong>, in which you can setup the request parameters</li>
<li><strong>Connected</strong>, where you can send and receive data. You can only send data first and then receive the answer.</li>
<li><strong>Closed</strong>, after you read the data and the connection is ended.</li>
</ul>
<p>When you receive the HttpConnection object from the Connector it&#8217;s in the Setup state. You can then configure the request parameters. One of the main options is the HTTP request method (POST, GET or HEAD).</p>
<pre>
  public byte[] httpConnection(String url, byte[] dataToSend) throws IOException {
    [..]
    if (dataToSend == null){
      hc.setRequestMethod( HttpConnection.GET );
    } else {
      hc.setRequestMethod( HttpConnection.POST );
    }
    [...]
  }
</pre>
<p>You can also configure the request properties like the content type of what you are sending in case of a POST.</p>
<pre>
    hc.setRequestProperty("Content-type", "application/octet-stream" );
</pre>
<p>After you have configured the connection you can start send data, when you start this process you cannot change the request parameters. If the communication goes trough you start receiving data.</p>
<pre>
  public byte[] httpConnection(String url, byte[] dataToSend) throws IOException {
    [...]
    if (dataToSend != null){
      // Write Data
      OutputStream os = hc.openOutputStream();
      os.write( dataToSend );
      os.close();
    }
    // gets answer from  server
    int rc = hc.getResponseCode();
    // check http response
    if (rc == HttpConnection.HTTP_OK){
      // Read Data
      InputStream in = hc.openInputStream();
      ByteArrayOutputStream tmp = new ByteArrayOutputStream();
      int ch;
      while ((ch = in.read()) != -1) {
          tmp.write(ch);
      }
      data = tmp.toByteArray();
      in.close();
      hc.close();
    }

    return data;
  }
</pre>
<p>We now have our httpConnection() method complete let&#8217;s use it in our game to send the high scores to a server. Start by adding a new option to our highscores screen:</p>
<pre>
public Displayable initScoreForm() {
  [...]
  cmdSendHighScore = new Command("Send to Server", Command.ITEM, 1);
  highScoreForm.addCommand(cmdSendHighScore);
  [...]
}
</pre>
<p>And then create a method to use it when this Command is selected:</p>
<pre>
  public String sendScore(String user, int score) {
    String result = "No Answer";
    // server to send data
    String url = "http://www.sergioestevao.com/midpAdventures/post.php";
    // prepare http request
    String urlTotal = url + "?user=" + user + "&amp;score=" + score;
    byte[] data = null;
    try {
      data = network.httpConnection(urlTotal, null);
    } catch (IOException e) {
      result = "Communication Problems";
      e.printStackTrace();
    } catch (SecurityException s) {
      // user denied access to communication
      result = "You need to allow communications in order to send the highscore to server.";
      s.printStackTrace();
    }
    // chek data return.
    if (data != null) {
      result = new String(data);
    }
    return result;
  }
</pre>
<p>And call it when the Command is used</p>
<pre>
   if (cmd == comInviteSend) {
        result = sendScore(scores[0].name, scores[0].value);
        display(new Alert("Result", result, null, AlertType.INFO));
   }
</pre>
<p>If you try this code has it is you will receive the following warning:</p>
<blockquote><p>
Warning: To avoid potential deadlock, operations that may block, such as networking, should be performed in a different thread than the commandAction() handler.
</p></blockquote>
<p>Remember, you are executing this network code as an answer to an user event, that is being executed on the UI thread. If this code blocks or takes a long time to execute all the application will be stuck.</p>
<p>To avoid this issue you must use a thread to do you network related tasks. We start by declaring a thread and some state variables to control the actions of the thread.</p>
<pre>
  private static final int ACTION_SEND_HIGHSCORE = 0;
  public Thread workThread;
  public boolean active = false;
</pre>
<p>Then every time we need to do a time consuming event, we call a method that prepares the thread and starts the action.</p>
<pre>
  public void doAction(int action) {
    // stores action to do
    this.action = action;
    // check if thread is already created
    if (workThread == null) {
      workThread = new Thread(this);
      workThread.start();
      active = true;
    }
    // wakes up thread to work
    synchronized (this) {
      notify();
    }
  }
</pre>
<p>The new thread will execute our run method and do the actions we need</p>
<pre>
public void run() {
    while (active) {
      // check what action to do
      switch (action) {
        case (ACTION_SEND_HIGHSCORE):
          // send the first score to the server
          result = sendScore(scores[0].name, scores[0].value);
          commandAction(cmdReceiveHighScore, highScoreForm);
        break;
      }
      // waits for action to do.
      synchronized (this) {
        try {
          wait();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
</pre>
<p>Don&#8217;t forget to declare the Runnable interface in your midlet</p>
<pre>
 public class MyMidlet extends MIDlet implements CommandListener, Runnable {
</pre>
<p>Now we just need to call our doAction() method when the user chooses the send high score option.<br />
You may have noticed that our run() method invokes a command called cmdReceiveHighScore. This is used to show results of the communication to the user.</p>
<pre>
      if (cmd == cmdSendHighScore) {
        doAction(ACTION_SEND_HIGHSCORE);
      }
      if (cmd == cmdReceiveHighScore) {
        display(new Alert("Result", result, null, AlertType.INFO));
      }
</pre>
<h3>SMS</h3>
<p>Our second use to communications in JavaME is to send invitations to play the game to our friends. And you can have some  competition in the high-scores tables.</p>
<p>First we are going to implement the method that sends the sms on our network class.</p>
<pre>
  public boolean sendSms(String number, String message){
    boolean result = true;
    try {
      //sets address to send message
      String addr = "sms://"+number;
      // opens connection
      MessageConnection conn = (MessageConnection) Connector.open(addr);
      // prepares text message
      TextMessage msg =
      (TextMessage)conn.newMessage(MessageConnection.TEXT_MESSAGE);
      //set text
      msg.setPayloadText(message);
      // send message
      conn.send(msg);
      } catch (Exception e) {
        result = false;
      }
      return result;
  }
</pre>
<p>As you can see we just need to use the open() method of the Connector class with an url of the format &#8220;sms://number&#8221;. Then  you create a TextMessage and send it trough the Connection. The size of the message is limited to around 160 characters.</p>
<p>Now we need to create a form to receive the name and phone information from the user.</p>
<pre>
  public Displayable initInviteForm() {
    if (inviteForm == null) {
      inviteForm = new Form("Invite");
      inviteForm.setCommandListener(this);
      inviteForm.addCommand(initBackCommand());

      inviteName = new TextField("Name:", "", 20, TextField.ANY);
      inviteNumber = new TextField("Number:", "", 20, TextField.PHONENUMBER);
      inviteForm.append(inviteName);
      inviteForm.append(inviteNumber);
      comInviteSend = new Command("Invite", Command.ITEM, 1);
      inviteForm.addCommand(comInviteSend);
    }

    return inviteForm;
  }
</pre>
<p>And implement the commands action to show our form and send the message using our worker thread.</p>
<pre>
public void commandAction(Command cmd, Displayable display) {
   [...]
   else if (display == inviteForm) {
      if (cmd == comBack) {
        display(initMainForm());
      }
      if (cmd == comInviteSend) {
        doAction(ACTION_SEND_INVITE);
      }
    }
  [...]
}
</pre>
<p>Finally we implement the new action in our run method</p>
<pre>
public void run() {
  [...]
  case (ACTION_SEND_INVITE):
    // invite another player to play
    String inviteMessage = " invites you to play Transnoid!";
    network.sendSms(inviteNumber.getString(), inviteName.getString()
      + inviteMessage);
    break;
  }
  [..]
}
</pre>
<p>Now run your game and start sending invitations to your friends :). See you soon.</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2008/02/lesson7-source.rar' title='Lesson 7 - Full Source Code'>Full Source Code</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2008/02/formacao7.jad' title='Lesson 7 - Jad File'>Jad File</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2008/02/formacao7.jar' title='Lesson 7 - Jar File'>Jar File</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2008/02/10/lesson-7-network/feed/</wfw:commentRss>
		</item>
		<item>
		<title>2008 - News</title>
		<link>http://sergioestevao.com/blogs/midp/2008/02/10/2008-news/</link>
		<comments>http://sergioestevao.com/blogs/midp/2008/02/10/2008-news/#comments</comments>
		<pubDate>Sun, 10 Feb 2008 21:51:51 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=53</guid>
		<description><![CDATA[Hi guys,
I&#8217;ve been somewhat quite for the last couple of months, the reason of my silence was a very busy holiday season and a beginning of the year with a lot of work.
Now that i have some free time i restarted to write for MIDP adventures, i already have ready one more lesson about networking [...]]]></description>
			<content:encoded><![CDATA[<p>Hi guys,</p>
<p>I&#8217;ve been somewhat quite for the last couple of months, the reason of my silence was a very busy holiday season and a beginning of the year with a lot of work.</p>
<p>Now that i have some free time i restarted to write for MIDP adventures, i already have ready one more lesson about networking and hope to write two more articles, one  about &#8220;log and debug&#8221; and another about &#8220;post multipart forms&#8221;.</p>
<p>I you have any requests for new articles tutorials feel free to send me an email or a comment.</p>
<p>See you soon</p>
<p>P.S: One of the gifts i received this Christmas has a brand new N95 from the Nokia folks (thanks Ron). Now i can test some new features this device has: internal GPS, motion sensor and hopefully write  some articles about these.</p>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2008/02/10/2008-news/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Lesson 6 - Multimedia</title>
		<link>http://sergioestevao.com/blogs/midp/2007/11/29/lesson-6-multimedia/</link>
		<comments>http://sergioestevao.com/blogs/midp/2007/11/29/lesson-6-multimedia/#comments</comments>
		<pubDate>Thu, 29 Nov 2007 17:29:46 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=16</guid>
		<description><![CDATA[In our last lesson we learned how to save our game settings, the Sound On/Off screen, but why we have this option, if we don&#8217;t have any sound in our game? It&#8217;s time to learn about Java Mobile Multimedia API (MMAPI) and add some sound to our game. Let&#8217;s rock!
MMAPI offers a set of multimedia [...]]]></description>
			<content:encoded><![CDATA[<p>In our last lesson we learned how to save our game settings, the Sound On/Off screen, but why we have this option, if we don&#8217;t have any sound in our game? It&#8217;s time to learn about Java Mobile Multimedia API (MMAPI) and add some sound to our game. Let&#8217;s rock!</p>
<p>MMAPI offers a set of multimedia capabilities for mobile devices, including playback and recording of audio and video data from a variety of sources. Of course, not all mobile devices support all the options, but MMAPI is designed in such a way that it takes full advantage of the capabilities that are available, while ignoring those that it cannot support.<br />
<span id="more-24"></span></p>
<h3>MMAPI Info</h3>
<p>The MMAPI is built on a high-level abstraction of all the multimedia devices. This abstraction is implemented  in three classes that form the core of operations that you do with this API. These classes are the Player and Control interfaces, and the Manager class. Another class, the DataSource abstract class, is used to locate resources, but unless you define a new way of reading data you will probably never need to use it directly.</p>
<p>In a nutshell, you use the Manager class to create Player instances for different media by specifying DataSource instances. The Player instances thus created are configurable by using Control instances. For example, almost all Player instances would theoretically support a VolumeControl to control the volume of the Player. Check the following diagram:</p>
<p><a href='http://sergioestevao.com/blogs/midp/files/2007/11/mmapi-mainclasses.png' title='MMAPI - Main Classes'><img src='http://sergioestevao.com/blogs/midp/files/2007/11/mmapi-mainclasses.png' alt='MMAPI - Main Classes' /></a></p>
<p>So let&#8217;s start with the Manager class, basically its a factory of players supporting the following creation methods:</p>
<ul>
<li>createPlayer(DataSource source), creates a player based on a DataSource</li>
<li>createPlayer(InputStream stream, String type), creates a player using the input stream as source and assuming the the media type provided. For a list of media types check at <a href="http://www.iana.org/assignments/media-types/">IANA</a> web site.</li>
<li>createPlayer(String locator), creates a player using a URL type parameter to identify the source data</li>
</ul>
<p>This last method allows you to alocate different types of media depending of the URL protocol you choose. Here is a list of supported types:</p>
<ul>
<li>Midi Player - &#8220;device://midi&#8221;, creates a midi Player.</li>
<li>Tone Player - &#8220;device://tone&#8221;, creates a tone Player.</li>
<li>Capture Audio -  &#8220;capture://audio&#8221;, allows to capture audio from the device mic.</li>
<li>Capture Video -  &#8220;capture://video&#8221;, allows to capture video from the device camera.</li>
<li>Capture Radio -  &#8220;capture://radio?f=105.1&amp;st=stereo&#8221;, allow to capture radio.</li>
</ul>
<p>If you want to know what content types and protocols are supported for your device, use the following methods of Manager class:</p>
<ul>
<li>getSupportedContentTypes(), provides a list of available content types for all protocols or to a specific one.</li>
<li>getSupportedProtocols(), provides a list of available protocols for all content types or to a specific one.</li>
</ul>
<p>After you created a Player, you can start using it by simple calling the start() method, when it reach the end of media it will automatically stop.<br />
This is the more simplistic view of the Player class, actually it has five states:</p>
<ul>
<li>UNREALIZED, this is the initial state of Player when obtain from the Manager.</li>
<li>REALIZED, when realized() is called the Player switch to this state obtaining the information required to acquire the media resources. Realizing a Player can be a resource and time consuming process. The Player may have to communicate with a server, read a file, or interact with a set of objects. </li>
<li>PREFETCHED, after a player is realized, it may still need to acquire scarce or exclusive resources, fill buffers with media data, or perform other start-up processing. This is done by calling the prefetch() method that switch the player to this state.</li>
<li>STARTED, when start() is called the Player starts to play the media resource until it reach the end of the media.</li>
<li>CLOSED, when close() is called the Player switch to this state, releasing all the resources acquired. It can&#8217;t be used again.</li>
</ul>
<p>The following figure shows the various states and the transitions possible between them:</p>
<p><a href='http://sergioestevao.com/blogs/midp/files/2007/11/mmapi-playerstates.png' title='MMAPI - Player States'><img src='http://sergioestevao.com/blogs/midp/files/2007/11/mmapi-playerstates.png' alt='MMAPI - Player States' /></a></p>
<p>If your application needs information about the state changes you need to implement the PlayerListerner interface.</p>
<h3>Play a Sound</h3>
<p>Now that he have all the background information about MMAPI, let&#8217;s start using it in our Arkanoid clone. The idea is to play a sound each time the ball hits a brick or the pad. To do this  we are going to create a class called Multimedia with a playSound() method:</p>
<pre>
//multimedia libraries
import javax.microedition.media.Manager;
import javax.microedition.media.Player;
import javax.microedition.media.MediaException;
public class Multimedia {
  public void playSound(String file, String format) {
    try {
      InputStream is = getClass().getResourceAsStream(file);
      Player p = Manager.createPlayer(is, format);
      p.start();
    } catch (IOException ioe) {
    } catch (MediaException me) {
    }
  }
</pre>
<p>Now he just need to use this method each time we detect a collision between the ball and the other entities. I created for this purpose a sound named &#8220;click.wav&#8221; that i added to our resource folder.</p>
<pre>
public void updateGameState(){
  ...
  byte colision = ball.colided(pad);
  if (colision != Entity.COLLISION_NONE){
      if (midlet.soundOn){
        midlet.multimedia.playSound("click.wav", "audio/X-wav");
      }
    }
  ...
}
</pre>
<p>If you run your application, you will finally hear some sound on your game.</p>
<h3>Capture video</h3>
<p>Now that we have sound let&#8217;s add another cool feature, let&#8217;s capture the player photo each time he achieves a high score. For that we first need to access the camera video and show it to the player, the following method captures the camera video stream to an Item.</p>
<pre>
  Player p;
  VideoControl vc;
  public Item showVideo(String url){
    Item result = null;
    try {
        p = Manager.createPlayer(url);
        p.realize();
        // Grab the video control .
        vc = (VideoControl)p.getControl("VideoControl");
        if (vc != null) {
            // create the Item with the video image
            result =((Item)vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null));
            // add a label
            result.setLabel("Photo");
        }
        // start capture
        p.start();
    } catch (IOException ioe) {
    } catch (MediaException me) { }
    return result;
  }
</pre>
<p>As you can see we are using a Control, the VideoControl,  to create the Item to use in our Form.</p>
<pre>
public Displayable initNewHighScore(int score, int pos) {
  ...
  newHighScoreForm.append(multimedia.showVideo("capture://video"));
  ...
}
</pre>
<p>Now we need to use our VideoControl to capture an image from the camera,</p>
<pre>
  public Image captureVideo(){
    Image result = null;
    try {
        // grab data
        byte[] imageData = vc.getSnapshot("encoding=png");
        // create image;
        result = Image.createImage(imageData, 0, imageData.length);
    } catch (MediaException me) {
      me.printStackTrace();
    }
    return result;
  }
</pre>
<p>and then call this method when we save a high score.</p>
<pre>
  // we added an extra field to Score to store the image
  scores[pos].image = multimedia.captureVideo();
</pre>
<p>After this we just need to show our images in the high scores screen.</p>
<pre>
public Displayable initScoreForm() {
...
  if (scores[i].image != null){
    highScoreForm.append(scores[i].image);
  }
...
}
</pre>
<p>Just run the application to check our new feature! With this we end this lesson, next lesson we are going to see how to use the network capabilities of your phone. See you soon.</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/lesson6-source.rar' title='Full Source Code'>Full Source Code</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/formacao6.jad' title='Lesson 6 - Jad File'>Jad File</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/formacao6.jar' title='Lesson 6 - Jar File'>Jar File</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2007/11/29/lesson-6-multimedia/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Optimization</title>
		<link>http://sergioestevao.com/blogs/midp/2007/11/27/optimization/</link>
		<comments>http://sergioestevao.com/blogs/midp/2007/11/27/optimization/#comments</comments>
		<pubDate>Tue, 27 Nov 2007 15:01:18 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[How to]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=41</guid>
		<description><![CDATA[There are three key factors to considered when you want to optimize your Java ME applications

Performance
Size

You should delay optimization until the last minute, after you create the main features of our application, but you need to keep in mind all the key factors throughout the development cycle to avoid huge changes at the end.

Performance
Rule number [...]]]></description>
			<content:encoded><![CDATA[<p>There are three key factors to considered when you want to optimize your Java ME applications</p>
<ul>
<li>Performance</li>
<li>Size</li>
</ul>
<p>You should delay optimization until the last minute, after you create the main features of our application, but you need to keep in mind all the key factors throughout the development cycle to avoid huge changes at the end.</p>
<p><span id="more-21"></span></p>
<h3>Performance</h3>
<p>Rule number one for performance is <strong>&#8220;keep it simple&#8221;</strong>, don&#8217;t try to create over complex systems, for your mobile phone, remember people want fast and easy to use applications/games, to use on the move.<br />
With this mind take in account the following issues:</p>
<h4>Threads </h4>
<ul>
<li>Use only one application thread, avoid multiple threads. Many devices cannot handle too many threads, they simple stop. Network thread is the only exception for creating a new thread</li>
<li>Minimized usage of synchronized, is expensive on legacy devices and is very common to create poorly synchronized code. Synchronizing run with paint() and keyPressed() is ok.</li>
<li>Avoid using Timer class, an extra thread is created for each one.
<li>Create a background thread in startApp() and reuse it.</li>
<li>Don’t use Display.callSerially(), is very slow and buggy on many devices. A new thread is created in most implementations</li>
<li>Avoid serviceRepaints() on legacy devices when performance become an issue</li>
<li>Might need to ensure thread safety (background thread and system thread) if serviceRepaints() is not used</li>
</ul>
<p>An example for the base structure for you application:</p>
<pre>
public void startApp() {
  animationThread = new Thread(this);
}

public void run() {
  init();
  while(!exitApp) {
    updateModel(); // your app logic
    repaint();
    serviceRepaint();
    sleep(50); // may choke slow devices if too small
  }
}
</pre>
<h4>System Callbacks</h4>
<p>You must handle with care the system callbacks, they are called by the system thread. They must not block and should return    as soon as possible to avoid slowing down the VM. A crash can happen if not returning quick enough.<br />
Here is a list with the more common system callbacks:</p>
<ul>
<li>paint</li>
<li>keyPressed</li>
<li>startApp/pauseApp</li>
<li>hideNotify/showNotify</li>
<li>MIDlet constructor</li>
</ul>
<p>Below you have a bad example of a system callback:</p>
<pre>
public void paint(Graphics g) {
  updateModel();
  drawBackground(g);
  drawForeground(g);
}

public void run() {
  while(!exitApp) {
    repaint();
    serviceRepaints();
    sleep(50);
  }
}
</pre>
<p>As you may have noticed we are updating our model, an expensive operation, during the system event paint. We should change our code to the following:</p>
<pre>
public void paint(Graphics g) {
  drawBackground(g);
  drawForeground(g);
}

public void run() {
  while(!exitApp) {
    updateModel(); // better do it here
    repaint();
    serviceRepaints();
    sleep(50);
  }
}
</pre>
<h4>Different Devices - Different Performances</h4>
<p>There are huge differences between high end and low end devices, devices can be much faster or slower than you expected, so you cannot assume performance.</p>
<p>If you have your game logic based on frame rate this may result in totally unplayable game. You should instead base your game on actual time instead, like the example below:</p>
<pre>
public void updateModel() {
  curTime = System.currentTimeMillis();
  elapsedTime = curTime – prevTime;
  // using elapsedTime for your app logic here
  prevTime = curTime;
}

public void run() {
  while(!exitApp) {
    updateModel();
    repaint();
    serviceRepaints();
    sleep(50);
  }
}
</pre>
<p>Another thing to take in account is the performance of some APIs, some calls are slower than others:</p>
<ul>
<li>drawString(),  replace with graphics font</li>
<li>drawArc(), Vector, Hashtable, replace with own implementation</li>
<li>drawImage(), replace large images with a series of smaller images for some devices</li>
</ul>
<p>Another thing to handle with care is collision detection, it must be calculated in between frames to avoid problems on low frame rate devices.</p>
<p>Disable certain features on slow device via JAD entry. E.g. if &#8220;tree.png&#8221; does not exist, don&#8217;t draw the tree sprite</p>
<h4>I/O</h4>
<p>The use of RMS and getResourceAsStream calls is very  slow. Take the following consideration when using them:</p>
<p><strong>RMS</strong></p>
<ul>
<li>Read entire record into a buffer</li>
<li>Then parse the buffer</li>
<li>Similarly, write to a single buffer, then write the buffer to a record</li>
</ul>
<p><strong>getResourceAsStream()</strong></p>
<ul>
<li>Extremely slow on some devices (as slow as 20 bytes per second)</li>
<li>Class loading is much faster on these devices</li>
<li>Workaround—store data in separate class files instead of using resource. This may result in slightly longer application load time</li>
</ul>
<h4>General</h4>
<p>Here some “Little things” that make big differences:</p>
<ul>
<li>Avoid unnecessary object creation/memory allocation.</li>
<li>Reduce, reuse, recycle the object instances you use</li>
<li>Strings, don&#8217;t do big string concatenations using &#8220;+&#8221;, use StringBuffer class instead</li>
<li>Image, small is good—split large images, create a Image cache
<li>Object pooling might work in some cases</li>
<li>Loops, avoid unecessary creation/disposal of variables inside loops</li>
<li>Use switch-case instead of if-blocks, they are translated to faster java bytecodes</li>
<li>Use public variables directly instead of using get/set methods.</li>
<li>Set variables to null  when you don&#8217;t need them anymore</li>
<li>Garbage Collector, call frequently and explicitly on some devices. Beware of non-compacting GC</li>
<li>Use local variables instead of global variables when you can. Local variables are faster and use less bytecode</li>
</ul>
<p>Take a look at the following example:</p>
<pre>
for(y = 0; y &lt; oriHeight; y++) {
  for(x = 0; x &lt; oriWidth / 2; x++) {
    int idx1 = y * oriWidth + x;
    int idx2 = (y + 1) * oriWidth – 1 - x;
    curPixel = buf[idx1];
    buf[idx1] = buf[idx2];
    buf[idx2] = curPixel;
  }
}
</pre>
<p>If we do the index creation outside of the loops like this:</p>
<pre>
  int idx1;
  int idx2;
  for(y = 0; y &lt; oriHeight; y++) {
    idx1 = y * oriWidth;
    idx2 = (y + 1) * oriWidth – 1;
    for(x = 0; x &lt; oriWidth / 2; x++) {
      curPixel = buf[idx1];
      buf[idx1] = buf[idx2];
      buf[idx2] = curPixel;
      idx1++;
      idx2--;
    }
  }
</pre>
<p>It can save a few seconds on a real device!</p>
<h3>Size</h3>
<p>The size restriction for Java ME applications comes from two sources:</p>
<ul>
<li>Device capability, some devices only accept 64 kb applications!! </li>
<li>Operator’s gateway limitation, to avoid customers waiting too long (and pay to much)for an application to download some operators limit the max application size (normally around 300kb)</li>
</ul>
<p>Device JAR size limit has improved continuously over time, but it is never enough for developers! So here some tips to help you</p>
<ul>
<li> Minimize classes number, avoid OOP (if practical), each class/interface contribute at least 250 bytes of overhead after compression. Can get away with 2 classes: one MIDlet class and one Canvas class.</li>
<li>Use an Obfuscator</li>
<li>Optimize Images</li>
<li>Change ZIP algorithm, JDK’s JAR utility is not optimal. Use open source, freeware or commercial alternatives, where number of passes are configurable, but beware of device compatibility.</li>
</ul>
<h4>Obfuscator</h4>
<p>What does it do? It&#8217;s original purpose is to make reverse engineering very difficult by:</p>
<ul>
<li>Eliminate packages (i.e. always use default package)</li>
<li>Rename method/field names</li>
<li>Remove unused code</li>
</ul>
<p>But is has the nice side effect of creating smaller class files size (and also slightly faster). Some of them also perform bytecode optimization. They can typically can reduce file size by 30–50%<br />
There are very good Open source obfuscators (<a href="http://proguard.sourceforge.net/">Proguard</a>, <a href="http://www.retrologic.com/">Retroguard</a>) and many other commercial products.</p>
<h4>Images</h4>
<p>What are the problems?</p>
<ul>
<li>Not compressible</li>
<li>Each PNG file contains more of less the same header and footer</li>
<li>Flipped images, transformed images on MIDP 2.0 devices are either very slow or not working. Isn&#8217;t supported in MIDP 1.0 devices. Must include flipped version of sprites at build time this can  double or quadruple the size</li>
</ul>
<p>Here are the solutions:</p>
<ul>
<li>Use PNG optimizer like <a href="http://optipng.sourceforge.net/">OptiPNG</a> or <a href="http://pmt.sourceforge.net/pngcrush/">PNGCRUSH</a></li>
<li>Alternatively, do not compress image content - larger PNG sizes before compression but smaller at the end</li>
<li>Combine multiple PNGs into a single resource bundle or a large image. It becomes more compressible and we stripped off the header and footer</li>
<li>Flipped images</li>
<li>Dynamically flip images at run time</li>
<li>Potentially a performance/JAR size tradeoff</li>
<li>Reduce colour depth (if possible)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2007/11/27/optimization/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Read location from Bluetooth GPS</title>
		<link>http://sergioestevao.com/blogs/midp/2007/11/25/read-location-from-bluetooth-gps/</link>
		<comments>http://sergioestevao.com/blogs/midp/2007/11/25/read-location-from-bluetooth-gps/#comments</comments>
		<pubDate>Sun, 25 Nov 2007 15:31:25 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[How to]]></category>

		<category><![CDATA[bluetooth]]></category>

		<category><![CDATA[gps]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=36</guid>
		<description><![CDATA[One of the most sold accessories for mobile phones and PDAs are Bluetooth GPS (BT-GPS). These simple devices connect to the GPS satellite system and allows to pinpoint your position with 5 meters precision. It&#8217;s possible to access this information trough a JavaME application you just need to have Bluetooth phone with the JSR 82 [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most sold accessories for mobile phones and PDAs are Bluetooth GPS (BT-GPS). These simple devices connect to the GPS satellite system and allows to pinpoint your position with 5 meters precision. It&#8217;s possible to access this information trough a JavaME application you just need to have Bluetooth phone with the JSR 82 Bluetooth API available on it.</p>
<p>To read location information from a bluetooth GPS, we need to implement the following tasks:</p>
<ol>
<li>Search for the Bluetooth GPS  device</li>
<li>Connect to the GPS device</li>
<li>Read and Parse NMEA sentences</li>
</ol>
<p><span id="more-20"></span></p>
<p>For the first step we need to search for a Bluetooth device that implements the RFCOMM service, I include in the sample code a class, &#8220;BTManager.class&#8221;, that does all this work. If you want to have more information about this, see this <a href="http://sergioestevao.com/midp/?p=37">post</a>.</p>
<p>For the purpose of reading data from the BT-GPS lets create an GpsBt class. The first thing to do is to create some variable to store the URL address for your BT-GPS.</p>
<pre>  // current bluetooth device
  public String btUrl = "";
  public String btName = "";

  public void setDevice(String btUrl, String btName) {
    this.btUrl = btUrl;
    this.btName = btName;
  }</pre>
<p>Now we need to connect to the device and start reading  the data.</p>
<pre>    public void start() {
    if (isActive) {
      stop();
    }
    connect();
    if (isConnected) {
      isActive = true;
      Thread t = new Thread(this);
      t.start();
    }
  }

  public void connect() {
    if (btUrl == null || (btUrl.trim().compareTo("") == 0)) {
      isConnected = false;
      return;
    }
    try {
      conn = (StreamConnection) Connector.open(btUrl, Connector.READ_WRITE);
      in = new DataInputStream(conn.openInputStream());
      isConnected = true;
      mode = 0;
    } catch (IOException e) {
      close();
    }
  }

  public void run() {
    isActive = true;
    while (isActive) {
        // check if connection is still open
        if (!isConnected &amp;&amp; isActive) {
          // connect to gps device
          connect();
        } else {
          // read NMEA Strings
          readNMEASentences();
        }
    }
    close();
    isActive = false;
  }</pre>
<p>As you may have noticed I&#8217;m implementing the reading loop using a thread. The reason for this, is that the BT-GPS is always sending data so you need to keep read from it before the connection buffer overflows. The data the BT-GPS sends are NMEA sentences, these sentences gives several information about the GPS status. The one we are searching for is the GPGGA sentence that gives essential fix data  and provides 3D location and accuracy data.</p>
<pre> public void readNMEASentences() {
    try {
      if (!isConnected) {
        return;
      }
      // check characters available
      int size = in.available();
      if (size &lt;= 0) {
        return;
      }
      // read data
      for (int j = 0; j &lt; size; j++) {
        int i = in.read();
        if (i != -1) {
          char l = (char) i;
          switch (mode) {
          case (STATE_SEARCH_SENTENCE_BEGIN): {
            // search for the sentence begin
            if (l == '$') {
              // found begin of sentence
              mode = 1;
              sb.setLength(0);
            }
          }
            break;
          case (STATE_READ_DATA_TYPE): {
            // check what kind of sentence we have
            sb.append(l);
            if (sb.length() == 6) {
              if (sb.toString().startsWith("GPGGA")) {
                mode = STATE_READ_SENTENCE;
                sb.setLength(0);
              } else {
                mode = STATE_SEARCH_SENTENCE_BEGIN;
                sb.setLength(0);
              }
            }
          }
            break;
          case (STATE_READ_SENTENCE): {
            // read data from sentence
            sb.append(l);
            if ((l == 13) || (l == 10) || (l == '$')) {
              mode = STATE_SEARCH_SENTENCE_BEGIN;
              currentInfo = new String(sb.toString());
            }
          }
            break;
          }

        } else {
          close();
        }
      }

    } catch (Exception e) {
      close();
    }
  }</pre>
<p>After we have the correct sentence we just need to parse the information  and retrieve it to the user</p>
<pre> public Location getLocation() {
    Location location = new Location();
    if (isConnected &amp;&amp; isActive &amp;&amp; currentInfo != null) {
        location.parseGPGGA(currentInfo);
    }
    return location;
  }</pre>
<p>To help us to retrieve data we use a class, called Location, to parse the GGA sentence and wrap the position data. We are also using a class called StringTokenizer to split the tokens in the sentence.</p>
<pre>public class Location {

  // NMEA GPGGA Elements
  String utc;
  String latitude;
  String northHemi;
  String longitude;
  String eastHemi;
  String altitude;
  int quality;
  int nSat;
  String horDilution;
  String altitudeUnit;
  String geoidalHeight;
  String geoidalHeightUnit;
  String diffCorrection;
  String diffStationId;

  /**
   * Method that parses a NMEA string and returns Location. For more info check
   * this page: http://www.gpsinformation.org/dale/nmea.htm#GGA
   *
   * @param value -
   *          string that represent NMEA GGA string
   */
  public void parseGPGGA(String value) {
    // Helper class to parse strings
    StringTokenizer tok = new StringTokenizer(value, ",");

    utc = tok.nextToken();
    latitude = tok.nextToken();
    northHemi = tok.nextToken();
    longitude = tok.nextToken();
    eastHemi = tok.nextToken();
    quality = Integer.parseInt(tok.nextToken());
    nSat = Integer.parseInt(tok.nextToken());
    horDilution = tok.nextToken();
    altitude = tok.nextToken();
    altitudeUnit = tok.nextToken();
    geoidalHeight = tok.nextToken();
    geoidalHeightUnit = tok.nextToken();
    diffCorrection = tok.nextToken();
    diffStationId = tok.nextToken();
  }
}</pre>
<p>And that&#8217;s a wrap we now have a class capable of reading the NMEA sentences from the BT-GPS and retrieve location info. Check the full source code for an complete application that allows you to search for devices, connect to them and shows the location info on the screen.</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a title="Bluetooth GPS - Full Source Code" href="http://sergioestevao.com/midp/wp-content/uploads/2007/11/bluetoothgps-source-code.rar">Full Source Code</a></li>
<li><a title="Bluetooth GPS - Jad File" href="http://sergioestevao.com/midp/wp-content/uploads/2007/11/bluetoothgps.jad">Jad File</a></li>
<li><a title="Bluetooth GPS - Jar File" href="http://sergioestevao.com/midp/wp-content/uploads/2007/11/bluetoothgps.jar">Jar File</a></li>
</ul>
<p><strong>References</strong>:</p>
<ul>
<li><a href="http://www.digitalmobilemap.com/">Vietnamese GPS - Intelligent on the go</a></li>
<li><a href="http://www.gpsinformation.org/dale/nmea.htm#nmea">NMEA Reference</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2007/11/25/read-location-from-bluetooth-gps/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Search for Bluetooth devices and services</title>
		<link>http://sergioestevao.com/blogs/midp/2007/11/25/search-for-bluetooth-devices-and-services/</link>
		<comments>http://sergioestevao.com/blogs/midp/2007/11/25/search-for-bluetooth-devices-and-services/#comments</comments>
		<pubDate>Sun, 25 Nov 2007 14:52:01 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[How to]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=37</guid>
		<description><![CDATA[To use the Bluetooth protocol on an JaveMe application your mobile device must implement the JSR 82 Bluetooth API.
One of the main challenges on bluetooth applications is to find out the connection address, for devices with an specific services available on them.
In the following sample we are going to see how to implement this code [...]]]></description>
			<content:encoded><![CDATA[<p>To use the Bluetooth protocol on an JaveMe application your mobile device must implement the JSR 82 Bluetooth API.<br />
One of the main challenges on bluetooth applications is to find out the connection address, for devices with an specific services available on them.</p>
<p>In the following sample we are going to see how to implement this code using  an class called BtManager.<br />
<span id="more-19"></span><br />
Let&#8217;s start creating the class and some variables to store our results.</p>
<pre>
import java.util.Vector;
// bluetooth classes
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;

public class BTManager implements DiscoveryListener {
  // used to store devices we found
  public Vector btDevicesFound;
  // used to store service information for each device
  public Vector btServicesFound;

  public BTManager() {
    btDevicesFound = new Vector();
    btServicesFound = new Vector();
  }

  public int find(UUID[] aServices){
    // search for devices
    findDevices();
    // search for services in the devices found
    findServices(aServices);
    return btDevicesFound.size();
  }
</pre>
<p>As you can see we are going to implement the DiscoveryListener interface. This interface provides all the callbacks for our bluetooth calls. Let&#8217;s start for searching for devices:</p>
<pre>
public int findDevices() {
    try {
      // cleans previous elements
      btDevicesFound.removeAllElements();
      // resets status variable
      isBTSearchComplete = false;
      LocalDevice local = LocalDevice.getLocalDevice();
      DiscoveryAgent discoveryAgent = local.getDiscoveryAgent();
      // start discovery of new devices
      discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
      while ((!isBTSearchComplete)) {
        //waits for a fixed time, to avoid long search
        synchronized (this) {
          this.wait(BTManager.BLUETOOTH_TIMEOUT);
        }
        // check if search is completed
        if (!isBTSearchComplete) {
          // search no yet completed so let's cancel it
          discoveryAgent.cancelInquiry(this);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    // returns the number of devices found
    return btDevicesFound.size();
  }

  public void deviceDiscovered(RemoteDevice remoteDevice,
      DeviceClass deviceClass) {
    btDevicesFound.addElement(remoteDevice);
  }

  public void inquiryCompleted(int param) {
    isBTSearchComplete = true;
    // notifies and wake main thread that device search is completed
    synchronized (this) {
      this.notify();
    }
  }
</pre>
<p>Now that we have a list of devices, let&#8217;s search for the services we want:</p>
<pre>
public void findServices(UUID[] aServices) {
     // cleans previous elements
     btServicesFound.removeAllElements();
     try {
       LocalDevice local = LocalDevice.getLocalDevice();
       DiscoveryAgent discoveryAgent = local.getDiscoveryAgent();
      // discover services
      if (btDevicesFound.size() &gt; 0) {
        for (int i = 0; i &lt; btDevicesFound.size(); i++) {
          isBTSearchComplete = false;
          // adds a null element in case we don't found service
          btServicesFound.addElement(null);
          int transID = discoveryAgent.searchServices(null, aServices,
              (RemoteDevice) (btDevicesFound.elementAt(i)), this);
          // wait for service discovery ends
          synchronized (this) {
            this.wait(BTManager.BLUETOOTH_TIMEOUT);
          }
          if (!isBTSearchComplete) {
            discoveryAgent.cancelServiceSearch(transID);
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

 public void servicesDiscovered(int param, ServiceRecord[] serviceRecord) {
    int index = btServicesFound.size() - 1;
    for (int i = 0; i &lt; serviceRecord.length; i++) {
      btServicesFound.setElementAt(serviceRecord[i], index);
    }
  }

 public void serviceSearchCompleted(int transID, int respCode) {
    isBTSearchComplete = true;
    // notifies and wake mains thread that service search is completed
    synchronized (this) {
      this.notify();
    }
  }
</pre>
<p>After we got all the data stored in our Vectors, we just need to add two methods to retrieve information, one to retrieve the Bluetooth Url and another an Bluetooth user friendly name, after all Bluetooth urls, don&#8217;t have a lot of meaning to the end users of our application.</p>
<pre>
  public String getDeviceName(int deviceID) {
    try {
      return ((RemoteDevice) btDevicesFound.elementAt(deviceID))
          .getFriendlyName(false);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "Error";
  }

  public String getServiceURL(int deviceID) {
    try {
      return ((ServiceRecord) btServicesFound.elementAt(deviceID))
          .getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "Error";
  }
</pre>
<p>And with those last methods we completed our Bluetooth finder class. You can check the full source code where I provide a example of how to use it to search for bluetooth GPS.</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/bluetoothgps-source-code.rar' title='Bluetooth GPS - Full Source Code'>Full Source Code</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/bluetoothgps.jad' title='Bluetooth GPS - Jad File'>Jad File</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/bluetoothgps.jar' title='Bluetooth GPS - Jar File'>Jar File</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2007/11/25/search-for-bluetooth-devices-and-services/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Lesson 5 - Files</title>
		<link>http://sergioestevao.com/blogs/midp/2007/11/21/lesson-5-files/</link>
		<comments>http://sergioestevao.com/blogs/midp/2007/11/21/lesson-5-files/#comments</comments>
		<pubDate>Wed, 21 Nov 2007 21:49:55 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=15</guid>
		<description><![CDATA[After our last lesson we had a completely functional Arkanoid midlet but one important thing is still missing, can you guess what? To save the high scores! Until know our high scores were lost each time we exit the application (the same happens for the game settings). What&#8217;s the point of playing our game if [...]]]></description>
			<content:encoded><![CDATA[<p>After our last lesson we had a completely functional Arkanoid midlet but one important thing is still missing, can you guess what? To save the high scores! Until know our high scores were lost each time we exit the application (the same happens for the game settings). What&#8217;s the point of playing our game if we cannot save the scores to show off to our friends!!!</p>
<p>To implement this functionality you need to understand how the Midlet Input Output works and then how to use RecordStores.</p>
<p><span id="more-18"></span></p>
<p>Let&#8217;s start with the simple IO operations, the classes that implement them are in the java.io package. JavaMe only has a fraction of the classes available in JavaSE but they are the most useful:</p>
<ul>
<li><strong>Input Stream, Output Stream</strong>: the base classes for binary bytes streams</li>
<li><strong>ByteAraryInputStream, ByteArrayOutputStream</strong>: streams to buffer arrays in memory</li>
<li><strong>DataInputStream, DataOutputStream</strong>: read and write primitive Java types(int, float, String, &#8230;) to streams</li>
<li><strong>Reader, Writer</strong>: the base classes for character streams</li>
<li><strong>OutputStreamWriter, InputStreamReader</strong>: classes for read characters streams using encondings</li>
</ul>
<p>To exemplify the use of these classes let&#8217;s create a settings file were we store some of the game options:</p>
<ul>
<li>Number of lifes</li>
<li>Ball speed</li>
<li>Time to complete a level</li>
<li>Number of points for each brick we hit</li>
</ul>
<p>To implement this setting file we are going to create a simple text file &#8220;settings.txt&#8221; where each line represents a setting, the setting name and it&#8217;s value are separated by a &#8220;=&#8221; character.</p>
<pre>
ball_speed=2
start_lifes=4
level_time=100
brick_points=10
</pre>
<p>After you create this file  add it to your project resources and make sure this file will be stored inside the jar file along with your classes.<br />
Now how to access this file? You need use the method getResourceAsStream(String name) from the Class class. This method gives you access to any file stored inside your jar file. The root path &#8220;/&#8221; points to the root level of you jar file. For example to access the settings file we can use the following code:</p>
<pre>
InputStream is = this.getClass().getResourceAsStream("/settings.txt");
// read first byte
byte c= is.read();
</pre>
<p>This code gives you the first byte of the file, but what you really need is to read each line as an character stream for that we can use  the InputStreamReader and then  parse each line for the settings key and value.</p>
<pre>
public class Settings {
  public Hashtable values;

  public Settings(String file) {
    values = new Hashtable(10);
    read(file);
  }

  public String getSetting(String key){
    return (String)(values.get(key));
  }

  /**
   * Opens the file and reaas all the settings to the hashtable
   * @param file, the name of the file to read
   */
  public void read(String file){
    // open file
    InputStream is = this.getClass().getResourceAsStream(file);
    InputStreamReader isr = new InputStreamReader(is);
    // create a buffer to store lines
    StringBuffer lineBuffer = new StringBuffer();
    int c;
    try {
      c = isr.read();
      while(c != -1){
        lineBuffer.append((char)c);
        c = isr.read();
        // checks for end of line character
        if ( c == 10 || c==-1){
          // cleans extra spaces or end of lines chars
          String line = lineBuffer.toString().trim();
          // splits the string using the = character
          int pos = line.indexOf("=");
          if (pos != -1){
            // adds a new setting
            String key = line.substring(0,pos);
            String value = line.substring(pos+1);
            values.put(key, value);
          }
          // clean buffer
          lineBuffer.setLength(0);
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        is.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}
</pre>
<p>Now you just need to use this class in our Canvas class in our init() method:</p>
<pre>
 public void initSettings(){
    Settings setting = new Settings("/settings.txt");
    BALL_SPEED = Integer.parseInt(setting.getSetting("ball_speed"));
    MAX_LIFES = Integer.parseInt(setting.getSetting("start_lifes"));
    MAX_TIME = Integer.parseInt(setting.getSetting("level_time"));
    BRICK_SCORE = Integer.parseInt(setting.getSetting("brick_points"));
  }

 public void init(){
   initSettings();
   [...]
 }
</pre>
<p>Ok, know we have a configuration file, but still you ask how can i save my highscores!! The getResourceAsStream() method  only allows you to read files stored in the jar not to write to them.</p>
<h3>RecordStore</h3>
<p>To write to files you need to use the RecordStore class, this class allows you to create mini-databases where you can store and retrieve data, that is persistent between evocations of the midlet.</p>
<p>This class is implemented in the javax.microedition.rms package and it provides the following static constructor methods:</p>
<ul>
<li>openRecordStore(String recordStoreName, boolean createIfNecessary)</li>
<li>openRecordStore(String recordStoreName, boolean createIfNecessary, int authmode, boolean writable)</li>
<li>openRecordStore(String recordStoreName, String vendorName, String suiteName) </li>
</ul>
<p>All these methods allow to create and/or open an record store. The names of the record stores are case sensitive and have a maximum of 32 characters.<br />
One special feature to take in account is the authmode setting. This setting as two values:</p>
<ul>
<li>AUTHMODE_PRIVATE, in this mode only the Midlet that created the RecordStore can have access to it.</li>
<li>AUTHMODE_ANY, in this mode any Midlet can open the record store, read data from it and if the writable setting is true write data to it. This allow you to share data between Midlets, so for example you can have two different games that share the high scores tables. The RecordStores are unique identified by their creation name and the Midlet-Name,Midlet-Vendor properties in the Jad file.</li>
</ul>
<p>After you open the RecordStore you can add records to it, each record is made of an array of bytes and it&#8217;s identified by a unique id at the moment of it&#8217;s creation. After you create an record you can retrieve it&#8217;s data, change the data and delete it. The following methods support these operations:</p>
<ul>
<li>addRecord(byte[] data, int offset, int numBytes)</li>
<li>deleteRecord(int recordId)</li>
<li>setRecord(int recordId, byte[] newData, int offset, int numBytes) </li>
</ul>
<p>The maximum size of an RecordStore is device dependent, you can use the getSizeAvailable() method, but the value returned  isn&#8217;t accurate in the majority of the devices.</p>
<p>Now that we understand the RecordStore class better let&#8217;s use it to save our high scores:</p>
<pre>
  public void saveData() {
    try {
      // open records store options
      RecordStore options = RecordStore.openRecordStore("options", true);
      byte[] data = saveOptions();
      // check if record store not empty
      if (options.getNumRecords() != 0) {
        // update the settings
        options.setRecord(1, data, 0, data.length);
      } else {
        // adds the settings
        options.addRecord(data, 0, data.length);
      }
      // closes the record store
      options.closeRecordStore();
    } catch (RecordStoreException ex) {
    }
  }

  public byte[] saveOptions() {
    // create a byte array stream to store data temporarily
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(baos);
    try {
      dos.writeBoolean(soundOn);
      // write scores
      for (int i =0; i &lt; scores.length; i++){
        dos.writeInt(scores[i].value);
        dos.writeUTF(scores[i].name);
        dos.writeLong(scores[i].when.getTime());
      }
      // push all the data to the byte array stream
      dos.flush();
    } catch (IOException ex) {

    }
    // returns bytes from stream
    return baos.toByteArray();
  }
</pre>
<p>As you can see we are creating a &#8220;options&#8221; Record Store and use it to store our settings and the high scores. For the save process we are using an DataOutputStream with an ByteArrayOutputStream to facilitate our work to convert our data to an binary array.</p>
<p>Now we just need to implement the reading of data:</p>
<pre>
  public void loadData() {
    try {
      RecordStore options = RecordStore.openRecordStore("options", true);
      // check if record store not empty
      if (options.getNumRecords() != 0) {
        loadOptions(options.getRecord(1));
      }
      options.closeRecordStore();
    } catch (RecordStoreException ex) {
    }
  }

  public void loadOptions(byte[] data) {
    // create a byte array stream to store data temporarily
    ByteArrayInputStream bais = new ByteArrayInputStream(data);
    // creates a data input stream to read from
    DataInputStream dis = new DataInputStream(bais);
    try {
      soundOn = dis.readBoolean();
      // read scores
      for (int i = 0; i &lt; scores.length; i++) {
        int value = dis.readInt();
        String name = dis.readUTF();
        Date date = new Date(dis.readLong());
        scores[i] = new Score(value, name, date);
      }
      dis.close();
    } catch (IOException ex) {

    }
  }
</pre>
<p>We simple open the record store and check if it has a record available. If this is the case retrieve the data and use the an DataInputStream combined with an ByteArrayInputStream.</p>
<p>Now we just need to add calls for these methods on our startup and shutdown of the Midlet.</p>
<pre>
  public void initOptions() {
    soundOn = true;
    if (scores == null) {
      scores = new Score[10];
      for (int i = 0; i &lt; scores.length; i++) {
        scores[i] = new Score(0, "Empty", new Date());
      }
    }
    // loads data in record stores if available
    loadData();
  }

  public void exit() {
    // store high scores and setting to record store
    saveData();
    notifyDestroyed();
  }
</pre>
<p>After this last changes, we finally have our game saving the player high scores and settings. Next lesson we finally put to use our game settings, we are going to add sound to our game! See you soon.</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/lesson5-source.rar' title='Lesson 5 - Full Source Code'>Full Source Code</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/formacao5.jad' title='Lesson 5 - Jad File'>Jad File</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/formacao5.jar' title='Lesson 5 - Jar File'>Jar File</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2007/11/21/lesson-5-files/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Lesson 4 - Images, Sprites and Tiles</title>
		<link>http://sergioestevao.com/blogs/midp/2007/11/19/lesson-4-images-sprites-and-tiles/</link>
		<comments>http://sergioestevao.com/blogs/midp/2007/11/19/lesson-4-images-sprites-and-tiles/#comments</comments>
		<pubDate>Mon, 19 Nov 2007 08:07:44 +0000</pubDate>
		<dc:creator>Sérgio Estêvão</dc:creator>
		
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://sergioestevao.com/midp/?p=14</guid>
		<description><![CDATA[In our last lesson, we completed our GameCanvas class with all the main interaction between elements. Now that we have all gameplay elements build it&#8217;s time to improve the look of our game.
The ideia is to use some images files to represent our game entities instead of using Graphics draw/fill methods.
With this in mind i [...]]]></description>
			<content:encoded><![CDATA[<p>In our last lesson, we completed our GameCanvas class with all the main interaction between elements. Now that we have all gameplay elements build it&#8217;s time to improve the look of our game.<br />
The ideia is to use some images files to represent our game entities instead of using Graphics draw/fill methods.<br />
With this in mind i created the some images, based on the free SpriteLib resource pack, to use in our game.</p>
<p><a href='http://sergioestevao.com/blogs/midp/files/2007/11/arkanoid-graphics.png' title='Arkanoid - Graphics'><img src='http://sergioestevao.com/blogs/midp/files/2007/11/arkanoid-graphics-150x150.png' alt='Arkanoid - Graphics' /></a><br />
<span id="more-17"></span></p>
<h3>Image</h3>
<p>To access and display these images in our Midlet we need to use another of the Low-Level user interface elements the Image class. This class stores graphical  image data independently of the display device, in a off-screen memory buffer.<br />
Images are either mutable or immutable depending upon how they are created. Immutable images are generally created by loading image data from resource bundles, from files, or from the network. To create immutable Images you can use one the static createImage() methods available in the Image class, remember they may not be modified once created.<br />
Mutable images are created as blank images containing only white pixels. To create them use the Image constructors. The application may render on a mutable image by calling getGraphics() on the Image to obtain a Graphics object expressly for this purpose.</p>
<p>For our game we are going to use imutable images to represent the game entities. Let&#8217;s start by changing ou Pad class, first we need to create a Image object in our constructor.</p>
<pre>
Image image;
public Pad() {
    try {
      image = Image.createImage("/pad.png");
      width = image.getWidth();
      height = image.getHeight();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
</pre>
<p>Then we rewrite the paint method of our Pad class to draw the image we created</p>
<pre>
public void paint(Graphics g) {
    g.drawImage(image, x,y, Graphics.TOP | Graphics.LEFT);
  }
</pre>
<p>As you may have noticed we are using the PNG format, this is the only format that is mandatory in all MIDP implementations, some devices can support other formats like jpeg or bmp but PNG it&#8217;s the only safe option for all devices.</p>
<p>If you run your Midlet you will see your new good looking pad! Let&#8217;s do the same for our ball, she&#8217;s feeling jelous <img src='http://sergioestevao.com/blogs/midp/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre>
 Image image;
 public Ball() {
    try {
      image = Image.createImage("/ball.png");
      width = image.getWidth();
      height = image.getHeight();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void paint(Graphics g) {
    g.drawImage(image, x,y, Graphics.TOP | Graphics.LEFT);
  }
</pre>
<p>If you run your Midlet now you will have a nice looking ball, now you say, let&#8217;s do the same for our bricks, hold on, take a look to our bricks images. It  contains several bricks elements inside it, so we need a way to crop one brick image from the big Image. We could do this by using the setClip methods on the Graphics class, but in Midp 2.0 there is a easier way, the Sprite class.</p>
<h3>Sprite</h3>
<p>An sprite is common term in games, it refers to a visual element made of an image, normally animated, that can be moved around the game independently of other elements. The Sprite class is the MIDP 2.0 representation of this concept it allows the creation of sprites based on Images with multiple frames. It can change the frames, control animations and check collisionns with other elements.</p>
<p>We could use all these capabilities in our game entities but for know let&#8217;s start with our Brick class.</p>
<pre>
public static int BRICK_FRAMES = 20;
Image image = null;
Sprite sprite = null;
public Brick(){
    // load image
    image = Image.createImage("/bricks.png");
    // create the sprite with 20 frames one for each brick
    sprite = new Sprite(image,image.getWidth()/BRICK_FRAMES, image.getHeight());
    width = sprite.getWidth();
    height = sprite.getHeight();
  }
</pre>
<p>This code creates a sprite with 20 frames, one for each brick available on the image, now before we paint our brick we need to change the the frame  we are going to use.</p>
<pre>
  public void paint(Graphics g) {
    if (active){
      sprite.nextFrame();
      sprite.setPosition(x, y);
      sprite.paint(g);
    }
  }
</pre>
<p>Now if you run your Midlet you will have some nice Disco bricks, changing colours all the time. Another problem we have is that we are loading the bricks.png image for each Brick we create, not very optimized. Let&#8217;s refactor our code to address these problems:</p>
<pre>
  public Brick(Image image, int numFrames, int frameSelected){
    sprite = new Sprite(image,image.getWidth()/numFrames,image.getHeight());
    // set frame
    sprite.setFrame(frameSelected);
    // get size for collision detection
    width = sprite.getWidth();
    height = sprite.getHeight();
  }

  public void paint(Graphics g) {
    if (active){
      sprite.setPosition(x, y);
      sprite.paint(g);
    }
  }
</pre>
<p>Now you just load the Image one time in our init method and select one frame to be used during the lifetime of a brick.</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/lesson4-source.rar' title='Lesson 4 - Source Code'> Full Source Code</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/formacao4.jad' title='Lesson 4 - Jad File'>Jad File</a></li>
<li><a href='http://sergioestevao.com/midp/wp-content/uploads/2007/11/formacao4.jar' title='Lesson 4 - Jar File'>Jar File</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://sergioestevao.com/blogs/midp/2007/11/19/lesson-4-images-sprites-and-tiles/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
