We are building an app that is supposed to do several things based on an input text file. First it parses the data in the text file and extracts the useful information and builds a linkedList. The Linked List is a group of BinaryBlock objects. From there we want to dynamically graph the getwfs() function of the BinaryBlocks. At this point, we have got the graph somewhat working but instead of graphing over time it graphs in one big clump and scrolls all the way to the end.
BinaryBlock is listed here:
This is fully tested and functional and really only important in the larger context of the program:
// BinaryBlock.java
public class BinaryBlockLite {
private int pwda[], wfs[];
String lineData;
public BinaryBlockLite( String data ){ // class constructor
lineData = data;
pwda = new int[5];
wfs = new int[4];
setWfs();
}//end constructor
public String WfsToString(){
if (wfs.length == 0)
return "";
String data = "Channel 2: ";
for(int i = 0; i < wfs.length; ++i ){
data = data + "wfs[" + i + "]=" + wfs[i] + " ";
}
return data + "\n";
}
//===========================================================
// Setters
//=============================================================
//read the 5 individual bytes of the Pwda from LineData and into the pwda[] array
private void setPwda(){
int location = 13;
for(int i = 0; i < 5; ++i){
String temp = "" + lineData.charAt(++location) + lineData.charAt(++location);
pwda[i] = Integer.parseInt(temp, 16);
}
}
//logically manipulate the 5 bytes of the PWDA into 4 10-bit WFSs
private void setWfs(){
setPwda();
int j = 0;
for (int i = 0; i < 4; ++i){
wfs[i] = ((pwda[j] << 2) | (( pwda[j + 1] >> 6) & 0x03)) & 0x03ff;
wfs[++i] = ((pwda[j + 1] << 4) | (( pwda[j + 2] >>> 4) & 0x0f)) & 0x03ff;
wfs[++i] = ((pwda[j + 2] << 6) | (( pwda[j + 3] >>> 2) & 0x3f)) & 0x03ff;
wfs[++i] = ((pwda[j + 3] << 8) | (( pwda[j + 4] >>> 0) & 0xff)) & 0x03ff;
}
}
//===========================================================
// Getters
//=============================================================
public int[] getPwda(){
return pwda;
}
public int[] getWfs(){
return wfs;
}
}//end BinaryBlock Class
The main harness is listed here:
The problem is simply that instead of repainting each time and graphing it across the screen, it graphs all of the point at one time.
//MainActivity.java
import android.os.Bundle;
import android.app.ActionBar.LayoutParams;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Color;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import com.smith.fsu.wave.BinaryBlockLite;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.ListIterator;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
public class MainActivity extends Activity {
public static LinkedList<BinaryBlockLite> list;
Button btnMain;
Boolean fileLoaded = false;
int xTick = 0,
lastMinX = 0;
Context context = this;
//
////////////////////////////////////////////////////////////////
//import test
private XYMultipleSeriesDataset WFDataset = new XYMultipleSeriesDataset();
private XYMultipleSeriesRenderer WaveFormRenderer = new XYMultipleSeriesRenderer();
private XYSeries WFCurrentSeries;
private GraphicalView WFChartView;
//////////////////////////////////////////////////////////////////////////
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new LinkedList<BinaryBlockLite>();
btnMain=(Button)findViewById(R.id.btnMain);
WaveFormRenderer.setAxisTitleTextSize(16);
WaveFormRenderer.setChartTitleTextSize(20);
WaveFormRenderer.setLabelsTextSize(15);
WaveFormRenderer.setLegendTextSize(15);
WaveFormRenderer.setMargins(new int[] {20, 30, 15, 0});
WaveFormRenderer.setAxesColor(Color.YELLOW);
String seriesTitle = "Input Data";
XYSeries series = new XYSeries(seriesTitle);
WFDataset.addSeries(series);
WFCurrentSeries = series;
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.GREEN);
WaveFormRenderer.addSeriesRenderer(renderer);
WaveFormRenderer.setXAxisMin(0.0);
WaveFormRenderer.setXAxisMax(500);
// renderer.setFillBelowLine(true) ;
// renderer.setFillBelowLineColor(Color.BLUE);
}
public void chartClick(View view) throws IOException{
String strData = "";
AssetManager amInput = context.getAssets();
BufferedReader reader;
InputStream is = null;
try {
is = amInput.open("Dinamap-Data.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
reader = new BufferedReader(new InputStreamReader(is));
try {
while( (strData = reader.readLine()) != null ) {
addBlock( strData ); //call to paint line
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//while loop
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//end mainClick() method for btnMain
public void writeClick(View view){
//write decimal data for wfs out to file from LinkedList<BinaryBlock>
//using WfsToString() method of BinaryBlock class in separate thread
(new Thread(new Runnable() {
#Override
public void run() {
FileOutputStream fos = null;
try {
fos = openFileOutput("wfs.txt", Context.MODE_WORLD_READABLE);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
ListIterator<BinaryBlockLite> itr = list.listIterator();
while (itr.hasNext()){
String temp = itr.next().WfsToString();
try {
fos.write(temp.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
})).start();
btnMain.setEnabled(false);
}
private void addBlock(final String strData) {
new Thread(new Runnable() {
public void run() {
int wfs[];
//read line into binaryBlockLite object and store object in Linked List
BinaryBlockLite bb = new BinaryBlockLite(strData);
list.add(bb);
//get the wfs data from the BinaryBlockLite object
wfs = new int[bb.getWfs().length];
wfs = bb.getWfs();
//grab each wfs individually and paint to the chart, and increment xTick
for (int k = 0; k < wfs.length; ++k){
/* check if we need to shift the x axis */
if (xTick > WaveFormRenderer.getXAxisMax()) {
WaveFormRenderer.setXAxisMax(xTick);
WaveFormRenderer.setXAxisMin(++lastMinX);
}
if (wfs[k] > 1000){
WFCurrentSeries.add(xTick, WFCurrentSeries.getY(xTick - 1));
}
else{
WFCurrentSeries.add(xTick, wfs[k]);
}
++xTick;
}
WFChartView.repaint();
}
}).start();
}
#Override
protected void onResume() {
super.onResume();
if (WFChartView == null) {
LinearLayout layout = (LinearLayout) findViewById(R.id.WFchart);
WFChartView = ChartFactory.getLineChartView(this, WFDataset, WaveFormRenderer);
layout.addView(WFChartView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// boolean enabled = WFDataset.getSeriesCount() > 0;
// setSeriesEnabled(enabled);
} else {
WFChartView.repaint();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
I think it's either super simple or a threading issue which is something that I haven't played with enough. Any help would be appreciated.
Looking at the code, I see that you add all the data to the series and then call repaint.
If you want the data to be gradually added, then move the repaint inside the for loop and put a Thread.sleep() inside, to give a chance to the UI thread to actually do the repaint.
Related
I am new to Tensorflow and Android, I am trying to classify data from external accelerometer to predict weather it align to left, right, forward , back or center. So I trained model using colab and converted it to tflite and added it to Android App, I could not make any sense of output
package com.yogai.tensorflowlava;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import android.widget.Toolbar;
import com.yogai.tensorflowlava.ml.Adxl345;
import org.tensorflow.lite.DataType;
import org.tensorflow.lite.TensorFlowLite;
import org.tensorflow.lite.support.tensorbuffer.TensorBuffer;
import java.io.IOException;
import java.nio.ByteBuffer;
public class MainActivity extends AppCompatActivity {
Button submitButton;
EditText editText;
String text;
String TAG = "My_APp";
// private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context context;
editText = findViewById(R.id.editText);
submitButton = findViewById(R.id.submitButton);
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
text = editText.getText().toString().trim();
//String str = "geekss#for#geekss";
// String[] arrOfStr = text.split(",", 3);
//
// // String[] strings = new String[] {"1", "2", "3", "4"};
// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
// Float[] floats = Arrays.stream(arrOfStr).map(Float::valueOf).toArray(Float[]::new);
// }
String[] parts = text.split(",");
float[] numbers = new float[parts.length];
for (int i = 0; i < parts.length; ++i) {
float number = Float.parseFloat(parts[i]);
float rounded = (int) Math.round(number * 1000) / 1000f;
numbers[i] = rounded;
}
// float[][] array2d = new float[1][3];
//
//
//
// for(int j=1;j<4;j++) {
// array2d[1][j] = numbers[j];
//
//
// }
// Float testValue = array2d[1][1]+1;
Log.d(TAG,String.valueOf(numbers[1]));
ByteBuffer.allocate(4).putFloat(numbers[0]).array();
byte[] byteArray= FloatArray2ByteArray(numbers);
ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
getOutput(byteBuffer);
}
});
}
public static byte[] FloatArray2ByteArray(float[] values){
ByteBuffer buffer = ByteBuffer.allocate(4 * values.length);
for (float value : values){
buffer.putFloat(value);
}
return buffer.array();
}
private void getOutput(ByteBuffer byteBuffer) {
try {
Adxl345 model = Adxl345.newInstance(getApplicationContext());
// Creates inputs for reference.
TensorBuffer inputFeature0 = TensorBuffer.createFixedSize(new int[]{1, 3}, DataType.FLOAT32);
inputFeature0.loadBuffer(byteBuffer);
// Runs model inference and gets result.
Adxl345.Outputs outputs = model.process(inputFeature0);
TensorBuffer outputFeature0 = outputs.getOutputFeature0AsTensorBuffer();
String converted = new String(buffer.array(), "UTF-8");
Toast.makeText(this,"output: "+outputFeature0.toString(),Toast.LENGTH_SHORT).show();
// Releases model resources if no longer used.
model.close();
} catch (IOException e) {
// TODO Handle the exception
Toast.makeText(this,"Error: "+ e.toString(),Toast.LENGTH_SHORT).show();
}
}
}
You can use outputFeature0.getDataType().toString() to check the type of the data.
It would return a string among "FLOAT32","INT32","UINT8","INT64","STRING","INT8".
If the type of the data is FLOAT32, you can get the data like below:
float[] data=outputFeature0.getFloatArray()
I'm using this very useful tutorial (https://github.com/RaghavSood/ProAndroidAugmentedReality) for developing a custom AR app.
It works pretty fine, but when I display markers extracted from a file folder (sometimes) the app gets blocked and restarts from the previous activity.
I suppose it's because of the big number of markers situated in the same point of the screen.
Infact, when I lower the radius, and then showing a littler number of markers, the activity continues to work.
Besides, I've tried to modify the function "getTextWidth()" as many people suggest on the net.
I don't know how to reduce the number of Markers drawn on the same point of the screen (so indipendently from reducing the radius). Can you suggest me something? THANKS A LOT!!!!!
I show you the LocalDataSource.java modified:
package com.example.pointofinterests;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import com.example.pointofinterests.R;
import com.example.pointofinterests.IconMarker;
import com.example.pointofinterests.Marker;
/**
* This class should be used as a example local data source. It is an example of
* how to add data programatically. You can add data either programatically,
* SQLite or through any other source.
*
* #author Justin Wetherell <phishman3579#gmail.com>
*/
public class LocalDataSource extends DataSource {
private List<Marker> cachedMarkers = new ArrayList<Marker>();
private static Bitmap icon = null;
public LocalDataSource(Resources res) {
if (res == null) throw new NullPointerException();
createIcon(res);
}
protected void createIcon(Resources res) {
if (res == null) throw new NullPointerException();
icon = BitmapFactory.decodeResource(res, R.drawable.icon);
}
public List<Marker> getMarkers() {
try{
String TestoIDPercorsi = readFileAsString("/sdcard/Epulia/IDPercorsi.txt");
if(TestoIDPercorsi==""){
// DOING NOTHING
}else {
String[] IDPercorso = TestoIDPercorsi.split("#");
for(int l=0; l<IDPercorso.length-1; l++){
String TestoPercorso = readFileAsString("/sdcard/Epulia/Percorso" + IDPercorso[l] + ".txt");
if (TestoPercorso.equals("")){
}else {
ArrayList<String> IDSTEPS2 = new ArrayList<String>();
String[] temp = TestoPercorso.split("#");
for (int j=1; j < temp.length; j++){
Log.d("RIGA_" + j + "_" + IDPercorso[l], temp[j]);
if(temp[j].substring(0,2).contains("P")){//POI
String[] POI = temp[j].split("\\|");
String id = POI[1];
String description = POI[2];
Double lat = Double.parseDouble(POI[3]);
Double lng = Double.parseDouble(POI[4]);
String type = POI[5];
Marker poi = new IconMarker(description, lat,lng, 0, Color.DKGRAY, icon);
cachedMarkers.add(poi);
}
}
}
}
}
}catch (Exception e){
Log.e("EXCEPTION", "> " + e);
}
return cachedMarkers;
}
public static String readFileAsString(String filePath) {
String result = "";
File file = new File(filePath);
if ( file.exists() ) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
char current;
while (fis.available() > 0) {
current = (char) fis.read();
result = result + String.valueOf(current);
}
} catch (Exception e) {
Log.d("TourGuide", e.toString());
} finally {
if (fis != null)
try {
fis.close();
} catch (IOException ignored) {
}
}
}
return result;
}
}
I would like to thank the Author of the Tutorial who helped me in fixing the problem.
I report his answer that soled my problem:
Not sure why you have that limitation but this should limit the number of Markers drawn on the screen.
In class AugmentedView.java
You can introduce a new member variable:
private static int MAX_NUM_TO_DRAW = 10;
Then in the method onDraw(Canvas canvas):
You can quit the drawing loop early.
int i=0;
ListIterator<Marker> iter = collection.listIterator(collection.size());
while (iter.hasPrevious() && i<MAX_NUM_TO_DRAW ) {
Marker marker = iter.previous();
marker.draw(canvas);
i++;
}
I'm sampling audio on android, and sending some RGB values based on this to an arduino device using Bluetooth.
There's a long delay (several seconds) between the audio samples being sent, and the arduino reacting. I'm assuming this is caused by android being much faster than the arduino, and some sort of flow control going on where the transmitting bytes are getting backed up into a buffer on the phone. The code to connect bluetooth is:
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
mmSocket.connect();
mmOutputStream = mmSocket.getOutputStream();
and then to send data:
mmOutputStream.write(0xFF);
mmOutputStream.write(outputFreq);
mmOutputStream.write(outputMagnitude);
I don't mind losing data, as I only need the most recent values to be sent.
What is the best way to achive this? I'm new to Android programming would like this to work quite soon so simpler solutions are better! I've though about some sort of stack, and a seperate thread that runs on a timer, and skims the top of the stack and sends just those values, but it sounds quite complex as i don't know anything about thread programming.
Is there a way instead to configure the outputstream that it simply discards data that hasn't been sent in time?
Here is the full code if it's any help:
package com.example.fft1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import com.androidplot.series.XYSeries;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.SimpleXYSeries;
import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;
import android.graphics.Color;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
XYPlot plot;
SimpleXYSeries plotSeries;
AudioRecord audioRecord;
RecordAudio recordTask;
int frequency = 44100;
int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
BluetoothAdapter mBluetoothAdapter;
BluetoothSocket mmSocket;
BluetoothDevice mmDevice;
OutputStream mmOutputStream;
InputStream mmInputStream;
int counter;
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
plot.setRangeBoundaries(-1000000, 1000000, BoundaryMode.FIXED);
Number[] seriesData = {1,2,3,4,5,6};
// Turn the above arrays into XYSeries':
plotSeries = new SimpleXYSeries(
Arrays.asList(seriesData), // SimpleXYSeries takes a List so turn our array into a List
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value
"Series1"); // Set the display title of the series
// Create a formatter to use for drawing a series using LineAndPointRenderer:
#SuppressWarnings("deprecation")
LineAndPointFormatter series1Format = new LineAndPointFormatter(
Color.rgb(0, 200, 0), // line color
Color.rgb(0, 100, 0), // point color
null); // fill color (none)
// add a new series' to the xyplot:
plot.addSeries(plotSeries, series1Format);
// reduce the number of range labels
plot.setTicksPerRangeLabel(3);
// by default, AndroidPlot displays developer guides to aid in laying out your plot.
// To get rid of them call disableAllMarkup():
plot.disableAllMarkup();
Button startBtn = (Button)findViewById(R.id.startButton);
int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(
MediaRecorder.AudioSource.DEFAULT,
frequency,
channelConfiguration,
audioEncoding,
bufferSize
);
startBtn.setOnClickListener(new startBtnClick());
Button connectBtn = (Button)findViewById(R.id.connectBtn);
connectBtn.setOnClickListener(new connectBtnClick());
}
class startBtnClick implements Button.OnClickListener {
#Override
public void onClick(View view) {
Button button = (Button) view;
if (button.getText().toString().equals("Start")) {
button.setText("Stop");
recordTask = new RecordAudio();
recordTask.execute();
} else {
button.setText("Start");
recordTask.cancel(false);
}
}
}
class connectBtnClick implements Button.OnClickListener {
#Override
public void onClick(View view) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(!mBluetoothAdapter.isEnabled()) {
Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 0);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
if(pairedDevices.size() > 0) {
for(BluetoothDevice device : pairedDevices) {
Log.v("BT2", "Device: " + device.getName());
if(device.getName().equals("linvor")) {
mmDevice = device;
break;
}
}
}
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard SerialPortService ID
try {
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
mmSocket.connect();
mmOutputStream = mmSocket.getOutputStream();
mmInputStream = mmSocket.getInputStream();
for (int i = 0; i < 255; i++) {
mmOutputStream.write(0xFF);
mmOutputStream.write(i);
mmOutputStream.write(255);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//beginListenForData();
}
private class RecordAudio extends AsyncTask<Void, Integer[], Void> {
#Override
protected Void doInBackground(Void... params) {
int blockSize = 128;
short[] buffer = new short[blockSize];
double[] bufferD = new double[blockSize];
audioRecord.startRecording();
// Here's the Fast Fourier Transform from JTransforms
DoubleFFT_1D fft = new DoubleFFT_1D(buffer.length);
while (!isCancelled()) {
counter = (counter + 1) % 1000;
//Log.v("FFT1", String.valueOf(counter));
int sumEnergy = 0;
logTime("start");
// Read audio to 'samples' array and convert it to double[]
audioRecord.read(buffer, 0, buffer.length);
logTime("after reading");
for (int i = 0; i < buffer.length; i++) {
bufferD[i]=buffer[i];
}
fft.realForward(bufferD);
logTime("after fft");
Integer[] spectrum = new Integer[blockSize/2];
for (int k = 0; k < blockSize / 2; k++) {
spectrum[k] = new Integer((int) Math.sqrt( (bufferD[2*k] * bufferD[2*k]) + (bufferD[2*k+1] * bufferD[2*k+1]) ));
}
int averageMagnitude = 0;
int middleFreqBin = 0;
for (int i = 0; i < spectrum.length; i++) {
averageMagnitude += spectrum[i];
}
averageMagnitude /= spectrum.length;
int halfMagnitudeSum = 0;
for (int i = 0; i < spectrum.length / 2; i++) {
halfMagnitudeSum += spectrum[i] * i;
}
halfMagnitudeSum /= 2;
int runningTotal = 0;
for (int i = 0; i < spectrum.length; i++) {
runningTotal += spectrum[i] * i;
if (runningTotal > halfMagnitudeSum) {
middleFreqBin = i;
break;
}
}
int outputMagnitude = map(averageMagnitude, 0, 50000, 0, 254);
int outputFreq = map(middleFreqBin, 0, spectrum.length, 0, 254);
if (outputMagnitude > 254) outputMagnitude = 254;
try {
//Log.v("FFT1", "OutputFreq: " + outputFreq + ", outputMagnitude: " + outputMagnitude);
mmOutputStream.write(0xFF);
mmOutputStream.write(outputFreq);
mmOutputStream.write(outputMagnitude);
Thread.sleep(10);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.v("FFT1","Not connected");
}
logTime("after bluetooth");
publishProgress(spectrum);
}
return null;
}
protected void onCancelled() {
audioRecord.stop();
}
protected void onProgressUpdate(Integer[]... args) {
Integer[] spectrum = args[0];
plotSeries.setModel(Arrays.asList(spectrum), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
plot.redraw();
}
int map(int x, int in_min, int in_max, int out_min, int out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void logTime(String text) {
if (counter < 5) {
String time = String.valueOf(new java.util.Date().getTime());
Log.v("FFT1", text + ": " + time.substring(time.length()-4, time.length()));
}
}
}
The OutputStream.write(); lines returned immediately, but the amount of delay increased over time. Clearly data was getting backed up somewhere in the bluetooth stack, which was why I put in the Thread.sleep(10), to try and slow things down.
That caused other problems around blocking though, and I replaced it with a couple of lines that check when the last write() was before sending any new data. If it was less than a configured time (call it timeDelay), then it skips the new write(). Manually tuning the value of timeDelay then enabled me to avoid flooding the bluetooth stack. For in
I am having a little problem with Relative Layouts. I'm doing a project in which I have to read some values from a .CSV file and display them dynamically in a Relative Layout. I'll put a couple of code snippets and images and then explain my problem.
First Code snippet:
package ekalavya.pratnala.quiz;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.StringTokenizer;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
public class QuizActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Beginning of variable declarations
File quizSpecs = new File("mnt/sdcard/teacher.csv"); // Read the file
BufferedReader csvReader = null;
String line = ""; // Storing each line in a string
StringTokenizer currentLine = null;
int noOfQuestions = 0; // Number of questions in the quiz
int time = 0; // Duration of the quiz
int[][] quizData; // Storing the quiz specifications in an integer array
int i = 0, j = 0; // Loop variables
int[][] questionImages = {
{ R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d,
R.drawable.e, R.drawable.f, R.drawable.g, R.drawable.h,
R.drawable.i, R.drawable.j },
{ R.drawable.a_checked, R.drawable.b_checked,
R.drawable.c_checked, R.drawable.d_checked,
R.drawable.e_checked, R.drawable.f_checked,
R.drawable.g_checked, R.drawable.h_checked,
R.drawable.i_checked, R.drawable.j_checked },
{ R.drawable.zero, R.drawable.one, R.drawable.two,
R.drawable.three, R.drawable.four, R.drawable.five,
R.drawable.six, R.drawable.seven, R.drawable.eight,
R.drawable.nine },
{ R.drawable.zero_checked, R.drawable.one_checked,
R.drawable.two_checked, R.drawable.three_checked,
R.drawable.four_checked, R.drawable.five_checked,
R.drawable.six_checked, R.drawable.seven_checked,
R.drawable.eight_checked, R.drawable.nine_checked } };
// End of variable declarations
try {
csvReader = new BufferedReader(new FileReader(quizSpecs));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
line = csvReader.readLine();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
currentLine = new StringTokenizer(line, ",");
noOfQuestions = Integer.parseInt(currentLine.nextToken());
time = Integer.parseInt(currentLine.nextToken());
while (currentLine.hasMoreTokens())
;
quizData = new int[noOfQuestions][6];
for (i = 0; i < noOfQuestions; i++) {
try {
line = csvReader.readLine();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
currentLine = new StringTokenizer(line, ",");
for (j = 0; j < 6; j++) {
quizData[i][j] = Integer.parseInt(currentLine.nextToken());
}
}
try {
csvReader.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ScrollView s1 = new ScrollView(this);
RelativeLayout r1 = new RelativeLayout(this);
for (i = 0; i < 2; i++) {
switch (quizData[i][1]) {
case 1:
case 2:
for (j = 0; j < quizData[i][2]; j++) {
ImageView option = new ImageView(this);
option.setImageResource(questionImages[0][j]);
option.setId(j + (10 * (i + 1)));
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.RIGHT_OF, j - 1
+ (10 * (i + 1)));
option.setLayoutParams(params);
r1.addView(option, params);
}
break;
}
}
s1.addView(r1, new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
this.setContentView(s1);
}
}
Image 1: https://www.dropbox.com/s/vzpilyotvgtipbb/pic2.png
Second Code snippet:
package ekalavya.pratnala.quiz;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.StringTokenizer;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
public class QuizActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Beginning of variable declarations
File quizSpecs = new File("mnt/sdcard/teacher.csv"); // Read the file
BufferedReader csvReader = null;
String line = ""; // Storing each line in a string
StringTokenizer currentLine = null;
int noOfQuestions = 0; // Number of questions in the quiz
int time = 0; // Duration of the quiz
int[][] quizData; // Storing the quiz specifications in an integer array
int i = 0, j = 0; // Loop variables
int[][] questionImages = {
{ R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d,
R.drawable.e, R.drawable.f, R.drawable.g, R.drawable.h,
R.drawable.i, R.drawable.j },
{ R.drawable.a_checked, R.drawable.b_checked,
R.drawable.c_checked, R.drawable.d_checked,
R.drawable.e_checked, R.drawable.f_checked,
R.drawable.g_checked, R.drawable.h_checked,
R.drawable.i_checked, R.drawable.j_checked },
{ R.drawable.zero, R.drawable.one, R.drawable.two,
R.drawable.three, R.drawable.four, R.drawable.five,
R.drawable.six, R.drawable.seven, R.drawable.eight,
R.drawable.nine },
{ R.drawable.zero_checked, R.drawable.one_checked,
R.drawable.two_checked, R.drawable.three_checked,
R.drawable.four_checked, R.drawable.five_checked,
R.drawable.six_checked, R.drawable.seven_checked,
R.drawable.eight_checked, R.drawable.nine_checked } };
// End of variable declarations
try {
csvReader = new BufferedReader(new FileReader(quizSpecs));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
line = csvReader.readLine();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
currentLine = new StringTokenizer(line, ",");
noOfQuestions = Integer.parseInt(currentLine.nextToken());
time = Integer.parseInt(currentLine.nextToken());
while (currentLine.hasMoreTokens())
;
quizData = new int[noOfQuestions][6];
for (i = 0; i < noOfQuestions; i++) {
try {
line = csvReader.readLine();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
currentLine = new StringTokenizer(line, ",");
for (j = 0; j < 6; j++) {
quizData[i][j] = Integer.parseInt(currentLine.nextToken());
}
}
try {
csvReader.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ScrollView s1 = new ScrollView(this);
RelativeLayout r1 = new RelativeLayout(this);
for (i = 0; i < 1; i++) {
switch (quizData[i][3]) {
case 1:
case 2:
for (j = 0; j < quizData[i][2]; j++) {
ImageView option = new ImageView(this);
option.setImageResource(questionImages[0][j]);
option.setId(j + (10 * (i + 1)));
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.RIGHT_OF, j - 1
+ (10 * (i + 1)));
option.setLayoutParams(params);
r1.addView(option, params);
}
break;
}
}
s1.addView(r1, new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
this.setContentView(s1);
}
}
Image 2: https://www.dropbox.com/s/itazcpshjzbza4t/pic1.png
When the loop in the switch case with variable 'i' is run only once, the second output comes. And if I run it twice, the first output comes. But that's not what I want. I want the first output row to show below the second output row. I know something is wrong in the code but I don't know how to rectify it. Please help me! Also, I want to know how to place those elements anywhere on the screen.
P.S. I haven't been allowed to upload images because my reputation is less than 10 (I'm a newbie here). So, I put them on Dropbox and have put the links here. Sorry for the inconvenience.
I have solved this: I specified only the RIGHT_OF property before and hence it didn't know where to place it vertically and so put it at the top. Specifying the BELOW property as well fixed the issue.
I am developing an application on Android 2.2 . Mainly what it does , is that it grab data from the internet and then it shows it on the device's screen. I have finished an Activity , but , it is too slow , it takes too much to get the web content . I would like to make it run faster . I guess that Async Task would be the most appropriate method that I should use . I've tried to change the code , to insert the Async Task but I cant figure out how to do it right .
This is my code :
package com.nextlogic.golfnews;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Html;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class Activity1 extends Activity {
View vw;
ImageView im;
Bitmap bmp;
URL url = null;
//ImageView t;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
String s="";
String pag="";
String aux1="";
ArrayList<String> pg;
ArrayList<String> links;
ArrayList<String> sbt;
TableLayout tableView = (TableLayout) findViewById(R.id.tableView);
String q="";
String tt="";
pag=getPage();
aux1=pag.substring(pag.indexOf("\">Annonse<"),pag.indexOf("<!-- START articleListBullets -->"));
pg=title(aux1);
links=urls(aux1);
sbt=subtitle(aux1);
///////////////////////////////////////////////////////////////////////////
for(int i=0; i<pg.size(); i++) {
s = "http://www.golfnews.no/" +links.get(i);
q=pg.get(i);
tt=sbt.get(i);
// create a new TableRow
TableRow row = new TableRow(this);
row.setBackgroundColor(Color.WHITE);
row.setTag(i);
row.setClickable(true);
row.setClickable(true);
row.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), News.class);
startActivityForResult(myIntent, 0);
}
});
// create a new TextView
TextView fin = new TextView(this);
vw = new View(this);
im = new ImageView(this);
////////////////////////////////////
bmp=getbmp(s);
im.setImageBitmap(bmp);
vw.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, 1));
vw.setBackgroundColor(Color.LTGRAY);
row.addView(im, new TableRow.LayoutParams(70,30));
q=titleEdit(q);
tt=subtitleEdit(tt);
//////////////////////////////////////
fin.setText(Html.fromHtml("<b>" + q + "</b>" + "<br />" +
"<small>" + tt + "</small>"));
row.addView(fin);
tableView.addView(vw);
tableView.addView(row, new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
}
public Bitmap getbmp(String s)
{
Bitmap bmp = null;
try{
url = new URL(s);
}
catch(MalformedURLException e)
{
e.printStackTrace();
}
try{
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bmp = BitmapFactory.decodeStream(is);
} catch (IOException e)
{
e.printStackTrace();
}
return bmp;
}
public String titleEdit(String q)
{
if(q.length()>33)
{
String q1 = q.substring(0,33);
String q2 = q.substring(33);
q =q1 + "<br />" +q2;
}
return q;
}
public String subtitleEdit(String tt)
{
if(tt.length()>40)
{
String tt1 = tt.substring(0,40);
String tt2 = tt.substring(40);
if(tt2.length()>42)
{
String z1 = tt2.substring(0,40);
String z2 = tt2.substring(40);
if(z2.length()>42)
{
String z21 = z2.substring(0,40);
String z22 = z2.substring(40);
z2=z21+"<br />"+z22;
}
tt2=z1+"<br />"+z2;
}
tt = "<br />"+tt1 + "<br />" +tt2;
}
return tt;
}
private ArrayList<String> title (String trax)
{
ArrayList<String> result= new ArrayList<String>();
int ok=1;
int s1,s2;
while(ok==1)
{
//System.out.println("INDEX = "+trax.indexOf("alt="));
ok=0;
if((trax.indexOf("alt=")!=-1&&trax.indexOf("\"/>")!=-1)&&((trax.indexOf("alt=")<trax.indexOf("\"/>"))))
{
ok=1;
s1 =trax.indexOf("alt=");
s2 = trax.indexOf("\"/>");
//System.out.println("s1= "+s1+" s2 = "+s2+" length="+trax.length());
result.add(trax.substring(s1+5,s2));
// i++;
trax = trax.substring(s2 + 3);
}
}
return result;
}
private ArrayList<String> subtitle (String trax)
{
ArrayList<String> result= new ArrayList<String>();
int ok=1;
int s1,s2;
while(ok==1)
{
ok=0;
if(trax.indexOf("<p>")!=-1)
{
ok=1;
s1 =trax.indexOf("<p>");
s2 = trax.indexOf(")");
//System.out.println("s1= "+s1+" s2 = "+s2+" length="+trax.length());
result.add(trax.substring(s1+3,s2+1));
trax = trax.substring(s2+1 );
}
}
return result;
}
private ArrayList<String> urls (String trax)
{
ArrayList<String> result= new ArrayList<String>();
int ok=1;
int s1,s2;
while(ok==1)
{
//System.out.println("INDEX = "+trax.indexOf("alt="));
ok=0;
if((trax.indexOf("<img src")!=-1&&trax.indexOf("alt=\"")!=-1)&&((trax.indexOf("<img src")<trax.indexOf("alt=\""))))
{
ok=1;
s1 =trax.indexOf("<img src");
s2 = trax.indexOf("alt=\"");
// System.out.println("s1= "+s1+" s2 = "+s2+" length="+trax.length());
result.add(trax.substring(s1+10,s2-2));
// i++;
trax = trax.substring(s2 + 6);
}
}
return result;
}
private String getPage() {
String str = "***";
try
{
HttpClient hc = new DefaultHttpClient();
HttpPost post = new HttpPost("http://golfnews.no/nyheter.php");
HttpResponse rp = hc.execute(post);
if(rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
str = EntityUtils.toString(rp.getEntity());
}
}catch(IOException e){
e.printStackTrace();
}
return str;
}
}
The Activity takes too much time to load .(About 10 seconds) . So please , can you help me figure out where and how to insert the Async Task ? Or maybe you can suggest me something else to make the application run faster ? Something like a handler for example ? I don't really know much since I am new to Android programming . Any advice would be much appreciated . Thanks.
1) You need improve your code style
2) For such purposes you must use AsynchTask or Handler+Separate Thread
1,2