iPhone battery drains ridiculously fast on iOS 4.3.2

It's a huge problem for iPhone users, especially when we upgrade our iPhone firmware. The upgraded operating software often kills battery life more than before the upgrade. Here's some of the steps I took to mediate the issue:

  1. Turn off Mail Push for the iPhone, and reboot the phone before adding mail accounts. If the mail accounts are already added, remove them, turn Push off, and reboot the phone. Then add the accounts back
  2. Turn off Bluetooth, Personal Hotspot
  3. Sign out of iTunes App Store when not in use (Unverified, but doesn't hurt)

The above should be sufficient to stem the ridiculous battery drain. However, if you still need to save more power, and don't mind sacrificing features, you can do the following:

  1. Turn off Location Services
  2. Turn off Push Notifications
  3. Kill off all apps after you are done with them. Do this by double-pressing on the Home button, long-tap on an app (wait for the icons to wobble), and tap the red blob at the top right hand corner of the app icon
  4. Turn off 3G network service if you are not using data, and turn it on only when you are using it
  5. Switch your iPhone to Airplane mode when you are in an area of very weak cellular reception. Switch your phone back on when you are back in an area of acceptable cellular reception
  6. Dim the screen

Hope this helps people who are facing issues with their iPhone's iOS 4.3.2 firmware.

P.S: It's a nice firmware though, especially that Personal Hotspot feature (even if it drains the battery in record time), the new Javascript engine in Mobile Safari. It also seems to have solved that persistent problem where the slider snaps back whenever I try to answer a call (occasional bug probably)

Unable to find Java_Home error in Eclipse

The author at http://www.dynamicobjects.com/d2r/archives/002591.html has found a solution to the issue. If you've installed a new copy of Eclipse, and gotten this error when you are trying to deploy a Livescribe Penlet project, or any other compilation tasks that include Ant, then it means that the path to tools.jar hasn't been set in Eclipse. To do so:

In Eclipse, click on Window -> Preferences.

Expand Ant on the left-hand side, and choose the Runtime label.

Click on Global Properties node in the right-panel, and click Add External JARs.

Add the path to tools.jar in the JDK directory (C:\Program Files\Java\jdk_1.x.x\lib\tools.jar)

Click OK.

 

All fixed.

Manipulating the Lifecycle of a Penlet

This article assumes that you, the reader, already has basic knowledge of the lifecycle (the whole init-activate-deactivate-destroy thing). If you don’t, I’d highly suggest reading up on it first. These lines (shamelessly stolen from Penlets.com) should summarize it:

Starting from the top, our penlet class extends Penlet . This is the parent class of all penlets, providing access to context information and lifecycle events.

These lifecycle events are handled by four abstract methods of Penlet that we need to implement. In order these event handlers are initApp , which will be called once to initialize the penlet. In this basic template we call context.getDisplay() to get a handle to the pen’s OLED display. We also create a new ScrollLabel instance. A ScrollLabel is a subclass of Canvas , which is a class that allows you to render text and graphics on the OLED display. The ScrollLabel in particular is used to render text on the OLED, and if the text is too long to fit on the display it will scroll the text so that the entire message can be read.

The next handler is activateApp , which is called when the penlet is activated. Typically this is when the penlet is selected on the pen’s menu, just like the demo apps that come with the pen. In this method you will typically want to change what is displayed on the OLED or perhaps play an audio clip. In this basic penlet we take that ScrollLabel we created and set that as the current display. And we set the message in the ScrollLabel to say “Hello World”.

Now eventually your penlet will be deactivated. This could be due to the user quitting the application, or maybe they just turned off the pen. This is handled by the deactivateApp handler, which also receives a code that specified the reason for the deactivation. All of the reason codes are available as static constants of the Penlet superclass. These include DEACTIVATED_BY_MENU , DEACTIVATED_BY_SHUTDOWN , and others. You will typically use this handler to free up resources that you created in activateApp . For example, you may have registered one or more event listeners like the StrokeListener or the PenTipListener that you want to unregister.

Last but not least, eventually the pen will completely shutdown the penlet, typically when the pen is powered down. This event is captured by destroyApp , allowing you to do any final cleanup that may be required.

Back to the matter at hand: how do you control the lifecycle of a penlet?

Initially you might think something like this would cause the application to deactivate:

this.deactivateApp(2);

This is, of course, wrong.

deactivateApp, along with the other abstract lifecycle methods, is strictly an event handler. At no point in time should the penlet call the methods; they are meant to be called by the JVM (Java Virtual Machine) as and when they’re needed.

Does this mean that it’s impossible to control the lifecycle (apart from tapping left on the Nav Menu to exit)? Nope.

As of this writing, only 3 methods (all found in the PenletContext class) have any effect on the lifecycle:

  • boolean notifyStateChange(boolean requestActive)
  • void notifyDataOnDisplay(boolean valid)
  • boolean requestActivation(long delay)

notifyStateChange

This method is the only one that allows you to directly influence the lifecycle. Unfortunately, you can only use it to activate or deactivate a penlet, which will be determined by the boolean parameter.

The method returns a boolean which describes whether or not the pen will entertain your request.

To deactivate a penlet, for example, use the following code in the penlet:

boolean willDeactivate = this.context.notifyStateChange(false);
this.logger.debug("Will the penlet deactivate? " + willDeactivate);

Deactivating a penlet this way should also cause its termination, though there is a special case.

Generally, you should only need to use notifyStateChange(false) since there’s no way you can run code while a penlet is deactivated.

notifyDataOnDisplay

This method forces a penlet to delay its termination after it’s been deactivated due to Notes Mode. What does this mean?

Basically, if a penlet’s not expecting handwriting or even tapping, it exits to Notes Mode when you put your pen on Open Paper (AKA any basic Livescribe notebook). Notes Mode is the pen’s “basic mode”, just FYI.

Since the penlet terminates immediately, you lose anything that’s on the display immediately too. If, however, you want to give the user the opportunity to write down the result on Open Paper, the method lets you freeze the screen and delay the penlet’s termination.

Simply supply a boolean value of true to activate this feature:

!#java
this.context.notifyDataOnDisplay(true);

Do note that this is actually included as part of the Livescribe Smartpen Open Paper Certification, under the test named INT.LIVESCRIBE.DOD.01. If you ever run into this situation, do take this into account.

requestActivation

This method trudges into advanced penlet programming territory. What it does is let you reactivate an already deactivated penlet after a set amount of time.

The catch? The penlet cannot be terminated.

Officially, only one penlet is capable of staying resident in memory, and it’s the Paper Replay penlet. In fact, Paper Replay uses this exact method to perform its “snapback” feature, which lets it take over the penlet when it’s idle after 10 seconds if a recording is running. I’ve seen enough debug messages in the Smartpen Emulator to confirm this.

Is it possible, unofficially? Well, yes, but only through a certain caveat.

Normally, a penlet immediately terminates after it exits. However, I’ve found that if the following factors are present, the penlet won’t deactivate immediately:

  • The penlet starts due to the user tapping on one of its regions.
  • The penlet deactivates when it calls notifyStateChange.

I won’t fully illustrate how to achieve this; if you’re really willing to find out more, you should be able to code up a simple app using the pointers above. In any case though, you simply call the method with the delay (in milliseconds) as its parameter:

boolean willReactivate = this.context.requestActivation(5000);
this.logger.debug("Will it reactivate? " + willReactivate);

Similar to notifyStateChange, this method returns a boolean describing whether the pen will reactivate the penlet later as instructed.

I wouldn’t advise trying it in your commercial penlet, though. You’re not supposed to interfere with the way Paper Replay works; in fact, your penlet must be able to support Paper Replay recording in the background (or simply refuse to run) to be certified.

Oh well. ( –_–)y

MIDI + Livescribe Pulse - The Basics

The first thing you need to know is that yes, there is a synthesizer built into the pen. It obeys the General MIDI specification, too (as far as I know), so you can perform a few tricks with it.

Before you can start, though, you’ll need to ask the pen for control over the synthesizer. It goes a little something like this:

import javax.microedition.media.Player;
import javax.microedition.media.control.MIDIControl;
...
Player midiPlayer = Manager.createPlayer(Manager.MIDI_DEVICE_LOCATOR);
midiPlayer.addPlayerListener(playerEventHandler);
midiPlayer.realize();
midiPlayer.prefetch();
midiPlayer.start();
MIDIControl midiControl = (MIDIControl) midiPlayer.getControl("MIDIControl");

Once that’s done, you can start messing with the synthesizer and getting it to play notes.

To play notes, use the following:

int channel = 0; // Must be between 0 and 15, inclusive.
int note = 60; // Must be between 0 and 127, inclusive; 60 is Middle C.
int velocity = 100; // Must be between 0 and 127, inclusive.
midiControl.shortMidiEvent(MIDIControl.NOTE_ON | channel, note, velocity);

Unless you’re trying to mimic a band with several instruments playing at once, you generally don’t need to use any other channel other than the first one (0).

To change to another instrument, use the following:

int instrument = 2; // Must be between 0 and 127, inclusive; 2 represents the Electric Grand Piano instrument.
int channel = 0; // Must be between 0 and 15, inclusive.
int PROGRAM_CHANGE = 192;
midiControl.shortMidiEvent(PROGRAM_CHANGE | channel, instrument, 0);

You can head on over to the General MIDI Wikipedia article for a list of instruments in the GM specification.

Also, don’t forget to release the synthesizer resources when you’re done:

midiControl = null;
midiPlayer.close();
midiPlayer = null;

Livescribe paper product project: changes to source file doesn't reflect in the built distribution file

Ran into problems getting the updated paper project file to save the updates to the distribution file. Below is the solution to get it to work properly:

  1. Save changes to paper project
  2. Delete dist folder
  3. Clean and build the project
  4. Print the paper product
  5. Build the project again

Need I say that having to work-around software that should simply just work really gets on my nerves?

Workaround for Livescribe Paper product in Eclipse

You may run into problems deploying the Paper product to your pen. That is a bug. http://www.livescribe.com/forums/showthread.php?t=5336

Error message: LS_FILE_OPEN_ERROR when trying to deploy the paper product to the Livescribe smart pen

  1. Create the paper project, and finish the wizard normally.
  2. Add 2 rectangle regions to the paper, and save the file.
  3. Go to Project -> Clean, and clean the project. Immediately, choose to build the project.
  4. Print the paper
  5. Build the project again.

Recognising equality sign "=" with Livescribe ICR text recogniser

I had been trying to get the pen to recognise the "=" sign, but it usually comes up as "- -", which is frustrating. There're no useful solutions to this problem, so I wrote a dirty hack to search for all the "- -" strings in the hwrResult method, and replace them all with the "=" character manually. It's a bad and dirty hack, and I think my programming lecturers will murder me for doing this, but it's the only way I could think of to get the recognition to work properly.

Anyone has better suggestions on how to fix this? I would love to drop the bad hack!

http://www.livescribe.com/forums/showthread.php?t=7750

 

// Extreme bad hack because the ICR tends to recognise "- -"
// when the user writes '=' so we have to resort to this
if (result.indexOf("- -")!= -1) {
        int indexOfEquality = result.indexOf("- -");
        result = result.substring(0, indexOfEquality) + "=" + result.substring(indexOfEquality + 3, result.length());
}