I try do indoor navigation android application using Estimote beacons. Here is the code which I used to get distance between android device and beacons. This code sections runs approximately in every 1 second.
I need to execute this in every 100 milliseconds.
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
runOnUiThread(new Runnable() {
#Override public void run() {
long time= System.currentTimeMillis();
Log.i("###################### ", " #################");
Log.i("Time Class ", " Time value in millisecinds "+time);
toolbar.setSubtitle("Found beacons: " + beacons.size());
ArrayList<Beacon> newBeacons = new ArrayList<>();
for (int x=0; x<beacons.size();x++) {
int major= beacons.get(x).getMajor();
int minor = beacons.get(x).getMinor();
if (major==3&&minor==3) {
newBeacons.add(beacons.get(x));
Dsi[0] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==4&&minor==4) {
newBeacons.add(beacons.get(x));
Dsi[1] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==2&&minor==2) {
newBeacons.add(beacons.get(x));
Dsi[2] = Utils.computeAccuracy(beacons.get(x));
}
}
double[][] positions = new double[][] { { -3.4, 0.8}, { 0, 7.5 }, { 6.7, 6.7 } };
double[] distances = new double[] { Dsi[0], Dsi[1], Dsi[2] };
TrilaterationFunction trilaterationFunction = new TrilaterationFunction(positions, distances);
LinearLeastSquaresSolver lSolver = new LinearLeastSquaresSolver(trilaterationFunction);
NonLinearLeastSquaresSolver nlSolver = new NonLinearLeastSquaresSolver(trilaterationFunction, new LevenbergMarquardtOptimizer());
double[] expectedPosition = new double[] { 3.3, 15.0 };
RealVector x = lSolver.solve();
Optimum optimum = nlSolver.solve();
testResults(expectedPosition, 1, optimum, x);
adapter.replaceWith(newBeacons);
time= System.currentTimeMillis();
Log.i("Time Class ", " Time value in millisecinds "+time);
Log.i("###################### ", " #################");
}
});
}
});
How do I do that?
I got the answer for this problem. Here is the answer and explanation for the Estimote Beacon users and lovers.
There is a method called setForegroundScanPeriod in the Estimote Android SDK. This method implemented in BeaconManager class. This can be used to increase or decrease scanning time period.
This is the method definition
setForegroundScanPeriod(long scanPeriodMillis,long waitTimeMillis)
First parameter for the change the scan period and second parameter for the waiting time between two scanning period. Values of all parameters are taken as milliseconds. Example as follows.
setForegroundScanPeriod(200,5)
If you called like this, Then code section is executing in every 200 milliseconds with 5 milliseconds time interval.
Default values of the method is 1s for the scan time period and 0s for the waiting period. 200ms is minimum scan time period and 0ms is minimum waiting period. (if you reduce the scanning period scanning period, Broadcasting interval of your Estimote Beacon should be reduced. Broadcasting interval should less than scan time period and also minimum Broadcasting interval is 100ms)
Reducing Broadcast interval is negatively effect for Battery life of Beacon and Reducing scan time period is negatively effect for Battery life of Android device.
Here is the full example which I used to scan Beacons.
BeaconManager beaconManager = new BeaconManager(this);
beaconManager.setForegroundScanPeriod(200,0);
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override public void onBeaconsDiscovered(Region region, final List<Beacon> beacons) {
runOnUiThread(new Runnable() {
#Override public void run() {
toolbar.setSubtitle("Found beacons: " + beacons.size());
ArrayList<Beacon> newBeacons = new ArrayList<>();
for (int x=0; x<beacons.size();x++) {
int major= beacons.get(x).getMajor();
int minor = beacons.get(x).getMinor();
if (major==3&&minor==3) {
newBeacons.add(beacons.get(x));
Dsi[0] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==4&&minor==4) {
newBeacons.add(beacons.get(x));
Dsi[1] = Utils.computeAccuracy(beacons.get(x));
}
else if (major==2&&minor==2) {
newBeacons.add(beacons.get(x));
Dsi[2] = Utils.computeAccuracy(beacons.get(x));
}
}
adapter.replaceWith(newBeacons);
}
});
}
});
Related
When the condition is true my counter value is increasing continuously instead of only one value. If angle is greater than 90 degree it keeps increasing like 1,2,3,4,5 instead of 1 than 2 than 3
Shoulder = new float[] {landmarks.getLandmark(12).getX(),landmarks.getLandmark(12).getY()};
elbow =new float[] {landmarks.getLandmark(24).getX(),landmarks.getLandmark(24).getY()};
wrist = new float[] {landmarks.getLandmark(15).getX(),landmarks.getLandmark(15).getY()};
double angle = calculate_angle(Shoulder, elbow, wrist);
System.out.println(angle);
runOnUiThread(new Runnable() {
#Override
public void run() {
String stage="down";
// Stuff that updates the UI
if (angle > 90) {
stage = "down";
tv.setText(stage);
}
if (angle <=90 ){
stage = "up";
tv.setText(stage);
doSomething();
System.out.println("This is"+counter);
}
}
});
// Note: If eye_presence is false, these landmarks are useless.
Log.v(
TAG,
"[TS:"
+ packet.getTimestamp()
+ "] #Landmarks for iris: "
+ landmarks.getLandmarkCount());
Log.v(TAG, getLandmarksDebugString(landmarks));
} catch (InvalidProtocolBufferException e) {
Log.e(TAG, "Couldn't Exception received - " + e);
return;
}
});
// }
}
public int doSomething(){
counter = counter +1;
tv2.setText(String.valueOf(counter));
System.out.println("This is bingo"+counter);
return (counter);
}
Seems like you want to add some delay. You'll need to either tamper with the UI thread ie Thread.sleeep() or use System.currentTimeMillis() to check the last time the thread ran it's work.
Beg you pardon I'm a new developer.
I am using SystemClock.uptimeMillis inside of Runnable to make it look like stopwatch. I took the stopwatch source code from google.
Afterwards I make a modification every 30 seconds a variable (named price) will increase.
The weird thing is, when I start over the stopwatch, the price won't return to initial value. I've tried reset the price value in onActivityResult but the stopwatch displayed random numbers. How to make the price variable return to initial value?
Here are my codes:
Handler handler = new Handler();
long startTime = 0L, timeinMilliseconds=0L,timeSwapBuff=0L, updateTime=0L;
int pressCounter = 0;
int price = 3000;
Runnable updateTimerThread = new Runnable() {
#SuppressLint({"DefaultLocale", "SetTextI18n"})
#Override
public void run() {
timeinMilliseconds = SystemClock.uptimeMillis()-startTime;
updateTime = timeSwapBuff+timeinMilliseconds;
int secs = (int)(updateTime/1000);
int mins = secs/60;
int hours = mins/60;
secs%=60;
int milliseconds = (int)(updateTime%1000);
tv_timer.setText(String.format("%2d",hours)+":"+String.format("%2d",mins)+":"+String.format("%2d",secs)+":"
+String.format("%3d",milliseconds));
if (secs % 30 == 0){
price++;
tv_biaya.setText("Rp. "+price+",00");
}
handler.postDelayed(this,0);
}
};
and when the button clicked the method trigger this code
startTime = SystemClock.uptimeMillis();
handler.postDelayed(updateTimerThread,0);
It seems that the Price still increasing because the "price % 30 == 0" logic. My bad. When the stopwatch the secs turn 0 which %30 is also 0. Therefore, it's not go to initial value.
I've changed the logic, that I make a new a new Runnable for price.
I don't know why this count down counter shows a random number at the end?
I mean that it sometimes shows 60:15, sometimes 60:07, so on this way
min=sec=0;
new Thread(new Runnable() {
#Override
public void run() {
while (min < 60 && flagTime) {
try {
Thread.sleep(1);
G.HANDLER.post(new Runnable() {
#Override
public void run() {
String preSec="";
String preMin="";
if (sec < 59) {
sec += 1;
}
if (sec < 10) {
preSec = "0";
}
if (min < 10) {
preMin = "0";
}
score =preMin + min + ":"
+ preSec + sec;
txt[elementNumber + 1].setText(score);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
Please someone tell me why it works so weird?
Timing in ALL OSes is NOT precise, unless you use a framework or tools that is already designed for this task. You can however work with Thread.Sleep with a reasonable uncertainty. But for "reasonable" and "precise" timing, it depends on the problem you are trying to solve.
In threads, sleep(1000) does not mean that the thread will sleep exactly 1 second, so that the thread will sleep less or more every time you run your app. that is why you get random results.
This has many things else to consider like the priority of the thread.
so a better way to count down is to use other ways which is provided by android:
CountDownTimer
Timer
you may check on google and you will find many examples about how to use them.
those are more reliable and more precise.
hope this helps.
The likely reason that you're getting weird results in your TextView is that you're updating it from a thread that is not the main UI thread.
But you're making this harder than it needs to be. An easier approach would be to use a simple CountDownTimer object like this:
final long SECS_IN_1_MIN = 60;
final long MILLIS_IN_1_SEC = 1000;
final long MILLIS_IN_60_MINS = 3600000;
final TextView timer = (TextView) findViewById(R.id.timer);
new CountDownTimer(MILLIS_IN_60_MINS, MILLIS_IN_1_SEC) {
public void onTick(long millisUntilFinished) {
if (flagTime) {
long secs = (MILLIS_IN_60_MINS - millisUntilFinished) / MILLIS_IN_1_SEC;
timer.setText(String.format("%02d:%02d", secs / SECS_IN_1_MIN, secs % SECS_IN_1_MIN));
} else {
timer.setText("cancelled");
cancel();
}
}
public void onFinish() {
timer.setText("time expired");
}
}.start();
Edit: It uses a CountDownTimer to handle the timing, while using its millisUntilFinished value to calculate and display what appears to be an increasing seconds count. I threw in some symbolic names to make the code clearer and a String.format to handle single digit values in a more elegant fashion. Enjoy!
I am trying to build a timer that counts down in seconds and updates a TextView every time so it shows the time remaining. From what I can tell the timer code is working fine (1 second between events and converts from hrs and mins to secs fine) cause I have tested it outside of Android and using Log.d() in android. Updating the textview is whats giving me problems. I was getting null pointers when originally trying to update the textview cause only the UI thread can access the UI(my interpretation of the error message) and I added the runOnUiThread() which allows it to be accessed and updated but it now doesn't update correctly. I think this is where the problem lies but I am not totally sure and don't know enough to figure out how to fix it or come up with a better way to do this. I would appreciate another set of eyes. Thanks
final static int delay = 1000;
final static int period = 1000;
public void start(int hin, int min) {
run = true;
int hrinsec = (hin * (60 * 60));
int mininsec = (min * 60);
secs = hrinsec + mininsec;
run = false;
interval = secs;
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
public void run() {
// Convert seconds back to hrs and mins
hrsFromSecs(secs);
minsFromSecs(secs);
secsFromSecs(secs);
dint total = hours + minutes + seconds;
output = hours + " Hours " + minutes + " Minutes " + seconds
+ " Seconds";
// Countdown and update the textview
runOnUiThread(new Runnable() {
#Override
public void run() {
timer.setText(output);
}});
secs = secs - 1;
checkIfDone(total);
}
}, delay, period);
}
Use CountDownTimer no need to reinvent anything
I am trying to make an Android app which takes the location data in certain intervals e.g:- 5 sec, 1 min,etc. Here is my code :-
public void onLocationChanged(Location loc) {
// TODO Auto-generated method stub
if(loc!=null)
{
//Required Interval
tInterval =(minInterval*60*1000) + (secInterval)*1000 - 1000;
//The app also supports interval mode
RadioButton sel = (RadioButton) findViewById(mode.getCheckedRadioButtonId());
//Code for Manual Functionality
if(sel.getText().equals(MANUAL_RADIO))
{
Time t = new Time();
t.setToNow();
db.addLocationAtTime(loc, t);
Toast.makeText(getApplicationContext(), "Location Added to Database",Toast.LENGTH_SHORT).show();
locate.removeUpdates(this);
b.setText(MANUAL_BUTTON);
d.setEnabled(true);
}
//Code for Interval functionality
else if(sel.getText().equals(INTERVAL_RADIO))
{
//count is object of Countdown class which is a Thread object
if(count == null)
{
//t is a Time object
t.setToNow();
//SQLiteDatabase object for logging Location with Time
db.addLocationAtTime(loc, t);
Toast.makeText(getApplicationContext(), "Location Added to Database",Toast.LENGTH_SHORT).show();
count = new CountDown( tInterval);
count.start();
}
else if(count.getState().toString().equals("TERMINATED"))
{
t.setToNow();
db.addLocationAtTime(loc, t);
Toast.makeText(getApplicationContext(), "Location Added to Database",Toast.LENGTH_SHORT).show();
count = new CountDown(tInterval);
count.start();
}
}
}
}
Here is the code for the Countdown class:-
This class is used to add the interval to the app
public class CountDown extends Thread
{
long time;
public CountDown(long duration)
{
time = duration;
}
public void run()
{
long t1 = System.currentTimeMillis();
long t2 = 0;
do
{
t2 = System.currentTimeMillis();
}while(t2 - t1 < time);
}
}
The problem is that using the above code I am not getting accurate intervals. I am always getting 1 sec extra (due to which I subtracted 1000 in the formula) , but this 1 sec is not happening always. So can anyone please tell me what I am doing wrong ?
Look at LocationManager.requestLocationUpdates, just pass your time interval in parameter..
LocationManager mLocationManager = (LocationManager).getSystemService(mActivity.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 0, new GeoUpdateHandler());
i think here you need to use default features , no need to use Timer
NETWORK_PROVIDER
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, networkLocationListener);
GPS_PROVIDER
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, gpsLocationListener);
Here ,
minTime(2nd field) => minimum time interval between location updates, in milliseconds
minDistance(3rd field) => minimum distance between location updates, in meters
Documentation
I don't think the minTime param of the requestLocationUpdates(...) methods does anything at all. It does not seem to prevent distance-based updates from coming at shorter intervals, and it definitely does not cause updates to come at the specified interval, as many people seem to think. I've tried it on devices from Android 2.3.6 to 4.0.4.