I am trying to implement an animation of Markers on a Google Map. The issue I am running into is an Animation being started while another Animation is still happening for a specific Marker.
Is there a way to stop the iteration of a loop, and continue only when
a certain criteria is met?
Get LatLng - Start Animation - Callback Fires (Animation Finished) - Get LatLng.. Etc.
public void animateMarker(final String key, final List<LatLng> latlngList) {
Log.e(TAG, "------------- MARKER " + key + "-------------");
Handler mHandler = new Handler();
mHandler.post(new Runnable() {
final AnimateCarObj animateCarObj = animateCarObjMap.get(key);
final Marker marker = markersHashMap.get(key);
Boolean isAnimationRunning = false;
#Override
public void run() {
final Iterator<LatLng> iterator = latlngList.iterator();
while (iterator.hasNext()) {
if (!(isAnimationRunning)) {
Log.e(TAG, "START -- " + key + ": " + iterator.next().toString());
try {
isAnimationRunning = true;
LatLngInterpolator latlonInter = new LinearFixed();
latlonInter.interpolate(1, marker.getPosition(), iterator.next());
MarkerAnimation.animateMarker(new RunningCallback() {
#Override
public void onFinish() {
Log.e(TAG, "FINISH -- " + key + ": " + iterator.next().toString());
isAnimationRunning = false;
}
}, latlngList.size(), marker, iterator.next(), latlonInter);
} catch (Exception e) {
Log.e(TAG, "EXCEPTION: " + e.getMessage());
e.printStackTrace();
}
}
}
}
});
}
Just use a while loop to stop your iterator logic.
while (iterator.hasNext()) {
// wait
while (!someBooleanConditionToWaitFor) { }
// do your other stuff
// when you're done your other stuff, set it back to false.
someBooleanConditionToWaitFor = false;
}
When your animation has finished, set the condition to true so that it continues. When you're at the end of that iteration, set it back to false so it waits again.
Create a global static boolean flag
public static boolean criteriaMet=false;
After your criteria is met set it to true. Continue the iteration of the loop only if the flag is true.
Related
I have a For loop in which I call a method to upload images to the server , the problem that i am facing that at a certain limit the server will force stop the opened socket so i have to upload every image at once
for (int i = 0; i < paths.size(); i++) {
transferData(paths.get(i), i);
}
and the transferData Function I am using the transfer Utility aws s3 function
TransferUtility transferUtility =
TransferUtility.builder()
.context(this)
.awsConfiguration(AWSMobileClient.getInstance().getConfiguration())
.s3Client(amazonS3Client)
.defaultBucket("name")
.build();
TransferObserver uploadObserver = transferUtility.upload("name", name, new File(path), CannedAccessControlList.PublicRead);
uploadObserver.setTransferListener(new TransferListener() {
#Override
public void onStateChanged(int id, TransferState state) {
Log.d(TAG, "onStateChanged: " + id + ", " + state);
if (TransferState.COMPLETED == state) {
}
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
float percentDonef = ((float) bytesCurrent / (float) bytesTotal) * 100;
int percentage = (int) percentDonef;
Log.d(TAG, "onProgressChanged: " + percentage);
}
#Override
public void onError(int id, Exception ex) {
Log.e(TAG, "Error during upload: " + id, ex);
try {
showToast(ex.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
ex.printStackTrace();
}
});
How to wait for the method to finish execution then continue the loop
to wait loop use this code :
CountDownLatch latch=new CountDownLatch(1);
for (int i = 0; i < paths.size(); i++) {
transferData(paths.get(i), i);
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and put this at the end of your method that finished upload image or failed
latch.countDown();
when your method rich to latch.countDown(); your loop will be continue
notice that you must put your loop in another thread except main thread
I am building a collector application that continuously scans the Bluetooth and writes the RSSI results in a file, I used this code but it scans and records the data every 5-second.
I want to make it scan and collect the RSSI data every 100 mill second.Please help me to modify this.
private ScanCallback leScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, final ScanResult result) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
// Tried new Handler(Looper.myLopper()) also
#Override
public void run() {
peripheralTextView.append("MAC: " + result.getDevice().getAddress() +","
+ result.getDevice().getName() +","
+ " RSSI: " + result.getRssi() + "\n");
}
});
try {
long TimeStampMillSec = TimeStampMillSec();
String DateTimeToIso8601Datetimehhmmss = DateTimeToIso8601Datetimehhmmss();
JSONObject jsonMsg =new JSONObject();
//Edited by Mansour
jsonMsg.put("BLue",
"6"+","+phoneIMEI+","+DateTimeToIso8601Datetimehhmmss+
","+TimeStampMillSec+","+result.getDevice().getName()
+ "," + result.getRssi());
WriteMessageLog(0, jsonMsg +"\n");
// auto scroll for text view
final int scrollAmount =
peripheralTextView.getLayout().getLineTop(peripheralTextView.getLineCount())
- peripheralTextView.getHeight();
// if there is no need to scroll, scrollAmount will be <=0
if (scrollAmount > 0)
peripheralTextView.scrollTo(0, scrollAmount);
}
catch (Exception e)
{
e.printStackTrace();
}
}
};`
I am working on a fitness app using Google fit API.
Step data from the API is passed to a method stepDisplayer with e.g. params (3300, "steps").
I am trying to update the progress bar once value == daily1 so that the max of bar is then pbStepBar.setMax(daily2) and again to pbStepBar.setMax(daily3) when value == daily2, while the progress of the bar is always set to value e.g. 3500/4000 then 4102/8000 and 8900/12000.
I tried to use a switch statement comparing the goals to value with a method called setNextGoal(value) with getter and setter methods getCurrentGoal() and setCurrentGoal() as seen below, but that did not work. Max value does not change from daily1 when I run the application and it looks something like this 5050/4000.
What am I doing wrong? Can I replace pbStepBar with another progress bar and and switching visibility?
Layout
<ProgressBar
android:id="#+id/pbStepBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="300dp"
android:layout_height="15dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="5dp"
android:layout_marginTop="25dp"
android:indeterminate="false"
android:scaleY="3"
/>
public class MainActivity {
//these are goals
int daily1 = 4000
int daily2 = 8000
int daily3 = 12000
//set to this onCreate
pbStepBar.setMax = daily1
private void stepDisplayer(final int value, final String field) {
tvHomeSteps = (TextView) findViewById(R.id.tvHomeSteps);
pbStepBar = (ProgressBar) findViewById(R.id.pbStepBar);
setNextGoal(value);
runOnUiThread(new Runnable() {
#Override
public void run() {
tvHomeSteps.setText("today's " + field + " " + value + "/" + dailyStepGoal);
}
});
new Thread(new Runnable() {
#Override
public void run() {
while (value <= getCurrentGoal()) {
handler.post(new Runnable() {
#Override
public void run() {
pbStepBar.setProgress(value);
}
});
try {
Thread.sleep(25);
}
catch (InterruptedException e) {
e.printStackTrace();
}
if (getCurrentGoal() == value) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Well done you reached your daily goal of " + getCurrentGoal() + " " + field,
Toast.LENGTH_LONG).show();
}
});
}
setNextGoal(value);
}
}
}).start();
}
private void setNextGoal (final int value) {
switch (value) {
case dailyStepGoal:
setCurrentGoal(dailyStepGoal + stepGoalIncrement);
pbStepBar.setMax(dailyStepGoal + stepGoalIncrement);
break;
case dailyStepGoal + stepGoalIncrement:
setCurrentGoal(dailyStepGoal + (stepGoalIncrement*2));
pbStepBar.setMax(dailyStepGoal + (stepGoalIncrement*2));
break;
case dailyStepGoal + (stepGoalIncrement*2):
setCurrentGoal(dailyStepGoal + (stepGoalIncrement*3));
pbStepBar.setMax(dailyStepGoal + (stepGoalIncrement*3));
break;
case dailyStepGoal + (stepGoalIncrement*3):
setCurrentGoal(dailyStepGoal + (stepGoalIncrement*4));
pbStepBar.setMax(dailyStepGoal + (stepGoalIncrement*4));
break;
case dailyStepGoal + (stepGoalIncrement*4):
setCurrentGoal(dailyStepGoal + (stepGoalIncrement*5));
pbStepBar.setMax(dailyStepGoal + (stepGoalIncrement*5));
break;
}
}
I found the solution.
I used an int variable currentGoal as seen below to keep track of the current goal. I think the problem was that I was trying to call methods in the activity from the UI thread. I used a simple if statement, don't know why I didn't think of this earlier.
I also tested the solution it works well.
private void stepDisplayer(final int value, final String field) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (value >= currentGoal) {
Toast.makeText(getApplicationContext(), "Well done you reached your daily goal of " + currentGoal + " " + field,
Toast.LENGTH_LONG).show();
currentGoal += stepGoalIncrement;
tvHomeSteps.setText("today's " + field + " " + value + "/" + currentGoal);
}
else {
tvHomeSteps.setText("today's " + field + " " + value + "/" + currentGoal);
}
}
});
new Thread(new Runnable() {
#Override
public void run() {
while (value <= currentGoal) {
handler.post(new Runnable() {
#Override
public void run() {
pbStepBar.setProgress(value);
if (value >= pbStepBar.getMax()) {
pbStepBar.setMax(currentGoal);
pbStepBar.setProgress(value);
}
else {
pbStepBar.setProgress(value);
}
}
});
try {
Thread.sleep(25);
}
catch (InterruptedException e) {
e.printStackTrace();
}
//setNextGoal(pbStepBar, value);
}
}
}).start();
}
For the last week, I have been using Android Studio to write code that achieves the following goals:
Wait for the user to be within a certain distance of the start waypoint
Once at start waypoint, begin a timer that logs gps data and current time
Stops timer when the end waypoint is crossed
At the moment, I have the start and end waypoints hard coded but I seem to run into an error that I have been trying to trace with the step through function on my IDE but can't seem to find it. Below is the code I have been using:
void StartTimer (View view){
//Location l = null;
boolean hasLoc = false; //are we at the start?
float speed = 0;
float topSpeed = 0;
while(hasLoc == false && cancel == false){
float d = l.distanceTo(t);
if(d < 2.0)
hasLoc = true;
//if(!l.equals(lm.getLastKnownLocation("")))
String msg = "Latitude: " + l.getLatitude() + "\nLongitude: "+ l.getLongitude();
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();
}
hasLoc = false;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// Actions to do after 10 seconds
buzzer();
}
}, 10000);
while(l.distanceTo(tf) > 2.0 && cancel == false){
float cSpeed = l.getSpeed();
if(cSpeed>topSpeed)
topSpeed = cSpeed;
String msg = "Current Speed: "+cSpeed+"Top Speed: "+topSpeed;
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();
}
cancel = false;
}
When I run the code, the phone I test it one will run it but it won't respond, which leads me to believe there is an unsatisfied loop that I have not considered.
Any suggestions would be helpful, thank you in advance for advice!
Your while loops are clogging up the CPU's execution which is what is causing it to not respond. Instead you should place your code inside a thread and call Thread.sleep(1000); inside the thread, this way the the while loop is paused for 1 second after every execution of the code inside it.
Something like this:
new Thread(new Runnable() {
#Override
public void run() {
while (hasLoc == false && cancel == false) {
float d = l.distanceTo(t);
if (d < 2.0)
hasLoc = true;
String msg = "Latitude: " + l.getLatitude() + "\nLongitude: " + l.getLongitude();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();
}
});
}
hasLoc = false;
new Handler().postDelayed(new Runnable() {
public void run() {
// Actions to do after 10 seconds
buzzer();
}
}, 10000);
while (l.distanceTo(tf) > 2.0 && cancel == false) {
float cSpeed = l.getSpeed();
if (cSpeed > topSpeed)
topSpeed = cSpeed;
String msg = "Current Speed: " + cSpeed + "Top Speed: " + topSpeed;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();
}
});
}
cancel = false;
}
}).start();
I'm trying to call my updateDisplay method through a for loop to set the text for the corresponding index, but in the output only the 5th index code is getting run.
Here is the for loop that I'm calling in my fragment's onCreateView();
private int mIndexofDays;
for(int i =1; i < 6; i++) {
DateTime nextday = mDateTime.plusDays(i);
long time = nextday.getMillis() / 1000;
getForecast(mLattitude, mLongitude, time);
mIndexofDays = i;
}
Here is the getForecast() method:
private void getForecast(double latitude, double longitude, long time)
{
String apiKey = getResources().getString(R.string.api_key);
String forecastUrl = "https://api.forecast.io/forecast/" + apiKey +
"/" + latitude + "," + longitude + "," + time;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecastUrl)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
}
#Override
public void onResponse(Call call, Response response) throws IOException {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
try {
String jsonData = response.body().string();
Log.v(TAG, jsonData);
if (response.isSuccessful()) {
mWeather = getCurrentDetails(jsonData);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d(TAG, "Running....");
updateDisplay();
}
});
} else {
Log.d(TAG, "Response not successful");
}
} catch (IOException e) {
Log.e(TAG, " IOException caught: ", e);
} catch (JSONException e) {
Log.e(TAG, "JSON exception caught: ", e);
}
}
});
}
And here is the updateDisplay() method:
private void updateDisplay() {
if(mIndexofDays == 1) {
mDayOfWeek1.setText(mDateTime.plusDays(1).dayOfWeek().getAsShortText());
Drawable drawable = getResources().getDrawable(mWeather.getIconId());
mDayOfWeekImage1.setImageDrawable(drawable);
mHighTemp1.setText(mWeather.getTemperatureMax() + "");
mLowTemp1.setText(mWeather.getTemperatureMin() + "");
}
if(mIndexofDays == 2) {
mDayOfWeek2.setText(mDateTime.plusDays(2).dayOfWeek().getAsShortText());
Drawable drawable = getResources().getDrawable(mWeather.getIconId());
mDayOfWeekImage2.setImageDrawable(drawable);
mHighTemp2.setText(mWeather.getTemperatureMax() + "");
}
if(mIndexofDays == 3) {
mDayOfWeek3.setText(mDateTime.plusDays(3).dayOfWeek().getAsShortText());
Drawable drawable = getResources().getDrawable(mWeather.getIconId());
mDayOfWeekImage3.setImageDrawable(drawable);
mHighTemp3.setText(mWeather.getTemperatureMax() + "");
}
if(mIndexofDays == 4) {
mDayOfWeek4.setText(mDateTime.plusDays(4).dayOfWeek().getAsShortText());
Drawable drawable = getResources().getDrawable(mWeather.getIconId());
mDayOfWeekImage4.setImageDrawable(drawable);
mHighTemp4.setText(mWeather.getTemperatureMax() + "");
}
if(mIndexofDays == 5) {
mDayOfWeek5.setText(mDateTime.plusDays(5).dayOfWeek().getAsShortText());
Drawable drawable = getResources().getDrawable(mWeather.getIconId());
mDayOfWeekImage5.setImageDrawable(drawable);
mHighTemp5.setText(mWeather.getTemperatureMax() + "");
}
else
{
Log.d(TAG, "Index to high!!!");
}
}
From the logs I can see that "Running" is getting called but updateDisplay never updates for 1-4 indexes only for the 5th index.
I am a very novice programmer, so please tell me on what is wrong with my style and better methods to do what I'm trying to do.
modify updateDisplay and pass a copy of mIndexofDays as a parameter, and this should work. I can provide the actual implementation code but I encourage you to try it first yourself.
hope this helps :)
change your for loop like this
for(int i =1; i < 6; i++) {
mIndexofDays = i;
DateTime nextday = mDateTime.plusDays(i);
long time = nextday.getMillis() / 1000;
getForecast(mLattitude, mLongitude, time, mIndexofDays); // new parameter: mIndexofDays
}
catch the parameter mIndexofDays in getForecast method and pass it through updateDisplay method. Next, use the value of mIndexofDays to compare in your if...else statements. You can use Log method or time delay method to check if it's actually working or not.
Well, the issue is that your updateDisplay() is called only when you receive response in onResponse(). Now, by the time this happens your loop has already ended and the value of mIndexofDays is 5. To fix the issue one of the things you can do is to pass the value of mIndexofDays to your getForecast() method:
private void getForecast(double latitude, double longitude, long time, int indexOfDays) {
...
updateDisplay(numberOfDays);
...
}
You also need to change your updateDisplay() method:
private void updateDisplay(int indexOfDays) {
...
}
Also, get rid of the mIndexOfDays instance variable since you [probably] don't need it anywhere.