achartengine chart will not zoom even though zoom is enabled - achartengine

I am running a data request from a service on a thread. I cannot seem to get pan or zoom to work for this app. Here is the method where I am setting it to allow zoom. I have also checked that zoom is enabled.
private void getRPData2()
{
final ScadaDataList l = new ScadaDataList();
final long value = new Date().getTime() - 3 * TimeChart.DAY;
new Thread(new Runnable()
{
public void run()
{
try
{
//System.out.println("made it");
l.Load(Cookie);
final Date d = new Date();
runOnUiThread(new Runnable() {
public void run() {
/*for (int i = 0; i < 100; i++) {
time_series.add(new Date(value + i * TimeChart.DAY / 4), i);
}*/
for (ScadaData sd: l)
{
if (sd.getDataTS().compareTo(d) <= 0)
{
time_series.add(sd.getDataTS(),sd.getActualLoad() * 1000);
ProtectedLoadSeries.add(sd.getDataTS(),sd.getProtectedLoad() * 1000);
}
}
mRenderer.setXLabels(12);
mRenderer.setYLabels(8);
mRenderer.setXLabelsAngle(60);
mRenderer.setXLabelsAlign(Align.LEFT);
//mRenderer.setYLabelsAngle(-60);
mRenderer.setYLabelsAlign(Align.RIGHT);
mRenderer.setPanEnabled(true);
mRenderer.setShowGrid(true);
mRenderer.setGridColor(Color.argb(180, 66, 66, 66));
mRenderer.setZoomEnabled(true);
mChartView.repaint();
progress.dismiss();
}
});
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}

It looks like you are using the wrong version of the methods. Use these instead:
mRenderer.setPanEnabled(true, true
mRenderer.setZoomEnabled(true, true);

Related

Blackberry switch screen

To navigate through the pages of my app i use:
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
UiApplication.getUiApplication().pushScreen(screen);
}
});
This is working well on simple screens with not too many fields. But when I try to go to a Screen more elaborated (it contains a custom "listField" made out of multiple managers with multiple fields) the UI takes A LOT of time to update. I've noticed that the page has actually finished constructing but it just doesn't show up, I have to move the trackpad or do a click and then the screen will show.
Code for the screen:
public class List extends MainScreen{
public List(Categoria categoria){
Bitmap bmap = Bitmap.getBitmapResource("img/fondo.png");
getMainManager().setBackground(BackgroundFactory.createBitmapBackground(bmap, Background.POSITION_X_LEFT, Background.POSITION_Y_TOP, Background.REPEAT_SCALE_TO_FIT));
setTitle("Establecimientos");
vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR);
try {
DbHelper dbHelper = new DbHelper();
dbHelper.open();
EstablecimientoDAO eDao = new EstablecimientoDAO(dbHelper.db);
OfertaDAO oDao = new OfertaDAO(dbHelper.db);
Vector ests = eDao.getEstablecimientosPorCategoria(categoria);
for(int i = 0; i < ests.size(); i++){
Establecimiento est = (Establecimiento) ests.elementAt(i);
Oferta oferta = oDao.getOferta(est.getIdEstablecimiento());
EstablecimientosListField elf1 = new EstablecimientosListField();
Bitmap bm = null;
String location = "";
FileSystem fs = Utilities.getFileSystem();
if(fs.hasSdCard()){
location = "/SDCard/Blackberry/pictures/";
}
else if(fs.hasMCard()){
location = "/store/";
}
FileConnection fc = (FileConnection)Connector.open("file://" + location + "e_" + est.getIdEstablecimiento() + ".jpg");
if(fc.exists() && fc.fileSize() > 0){
InputStream is = fc.openInputStream();
byte [] data = new byte[(int) fc.fileSize()];
data = IOUtilities.streamToBytes(is);
is.close();
fc.close();
//bm = Bitmap.createBitmapFromBytes(data, 0, data.length, 1);
EncodedImage eImage = EncodedImage.createEncodedImage(data, 0, data.length);
eImage = Utilities.resizeToWidth(eImage, Display.getWidth() / 3, 1, true);
Bitmap tmp = eImage.getBitmap();
if(tmp.getHeight() > 150){
eImage = Utilities.resizeToHeight(eImage, 1, 150, true);
}
bm = eImage.getBitmap();
}
else{
EncodedImage eImage = EncodedImage.getEncodedImageResource("img/default_esta.png");
eImage = Utilities.resizeToHeight(eImage, 1, 150, true);
bm = eImage.getBitmap();
}
String desc = "";
if(oferta != null && oferta.getDescripcion() != null){
desc = oferta.getDescripcion();
}
if(est.getDescEstablecimiento() != null){
desc += est.getDescEstablecimiento();
}
ButtonField verMas = new ButtonField("VER MÁS"){
protected boolean touchEvent( TouchEvent message ) {
int x = message.getX( 1 );
int y = message.getY( 1 );
if( x < 0 || y < 0 || x > getExtent().width || y > getExtent().height ) {
// Outside the field
return false;
}
switch( message.getEvent() ) {
case TouchEvent.UNCLICK:
fieldChangeNotify(0);
return true;
}
return super.touchEvent( message );
}
protected boolean navigationClick(int status, int time) {
if (status != 0) { // you did not have this check
fieldChangeNotify(0);
}
return true;
}
protected boolean trackwheelClick( int status, int time )
{
if (status != 0) fieldChangeNotify(0);
return true;
}
};
verMas.setCookie(est);
verMas.setChangeListener(new FieldChangeListener(){
public void fieldChanged(Field field, int context) {
final Establecimiento est = (Establecimiento)field.getCookie();
//if(field instanceof )
/*UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
UiApplication.getUiApplication().pushScreen(new DetalleEstablecimientoScreen(est));
}
});*/
Runnable runnable = new Runnable(){
public void run(){
UiApplication.getUiApplication().pushScreen(new DetalleEstablecimientoScreen(est));
}
};
PleaseWaitPopupScreen.showScreenAndWait(runnable, "Cargando...");
}
});
EncodedImage eImage = EncodedImage.getEncodedImageResource("img/det_fb.png");
eImage = Utilities.resizeToWidth(eImage, (int) (Display.getWidth() / 16), (int) (Display.getWidth() / 16), true);
BitmapField bmFb = new BitmapField(eImage.getBitmap(), Field.FOCUSABLE){
protected boolean touchEvent( TouchEvent message ) {
int x = message.getX( 1 );
int y = message.getY( 1 );
if( x < 0 || y < 0 || x > getExtent().width || y > getExtent().height ) {
// Outside the field
return false;
}
switch( message.getEvent() ) {
case TouchEvent.UNCLICK:
fieldChangeNotify(0);
return true;
}
return super.touchEvent( message );
}
protected boolean navigationClick(int status, int time) {
if (status != 0) { // you did not have this check
fieldChangeNotify(0);
}
return true;
}
protected boolean trackwheelClick( int status, int time )
{
if (status != 0) fieldChangeNotify(0);
return true;
}
};
bmFb.setCookie(est);
bmFb.setChangeListener(new FieldChangeListener(){
public void fieldChanged(Field field, int context){
try{
DbConnection dbHelper = new DbConnection();
dbHelper.open();
OfertaDAO oDao = new OfertaDAO(dbHelper.db);
final Establecimiento est = (Establecimiento)field.getCookie();
final Oferta oferta = oDao.getOferta(est.getIdEstablecimiento());
dbHelper.close();
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
try{
String post = "Banco de Bogotá";
if(oferta.getDescripcion() != null){
post = oferta.getDescripcion();
}
//String [] opciones = {"Aceptar", "Cancelar"};
int respuesta = Dialog.ask(Dialog.D_OK_CANCEL, "Usted está a punto de compartir la siguiente oferta:\n" + post, Dialog.YES);
if(respuesta == Dialog.D_OK){
new FacebookPost(oferta, est);
}
}
catch(Exception ex){
Dialog.alert("ERROR: " + ex.toString());
}
}
});
} catch(Exception ex){
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
Dialog.alert("Error al compartir");
}
});
}
}
});
eImage = EncodedImage.getEncodedImageResource("img/det_tw.png");
eImage = Utilities.resizeToWidth(eImage, (int) (Display.getWidth() / 16), (int) (Display.getWidth() / 16), true);
BitmapField bmTw = new BitmapField(eImage.getBitmap(), Field.FOCUSABLE){
protected boolean touchEvent( TouchEvent message ) {
int x = message.getX( 1 );
int y = message.getY( 1 );
if( x < 0 || y < 0 || x > getExtent().width || y > getExtent().height ) {
// Outside the field
return false;
}
switch( message.getEvent() ) {
case TouchEvent.UNCLICK:
fieldChangeNotify(0);
return true;
}
return super.touchEvent( message );
}
protected boolean navigationClick(int status, int time) {
if (status != 0) { // you did not have this check
fieldChangeNotify(0);
}
return true;
}
protected boolean trackwheelClick( int status, int time )
{
if (status != 0) fieldChangeNotify(0);
return true;
}
};
bmTw.setCookie(est);
bmTw.setChangeListener(new FieldChangeListener(){
public void fieldChanged(Field field, int context){
try{
DbConnection dbHelper = new DbConnection();
dbHelper.open();
OfertaDAO oDao = new OfertaDAO(dbHelper.db);
final Establecimiento est = (Establecimiento)field.getCookie();
final Oferta oferta = oDao.getOferta(est.getIdEstablecimiento());
dbHelper.close();
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
String tuit = "tweeteando desde fidelity";
if(oferta.getDescripcion() != null){
tuit = oferta.getDescripcion();
}
//String [] opciones = {"Aceptar", "Cancelar"};
int respuesta = Dialog.ask(Dialog.D_OK_CANCEL, "Usted está a punto de compartir la siguiente oferta:\n" + tuit, Dialog.OK);
if(respuesta == Dialog.OK){
UiApplication.getUiApplication().pushScreen(new BrowserFieldScreen(tuit));
}
}
});
} catch(Exception ex){
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
Dialog.alert("Error al compartir");
}
});
}
}
});
BitmapField pin = new BitmapField(Bitmap.getBitmapResource("img/pin.png"), Field.FOCUSABLE){
protected boolean touchEvent( TouchEvent message ) {
int x = message.getX( 1 );
int y = message.getY( 1 );
if( x < 0 || y < 0 || x > getExtent().width || y > getExtent().height ) {
// Outside the field
return false;
}
switch( message.getEvent() ) {
case TouchEvent.UNCLICK:
fieldChangeNotify(0);
return true;
}
return super.touchEvent( message );
}
protected boolean navigationClick(int status, int time) {
if (status != 0) { // you did not have this check
fieldChangeNotify(0);
}
return true;
}
protected boolean trackwheelClick( int status, int time )
{
if (status != 0) fieldChangeNotify(0);
return true;
}
};
pin.setCookie(new Long(est.getIdEstablecimiento()));
//pin.setChangeListener(this);
pin.setChangeListener(new FieldChangeListener(){
public void fieldChanged(Field field, int context) {
final long idEstablecimiento = ((Long)field.getCookie()).longValue();
//if(field instanceof )
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run(){
UiApplication.getUiApplication().pushScreen(new MapaScreen(idEstablecimiento, "establecimiento"));
}
});
}
});
elf1.add(new BitmapField(bm));
elf1.add(new LabelField(est.getNombre(), LabelField.ELLIPSIS));
elf1.add(new LabelField(desc, LabelField.ELLIPSIS));
elf1.add(verMas);
elf1.add(pin);
elf1.add(bmFb);
elf1.add(bmTw);
vfm.add(elf1);
}
} catch (Exception ex){
}
add(vfm);
//UiApplication.getUiApplication().requestForeground();
//invalidate();
}
}
I would be interested to know what device and OS level you are seeing this on.
I don't think we can figure out your problem from the information presented, we are just guessing. If you want some more detailed assistance, you will need to give example code. I appreciate that you may not want to post your own code, but perhaps you can create a small sample using an array of Data.
That said, my experience is that on the initial load of the screen, if there is a delay, then it is most likely a delay in loading content rather than the screen itself. So for example, if you are reading data and images off the SD Card to populate the screen, then that will slow it down. In fact you should not be doing this, you should populate your screen with 'filers' and then update by reading the required data off the SD Card and updating the screen as it goes from a Background Thread.
The other thing that comes to mind is that updating a screen with lots of managers present, can cause each of these managers to have to reposition. Once you get a large number of Managers, this update can introduce noticeable lag. But you would probably needs 100's for Managers/Fields to notice this. And this laying out occurs when the Screen is on display, not during construction.
Finally have you seen any signs of storage shortage, for example an hour glass or watch face icon on the screen during this slow processing.
I hope the above helps, if not, you may have to give us representative code.
Update
Looking at your code, it would seem you could do a lot of optimisation of this code before converting to asynchronous loading. Remember Bitmap manipulation is expensive in terms of performance. I would recommend proceeding in two stages:
Move the repeated code out of the loop
Do the loading that is outside the loop only once.
Here as example of step 1.
Currently inside the loop you have:
eImage = EncodedImage.getEncodedImageResource("img/det_tw.png");
eImage = Utilities.resizeToWidth(eImage, (int) (Display.getWidth() / 16), (int) (Display.getWidth() / 16), true);
BitmapField bmTw = new BitmapField(eImage.getBitmap(), Field.FOCUSABLE){
Outside the loop do
int displayWidth = Display.getWidth(); // I was told this was an expensive call so minimise its use
EncodedImage det_twEImage = EncodedImage.getEncodedImageResource("img/det_tw.png");
det_twEImage = Utilities.resizeToWidth(det_twEImage, (int) (displayWidth / 16), (int) (displayWidth / 16), true);
Bitmap bmTwBitmap = eImage.getBitmap();
and in the loop:
BitmapField bmTw = new BitmapField(bmTwBitmap, Field.FOCUSABLE){
And an example of step 2.
Currently you have this:
public List(Categoria categoria){
Bitmap bmap = Bitmap.getBitmapResource("img/fondo.png");
You could look at doing this:
static Bitmap bmap = null;
public List(Categoria categoria){
if ( bmap == null ) {
bmap = Bitmap.getBitmapResource("img/fondo.png");
)
This specific example is perhaps not so relevant, but you can appreciate that this approach can stop doing work twice.
Most large applications that I have worked on have implement some sort of caching for Bitmaps, which generally will involve preloading (while a splash screen is being displayed perhaps) all the static Bitmaps and dynamically loading but retaining a reference to other used Bitmaps so that they are only loaded once. Bitmaps are immutable, so you can reference them as many times as you like in BitmapFields.
There are few other things that might be contributing but one bit of code you need to look at is replacing this:
byte [] data = new byte[(int) fc.fileSize()];
data = IOUtilities.streamToBytes(is);
with
byte [] data = IOUtilities.streamToBytes(is);
which saves allocating and then throwing away a large chunk of memory.
If you do all this, and asynchronously load the images you can't load once, I think you will find performance improves significantly. Also as an experiment, always use the (loaded once) default image for your list items and that will give you an impression of how fast things will be.
Have you checked the event log on the device or simulator to see if an exception is thrown? You can see it by going to the device home screen, holding 'alt' and pressing L G L G. It could be something that goes wrong on the first paint, and then the user interaction with the trackpad causes a refresh.
All of the answers given are very useful to have a better app and I'll do them, but the actual "error" I've found after debugging the code couldn't be guessed by the code I had given. The error was in a LabelField I passed to the manager, inside the manager I was changing the font of the Labelfield and was causing this crazy error. To resolve it I simply changed the font in the constructor of the mainscreen rather than inside the manager.
Potential problems with your code:
Performing IO (DB/file/network connections) on the Main thread
FieldchangeListeners without checking for programmatic context (yes, that second param to fieldChanged is actually useful).
Multiple events handled for a single user input (touchEvent + navigationClick + trackwheelClick)
Even if doing IO in the Main thread is not the problem for your current data set, it is a bad practice, and you might run into problems in the future.
What you should be doing:
A)
Show loading dialog
Fetch data in background
Initialize list screen
Hide loading dialog
Change to list screen
or
B)
Change to list screen
Show loading dialog or message
Fetch data in BG
Initialize list
Hide loading dialog/message

Invalidate picturescrollfield

I am loading images in PictureScrollField from the server and want that until images are loaded from server, the PictureScrollField shows a blank image and when the image loads in image array, it repaints (redraw) the PictureScrollField like a ListField.
I read from BlackBerry documentation that every field can be invalidated (that is, we can repaint it) but when I use the PictureScrollField.invalidate() method in my program, I get an error :
The method invalidate from the type Field is not visible
The program I use is listed below
public final class GetMoreImage extends MainScreen {
public static PictureScrollField psf;
int size;
int length;
String text=null;
EncodedImage[] encodedImage;
VerticalFieldManager vmanger;
private LoadImages loadImages;
public GetMoreImage(int index) {
super(NO_VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR);
this.size=index;
try {
length=ListHome.object[size].getJSONArray("UrlArray").length();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ScrollEntry[] entries = new ScrollEntry[length];
for (int i = 0; i < length; i++) {
if(encodedImage != null && encodedImage.length > i && encodedImage[i] != null) {
EncodedImage encodedImg =ListHome.sizeImage(JPEGEncodedImage.encode(Bitmap.getBitmapResource("icon.png"),80),640,380);
Bitmap bmp=encodedImg.getBitmap();
entries[i] = new ScrollEntry(bmp, "hello", "");
}
else {
try {
text=ListHome.object[size].getJSONArray("UrlArray").getString(i).toString();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
EncodedImage encodedImg =ListHome.sizeImage(JPEGEncodedImage.encode(connectServerForImage(text),80),640,380);
Bitmap bmp=encodedImg.getBitmap();
entries[i] = new ScrollEntry(bmp, "hello", "");
}
}
psf = new PictureScrollField();
psf.setData(entries, 0);
psf.setHighlightStyle(HighlightStyle.ILLUMINATE_WITH_SHRINK_LENS);
add(psf);
loadImages = new LoadImages(80, 80);
loadImages.start();
}
private class LoadImages extends Thread {
int widthL;
int heightL;
LoadImages(int width, int height) {
this.widthL = width;
this.heightL = height;
}
public void run() {
encodedImage=new EncodedImage[length];
if (ListHome.object[size] != null) {
for (int i = 0; i < length; i++) {
try {
String text=ListHome.object[size].getJSONArray("UrlArray").getString(i).toString();
EncodedImage encodedImg = JPEGEncodedImage.encode(connectServerForImage(text), 80);//Get Image from Server
encodedImage[i] = ListHome.sizeImage(encodedImg, Display.getWidth(), Display.getHeight()-100);
psf.invalidate();//This Line generate error
} catch (Exception e)
{
e.printStackTrace();
}
}
} else {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("No Data Found");
}
});
}
}
}
}
Any help will be appreciated.
Thanks
The reason you get a compile error on this line:
psf.invalidate();//This Line generate error
is because the PictureScrollField#invalidate() method is protected, not public. So, code not in PictureScrollField or a class that extends PictureScrollField cannot use it directly.
However, you don't need to use invalidate(). invalidate() is a low-level method that instructs a field to repaint. However, PictureScrollField has a higher-level method that is designed to allow you to change images, and have the field (re)draw them: PictureScrollField#setData().
Because that method is changing the user interface (UI), it should be run on the UI/main thread. This will not automatically happen if you make the call inside the run() method you are using to download the images. So, you'll need something like this inside your LoadImages class:
public void run() {
encodedImage=new EncodedImage[length];
if (ListHome.object[size] != null) {
for (int i = 0; i < length; i++) {
try {
String text=ListHome.object[size].getJSONArray("UrlArray").getString(i).toString();
EncodedImage encodedImg = JPEGEncodedImage.encode(connectServerForImage(text), 80);//Get Image from Server
encodedImage[i] = ListHome.sizeImage(encodedImg, Display.getWidth(), Display.getHeight()-100);
//psf.invalidate();//This Line generate error
entries[i] = new ScrollEntry(encodedImage[i].getBitmap(), "label", "callout");
// we must update the scroll entries on the UI/main thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
// setting the field to index 'i' will scroll to the image
// that was just downloaded
psf.setData(entries, i);
});
} catch (Exception e)
{
e.printStackTrace();
}
}
}
In order to make this work, you must change the local entries variable to a member variable in your GetMoreImage class:
public final class GetMoreImage extends MainScreen {
public static PictureScrollField psf;
private ScrollEntry[] entries;
but, you can still instantiate it (entries = new ScrollEntry[length];) in your screen's constructor, or whenever you know the correct length.

Display a progress screen for BlackBerry app

How to display a progress screen when BlackBerry application is fetching data from remote server ?
I want an progress screen without animated gif without any button. (OK or Cancel )
public class ProgressDialog extends PopupScreen
{
public ProgressDialog(String waitString)
{
super(new VerticalFieldManager());
add(new LabelField(waitString,Field.FIELD_HCENTER));//add a string which u want to show for progressing
}
}
ProgressDialog progress = new ProgressDialog("Please Wait...");
//Add screen to UI
UiApplication.getUiApplication().pushScreen(progress);
//Remove screen from UI
progress.close();
ProgressBar progressBar = new ProgressBar("Waiting for location update....",50,1000);
progressBar.start(); // Start progress bar
progressBar.remove(); //remove progress bar
ProgressBar Thread
public class ProgressBar extends Thread {
Thread thd;
private int maximum, timeout;
private boolean useful = true;
private PopupScreen popup;
private int iterations = 0;
/**
* Object constructor
*
* #param title
* Text to display on popup area
* #param maximum
* Range / width of the gauge field of progress bar
* #param timeout
* Milliseconds to pause between updates to progress bar
* #see GaugeField
* #see Thread
* #see PopupScreen
*/
public ProgressBar(String title, int maximum, int timeout) {
this.maximum = maximum;
this.timeout = timeout;
VerticalFieldManager manager = new VerticalFieldManager();
popup = new PopupScreen(manager);
manager.add(new LabelField(title));
}
/**
* run() method for starting thread
*/
public void run() {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(popup);
}
});
int iterations = 0;
while (useful) {
System.out.println("I m here in while runn "+ useful);
try {
Thread.sleep(timeout);
} catch (Exception e) {
}
if (++iterations > maximum)
{
iterations = 1;
useful = false;
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
_locationProvider.reset();
Dialog.alert("Location not found.");
}
} );
}
// gaugeField.setValue(iterations);
}
if (popup.isDisplayed()) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().popScreen(popup);
}
});
}
}
/**
* Method to shutdown the thread and remove the popup screen
*
*/
public synchronized void remove() {
useful = false;
}
}

