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();
}
Related
I have a single activity game while playing (after login and character selection). My sound pool for SFX works great, but my background music randomly stops playing. I tried to add in setOnErrorListener, but never saw anything there. I am wondering if the thread is being garbage collected?
When you are in different towns or wilderness the music changes and that is checked here: !currentPlayingMusicFilename.equals(shortFilename). If you stay in the same music area, randomly the music stops looping.
I have read so many posts on here and google and can't find the "proper" way to play game background music. I've tried soundpool, but they are over 1MB, saw many things saying not to do service, and having an issue with this approach. Any help is greatly appreciated.
I am leaving in the "SFX" portion in case that code can help anyone and provide a full picture.
public static void playSoundOrMusic(final String shortFilename, final String type, double distanceFactor) {
String fullFilename = "";
if (type.equals("SFX")){
fullFilename = "res/sounds/sfx/" + shortFilename;
} else if (type.equals("MUSIC")){
if (mp3MUSICPlayer != null && mp3MUSICPlayer.isPlaying() && !currentPlayingMusicFilename.equals(shortFilename)){
mp3MUSICPlayer.stop();
}
fullFilename = "res/sounds/music/" + shortFilename;
}
float volumeManipulation = 1.0f;
if (type.equals("SFX")){
int sfxVolume = MyCommandReceiver.GetSharedPreferences().getInt(MyCommandReceiver.GetStringById(R.string.pref_general_sfx_volume_key), 100);
sfxVolume *= distanceFactor;
volumeManipulation = (float) (sfxVolume / 100.0);
//volumeManipulation = (float) (1 - (Math.log(MAX_VOLUME - sfxVolume) / Math.log(MAX_VOLUME)));
LoggerWrite("v", TAG, "sfxVolume: " + volumeManipulation);
} else if (type.equals("MUSIC")){
int musicVolume = MyCommandReceiver.GetSharedPreferences().getInt(MyCommandReceiver.GetStringById(R.string.pref_general_music_volume_key), 100);
volumeManipulation = (float) (musicVolume / 100.0);
//volumeManipulation = (float) (1 - (Math.log(MAX_VOLUME - musicVolume) / Math.log(MAX_VOLUME)));
LoggerWrite("v", TAG, "musicVolume: " + volumeManipulation);
}
final float finalVolume = volumeManipulation;
if (MyCommandReceiver.GetActiveActivity() == null){ //if not yet in Activity
return;
}
try {
Uri myUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/KisnardOnline/" + fullFilename));
if (type.equals("SFX")){
if (!soundPoolIds.containsKey(Environment.getExternalStorageDirectory() + "/KisnardOnline/" + fullFilename)){ //not yet in soundpool
int soundId = soundPool.load(Environment.getExternalStorageDirectory() + "/KisnardOnline/" + fullFilename, 1);
soundPoolIds.put(Environment.getExternalStorageDirectory() + "/KisnardOnline/" + fullFilename, soundId);
//play it manually one time
mp3SFXPlayer = new MediaPlayer();
mp3SFXPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp3SFXPlayer.setVolume(finalVolume, finalVolume);
mp3SFXPlayer.setDataSource(MyCommandReceiver.GetActiveActivity(), myUri);
new Thread(new Runnable() {
#Override
public void run() {
try {
mp3SFXPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp3SFXPlayer.start();
}
});
mp3SFXPlayer.prepare();
} catch (Exception ex) {
GameActivity.LoggerWrite("e", TAG, "Sound(sfx) playing issue" + ex);
}
}
}).start();
} else { //already in soundpool - play it
soundPool.play(soundPoolIds.get(Environment.getExternalStorageDirectory() + "/KisnardOnline/" + fullFilename), finalVolume, finalVolume, 0, 0, 1);
}
} else if (type.equals("MUSIC")){
if (!currentPlayingMusicFilename.equals(shortFilename)){
mp3MUSICPlayer = new MediaPlayer();
mp3MUSICPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp3MUSICPlayer.setVolume(finalVolume, finalVolume);
mp3MUSICPlayer.setDataSource(MyCommandReceiver.GetActiveActivity(), myUri);
}
}
} catch (Exception e) {
GameActivity.LoggerWrite("e", TAG, "Sound file issue" + e);
}
if (type.equals("MUSIC") && !currentPlayingMusicFilename.equals(shortFilename)){
new Thread(new Runnable() {
#Override
public void run() {
try {
mp3MUSICPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
currentPlayingMusicFilename = shortFilename;
mp3MUSICPlayer.start();
}
});
mp3MUSICPlayer.prepare();
mp3MUSICPlayer.setLooping(true);
} catch (Exception ex) {
GameActivity.LoggerWrite("e", TAG, "Sound(music) playing issue" + ex);
}
}
}).start();
}
}
Here is how I solved this as it does not seem there is an answer out there to why it dies randomly.
if (type.equals("MUSIC") && (!currentPlayingMusicFilename.equals(shortFilename) || !mp3MUSICPlayer.isPlaying())){
new Thread(new Runnable() {
...
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();
}
}
};`
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.