J2ME/Blackberry - get audio signal amplitude level? - blackberry

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!

Related

Get data only one folder not for all folders in treeview - Blackberry

i want to show all folders(images, videos,files) with directories/files, currently only show images folder with files, but other folder are not show. I try to find solution but not found. Here is the code & its screenshot(http://postimg.org/image/wm5ypbk9d/).
FileManager.java
package com.rim.samples.device.mapactiondemo;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.KeypadListener;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.TreeField;
import net.rim.device.api.ui.component.TreeFieldCallback;
import net.rim.device.api.ui.container.MainScreen;
public class FilesManager extends MainScreen {
FTPMessages _ftp = null;
String[] fileList;
// ..................
private final Bitmap openIcon = Bitmap.getBitmapResource("open.png");
private final Bitmap closedIcon = Bitmap.getBitmapResource("closed.png");
private final Bitmap movieIcon = Bitmap.getBitmapResource("movie.png");
private final Bitmap songIcon = Bitmap.getBitmapResource("song.png");
private final Bitmap playIcon = Bitmap.getBitmapResource("play.png");
private final Bitmap imgIcon = Bitmap.getBitmapResource("images.png");
String nodeTen;
int node10;
TreeField myTree;
String[] nodeData;
// ListField to be displayed - null - no Field displayed
// List of entries to be displayed - null or length = 0 means no entries
// protected so that another Thread can update this list....
protected ListDirectory[] _resultsList = null; // entries available for
// display
private ListDirectory _selectedEntry = null;
public FilesManager(FTPMessages ftp) {
super();
_ftp = ftp;
// Setting starting directory
try {
/*
* fileList = _ftp.list(); for (int i = 0; i < fileList.length; i++)
* { _ftp.cwd(fileList[i]); }
*/
_ftp.cwd("images");
_ftp.cwd("files");
_ftp.cwd("videos");
} catch (Exception e) {
}
this.setTitle("Server File List");
TreeCallback myCallback = new TreeCallback();
myTree = new TreeField(myCallback, Field.FOCUSABLE) {
protected boolean navigationClick(int status, int time) {
// We'll only override unvarnished navigation click behavior
if ((status & KeypadListener.STATUS_ALT) == 0
&& (status & KeypadListener.STATUS_SHIFT) == 0) {
final int node = getCurrentNode();
if (getFirstChild(node) == -1) {
// Click is on a leaf node. Do some default action or
// else fall through.
// Note: this will also detect empty folders, which
// might or
// might not be something your app has to handle
Dialog.alert("clicked " + getCookie(node));
// TODO: open player screen, etc.
return true;
}
}
return super.navigationClick(status, time);
}
};
myTree.setDefaultExpanded(false);
myTree.setRowHeight(openIcon.getHeight());
try {
node10 = myTree.addChildNode(0, _ftp.pwd());
} catch (Exception e) {
}
this.add(myTree);
refreshList();
}
private void refreshList() {
// TODO Auto-generated method stub
_resultsList = null;
String[] directory = null;
try {
directory = _ftp.list();
} catch (Exception e) {
}
if (directory != null && directory.length > 0) {
_resultsList = new ListDirectory[directory.length];
for (int i = 0; i < directory.length; i++) {
_resultsList[i] = new ListDirectory(directory[i],
ListDirectory.UNIX_SERVER);
}
}
if (_resultsList != null && _resultsList.length > 0) {
// we have some results
for (int i = 0; i < _resultsList.length; i++) {
String bb = directory[i];
String nodeFive = new String(bb);
this.myTree.addChildNode(node10, nodeFive);
}
} else {
}
}
private class TreeCallback implements TreeFieldCallback {
public void drawTreeItem(TreeField _tree, Graphics g, int node, int y,
int width, int indent) {
final int PAD = 8;
String text = (String) _tree.getCookie(node);
Bitmap icon = closedIcon;
if (text.endsWith(".mp3")) {
icon = songIcon;
} else if (text.endsWith(".avi")) {
icon = movieIcon;
} else if (text.endsWith(".png") || text.endsWith(".jpg")) {
icon = imgIcon;
} else if (_tree.getExpanded(node)) {
icon = openIcon;
}
g.drawBitmap(indent, y, icon.getWidth(), icon.getHeight(), icon, 0,
0);
// This assumes filenames all contain '.' character!
if (text.indexOf(".") > 0) {
// Leaf node, so this is a playable item (movie or song)
g.drawBitmap(_tree.getWidth() - playIcon.getWidth() - PAD, y
+ PAD, playIcon.getWidth(), playIcon.getHeight(),
playIcon, 0, 0);
}
int fontHeight = getFont().getHeight();
g.drawText(text, indent + icon.getWidth() + PAD,
y + (_tree.getRowHeight() - fontHeight) / 2);
}
}
}
The other classes that used with this code, download from that link(complete project classes)
http://remote.offroadstudios.com/files/filemanager.zip
you can also check files on server, ip:64.207.150.31:21, username:remote, password:123456789

Xna (MonoGame) DynamicSoundEffectInstance Buffer already Full exception

I'm making this game in MonoGame (basically Xna) that uses DynamicSoundEffectInstance class. MonoGame does not have an implementation of DynamicSoundEffectInstance yet, so I made my own:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#if MONOMAC
using MonoMac.OpenAL;
#else
using OpenTK.Audio.OpenAL;
#endif
using System.Threading;
namespace Microsoft.Xna.Framework.Audio
{
public sealed class DynamicSoundEffectInstance : IDisposable
{
private const int BUFFERCOUNT = 2;
private SoundState soundState = SoundState.Stopped;
private AudioChannels channels;
private int sampleRate;
private ALFormat format;
private bool looped = false;
private float volume = 1.0f;
private float pan = 0;
private float pitch = 0f;
private int sourceId;
private int[] bufferIds;
private int[] bufferIdsToFill;
private int currentBufferToFill;
private bool isDisposed = false;
private bool hasSourceId = false;
private Thread bufferFillerThread = null;
// Events
public event EventHandler<EventArgs> BufferNeeded;
internal void OnBufferNeeded(EventArgs args)
{
if (BufferNeeded != null)
{
BufferNeeded(this, args);
}
}
public DynamicSoundEffectInstance(int sampleRate, AudioChannels channels)
{
this.sampleRate = sampleRate;
this.channels = channels;
switch (channels)
{
case AudioChannels.Mono:
this.format = ALFormat.Mono16;
break;
case AudioChannels.Stereo:
this.format = ALFormat.Stereo16;
break;
default:
break;
}
}
public bool IsDisposed
{
get
{
return isDisposed;
}
}
public float Pan
{
get
{
return pan;
}
set
{
pan = value;
if (hasSourceId)
{
// Listener
// Pan
AL.Source(sourceId, ALSource3f.Position, pan, 0.0f, 0.1f);
}
}
}
public float Pitch
{
get
{
return pitch;
}
set
{
pitch = value;
if (hasSourceId)
{
// Pitch
AL.Source(sourceId, ALSourcef.Pitch, XnaPitchToAlPitch(pitch));
}
}
}
public float Volume
{
get
{
return volume;
}
set
{
volume = value;
if (hasSourceId)
{
// Volume
AL.Source(sourceId, ALSourcef.Gain, volume * SoundEffect.MasterVolume);
}
}
}
public SoundState State
{
get
{
return soundState;
}
}
private float XnaPitchToAlPitch(float pitch)
{
// pitch is different in XNA and OpenAL. XNA has a pitch between -1 and 1 for one octave down/up.
// openAL uses 0.5 to 2 for one octave down/up, while 1 is the default. The default value of 0 would make it completely silent.
return (float)Math.Exp(0.69314718 * pitch);
}
public void Play()
{
if (!hasSourceId)
{
bufferIds = AL.GenBuffers(BUFFERCOUNT);
sourceId = AL.GenSource();
hasSourceId = true;
}
soundState = SoundState.Playing;
if (bufferFillerThread == null)
{
bufferIdsToFill = bufferIds;
currentBufferToFill = 0;
OnBufferNeeded(EventArgs.Empty);
bufferFillerThread = new Thread(new ThreadStart(BufferFiller));
bufferFillerThread.Start();
}
AL.SourcePlay(sourceId);
}
public void Apply3D(AudioListener listener, AudioEmitter emitter)
{
Apply3D(new AudioListener[] { listener }, emitter);
}
public void Pause()
{
if (hasSourceId)
{
AL.SourcePause(sourceId);
soundState = SoundState.Paused;
}
}
public void Apply3D(AudioListener[] listeners, AudioEmitter emitter)
{
// get AL's listener position
float x, y, z;
AL.GetListener(ALListener3f.Position, out x, out y, out z);
for (int i = 0; i < listeners.Length; i++)
{
AudioListener listener = listeners[i];
// get the emitter offset from origin
Vector3 posOffset = emitter.Position - listener.Position;
// set up orientation matrix
Matrix orientation = Matrix.CreateWorld(Vector3.Zero, listener.Forward, listener.Up);
// set up our final position and velocity according to orientation of listener
Vector3 finalPos = new Vector3(x + posOffset.X, y + posOffset.Y, z + posOffset.Z);
finalPos = Vector3.Transform(finalPos, orientation);
Vector3 finalVel = emitter.Velocity;
finalVel = Vector3.Transform(finalVel, orientation);
// set the position based on relative positon
AL.Source(sourceId, ALSource3f.Position, finalPos.X, finalPos.Y, finalPos.Z);
AL.Source(sourceId, ALSource3f.Velocity, finalVel.X, finalVel.Y, finalVel.Z);
}
}
public void Dispose()
{
if (!isDisposed)
{
Stop(true);
AL.DeleteBuffers(bufferIds);
AL.DeleteSource(sourceId);
bufferIdsToFill = null;
hasSourceId = false;
isDisposed = true;
}
}
public void Stop()
{
if (hasSourceId)
{
AL.SourceStop(sourceId);
int pendingBuffers = PendingBufferCount;
if(pendingBuffers > 0)
AL.SourceUnqueueBuffers(sourceId, PendingBufferCount);
if (bufferFillerThread != null)
bufferFillerThread.Abort();
bufferFillerThread = null;
}
soundState = SoundState.Stopped;
}
public void Stop(bool immediate)
{
Stop();
}
public TimeSpan GetSampleDuration(int sizeInBytes)
{
throw new NotImplementedException();
}
public int GetSampleSizeInBytes(TimeSpan duration)
{
int size = (int)(duration.TotalMilliseconds * ((float)sampleRate / 1000.0f));
return (size + (size & 1)) * 16;
}
public void SubmitBuffer(byte[] buffer)
{
this.SubmitBuffer(buffer, 0, buffer.Length);
}
public void SubmitBuffer(byte[] buffer, int offset, int count)
{
if (bufferIdsToFill != null) {
AL.BufferData (bufferIdsToFill [currentBufferToFill], format, buffer, count, sampleRate);
AL.SourceQueueBuffer (sourceId, bufferIdsToFill [currentBufferToFill]);
currentBufferToFill++;
if (currentBufferToFill >= bufferIdsToFill.Length)
bufferIdsToFill = null;
else
OnBufferNeeded (EventArgs.Empty);
} else {
throw new Exception ("Buffer already full.");
}
}
private void BufferFiller()
{
bool done = false;
while (!done)
{
var state = AL.GetSourceState(sourceId);
if (state == ALSourceState.Stopped || state == ALSourceState.Initial)
AL.SourcePlay(sourceId);
if (bufferIdsToFill != null)
continue;
int buffersProcessed;
AL.GetSource(sourceId, ALGetSourcei.BuffersProcessed, out buffersProcessed);
if (buffersProcessed == 0)
continue;
bufferIdsToFill = AL.SourceUnqueueBuffers(sourceId, buffersProcessed);
currentBufferToFill = 0;
OnBufferNeeded(EventArgs.Empty);
}
}
public bool IsLooped
{
get
{
return looped;
}
set
{
looped = value;
}
}
public int PendingBufferCount
{
get
{
if (hasSourceId)
{
int buffersQueued;
AL.GetSource(sourceId, ALGetSourcei.BuffersQueued, out buffersQueued);
return buffersQueued;
}
return 0;
}
}
}
}
Now, I followed this tutorial on making dynamic sounds in Xna, which worked with my custom MonoGame class. However, when I run the project (Xamarin Studio 4, Mac OS X 10.8, with MonoGame 3.0.1), it throws this exception:
Buffer already full
Pointing at the code in my custom class:
public void SubmitBuffer(byte[] buffer, int offset, int count)
{
if (bufferIdsToFill != null) {
AL.BufferData (bufferIdsToFill [currentBufferToFill], format, buffer, count, sampleRate);
AL.SourceQueueBuffer (sourceId, bufferIdsToFill [currentBufferToFill]);
currentBufferToFill++;
if (currentBufferToFill >= bufferIdsToFill.Length)
bufferIdsToFill = null;
else
OnBufferNeeded (EventArgs.Empty);
} else {
throw new Exception ("Buffer already full."); //RIGHT HERE IS THE EXCEPTION
}
}
I commented out the exception, and ran it again. It played the sound, with pops in it, but it still played it. How can I clear the buffer, so it is not full? I followed this tutorial EXACTLY, so all the code I added to my project is in there.
Oh! Figured it out myself; I changed the pending buffer count from 3 to 2. My final submit buffer code was:
while(_instance.PendingBufferCount < 2)
SubmitBuffer();
Where the 2 is, used to be a 3. Now it no longer throws the exception.

Blackberry BitmapField from SD card

I want to show a image from the SD card in a BitmapField. How to do that? Can anyone give me some sample code for that?
This may be Help full.
public Bitmap getImage(){
Bitmap bitmapImage=null;
try{
InputStream input;
FileConnection fconn = (FileConnection) Connector.open("file:///store/home/user/dirname/imgname.png", Connector.READ_WRITE);
input = fconn.openInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int j = 0;
while((j=input.read()) != -1) {
baos.write(j);
}
byte[] byteArray = baos.toByteArray();
bitmapImage = Bitmap.createBitmapFromBytes(byteArray,0,byteArray.length,1);
}catch(Exception ioe){
System.out.println(ioe);
}
return bitmapImage;
}
Enjoy..
Hi Guys above code is useful for BB OS >= 5.0
I'm using a code which can used for OS 4.2 or higher.
private Bitmap resizeBitmap(Bitmap image, int width, int height)
{
int rgb[] = new int[image.getWidth()*image.getHeight()];
image.getARGB(rgb, 0, image.getWidth(), 0, 0, image.getWidth(), image.getHeight());
int rgb2[] = rescaleArray(rgb, image.getWidth(), image.getHeight(), width, height);
Bitmap temp2 = new Bitmap(width, height);
temp2.setARGB(rgb2, 0, width, 0, 0, width, height);
return temp2;
}
private int[] rescaleArray(int[] ini, int x, int y, int x2, int y2)
{
int out[] = new int[x2*y2];
for (int yy = 0; yy < y2; yy++)
{
int dy = yy * y / y2;
for (int xx = 0; xx < x2; xx++)
{
int dx = xx * x / x2;
out[(x2 * yy) + xx] = ini[(x * dy) + dx];
}
}
return out;
}
Try this sample code:
public class LoadingScreen extends MainScreen implements FieldChangeListener
{
private VerticalFieldManager ver;
private ButtonField showImage;
private BitmapField bitmapField;
public LoadingScreen()
{
ver=new VerticalFieldManager(USE_ALL_WIDTH);
showImage=new ButtonField("Show Image",Field.FIELD_HCENTER);
showImage.setChangeListener(this);
ver.add(showImage);
bitmapField=new BitmapField(null,Field.FIELD_HCENTER);
bitmapField.setPadding(10, 0, 10, 0);
ver.add(bitmapField);
add(ver);
}
public void fieldChanged(Field field, int context)
{
if(field==showImage)
{
selectImageFromSDCARD();
}
}
private void selectImageFromSDCARD()
{
String PATH="";
if(SDCardTest.isSDCardAvailable())//sdcard available then
PATH = System.getProperty("fileconn.dir.memorycard.photos");//The default stored Images Path;
else
PATH = System.getProperty("fileconn.dir.photos");//The default stored Images Path;
FilePicker filePicker=FilePicker.getInstance();
filePicker.setPath(PATH);
filePicker.setListener(new Listener()
{
public void selectionDone(String url)
{
System.out.println("======================URL: "+url);
try
{
FileConnection file = (FileConnection)Connector.open(url);
if(file.exists())
{
InputStream inputStream = file.openInputStream();
byte[] data=new byte[inputStream.available()];
data=IOUtilities.streamToBytes(inputStream);
Bitmap bitmap=Bitmap.createBitmapFromBytes(data, 0, data.length,1);//Here we get the Image;
Bitmap scaleBitmap=new Bitmap(400, 300);//Now we are scaling that image;
bitmap.scaleInto(scaleBitmap, Bitmap.FILTER_LANCZOS);
bitmapField.setBitmap(scaleBitmap);
}
else
{
bitmapField.setBitmap(Bitmap.getBitmapResource("icon.png"));
}
}
catch (IOException e)
{
bitmapField.setBitmap(Bitmap.getBitmapResource("icon.png"));
}
}
});
filePicker.show();
}
protected boolean onSavePrompt() //It doesn't show the "Save","Discard","Cancel" POPUP;
{
return true;
}
public boolean onMenu(int instance) //It doesn't show the Menu;
{
return true;
}
}
If you have any doubts refer this Blog: Get Image From SDcard

loading indication in the ui screen itself with out using seperate screen or popup

I want to display a lodaing screen when user requests some http connections.I got some good samples from stackoverflow and google,But all of them displays the loading screen using a seperate screen.I want to show it in the same screen where user request for http Connection.
If any one have idea please share it to me,Thanks in advance.
I usually use a GaugeField in the status section of a MainScreen. Set it using the setStatus(Field field) method.
If your developing for OS v6.0 then RIM has provided the api for progress indication http://docs.blackberry.com/en/developers/deliverables/17971/Indicate_activity_1210002_11.jsp
For below OS v6.0 below code might help u.i.e ProgressAnimationField it is a custom field which takes the bitmap spinner/loader img, its num frames and style.
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
/**
* Custom class for spinner animation
*/
public class ProgressAnimationField extends Field implements Runnable
{
private Bitmap _bitmap;
private int _numFrames;
private int _frameWidth;
private int _frameHeight;
private int _currentFrame;
private int _timerID = -1;
private Application _application;
private boolean _visible;
public ProgressAnimationField( Bitmap bitmap, int numFrames, long style )
{
super( style | Field.NON_FOCUSABLE );
_bitmap = bitmap;
_numFrames = numFrames;
_frameWidth = _bitmap.getWidth() / _numFrames;
_frameHeight = _bitmap.getHeight();
_application = Application.getApplication();
}
public void run()
{
if( _visible ) {
invalidate();
}
}
protected void layout( int width, int height )
{
setExtent( _frameWidth, _frameHeight );
}
protected void paint( Graphics g )
{
g.drawBitmap( 0, 0, _frameWidth, _frameHeight, _bitmap, _frameWidth * _currentFrame, 0 );
_currentFrame++;
if( _currentFrame >= _numFrames ) {
_currentFrame = 0;
}
}
protected void onDisplay()
{
super.onDisplay();
_visible = true;
if( _timerID == -1 ) {
_timerID = _application.invokeLater( this, 200, true );
}
}
protected void onUndisplay()
{
super.onUndisplay();
_visible = false;
if( _timerID != -1 ) {
_application.cancelInvokeLater( _timerID );
_timerID = -1;
}
}
}

Image Button in BlackBerry

How do I implement an image button in BlackBerry?
here you go, complete code:
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.ButtonField;
/**
* Button field with a bitmap as its label.
*/
public class BitmapButtonField extends ButtonField {
private Bitmap bitmap;
private Bitmap bitmapHighlight;
private boolean highlighted = false;
/**
* Instantiates a new bitmap button field.
*
* #param bitmap the bitmap to use as a label
*/
public BitmapButtonField(Bitmap bitmap, Bitmap bitmapHighlight) {
this(bitmap, bitmapHighlight, ButtonField.CONSUME_CLICK|ButtonField.FIELD_HCENTER|ButtonField.FIELD_VCENTER);
}
public BitmapButtonField(Bitmap bitmap, Bitmap bitmapHighlight, long style) {
super(style);
this.bitmap = bitmap;
this.bitmapHighlight = bitmapHighlight;
}
/* (non-Javadoc)
* #see net.rim.device.api.ui.component.ButtonField#layout(int, int)
*/
protected void layout(int width, int height) {
setExtent(getPreferredWidth(), getPreferredHeight());
}
/* (non-Javadoc)
* #see net.rim.device.api.ui.component.ButtonField#getPreferredWidth()
*/
public int getPreferredWidth() {
return bitmap.getWidth();
}
/* (non-Javadoc)
* #see net.rim.device.api.ui.component.ButtonField#getPreferredHeight()
*/
public int getPreferredHeight() {
return bitmap.getHeight();
}
/* (non-Javadoc)
* #see net.rim.device.api.ui.component.ButtonField#paint(net.rim.device.api.ui.Graphics)
*/
protected void paint(Graphics graphics) {
super.paint(graphics);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap b = bitmap;
if (highlighted)
b = bitmapHighlight;
graphics.drawBitmap(0, 0, width, height, b, 0, 0);
}
public void setHighlight(boolean highlight)
{
this.highlighted = highlight;
}
}
Use RIM's Advanced UI Pack.
http://supportforums.blackberry.com/t5/Java-Development/Implement-advanced-buttons-fields-and-managers/ta-p/488276
This contains a BitmapButton field and a great number of of useful UI tools.
(No doubt Reflogs example is good, but I think for new BB developers landing on this page the Advanced UI pack is more beneficial)
perfect ImageButton for Blackberry , According to user point of view a Imagebutton should have four states
1. Normal
2. Focus
3. Selected Focus
4. Selected unfocus
the Following code maintain all four states (Field-Change-Listener and Navigation)
if you want to maintain all four states than use 1st Constructor, If you just want to handle Focus/Un-Focu state of the button than use 2nd one
########################################
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
public class ImageButton extends Field
{
Bitmap mNormalIcon;
Bitmap mFocusedIcon;
Bitmap mActiveNormalIcon;
Bitmap mActiveFocusedIcon;
Bitmap mActiveBitmap;
String mActiveText;
int mHeight;
int mWidth;
boolean isStateActive = false;
boolean isTextActive = false;
public boolean isStateActive()
{
return isStateActive;
}
public ImageButton(Bitmap normalIcon, Bitmap focusedIcon)
{
super(Field.FOCUSABLE | FIELD_VCENTER);
mNormalIcon = normalIcon;
mFocusedIcon = focusedIcon;
mActiveBitmap = normalIcon;
mActiveFocusedIcon = focusedIcon;
mActiveNormalIcon = normalIcon;
// isTextActive = false;
}
public ImageButton(Bitmap normalIcon, Bitmap focusedIcon, Bitmap activeNormalIcon, Bitmap activeFocusedIcon)
{
super(Field.FOCUSABLE | FIELD_VCENTER);
mNormalIcon = normalIcon;
mFocusedIcon = focusedIcon;
mActiveFocusedIcon = activeFocusedIcon;
mActiveNormalIcon = activeNormalIcon;
mActiveBitmap = normalIcon;
// isTextActive = true;
}
protected void onFocus(int direction)
{
if ( !isStateActive )
{
mActiveBitmap = mFocusedIcon;
}
else
{
mActiveBitmap = mActiveFocusedIcon;
}
}
protected void onUnfocus()
{
super.onUnfocus();
if ( !isStateActive )
{
mActiveBitmap = mNormalIcon;
}
else
{
mActiveBitmap = mActiveNormalIcon;
}
}
protected boolean navigationClick(int status, int time)
{
mActiveBitmap = mActiveNormalIcon;
toggleState();
invalidate();
fieldChangeNotify(1);
return true;
}
public void toggleState()
{
isStateActive = !isStateActive;
}
public int getPreferredWidth()
{
return mActiveBitmap.getWidth() + 20;
}
public int getPreferredHeight()
{
return mActiveBitmap.getHeight() + 10;
}
protected void layout(int width, int height)
{
mWidth = getPreferredWidth();
mHeight = getPreferredHeight();
setExtent(mWidth, mHeight);
}
protected void paint(Graphics graphics)
{
graphics.drawBitmap(0, 5, mWidth, mHeight, mActiveBitmap, 0, 0);
// graphics.setColor(0xff0000);
// graphics.drawText(mActiveText, ( mActiveBitmap.getWidth() -
// this.getFont().getAdvance("ON") ) / 2, mActiveBitmap.getHeight());
}
protected void drawFocus(Graphics graphics, boolean on)
{
}
public void activate()
{
mActiveBitmap = mActiveNormalIcon;
isStateActive = true;
invalidate();
}
public void deactivate()
{
mActiveBitmap = mNormalIcon;
isStateActive = false;
invalidate();
}
}
easiest way to do that:
step 1:draw a image with specific coordinates(imageX,imageY).
step 2:add a method in your Code:
void pointerControl(int x, int y) {
if (x>imageX && x<imageX+imageName.getWidth() && y>imageY && y < imageY+imageName.getHeight) {
//to do code here
}
}
where imageName:name of image
imageX=x coordinate of image(Top-Left)
imageY=y coordinate of image(Top-Left)

Resources