Blackberry Location Service fails on real device?

I've been trying to get longitude and latitude values using Blackberry's GPS listener. My device is a blackberry torch. The simulator I use also is a blackberry torch. The GPS listener seems to be working on the sim, but once on a real device it fails. When I say fail, it does not pick up longitude and latitude values, rather, it struggles to even connect to the GPS. I checked my options menu, and I'm able to pick up long and lat values from the location settings, so why would my app not be able to do it?
I call the class handleGPS in another class, i.e by doing this:
new handleGPS();
As I said, using the SIM I the provider finds my location after about 10 seconds. On the real device, I debug it and it does reach this statement (as the System.out's are printed)
try {
lp = LocationProvider.getInstance(cr);
System.out.println("location Provider");
lp.setLocationListener(new handleGPSListener(), 10, -1, -1);
//lp.setLocationListener(listener, interval, timeout, maxAge)
System.out.println("location Provider after listener");
} catch (LocationException e) {
e.printStackTrace();
}
However no values get returned. Below is my code.
GPS class:
public class handleGPS extends TimerTask {
//Thread t = new Thread(new Runnable() {
private Timer timer;
LocationProvider lp = null;
public handleGPS()
{
timer =new Timer();
System.out.println("timer");
GPS();
//timer.schedule(this, 0, 10000);
timer.schedule(this, 1000);
}
public void GPS() {
Criteria cr = new Criteria();
cr.setHorizontalAccuracy(Criteria.NO_REQUIREMENT);
cr.setVerticalAccuracy(Criteria.NO_REQUIREMENT);
cr.setCostAllowed(false);
cr.setPreferredPowerConsumption(Criteria.NO_REQUIREMENT);
//cr.setPreferredResponseTime(1000);
System.out.println("GPS ()");
try {
lp = LocationProvider.getInstance(cr);
System.out.println("location Provider");
lp.setLocationListener(new handleGPSListener(), 10, -1, -1);
//lp.setLocationListener(listener, interval, timeout, maxAge)
System.out.println("location Provider after listener");
} catch (LocationException e) {
e.printStackTrace();
}
}
// });
public void run() {
// TODO Auto-generated method stub
lp.setLocationListener(new handleGPSListener(), 10, -1, -1);
}
}
And here is the handler:
public class handleGPSListener implements LocationListener {
Coordinates c = null;
private static double lat=0.00;
private static double lon=0.00;
Database sqliteDB;
String username;
public static final String NAMESPACE = "http://tempuri.org/";
public String URL = "http://77.245.77.195:60010/Webservice/IDLMobile.asmx?WSDL";
public static final String SOAP_ACTION = "http://tempuri.org/Get_OfferCount_By_Location";
public static final String METHOD_NAME = "Get_OfferCount_By_Location";
private double x,y;
public void locationUpdated(LocationProvider loc, Location location) { //method to update as the location changes.
System.out.println("class handle GPS Listener");
if (loc == null) { //condition to check if the location information is null.
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("GPS not supported!"); //dialog box to alert gps is not started.
System.out.println("Problem 1");
return;
}
});
} else { //if not checked.
System.out.println("OK");
switch (loc.getState()) { //condition to check state of the location.
case (LocationProvider.AVAILABLE): //condition to check if the location is available.
System.out.println("Provider is AVAILABLE");
try {
location = loc.getLocation(-1); //location to get according to user present.
} catch (LocationException e) {
return;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
if (location != null && location.isValid()) { //condition to check if the location is not null and is valid.
c = location.getQualifiedCoordinates(); //to get the coordinates of the location.
}
if (c != null) { //condition to check if the location is not null.
lat = c.getLatitude(); //retrieve the latitude values into variable.
lon = c.getLongitude(); //retrieve the longitude values into variable.
System.out.println("lat and lon"+lat+lon);
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
updateFields();
getValues();
// Dialog.alert(lat+"GPS supported!"+lon);
return;
}
private void getValues() {
// TODO Auto-generated method stub
try {
URI uri = URI
.create("file:///SDCard/"
+ "database3.db"); //database3 to retrieve the values from location table.
sqliteDB = DatabaseFactory.open(uri);
Statement st = null;
st = sqliteDB
.createStatement("SELECT Latitude,Longitude FROM Location");//statement to retrieve the lat and lon values.
st.prepare();
Cursor c = st.getCursor();//cursor to point.
Row r;
int i = 0;
while (c.next()) { //loop to execute until there are no values in the cursor.
r = c.getRow(); //store the values in row.
i++;
lat=Double.parseDouble(r.getString(0)); //retrieve the latitude values from the database and store in variable.
lon=Double.parseDouble(r.getString(1)); //retrieve the longitude values from the database and store in variable.
System.out.println(r.getString(0)
+ " Latitude");
System.out.println(r.getString(1)
+ " Longitude");
}
st.close();
sqliteDB.close();
}
catch (Exception e) {
System.out.println(e.getMessage()
+ " wut");
e.printStackTrace();
}
try {
URI uri = URI
.create("file:///SDCard/"
+ "database1.db");
sqliteDB = DatabaseFactory.open(uri);
Statement st = null;
st = sqliteDB
.createStatement("SELECT Name FROM People");
st.prepare();
Cursor c = st.getCursor();
Row r;
int i = 0;
while (c.next()) {
r = c.getRow();
i++;
username=r.getString(0);
System.out.println(r.getString(0)
+ "Name");
}
st.close();
sqliteDB.close();
}
catch(Exception e)
{
e.printStackTrace();
}
SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME);
rpc.addProperty("Username", username);
rpc.addProperty("latitude", String.valueOf(lat));
rpc.addProperty("longitude", String.valueOf(lon));
rpc.addProperty("distance", "1.5");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.encodingStyle = SoapSerializationEnvelope.XSD;
HttpTransport ht = new HttpTransport(URL);
ht.debug = true;
try {
ht.call(SOAP_ACTION, envelope);
System.out.println("IN TRY");
SoapObject resultProperties = (SoapObject) envelope
.getResponse();
System.out.println("username INT RIGHT HERE " + resultProperties.getProperty(0));
System.out.println("username INT RIGHT HERE " + resultProperties.getProperty(1).toString());
System.out.println("username INT RIGHT HERE " + resultProperties.getProperty(2).toString());
System.out.println("lat and lon PARSE HERE " + lat+"\n"+lon);
/* here is the notification code */
//ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry.getInstance();
//EncodedImage image = EncodedImage.getEncodedImageResource("logosmall.png");
//ApplicationIcon icon = new ApplicationIcon( image );
//ApplicationIndicator indicator = reg.register( icon, false, true);
//indicator.setIcon(icon);
//indicator.setVisible(true);
//setupIndicator();
//setVisible(true, 0);
//NotificationsManager.triggerImmediateEvent(1, 0, 20, null);
//NotificationsManager.
/* end notification code */
} catch (org.xmlpull.v1.XmlPullParserException ex2) {
} catch (Exception ex) {
String bah = ex.toString();
}
}
private void updateFields() {
// TODO Auto-generated method stub
try {
URI myURI = URI
.create("file:///SDCard/"
+ "database3.db");
sqliteDB = DatabaseFactory.open(myURI);
Statement st = null;
Statement oops = null;
st = sqliteDB
.createStatement("SELECT Latitude,Longitude FROM Location");
st.prepare();
Cursor c = st.getCursor();
Row r;
int i = 0;
while (c.next()) {
r = c.getRow();
i++;
x=Double.parseDouble(r.getString(0));
y=Double.parseDouble(r.getString(1));
System.out.println(r.getString(0)
+ " Latitude in update fields");
System.out.println(r.getString(1)
+ " Longitude in update fields");
}
st = sqliteDB
.createStatement("UPDATE Location SET Latitude='"
+ lat
+ "' "
+ "WHERE Latitude="
+ "'" + x + "'" + "");
oops = sqliteDB
.createStatement("UPDATE Location SET Longitude='"
+ lon
+ "' "
+ "WHERE Longitude="
+ "'" + y + "'" + "");
System.out.println("location updated");
System.out
.println("lat and lon values are"
+ lat + lon);
st.prepare();
oops.prepare();
st.execute();
oops.execute();
st.close();
oops.close();
sqliteDB.close();
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
});
}
}
}
}
public void providerStateChanged(LocationProvider provider, int newState) {
if (newState == LocationProvider.OUT_OF_SERVICE) {
// GPS unavailable due to IT policy specification
System.out.println("GPS unavailable due to IT policy specification");
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("GPS unavailable due to IT policy specification");
return;
}
});
} else if (newState == LocationProvider.TEMPORARILY_UNAVAILABLE) {
// no GPS fix
System.out.println("GPS temporarily unavailable due to IT policy specification");
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("no GPS fix");
return;
}
});
}
}
public ApplicationIndicator _indicator;
public static handleGPSListener _instance;
public void setupIndicator() {
//Setup notification
if (_indicator == null) {
ApplicationIndicatorRegistry reg = ApplicationIndicatorRegistry.getInstance();
_indicator = reg.getApplicationIndicator();
if(_indicator == null) {
ApplicationIcon icon = new ApplicationIcon(EncodedImage.getEncodedImageResource ("daslogo.png"));
_indicator = reg.register(icon, false, true);
_indicator.setValue(0);
_indicator.setVisible(false);
}
}
}
public void setVisible(boolean visible, int count) {
if (_indicator != null) {
if (visible) {
_indicator.setVisible(true);
_indicator.setValue(count);
} else {
_indicator.setVisible(false);
}
}
}
handleGPSListener () {
}
public static handleGPSListener getInstance() {
if (_instance == null) {
_instance = new handleGPSListener ();
}
return(_instance);
}
public double returnLong(){
return lon;
}
public double returnLat(){
return lat;
}
}
Your handler's locationUpdated method is never being called, right? If you call getLocation directly does it work?
I was unable to get the listener to work correctly and eventually moved to using a timer instead from which I call getLocation...
I suspect that the listener only listens to events and does not create them, i.e. if something asked for the location, the listener will receive it as well, but if nothing asked for the location you get nothing.
In GPS it is wise to never trust the simulator, it lies. :)

