Android Beacon sample app - android

I trying to build a app on beacons. so I got a sample code from here.
I have run that code and as soon as I entered into range of beacon the app is crashed and error in the logcat is as follow:
06-20 17:48:24.256: E/AndroidRuntime(18104): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Please help me out.
I checked the code and the error lies in between these lines.
iBeaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
if (iBeacons.size() > 0) {
double distance = iBeacons.iterator().next().getAccuracy();
DecimalFormat decimalFormat = new DecimalFormat("##.##");
double distanceFormatted = Double.valueOf(decimalFormat.format(distance));
TextView distanceTextView = (TextView) findViewById(R.id.am_tv_distance);
distanceTextView.setText(String.valueOf(distanceFormatted) + " m");
}
}
});

You need to perform UI changes in the UI thread:
iBeaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
if (iBeacons.size() > 0) {
double distance = iBeacons.iterator().next().getAccuracy();
DecimalFormat decimalFormat = new DecimalFormat("##.##");
double distanceFormatted = Double.valueOf(decimalFormat.format(distance));
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView distanceTextView = (TextView) findViewById(R.id.am_tv_distance);
distanceTextView.setText(String.valueOf(distanceFormatted) + " m");
}
});
}
}
});

For the CalledFromWrongThreadException,
write a function and call that like:
private void toastToDisplay(final String line) {
runOnUiThread(new Runnable() {
public void run() {
//Toast.makeText(YourActivity.this, "" + line,
// Toast.LENGTH_LONG).show();
TextView yourTextView = (TextView) findViewById(R.id.your_tv);
yourTextView .setText(line);
}
});
}
You can edit that function with your required distanceTextView or other views if you want.
What happens there is that the Service is running on the background thread in your application, so when you directly call an operation that would update the UI, it conflicts with the thread you are in while writing that code.
So If the current thread is not the UI thread, the action is posted to the event queue of the UI thread by using runOnUiThread
What exactly is the meaning of "I am getting only distance not range" ?
...for the iBeacons.iterator().next().getAccuracy();, part.. you can collect the beacon details by using a for each loop like:
for (IBeacon iBeacon : iBeacons) {
String line = "Major: " + iBeacon.getMajor()
+ "Minor: " + iBeacon.getMinor()
+ "Accuracy in m(s): "
+ iBeacon.getAccuracy()
+ "BluetoothAddress: "
+ iBeacon.getBluetoothAddress()
+ "Proximity: " + iBeacon.getProximity()
+ "ProximityUuid: "
+ iBeacon.getProximityUuid() + "Rssi: "
+ iBeacon.getRssi() + "TxPower: "
+ iBeacon.getTxPower();
toastToDisplay(line);
}
In case you haven't already seen it, this Android iBeacon Library sample application is a good reference.

Related

why the id of thread changed

i don't understand why i get different Id for the same thread here is the output
i know the id field in any programming language must stay the same for future reference
PS:this code is inside a bound service class i know the bound service is on the main thread but why id of the "message thread" changed 3 times from -1 to 21947 to 41045
*logcat output:
onCreate: thread id = 1 name =main
first is alive true thread id -1 thread name =servicemessanger
sec is alive true thread id 21947 thread name =servicemessanger
handleMessage: thread id= 41045name = servicemessanger*
code :
#Override
public void onCreate() {
Log.i(TAG, "onCreate: thread id = "+ Thread.currentThread().getId()+" name =" +Thread.currentThread().getName() );
super.onCreate();
HandlerThread thread = new HandlerThread("servicemessanger");
thread.start();
Log.i(TAG, " first is alive "+thread.isAlive() + " thread id "+ thread.getThreadId()+ " thread name ="+thread.getName());
mHandler = new Handler(thread.getLooper()){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, "handleMessage: thread id= "+Thread.currentThread().getId()+"name = " + Thread.currentThread().getName());
}
};
mHandler.sendEmptyMessage(0);
Log.i(TAG, " sec is alive "+thread.isAlive() + " thread id "+ thread.getThreadId()+ " thread name ="+thread.getName());
}
thank you,

AsyncTask takes too much time the first time it executes

