I have a question when calculating the hash of files eg: md5, sha1, sha256 setting the progress in the progressBar through the asynchronous process
Thanks to Alejandro Duarte who shows a very practical example
https://github.com/newUserRepo/testbar/blob/issueBar/vaadin-upload/src/main/java/com/example/vaadinupload/ProcessingService.java#L44
the only way I can get it to work is that in method line 75, I put 4 milliseconds to process the task and the bar is updated, but it is too slow.
Yes, I do not sleep the Thread the application does not do the push correctly, and the changes are not reflected correctly to the client.
Another way that actually worked was with the Runnable interface and execute the heavy task in the run() method
#Override
public void run() {
calcularHash();
}
public void calcularHash() {
System.out.println("Path tmp archivo: " +
tmpPath.toFile().getAbsolutePath());
for(int f=0; f<hashType.size(); f++) {
try (InputStream bis = new
BufferedInputStream(Files.newInputStream(tmpPath))) {
t.initTime();
byte[] buffer = new byte[1024];
MessageDigest messageDigest =
MessageDigest.getInstance(hashType.get(f));
int dataRead = 0;
long largo = tmpPath.toFile().length();
Long acum = 0L;
while ((dataRead = bis.read(buffer)) != -1) {
messageDigest.update(buffer, 0, dataRead);
acum += dataRead;
Float per = ((float) acum / largo);
bar.setValue(per);
System.out.println(per * 100);
//textFieldPercent.setValue(Types.formatPercentaje(per *
100));
}
final byte[] bytesDigest = messageDigest.digest();
final StringBuilder sb = new StringBuilder();
for (int c = 0; c < bytesDigest.length; c++) {
sb.append(Integer.toString((bytesDigest[c] & 0xFF) + 0x100,
16).substring(1));
}
final String hashObtenido = sb.toString();
t.finishTime();
final String totalTime = t.getFinalTimeSec() + "seg " +
t.getFinalTimeMs() + "ms";
final String large = Types.getLargeFileFormat(largo);
System.out.println(hashObtenido);
ui.access(() -> {
checksumTransactions.initData(messageDigest.getAlgorithm(),
sb.toString(),large, totalTime);
});
//Files.delete(tmpPath); //fixme borrar desde el grid o UI
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
In the present picture I use a simple public void run () and the Progressbar is updated well
but we know that the application may have memory leaks and is not a good practice, the ideal would be to know how to execute that Background thread
I still do not know the best way to achieve this :$
I am facing some issues when I am trying to bind photo taken from camera through my application and binding it to the image view and binding image from gallery.
I use Micromax Phone for testing our application, it works fine and binds the image as it is from that phone, but when we change our phone for example Samsung the original orientation is different than the hardware orientation so what is happening is that it is binding as per the orientation set by the hardware.
I tried to correct the orientation but was not working at all.
Can any one please try to solve my problem......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Java.IO;
using Android.Graphics;
using Android.Provider;
using Android.Content.PM;
using MyApplication.Droid;
using Android.Media;
namespace MyApplication.Droid
{
[Activity(Label = "CameraActivity")]
public class CameraActivity : Activity
{
File _file;
File _dir;
Bitmap bitmap;
ImageView _imageView, _imageView1;
int PickImageId = 1;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Camera);
if (IsThereAnAppToTakePictures())
{
CreateDirectoryForPictures();
Button button = FindViewById<Button>(Resource.Id.TakePik);
_imageView = FindViewById<ImageView>(Resource.Id.imageView2);
_imageView1= FindViewById<ImageView>(Resource.Id.imageView1);
button.Click += TakeAPicture;
}
Button button1 = FindViewById<Button>(Resource.Id.Galary);
button1.Click += delegate
{
Intent intent = new Intent();
intent.SetType("image/*");
intent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(intent, "Select Picture"), PickImageId);
};
// Create your application here
}
private void CreateDirectoryForPictures()
{
_dir = new File(
Android.OS.Environment.GetExternalStoragePublicDirectory(
Android.OS.Environment.DirectoryPictures), "MRohit Task");
if (!_dir.Exists())
{
_dir.Mkdirs();
}
}
private bool IsThereAnAppToTakePictures()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
IList<ResolveInfo> availableActivities =
PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
return availableActivities != null && availableActivities.Count > 0;
}
private void TakeAPicture(object sender, EventArgs eventArgs)
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
_file = new File(_dir, String.Format("MRohit_Task_{0}.jpg", Guid.NewGuid()));
intent.PutExtra(MediaStore.ExtraOutput, Android.Net.Uri.FromFile(_file));
StartActivityForResult(intent, 0);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{if (requestCode == 1)
{
Android.Net.Uri uri = data.Data;
_imageView1.SetImageURI(uri);
}
else
{
base.OnActivityResult(requestCode, resultCode, data);
// Make it available in the gallery
Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
Android.Net.Uri contentUri = Android.Net.Uri.FromFile(_file);
mediaScanIntent.SetData(contentUri);
SendBroadcast(mediaScanIntent);
// string str_file_path = Android.Net.Uri.Parse(_file.Path.ToString()).ToString();
// Display in ImageView. We will resize the bitmap to fit the display.
// Loading the full sized image will consume to much memory
// and cause the application to crash.
int height = Resources.DisplayMetrics.HeightPixels;
int width = _imageView.Height;
bitmap = _file.Path.LoadAndResizeBitmap(width, height);
ExifInterface ei = new ExifInterface(_file.Path);
int orientation = ei.GetAttributeInt(ExifInterface.TagOrientation,
(int)Android.Media.Orientation.Undefined);
switch (orientation)
{
case (int)Android.Media.Orientation.Rotate90:
rotateImage(bitmap, 90);
break;
case (int)Android.Media.Orientation.Rotate180:
rotateImage(bitmap, 180);
break;
case (int)Android.Media.Orientation.Rotate270:
rotateImage(bitmap, 270);
break;
case (int)Android.Media.Orientation.Normal:
default:
break;
}
if (bitmap != null)
{
_imageView.SetImageBitmap(bitmap);
bitmap = null;
}
// Dispose of the Java side bitmap.
GC.Collect();
}
}
public static Bitmap rotateImage(Bitmap source, float angle)
{
Matrix matrix = new Matrix();
matrix.PostRotate(angle);
return Bitmap.CreateBitmap(source, 0, 0, source.Width, source.Height,
matrix, true);
}
}
//To crop the image size
public static class BitmapHelpers
{
public static Bitmap LoadAndResizeBitmap(this string fileName, int width, int height)
{
////// First we get the the dimensions of the file on disk
BitmapFactory.Options options = new BitmapFactory.Options { InJustDecodeBounds = true };
BitmapFactory.DecodeFile(fileName, options);
////// Next we calculate the ratio that we need to resize the image by
////// in order to fit the requested dimensions.
int outHeight = options.OutHeight;
int outWidth = options.OutWidth;
int inSampleSize = 1;
if (outHeight > height || outWidth > width)
{
inSampleSize = outWidth > outHeight
? outHeight / height
: outWidth / width;
}
// Now we will load the image and have BitmapFactory resize it for us.
options.InSampleSize = inSampleSize;
options.InJustDecodeBounds = false;
Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options);
return resizedBitmap;
}
}
}
I used the code from the following link: Signare's Blog. I have 10 image URLs and would like to retrieve and show them on my screen. When I use the code from the above link, it's taking more than 10 minutes to load all of the images. How do I speed up this loading?
URLBitmapField post_img= new URLBitmapField(image_url);
add(post_img);
where the class URLBitmapField is defined as:
import net.rim.device.api.math.Fixed32;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EncodedImage;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
public class URLBitmapField extends BitmapField implements URLDataCallback {
EncodedImage result = null;
public static EncodedImage _encoded_img = null;
int _imgWidth = 52;
int _imgHeight = 62;
int _imgMargin = 10;
public URLBitmapField(String url) {
try {
http_image_data_extrator.getWebData(url, this);
}
catch (Exception e) {}
}
public Bitmap getBitmap() {
if (_encoded_img == null) return null;
return _encoded_img.getBitmap();
}
public void callback(final String data) {
if (data.startsWith("Exception")) return;
try {
byte[] dataArray = data.getBytes();
_encoded_img = EncodedImage.createEncodedImage(dataArray, 0, dataArray.length); // with scale
_encoded_img = sizeImage(_encoded_img, _imgWidth, _imgHeight);
setImage(_encoded_img);
UiApplication.getUiApplication().getActiveScreen().invalidate();
}
catch (final Exception e){}
}
public EncodedImage sizeImage(EncodedImage image, int width, int height) {
int currentWidthFixed32 = Fixed32.toFP(image.getWidth());
int currentHeightFixed32 = Fixed32.toFP(image.getHeight());
int requiredWidthFixed32 = Fixed32.toFP(width);
int requiredHeightFixed32 = Fixed32.toFP(height);
int scaleXFixed32 = Fixed32.div(currentWidthFixed32,requiredWidthFixed32);
int scaleYFixed32 = Fixed32.div(currentHeightFixed32,requiredHeightFixed32);
result = image.scaleImage32(scaleXFixed32, scaleYFixed32);
return result;
}
}
public interface URLDataCallback {
public void callback(String data);
}
and the class http_image_data_extrator is defined as:
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.system.RadioInfo;
import net.rim.device.api.system.WLANInfo;
import net.rim.device.api.ui.UiApplication;
public class http_image_data_extrator {
static String url_="";
static StringBuffer rawResponse=null;
public static void getWebData(String url, final URLDataCallback callback) throws IOException {
HttpConnection connection = null;
InputStream inputStream = null;
try {
if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)&& RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) {
url += ";interface=wifi";
}
connection = (HttpConnection) Connector.open(url, Connector.READ, true);
String location=connection.getHeaderField("location");
if(location!=null){
if ((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)&& RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) {
location += ";interface=wifi";
}
connection = (HttpConnection) Connector.open(location, Connector.READ, true);
}else{
connection = (HttpConnection) Connector.open(url, Connector.READ, true);
}
inputStream = connection.openInputStream();
byte[] responseData = new byte[10000];
int length = 0;
rawResponse = new StringBuffer();
while (-1 != (length = inputStream.read(responseData))) {
rawResponse.append(new String(responseData, 0, length));
}
int responseCode = connection.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK){
throw new IOException("HTTP response code: "+ responseCode);
}
final String result = rawResponse.toString();
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run(){
callback.callback(result);
}
});
}
catch (final Exception ex) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
callback.callback("Exception (" + ex.getClass() + "): " + ex.getMessage());
}
});
}
}
}
Resize on the server
Resizing the images on the server is the best answer. Because downloading big images and scaling them down requires a lot of everything (network, memory, cpu) on the device.
Resize via a proxy
If the image server is not under your control, you could still use your own server as a resizing proxy (send the image url and desired size to your server, it gets the image, resizes, and returns the resized image). Maybe there is a service that does this already.
Cheaper decode option
Some decode options may make decoding (and resizing) cheaper. DECODE_NO_DITHER, DECODE_READONLY, and DECODE_NATIVE all seem worth trying.
http://www.blackberry.com/developers/docs/4.2api/net/rim/device/api/system/EncodedImage.html#DECODE_NO_DITHER
Serial instead of parallel
You mentioned you are loading 10 images. If 10 images takes more than 10x the time 1 image takes, then the system might be "thrashing". Like it might initiate all 10 requests, then wind up working on 10 fullscale images in memory at the same time in callbacks. Could try showing the first image before starting to download the next, which also gives the user something to look at sooner. Similarly, calling invalidate 10 times in parallel (in the callback) might cause a hiccup.
I have a screen which call a listfield.
public class Main_AllLatestNews extends MainScreen {
private Database_Webservice webservice;
private String[] title, category, date, imagepath = {"no picture", "no picture", "no picture", "no picture","no picture","no picture","no picture","no picture","no picture", "no picture"};
private int[] newsid;
private List_News newslist;
public Main_AllLatestNews(final boolean needdownload) {
super(USE_ALL_WIDTH);
webservice = new Database_Webservice();
add(new Custom_TopField(this, 0, -1, "", 1, 1));
add(new Custom_BottomField(this, 0));
add(new Custom_HeaderField(Config_GlobalFunction.latest));
if (needdownload){
Main.getUiApplication().pushScreen(
new Custom_LoadingScreen(30));
webservice.UpdateAllCatNews();
}else {
webservice.LoadtodayNews();
newsid = new int[webservice.news.size()];
title = new String[webservice.news.size()];
category = new String[webservice.news.size()];
date = new String[webservice.news.size()];
//imagepath = new String[webservice.news.size()];
for (int i = 0; i < webservice.news.size(); i++) {
newslist = (List_News) webservice.news.elementAt(i);
newsid[i] = newslist.getID();
title[i] = newslist.getNtitle();
category[i] = newslist.getNewCatName();
date[i] = newslist.getNArticalD();
//imagepath[i] = newslist.getImagePath();
}
add(new Custom_ListField(newsid, title, date, category, imagepath, true));
}
}
}
When I add custom_listfield then I get:
Failed to allocate timer 0: no slots left
Here is my listfield
public Custom_ListField(int newsid[], String title[], String date[],
String category[], String imagepath[], boolean islatest) {
super(0, ListField.MULTI_SELECT);
this.newsid = newsid;
setCallback(this);
setBackground(Config_GlobalFunction.loadbackground("background.png"));
this.islatest = islatest;
rows = new Vector();
for (int x = 0; x < title.length; x++) {
TableRowManager row = new TableRowManager();
titlelabel = new Custom_LabelField(title[x],
LabelField.USE_ALL_WIDTH | DrawStyle.LEFT);
titlelabel.setFont(Font.getDefault().derive(Font.BOLD, 23));
row.add(titlelabel);
datelabel = new Custom_LabelField(date[x], DrawStyle.ELLIPSIS
| LabelField.USE_ALL_WIDTH | DrawStyle.LEFT);
datelabel.setFont(Font.getDefault().derive(Font.BOLD, 18));
datelabel.setFontColor(Color.GRAY);
row.add(datelabel);
categorylabel = new Custom_LabelField(category[x],
DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
| DrawStyle.LEFT);
categorylabel.setFont(Font.getDefault().derive(Font.BOLD, 18));
categorylabel.setFontColor(Color.RED);
row.add(categorylabel);
/*Bitmap imagebitmap = null;
if (!imagepath[x].toString().equals("no picture")) {
imagebitmap = Util_ImageLoader.loadImage(imagepath[x]);
} else {
imagepath[x] = "image_base.png";
imagebitmap = Bitmap.getBitmapResource(imagepath[x]);
}
image = new BitmapField(imagebitmap, Field.FIELD_HCENTER
| Field.FIELD_VCENTER);
row.add(image);*/
//setRowHeight(image.getBitmapHeight() + 10);
setRowHeight(70);
rows.addElement(row);
}
setSize(rows.size());
}
In this list, it will call 10 images or more. First I will check got link send to it else load local images. So the row height must be not same, however, it does not auto set row height for each row but set a same height to all row. I think out of memory because i call too many images? but I call in android also no problem.
This is my imageloader.
public class Util_ImageLoader {
public static Bitmap loadImage(String url) {
HttpConnection connection = null;
InputStream inputStream = null;
EncodedImage bitmap;
byte[] dataArray = null;
try {
// can use this for BlackBerry 5.0+ :
// connection = (HttpConnection) (new
// ConnectionFactory()).getConnection(url).getConnection();
connection = (HttpConnection) Connector
.open(url + Util_GetInternet.getConnParam(),
Connector.READ, true);
int responseCode = connection.getResponseCode();
if (responseCode == HttpConnection.HTTP_OK) {
inputStream = connection.openDataInputStream();
dataArray = IOUtilities.streamToBytes(inputStream);
}
} catch (Exception ex) {
} finally {
try {
inputStream.close();
connection.close();
} catch (Exception e) {
}
}
if (dataArray != null) {
bitmap = EncodedImage.createEncodedImage(dataArray, 0,
dataArray.length);
return bitmap.getBitmap();
} else {
return null;
}
}
}
1) What can I do to reduce the use of memory?
2) How to set different row height? I am set bitmap.getbitmapheight() but different bitmap will have different height.
//Updated//
I am running on simulator 9930 OS 7.0 and 8520 OS 5.0. Both also same result. Real Device cannot run because after signing the key also prompt the warning message try to Secure APi. I am completely commented all the images also same. I did not call neither online nor local image. I think is the data problem?
#AlanLai, can you tell us which device this is being run on, and which OS? Is it a simulator, or real hardware? Why don't you try commenting out the image completely. Don't show any images (network images, or local images). See if you still get the problem. Let's try to narrow down where exactly the code is that's causing your problem. Note: please post the information about which device you're testing on above, in the question, not as a comment response here. Thanks
How about to have only one TableRowManager and every drawRow set values with layout with specific values?
There's a lot of things you can do to reduce memory usage. For one, try to avoid keeping objects in memory longer than you really need them. One way this happens is if you keep member variables in your class, that could really be local variables in a method. Keeping member variables may lead to objects living longer than they need to, preventing the release of the memory they occupy.
Util_ImageLoader
For example, in Util_ImageLoader, you do almost all the work in the constructor. But then, you keep the result around (the Bitmap) in a static member variable (_bmap), which keeps it in memory. I know you do this so that you can call getBitmap(). But, you could change the class to be like this:
public class Util_ImageLoader {
public static Bitmap loadImage(String url) {
HttpConnection connection = null;
InputStream inputStream = null;
EncodedImage bitmap;
byte[] dataArray = null;
try {
// can use this for BlackBerry 5.0+ :
// connection = (HttpConnection) (new ConnectionFactory()).getConnection(url).getConnection();
connection = (HttpConnection) Connector.open(url + Util_GetInternet.getConnParam(), Connector.READ,
true);
int responseCode = connection.getResponseCode();
if (responseCode == HttpConnection.HTTP_OK) {
inputStream = connection.openDataInputStream();
dataArray = IOUtilities.streamToBytes(inputStream);
}
} catch (Exception ex) {
}
finally {
try {
inputStream.close();
connection.close();
} catch (Exception e) {
}
}
if (dataArray != null) {
bitmap = EncodedImage.createEncodedImage(dataArray, 0, dataArray.length);
return bitmap.getBitmap();
} else {
return null;
}
}
}
Because your Util_ImageLoader class doesn't really have any state associated with it, you can probably make it a class with just one static method. The static method does not require you to create an instance of Util_ImageLoader to use it. Just do this:
Bitmap img = Util_ImageLoader.loadImage("http://domain.com/path/image.png");
This allows the image that's loaded to be released as soon as the UI is done with it. The existing code keeps that image in memory for the life of the program.
Also, I replaced your custom code that uses a byte[] buffer, with the useful IOUtilities.streamtoBytes() method. Let the built-in libraries do the work of optimizing for you. Most of the time, they will do a pretty good job of that.
You also had some fixed point scaling code in your Util_ImageLoader class that wasn't doing anything. It was creating a scaled image of the same size as the original. So, I just removed that code. That can only help your memory usage. Image manipulation can be expensive.
Finally, I checked the web server return code (HTTP_OK) before I created any of the large objects needed for this method. If the network request fails, you certainly don't want to waste memory for no reason.
Custom_ListField
Again, you are keeping some objects around, possibly longer than needed. Let's go through your member variables:
private Bitmap bg = Bitmap.getBitmapResource("background.png"),
imagebitmap;
I don't know how many instances of Custom_ListField you will have in your app, but if you are going to assign bg to a constant app resource image, you should at least make it a static member variable, so that if there are 10 instances of Custom_ListField, you will only be keeping one bg variable in memory:
private static Bitmap bg = Bitmap.getBitmapResource("background.png"),
imagebitmap;
But, in your case, I don't think you need to keep that member variable at all. You can simply replace it where it's used, like this:
Background background = BackgroundFactory.createBitmapBackground(Bitmap.getBitmapResource("background.png"));
Then, the imagebitmap member can also be replaced with a local variable:
Bitmap imageBitmap = null;
if (!imagepath[x].toString().equals("no picture")) {
imageBitmap = Util_ImageLoader.loadImage(imagepath[x]);
imageBitmap = loader.getbitmap();
} else {
imagepath[x] = "image_base.png";
imageBitmap = Bitmap.getBitmapResource(imagepath[x]);
}
image = new BitmapField(imageBitmap, Field.FIELD_HCENTER | Field.FIELD_VCENTER);
imageBitmap only needs to be a local variable, not a member variable.
Debugging memory usage usually requires having the whole program, running, and profiling it. With only some of your code, I can't see all the other code that uses it. How many of each class is created is important? Which images are the large ones, and which are small? These are all questions you need to ask yourself to get your memory usage down.
But, hopefully, the general techniques I showed example of above can help you get started.
The problem was the Custom_ListField. This should extends listfield
instead of custom extends manager
public class Custom_ListField extends ListField {
private String[] title, category, date, imagepath;
private int[] newsid, catsid;
private List_News newslist;
private Bitmap imagebitmap[], localimage = Bitmap
.getBitmapResource("image_base.png");
private BrowserField webpage;
private Custom_BrowserFieldListener listener;
private boolean islatest;
private Vector content = null;
private ListCallback callback = null;
private int currentPosition = 0;
public Custom_ListField(Vector content, boolean islatest) {
this.content = content;
this.islatest = islatest;
newsid = new int[content.size()];
title = new String[content.size()];
category = new String[content.size()];
date = new String[content.size()];
imagepath = new String[content.size()];
catsid = new int[content.size()];
imagebitmap = new Bitmap[content.size()];
for (int i = 0; i < content.size(); i++) {
newslist = (List_News) content.elementAt(i);
newsid[i] = newslist.getID();
title[i] = newslist.getNtitle();
category[i] = newslist.getNewCatName();
date[i] = newslist.getNArticalD();
imagepath[i] = newslist.getImagePath();
if (!imagepath[i].toString().equals("no picture")) {
imagebitmap[i] = Util_ImageLoader.loadImage(imagepath[i]);
} else {
imagebitmap[i] = localimage;
}
catsid[i] = newslist.getCatID();
}
initCallbackListening();
this.setRowHeight(localimage.getHeight() + 10);
}
private void initCallbackListening() {
callback = new ListCallback();
this.setCallback(callback);
}
private class ListCallback implements ListFieldCallback {
public ListCallback() {
setBackground(Config_GlobalFunction
.loadbackground("background.png"));
}
public void drawListRow(ListField listField, Graphics graphics,
int index, int y, int width) {
currentPosition = index;
graphics.drawBitmap(
Display.getWidth() - imagebitmap[index].getWidth() - 5,
y + 3, imagebitmap[index].getWidth(),
imagebitmap[index].getHeight(), imagebitmap[index], 0, 0);
graphics.setColor(Color.WHITE);
graphics.drawRect(0, y, width, imagebitmap[index].getHeight() + 10);
graphics.setColor(Color.BLACK);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 20));
graphics.drawText(title[index], 5, y + 3, 0, Display.getWidth()
- imagebitmap[index].getWidth() - 10);
System.out.println(Display.getWidth()
- imagebitmap[index].getWidth() - 10);
graphics.setColor(Color.GRAY);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 15));
graphics.drawText(date[index], 5, y + 6
+ Font.getDefault().getHeight() + 3);
if (islatest) {
graphics.setColor(Color.RED);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 15));
graphics.drawText(category[index], Font.getDefault()
.getAdvance(date[index]) + 3, y + 6
+ Font.getDefault().getHeight() + 3);
}
}
public Object get(ListField listField, int index) {
return content.elementAt(index);
}
public int getPreferredWidth(ListField listField) {
return Display.getWidth();
}
public int indexOfList(ListField listField, String prefix, int start) {
return content.indexOf(prefix, start);
}
}
public int getCurrentPosition() {
return currentPosition;
}
protected boolean navigationClick(int status, int time) {
int index = getCurrentPosition();
if (catsid[index] == 9) {
if (Config_GlobalFunction.isConnected()) {
webpage = new BrowserField();
listener = new Custom_BrowserFieldListener();
webpage.addListener(listener);
MainScreen aboutus = new Menu_Aboutus();
aboutus.add(webpage);
Main.getUiApplication().pushScreen(aboutus);
webpage.requestContent("http://www.orientaldaily.com.my/index.php?option=com_k2&view=item&id="
+ newsid[index] + ":&Itemid=223");
} else
Config_GlobalFunction.Message(Config_GlobalFunction.nowifi, 1);
} else
Main.getUiApplication().pushScreen(
new Main_NewsDetail(newsid[index]));
return true;
}
}
I'm using NAudio (but it applies to reading directly) to capture microphone wave data. It seems that if my app is busy it drops/skips some input data from the mic.
I've set the reading thread to top priority, but I'm doing heavy calculations in several other thread at the same time.
Is there a way to read data lossless?
(Or is it lossless, and my bug elsewhere?)
When I was making a similar app and had a similar problem, it turned out that I needed a buffer that can hold at least 3 seconds of data. Try to increase the buffer to 10 seconds of data and if it doesn't solve your problem then there are more issues. If it works try decreasing the buffer size until it works properly
EDIT: Here a quick & dirty managed dx recording for you to try.
public class BMSRecordingEventArgs : EventArgs
{
byte[] data;
bool endRec;
public BMSRecordingEventArgs(byte[] data, bool endRec)
{
this.data = data;
this.endRec = endRec;
}
public byte[] Data
{
get { return data; }
}
public bool EndRec
{
get { return endRec; }
}
}
public class AudioRecorder
{
public delegate void DataReceivedHandler(object sender, BMSRecordingEventArgs e);
public event DataReceivedHandler DataReceivedHandle;
public const int CAPTURE_BUFFER_SIZE = 32000;
DXS.Capture dxsCapDev;
DXS.CaptureBuffer dxsCapBuffer;
DXS.CaptureBufferDescription dxsCapBufferDesc;
System.Threading.Thread thrdCapturingThread;
DXS.BufferPositionNotify[] dxsBpna;
private volatile bool StopRec;
System.Threading.ManualResetEvent mreStillRunning = new System.Threading.ManualResetEvent(false);
DXS.BufferPositionNotify dxsBPNHalf;
DXS.BufferPositionNotify dxsBPNFull;
DXS.Notify Notify;
System.Threading.AutoResetEvent ARE;
public AudioRecorder(Guid DeviceGuid,DXS.WaveFormat wfWaveFormat,DXS.CaptureEffectDescription[] dxsCapEffectDesc)
{
dxsCapDev = new Microsoft.DirectX.DirectSound.Capture(DeviceGuid);
dxsCapBufferDesc = new Microsoft.DirectX.DirectSound.CaptureBufferDescription();
dxsCapBufferDesc.BufferBytes = CAPTURE_BUFFER_SIZE;
dxsCapBufferDesc.Format = wfWaveFormat;
dxsCapBufferDesc.WaveMapped = true;
dxsCapBufferDesc.CaptureEffectDescription = dxsCapEffectDesc;
dxsCapBufferDesc.ControlEffects = true;
dxsCapBuffer = new Microsoft.DirectX.DirectSound.CaptureBuffer(dxsCapBufferDesc, dxsCapDev);
ARE = new System.Threading.AutoResetEvent(false);
dxsBPNHalf = new Microsoft.DirectX.DirectSound.BufferPositionNotify();
dxsBPNFull = new Microsoft.DirectX.DirectSound.BufferPositionNotify();
dxsBPNHalf.Offset = CAPTURE_BUFFER_SIZE / 2 - 1;
dxsBPNFull.Offset = CAPTURE_BUFFER_SIZE-1;
dxsBPNFull.EventNotifyHandle = ARE.SafeWaitHandle.DangerousGetHandle();
dxsBPNHalf.EventNotifyHandle = ARE.SafeWaitHandle.DangerousGetHandle();
dxsBpna = new Microsoft.DirectX.DirectSound.BufferPositionNotify[2];
dxsBpna[0] = dxsBPNHalf;
dxsBpna[1] = dxsBPNFull;
Notify = new Microsoft.DirectX.DirectSound.Notify(dxsCapBuffer);
Notify.SetNotificationPositions(dxsBpna);
}
public void StartRecording()
{
if (thrdCapturingThread != null)
throw new Exception("Already Recording !");
StopRec = false;
thrdCapturingThread = new System.Threading.Thread(Record);
thrdCapturingThread.Start();
}
private void Record()
{
DataReceivedHandler drh2 = DataReceivedHandle;
dxsCapBuffer.Start(true);
byte[] TempBaf = new byte[CAPTURE_BUFFER_SIZE / 2];
int StartingOffset = 0;
while (dxsCapBuffer.Capturing && !StopRec)
{
ARE.WaitOne(-1,false);
StartingOffset %= CAPTURE_BUFFER_SIZE;
TempBaf = (byte[])dxsCapBuffer.Read(StartingOffset, typeof(byte), Microsoft.DirectX.DirectSound.LockFlag.FromWriteCursor, CAPTURE_BUFFER_SIZE / 2);
StartingOffset += TempBaf.Length;
if (drh2 != null)
drh2(this, new BMSRecordingEventArgs(TempBaf, false));
}
dxsCapBuffer.Stop();
if (drh2 != null)
drh2(this, new BMSRecordingEventArgs(TempBaf, true));
mreStillRunning.Set();
}
public void StopRecording()
{
StopRec = true;
mreStillRunning.WaitOne(-1,false);
thrdCapturingThread = null;
}
}