J2ME/Blackberry - get audio signal amplitude level?

Is it possible in j2me to measure signal amplitude of audio record made by JSR-135 Player?
I know I can access buffer, but then what?
Target model Bold 9000, supported formats PCM and AMR. Which format I should use?
See also
Blackberry Audio Recording Sample Code
How To - Record Audio on a BlackBerry smartphone
Thank you!
Get raw PCM signal level
Use menu and trackwheel to zoom in/out and move left/right within graph.
Audio format: raw 8000 Hz 16 bit mono pcm.
Tested on Bold 9000 RIM OS 4.6
Algorythm should work in any mobile, where j2me and pcm is supported, of course implementation may require changes.
Using thread for audio recording:
class VoiceNotesRecorderThread extends Thread {
private Player _player;
private RecordControl _rcontrol;
private ByteArrayOutputStream _output;
private byte _data[];
VoiceNotesRecorderThread() {
}
public void run() {
try {
_player = Manager
.createPlayer("capture://audio?encoding=audio/basic");
_player.realize();
_rcontrol = (RecordControl) _player
.getControl("RecordControl");
_output = new ByteArrayOutputStream();
_rcontrol.setRecordStream(_output);
_rcontrol.startRecord();
_player.start();
} catch (final Exception e) {
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
Dialog.inform(e.toString());
}
});
}
}
public void stop() {
try {
_rcontrol.commit();
_data = _output.toByteArray();
_output.close();
_player.close();
} catch (Exception e) {
synchronized (UiApplication.getEventLock()) {
Dialog.inform(e.toString());
}
}
}
byte[] getData() {
return _data;
}
}
And method for painting graph using byte[] buffer:
private Bitmap getGraph(byte[] buffer, int zoom, int startFrom) {
Bitmap result = new Bitmap(Display.getWidth(), Display.getHeight());
Graphics g = new Graphics(result);
g.setColor(Color.BLACK);
int xPos = 0;
int yPos = Display.getHeight() >> 1;
for (int i = startFrom; i < buffer.length; i += 2 * zoom) {
byte[] b = new byte[] { buffer[i], buffer[i + 1] };
int level = (signedShortToInt(b) * 100 / 32767);
if (100 < level) {
level -= 200;
}
g.drawPoint(xPos, yPos - level);
xPos++;
}
return result;
}
public static final int signedShortToInt(byte[] b) {
int result = (b[0] & 0xff) | (b[1] & 0xff) << 8;
return result;
}
Screen class:
class Scr extends MainScreen {
BitmapField mGraphField = new BitmapField(new Bitmap(Display.getWidth(),
Display.getHeight()));
private VoiceNotesRecorderThread m_thread;
public Scr() {
add(mGraphField);
add(new NullField(FOCUSABLE));
}
boolean mRecording = false;
private int mZoom = 1;
private int mStartFrom = 0;
byte[] mAudioData = null;
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(mRecordStopMenuItem);
menu.add(mPaintZoomIn);
menu.add(mPaintZoomOut);
menu.add(mPaintZoomToFitScreen);
menu.add(mPaintMoveRight);
menu.add(mPaintMoveLeft);
menu.add(mPaintMoveToBegin);
}
MenuItem mRecordStopMenuItem = new MenuItem("Record", 0, 0) {
public void run() {
if (!mRecording) {
m_thread = new VoiceNotesRecorderThread();
m_thread.start();
mRecording = true;
this.setText("Stop");
} else {
m_thread.stop();
mAudioData = m_thread.getData();
zoomToFitScreen();
mRecording = false;
this.setText("Record");
}
}
};
MenuItem mPaintZoomIn = new MenuItem("Zoom In", 0, 0) {
public void run() {
zoomIn();
}
};
MenuItem mPaintZoomOut = new MenuItem("Zoom Out", 0, 0) {
public void run() {
zoomOut();
}
};
MenuItem mPaintZoomToFitScreen = new MenuItem("Fit Screen", 0, 0) {
public void run() {
zoomToFitScreen();
}
};
MenuItem mPaintMoveLeft = new MenuItem("Left", 0, 0) {
public void run() {
moveLeft();
}
};
MenuItem mPaintMoveRight = new MenuItem("Right", 0, 0) {
public void run() {
moveRight();
}
};
MenuItem mPaintMoveToBegin = new MenuItem("To Begin", 0, 0) {
public void run() {
moveToBegin();
}
};
private void zoomOut() {
if (mZoom < 200)
mZoom++;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void zoomIn() {
if (mZoom > 1)
mZoom--;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void zoomToFitScreen() {
int lenght = mAudioData.length;
mZoom = (lenght / 2) / Display.getWidth();
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveRight() {
if (mStartFrom < mAudioData.length - 30)
mStartFrom += 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveLeft() {
if (mStartFrom > 30)
mStartFrom -= 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveToBegin() {
mStartFrom = 0;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
protected boolean navigationMovement(int dx, int dy, int status,
int time) {
if (dx < 0) {
moveLeft();
} else if (dx > 0) {
moveRight();
}
if (dy < 0) {
zoomIn();
} else if (dy > 0) {
zoomOut();
}
return super.navigationMovement(dx, dy, status, time);
}
}
Was helpfull:
ADC -> integer PCM file -> signal processing
SO - How is audio represented with numbers?
Convert byte array to integer
In most devices, only MID format with a single track is supported. That is the mid0 format that supports multiple instruments in one single track. I am not sure if the api provides the facility to measure the amplitude of a signal. To convert mid files to you can use Anvil Studio that has both free and pro versions
To record audio you need to use Manager.createPlayer("capture://audio"). Also leave the encoding (PCM or AMR) to the device implementation because some phones don't support PCM/AMR
Hope this helps!

Resources