Tuesday, May 4, 2010

Mobile Device Programming ... In Australia.

I recently got a new touch phone fake iPhone LG KC910 Renoir. I'm learning how to program for mobile devices. It's all Java based, but the standard is a subset of the usual JRE. It's called J2ME.
Some interesting notes so far:
  1. The J2ME SDK 3.0 is pretty good, and it's free.
  2. There is support for mobile device sensors, suchas:
    -Accelerometer
    -Camera
    -GPS reciever (!)
  3. I met a guy on the LA - SYD flight who does this for a living.
  4. I have a few Java applets I want to port to mobile.
This page will just be a log of what I had to do to port them.

4-May-2010
--------------

Built the default "Hello, World!" MIDlet that comes with the SDK. It loaded on my phone no worries:
  1. Copy .jad and .jar from the project Build directory to MicroSD card Others directory
  2. In phone: My Stuff / Others / [Click on .jad, install]
  3. Phone prompts to run untrusted software, and it runs!
  4. ... Now on to weaning myself from java.awt.*
5-May-2010
--------------

Porting Radial Applet:
  • Transition from Color to 0xFF0000...
  • Graphics handling a little different to Applet. Still figuring out. Not too bad.
  • Why no Save option for .java files in SDK 3.0?? I'm getting old.
  • Change from java.lang.Math.random() to java.util.Random()... wtf. (But better!)
  • Why remove .random() from the Math collection? Overboard with the cutting!
  • Did away with paint() and update() references to Graphics, just maintian a global graphics handle instead. Applet called these, MIDlet doesn't (?).
  • Painting sequence is totally different to an Applet, which may receive repaint() commands from the system. With a MIDlet you just make a canvas class which is a drawing machine, then Display.getDisplay(myMIDlet).setCurrent(myCanvas).
Actual text from a Java demo preamble:
* You acknowledge that this software is not designed, licensed or intended for use in the design, construction, operation or maintenance of any nuclear facility.


Almost there...
Bang! Radial5 has been ported. See thumbnails below for DIFF between the applet (right) and the MIDlet (left).



This is so much better than programming the Arduino. I feel sorry for the BoingBoing hipsters.

Full Radial5 mobile installation and source are here.

10-May-10
------------
Have you seen Brazil? Working with the J2ME subset I feel like the widowed Mrs. Buttle. "What have you done with his body????" StringTokenizer would have been worth keeping, Oracle, you twisted giant!

--------------
15-May-10

Some notes on subtle differences -
  1. awt.Graphics.drawOval -> Graphics.drawArc( + specify from-to angle)
  2. awt.Graphics.drawString -> Graphics.drawString( + specify anchor)
  3. awt.Color is gone, I had to rebuild a dummy class to avoid recoding large swaths of code
  4. awt.TextBox.setText -> TextBox.setString(String)
  5. sqrt is seemingly gone, but it seems like you can still include java.lang.Math... not sure on this one yet, it gives a warning in the SDK next to java.lang import statements. Update: My phone seems compatible with java.lang.*
SpringThing is now kindof running on the LG touchphone. It initialises and runs the game loop, but the elements zip offscreen. Could be that the numerical precision is so reduced that there is some instability induced. Not sure yet, but its on my phone now.

--------------
19-May-10

SpringThing Mobile v0.1 is now running and released on my website.

It took quite a bit of effort, and getting sick enough to have the time in bed to push it through.

Right now it doesn't have much to it, you can just drag the elements around. I'm planning to extend the console at the bottom of the screen to take input when clicked.

As you can see, my phone averages a measly 7FPS with 100 elements and 10 connections per element.

I can't seem to shake the stupid dumb-phone nav bar that the system has placed. I got a GPS app today which also is subject to the emulated buttons, which makes me think I'm not gonna win.

Touchscreen input is managed in the canvas class. I've made it a subclass of the MIDlet so I didn't have to change any of the code.


--------------
22-May-10

I've removed the nav bar by including some statements in the JAD and JAR (within the JAR manifest). They were added automatically by the J2ME SDK after I entered them in the project properties under "Application Descriptor." The fields I added were:
MIDlet-Touch-Support: True
UseNativeTextButtons: false
ReverseSoftkeys: true
UseNativeCommands: false
LGE-MIDlet-TargetLCD-Height: 240
LGE-MIDlet-TargetLCD-Width: 400
This also sets the screen into landscape mode (note -Height of the device is actually 400).
Now I'm working on adding accelerometer support. I had two ideas for how to use the input:

1. Use it to pan the view, so that when you moved the phone you were actually panning across the structure

2. Apply the accelerations directly to the structure.
I realised that the panning option was no good, as if you were to tilt the phone from horizontal, the mesh would simply slide off to infinity. So now I've decided to go with applying the accelerations directly to the structure.

I first tried to grab the accelerometer with the code:




accelSensors = SensorManager.findSensors("sensor:acceleration;contextType=device;model=acc01");
This worked in the SDK emulator, but crashed my phone! The actual URL to the accelerometer is device dependent!! This means it is better to use a general sensor search for "acceleration" rather than trying to find it with a specific URL. This worked:
accelSensors = SensorManager.findSensors("acceleration",null);
The Data[] returned by the SensorConnection is like this: Data[0]: X, Data[1]: Y, Data[2]: Z. Note that if your program runs at 90° on the screen, your X and Y accelerations will be swapped.


NOTE: Use the NetBeans IDE. The Java ME IDE is just a reduced functionality version of NetBeans, with some Java ME specific examples. Both are free, NetBeans is much better.

There are so many stupid little changes from Java to Java ME. For example, the Thread class no longer gives access to the (String) name member via Thread.setName(String name). You have to invoke the superclass with super("my thread name") in your Thread constructor. I thought compatibility was key to the Java Modus Operandi. Brimstone!
And it didn't even work. My debugger is still calling them "threadb1" etc.

No comments:

Post a Comment