The first time the Asynctask executes takes 30 or more seconds. It happens when I enter the activity. After that, subsequents call to the Asyntask(when I enter the activity again from the previous activity) takes only 4 or 5 seconds, which I consider to be "acceptable".
Here is the code where I execute the AsyncTask
#Override
public void onLocationChanged(Location location) {
if (location!=null) {
mlastLocation=location;
double latitud=Double.parseDouble(getIntent().getStringExtra("latitud").replace("Latitud:", ""));
double longitud=Double.parseDouble(getIntent().getStringExtra("longitud").replace("Longitud:", ""));
LatLng origen= new LatLng(latitud,longitud);
LatLng destino=new LatLng(mlastLocation.getLatitude(),mlastLocation.getLongitude());
if (mCount==0) {
FillVariablesAsyncTask tareaAsincrona = new FillVariablesAsyncTask();
tareaAsincrona.execute(origen, destino);
mCount++;
}
}
}
And here the code of the AsyncTask, where onPostExecute updates members variables and update the UI.
private class FillVariablesAsyncTask extends AsyncTask<LatLng,Void,Document>{
#Override
protected Document doInBackground(LatLng... params) {
md=new GMapV2Direction();
LatLng origen=new LatLng(params[0].latitude,params[0].longitude);
LatLng destino=new LatLng(params[1].latitude,params[1].longitude);
Document doc = md.getDocument(origen, destino, GMapV2Direction.MODE_WALKING);
/*mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);*/
return doc;
}
#Override
protected void onPostExecute(Document doc) {
super.onPostExecute(doc);
mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);
if (mUbicacionActual!=null && mDistancia!=null && mDuration!=null) {
progressBar.setVisibility(View.GONE);
btnIr.setEnabled(true);
tvOrigenLatitud.setText("Latitud:"+String.valueOf(mlastLocation.getLatitude()));
tvOrigenLongitud.setText("Longitud"+String.valueOf(mlastLocation.getLongitude()));
tvDestino.setText("Destino:" + getIntent().getStringExtra("info").replace("Info:", ""));
tvDestinoLatitud.setText("Latitud:" + getIntent().getStringExtra("latitud").replace("Latitud:", ""));
tvDestinoLongitud.setText("Longitud:" + getIntent().getStringExtra("longitud").replace("Longitud:", ""));
tvOrigen.setText("Origen:" + mUbicacionActual);
tvDistancia.setText("Distancia:"+mDistancia);
tvTiempo.setText("Tiempo:" + mDuration);
}
}
}
I've tried out .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) but the app crashes. I've tried out also with a handler but it shows the same Behaviour, the first time takes 30 seconds or so, while the subsequents takes only a few.
Edit to show to points where i added log:
if (mCount==0) {
FillVariablesAsyncTask tareaAsincrona = new FillVariablesAsyncTask();
mStart=System.currentTimeMillis();
Log.i("START_BEFORE_EXECUTE", mStart + "");
tareaAsincrona.execute(origen, destino);
long end=System.currentTimeMillis();
Log.i("ELAPSED_EXECUTE", ((end-mStart)/1000) + "");
mCount++;
}
Here :
protected Document doInBackground(LatLng... params) {
long end;
end =System.currentTimeMillis();
Log.i("ELAPSE_PRE_BACKGROUND",((end- mStart)/1000)+"");
md=new GMapV2Direction();
end=System.currentTimeMillis();
Log.i("ELAPSED_POS_GMAPV2DIR",((end- mStart)/1000)+"");
LatLng origen=new LatLng(params[0].latitude,params[0].longitude);
LatLng destino=new LatLng(params[1].latitude,params[1].longitude);
end=System.currentTimeMillis();
Log.i("ELAPSED_PRE_GETDOCUMENT",((end- mStart)/1000)+"");
Document doc = md.getDocument(origen, destino, GMapV2Direction.MODE_WALKING);
end=System.currentTimeMillis();
Log.i("ELAPSED_POS_BACKGROUND",((end- mStart)/1000)+"");
/*mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);*/
return doc;
}
and here:
long end=System.currentTimeMillis();
Log.i("ELAPSED_onPostExecute",((end-mStart)/1000)+"");
mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);
end=System.currentTimeMillis();
Log.i("ELAPSED_POST_FILLVARS",((end-mStart)/1000)+"");
if (mUbicacionActual!=null && mDistancia!=null && mDuration!=null) {
progressBar.setVisibility(View.GONE);
btnIr.setEnabled(true);
tvOrigenLatitud.setText("Latitud:" + String.valueOf(mlastLocation.getLatitude()));
tvOrigenLongitud.setText("Longitud" + String.valueOf(mlastLocation.getLongitude()));
tvDestino.setText("Destino:" + getIntent().getStringExtra("info").replace("Info:", ""));
tvDestinoLatitud.setText("Latitud:" + getIntent().getStringExtra("latitud").replace("Latitud:", ""));
tvDestinoLongitud.setText("Longitud:" + getIntent().getStringExtra("longitud").replace("Longitud:", ""));
tvOrigen.setText("Origen:" + mUbicacionActual);
tvDistancia.setText("Distancia:"+mDistancia);
tvTiempo.setText("Tiempo:" + mDuration);
end=System.currentTimeMillis();
Log.i("ELAPSED_POS_onPostExecute", ((end - mStart) / 1000) + "");
}
this image shows the log output, it shows 3 but in reality is 30 or more.
[IMG]http://i61.tinypic.com/95o1ef.png[/IMG]
The time is taking have absolutely nothing to do with AsyncTask or Thread or Handler or Executor
The issue is that library you're using really takes that long to make calls to a server, or to process the information and I don't believe there's much you can do about it. It's only the 1st time because I'm guessing the library caches the result, but it still have nothing to do with the threading model you use.
The main point of my answer is that you're asking the wrong question. The correct question is:
Why this library is taking that long to process and what can you do to shorten it?
Unfortunately the only possible way to answer it is by analysing the source code of it or talking directly with the library developer.
edit:
to help you measure the executions:
public static class TimeMeasure {
private final DecimalFormat format;
private final double start;
private final String tag;
public TimeMeasure(String tag) {
this.format = new DecimalFormat("0.0");
this.start = System.currentTimeMillis();
this.tag = tag;
log("start);
}
public void log(String message) {
double elapsed = ((double) (System.currentTimeMillis() - start)) / 1000.0;
Log.d(tag, format.format(elapsed) + ": " + message);
}
}
then during doInBackground
protected Document doInBackground(LatLng... params) {
TimeMeasure tm = new TimeMeasure("Carlos");
// execute something:
tm.log("action 1");
// execute next
tm.log("action 2);
// etc...
}
I can't comment yet so here you go: you can use your IDE's debugger after you place breakpoints on every line in the two given blocks of code to see which line takes the most to execute. Then post your findings.
As the above answer mentioned it is actually the library that takes too much time.
I had a similar problem a while ago, I remember that after debugging what causes the problem was distance and duration and also if you were getting some kind of an address, it will contribute to the delay
(For Example) getting street name, city name and country etc..
I didn't really find any better API or library to deal with this but what i did was something to improve the user experience:
1-start another AsyncTask from onPostExecute() that will get duration and distance.
2- while the app is getting duration and distance don't block the user interface with a progress dialog or progress bar, just put loading... as an default value of your TextView then when the app receives the data setText to the actual value.
3-Do all of you data manipulation later after setting important data.
Hope this will help.

Android trouble comparing strings with RecognitionListener

The thing that bugs me the most about this is; I have another activity that uses a different approach (using startActivityForResult(intent....) vs a listener class implementing RecognitionListener, and one works the other doesnt'. I'm certain I'm doing something stupidly wrong, but I sure can't figure out what.
I'm getting the speech recog results back using onResults, using a listener class that implements RecognitionListener.
public void onResults(Bundle results) {
Log.d("Speech", "onResults");
ArrayList strlist = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
for (int i = 0; i < strlist.size(); i++) {
String matchstring = matchpair[1].toString().toLowerCase();
String speechstring = strlist.get(i).toString().toLowerCase();
Log.d("Speech", "result=" + speechstring);
if (checkResult(matchstring, speechstring)) {
System.out.println("Phonetic match: " + speechstring + " = " + matchstring);
} else System.out.println("NO match: " + speechstring + " = " + matchstring);
}
}
The checkresult is simple, just a boolean compare:
public boolean checkResult(String result, String checkmatch) {
if (result.equals(checkmatch))
{
return true;
}
return false;
}
Looking at the debug info, the results appear to compare - but the boolean is returning false.
It's driving me nuts. I'm going this route so I can use the recognition functionality without having the Google dialog pop on every recognition attempt. In the activity I began with, the compare is working perfectly.
I welcome someone pointing out whatever very stupid thing I am overlooking.

Android: Updating int ever second

I am creating a text file with data related to my App's game.
I want to show the score at each second in the game.
How can I ensure that my int for seconds is updated, starting at zero
Example of output wanted:
Seconds Score
0 3
1 9
2 16
3 20
.....etc
Current output (seconds always 0):
Seconds Score
0 3
0 9
0 16
0 20
.....etc
Current code:
int seconds=0;
//creating header in the txt file Note: Blanked out as it is generating every second
writeToFileEEGPower(order("Seconds")+order("highAlpha")+order("lowAlpha")+order("highBeta")+order("LowBeta")+
order("lowGamma")+order("midGamma")+order("Delta")+order("Theta")+ "\n");
//creating the string to be written to file
String line = order(seconds+"")+order(eegPower.highAlpha+"")+order(eegPower.lowAlpha+"")+order(eegPower.highBeta+"")+
order(eegPower.lowBeta+"")+order(eegPower.midGamma+"")+order(eegPower.delta+"")+order(eegPower.theta+"")+ "\n";
//write the string to file
writeToFileEEGPower(line);
seconds++;
I think you should rather use a sqlite table for this. Greendao
is a good tool for managing those tables. You can save the information every second to a table. When the game is finished, you have a full list of the score for each second of the game.
In your code example the "second" variable is set to 0 each time before you write a new line. I think that is the problem.
Using TimerTask or Handler with postDelayed() method can do the trick.
You can use a handler to update your text file every second:
public class MyActivity extends Activity {
private android.os.Handler mHandler = new android.os.Handler();
private Runnable textFileLogger;
private int seconds = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
//Create header for text file
writeToFileEEGPower(order("Seconds") + order("highAlpha") + order("lowAlpha") + order("highBeta") + order("LowBeta") +
order("lowGamma") + order("midGamma") + order("Delta") + order("Theta") + "\n");
textFileLogger = new Runnable() {
#Override
public void run() {
seconds++;
String line = order(seconds + "") + order(eegPower.highAlpha + "") + order(eegPower.lowAlpha + "") + order(eegPower.highBeta + "") +
order(eegPower.lowBeta + "") + order(eegPower.midGamma + "") + order(eegPower.delta + "") + order(eegPower.theta + "") + "\n";
//write the string to file
writeToFileEEGPower(line);
//Repeats the logging after 1 second
mHandler.postDelayed(this, 1000);
}
};
//Starts the logging after 1 second
mHandler.postDelayed(textFileLogger, 1000);
}
#Override
protected void onDestroy() {
super.onDestroy();
//To stop the logging:
mHandler.removeCallbacks(textFileLogger);
}
}

Exception processing async thread queue java.lang.UnsupportedOperationException

I am having a problem when I create an array of strings, this only happens in 2.1 android api level 7 or lower and i need to install the application on a device with exactly this configuration, any idea how to solve the problem?
Below the source code, the message that pops up on screen and also logcat's message.
CODE:
private String[] fillPedidosName() {
TipoPedidoDAO tipoDAO = null;
try {
tipoDAO = new TipoPedidoDAO();
pedidosList = tipoDAO.selectAll();
String[] temp = new String[pedidosList.size()];
for (int i = 0; i < pedidosList.size(); i++) {
if (pedidosList.get(i) != null) {
temp[i] = pedidosList.get(i).getDescricao().toString();
}
}
return temp;
} catch (Exception ex) {
MyLoger.logar(ex);
return null;
} finally {
if (tipoDAO.getDB().isOpen()) {
tipoDAO.closeConnection();
}
}
}
THE MESSAGE THAT POPS UP DEBUGING:
Exception processing async thread queue
Exception processing async thread queue
java.lang.UnsupportedOperationException
lOGCAT'S MESSAGE:
03-03 17:57:57.124: ERROR/jdwp(1267): REQ: UNSUPPORTED (cmd=2/11 dataLen=8 id=0x0012ba)
You are probably not using a List that supports get(int).
Try changing your List implementation to ArrayList. When you create your list:
List myList = new ArrayList()
This is probably happening inside tipDAO.selectAll().
I had this problem. I got it fixed.
When working with Arrays of your Objects, make sure you have defined a constructor in the object file.
This piece of code was creating the error
List<Prediction> predictions = new ArrayList<Prediction>();
The fix.
Prediction class file was missing a constructor. After putting in a default constructor, the error is gone for me.
package com.thuptencho.torontotransitbus.models;
public class Prediction {
public String epochTime = "", seconds = "", minutes = "", isDeparture = "", affectedByLayover = "", branch = "",
dirTag = "", vehicle = "", block = "", tripTag = "";
//this constructor was missing..after coding this constructor. the error was gone.
public Prediction(){
super();
}
#Override
public String toString() {
return "epochTime:" + this.epochTime + " seconds:" + this.seconds + " minutes:" + this.minutes
+ " isDeparture:" + this.isDeparture + " affectedByLayover:" + this.affectedByLayover + " branch:"
+ this.branch + " dirTag:" + this.dirTag + " vehicle:" + this.vehicle + " block:" + this.block
+ " triptag:" + this.tripTag;
}
}

Categories

Resources