Threading and Progressbar in Android? - java

Hey guys so I'm trying to display gps distance between the user and some place on a card they can see. The problem is, I think the main thread splits or does 2 things at once. At the code below, Android makes a toast while doing the code in the if(flag) statement... so it toasts the GPS difference without getting the coordinates of the user...How do i make it so that, it does if(flag) statement first then goes on to do the toast after and outside the if statement?
#Override
public void onResume()
{
super.onResume();
ImagePath = getIntent().getStringExtra("imagePath");
if(ImagePath == null)
{
Toast.makeText(this,"hello everyone",Toast.LENGTH_LONG).show();
}
if(newCardAdded)
{
flag = displayGpsStatus();
if(flag)
{
editLocation.setText("Please!! move your device to" +
" see the changes in coordinates." + "\nWait..");
pb.setVisibility(View.VISIBLE);
locationListener = new MyLocationListener();//LocationListener actually physically gets your location
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
}
else
{
alertbox("Gps Status!!", "Your GPS is: OFF");
}
Global_Class.getInstance().getValue().getlatitude = place_lat;
Global_Class.getInstance().getValue().getlongitutde = place_lon;
String gps_distance = String.valueOf(gps_difference(user_lon, user_lat,place_lon,place_lat));
Toast.makeText(this, gps_distance, Toast.LENGTH_LONG).show();
}
}

LocationManager#requestLocationUpdates
Your locationListener must implement onLocationChanged(Location) method, which will be called for each location update. Then calculate distance and make a toast in that method. Because requestLocationUpdates(...) runs in another thread, there's no way to confirm that it is done before Toast.makeText(...), so you must use your MyLocationListener.

Related

OnClickListener causes infinite loop

I'm working on an aplication that allows the user to select between multiple animations before setting the selection as currently running live wallpaper.
I've reviewed links with similar questions such as:
call Live wallpaper within application
And:
Setting live wallpaper programmatically
They address how to make the selections, but not the error I am seeing.
The first screen dispayed to the user is a selection screen that shows multiple wallpapers. Each wallpaper has a button for the user to click which indicates the selection of that wallpaper.
Each button has a unique ID. Each is found and assigned to an instance of a Button object, and each is registered with an OnClickListener.
Once a button is clicked, I use a switch statement to determine which button was pressed, I create a new Intent, indicate which wallpaper class I want to run, and I start the activity.
When I run this in the emulator, the application loads as expected. I see my selection screen and it correctly displays the various wallpaper selections. The problem happens when I select a wallpaper to run. Once I click on a button, the display turns white and remains stuck that way until I shut down the debugger.
Having run this in debug mode, I found that after clicking on a selection button, the code performs the switch statement, runs through the creation of the intent which calls the startActivity(intent) method and then breaks. Then the code jumps through the View.java, Handler.java, and Looper.java classes where it finally loops forever in the Looper.java class in a for loop that deals with a message queue.
This is the MainActivity where I set the initial layout view, set my buttons, and create the onClickListener:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.selection);
// Capture our buttons from the selection layout
Button button_1 = (Button)findViewById(R.id.set1);
button_1.setOnClickListener(this);
// Capture our buttons from the selection layout
Button button_2 = (Button)findViewById(R.id.set2);
button_2.setOnClickListener(this);
// Capture our buttons from the selection layout
Button button_3 = (Button)findViewById(R.id.set3);
button_3.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
switch(v.getId())
{
//If button_1 was selected, set the first wallpaper.
case R.id.set1 :
setContentView(R.layout.activity_main);
Intent intent = new Intent(
WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new ComponentName(this, Wallpaper1.class));
startActivity(intent);
break;
//If button_2 was selected, set the second wallpaper.
case R.id.set2 :
setContentView(R.layout.activity_main);
intent = new Intent(
WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new ComponentName(this, Wallpaper2.class));
startActivity(intent);
break;
//If the Cuba button was selected, set the Cuba wallpaper.
case R.id.set3 :
setContentView(R.layout.activity_main);
intent = new Intent(
WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
new ComponentName(this, Wallpaper3.class));
startActivity(intent);
break;
}
}
Here is the message loop where the execution gets stuck, iterating infinitely:
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
The code doesn't seem to notice the click event until after correctly moving through the switch statement.
How can I get this to call the Intent correctly?

Call firebase getvalue oncreate

mRefQ.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String txt = dataSnapshot.getValue(String.class);
showtext.setText(txt);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
as it stands i can only access the value when the data is changed but i want to access it whenever i want(namely oncreate).
From the Firebase documentation for listening to value events:
This method is triggered once when the listener is attached and again every time the data, including children, changes.
You can access the Data only once by following this steps.
As #Frank mentioned having a listener will give you access when attached and every time it changes.
Bear in mind that all of this happens asynchronously on a separate thread, therefore in order to ensure the value is available on onCreate you may have to do the orchestration yourself and hold the main thread until the values is ready to be used.
Alright so it turns out it does call it when created, i just had to wait for the firebase to load up on the app
It is not triggerred once in onCreate() method. Without removeEventListener, addValueEventListener will never stop if you listen it in OnCreate() Method. Count is increasing and never stops and load was up to 85% when I run it and so I had to close my internet and uninstall it. But ienter image description heret has just been solved. Here's my code if you wanna check it.
Variables are declared global...
private DatabaseReference main;
private ValueEventListener valueEventListener;
In onCreate() Method.....
valueEventListener = main.addValueEventListener(new
ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
boolean countExists = false;
int count = 1; //starts from 1 when data is uploaded for the first time
for (DataSnapshot out: dataSnapshot.getChildren()) {
if (out.getKey().equals("count")) {
String temp = out.getValue(String.class);
countExists = true;
try {
count = Integer.parseInt(temp);
}
catch (NumberFormatException e) {
count = 1;
}
break;
}
}
if (!countExists) {
main.child("count").setValue(String.valueOf(count));
Toast.makeText(getApplicationContext(), "Count Created", Toast.LENGTH_SHORT).show();
upload.setClickable(true);
}
else {
main.child("count").setValue(String.valueOf(++count));
Toast.makeText(getApplicationContext(), "Count Updated", Toast.LENGTH_SHORT).show();
upload.setClickable(true);
}
main.removeEventListener(valueEventListener);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), "Failed to upload", Toast.LENGTH_SHORT).show();
}
});
Make sure you add removeEventListener when you call it in onCreate() method or it will never stops. It is not a problem if you don't call removeEventListener in onStart() method.
This is not your question but...
If you wanna use firebase for likely free, you can't let all users to download your data without necessary or your bandwidth may become full within a day. So, I count the data and just download that child's value and compare the result and make update. So it can reduce your bandwidth when you call addValueListener.

Seekbar 'unhooking' from media player on orientation change

I have a seekbar in my fragment that I use to show the progress of a MediaPlayertrack that is playing. Everything works as expected until I change orientation of the device. I save my fragment instance and load it back, and all of the other views are repopulated as they should be, and the music keeps right on playing as it should, but the seekbar goes right to the max, as if the track has reached it's max duration. The runnable that is updating the seekbar based on the mediaplayer's position keeps running after the orientation change as well, and logging the currentPos value in the runnable shows that it stays in sync with the mMediaPlayer.getCurrentPosition() as it should, even after the orientation change...So basically, it continues to feed the correct position to the seekbar; the seekbar just isn't updating after the orientation change. It makes me wonder if the seekbar instance stays the same after the change. If it doesn't stay the same instance, I can't figure out why or how to fix it.
The onCLick method of my play button calls the following to start the track and hook up the seekbar to it:
private void startPlayer(String url){
try {
mMediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
playerState = PlayerState.PLAYING;
setButtonsForPlayerState();
setSeekBarValues();
mHandler = new Handler();
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (mMediaPlayer != null ) {
int currentPos = mMediaPlayer.getCurrentPosition();
Log.e(LOG_TAG, "Current pos is " + currentPos);
seekBar.setProgress(currentPos);
if (currentPos<10000){
seekBarStartTime.setText("0:0" + currentPos / 1000);
}else{
seekBarStartTime.setText("0:" + currentPos / 1000);
}
}
if (mMediaPlayer.isPlaying()){
mHandler.postDelayed(this, 50);
}
}
}
);
}
});
}
and here is the setSeekBarValues() method that is called in the above method:
private void setSeekBarValues() {
seekBar.setMax(mMediaPlayer.getDuration());
seekBarFinishTime.setText("0:" + seekBar.getMax()/1000);
seekBar.setProgress(0);
}
seekBarStartTime and seekBarFinishTime are just TextViews that show the current position and end time of the track, respectivily.
Since all of my other views, streaming music, etc. seems to be working as it should on the re-creation of Activity and Fragment, I don't think it's an issue with saving instance state, but if you want me to post that code as well please let me know.
Any ideas are appreciated.

rotation cell stops media player android

My code plays a song from a listview, everything perfect, BUT, if I specifically rotate it, the media player stop, how can i keep it playing?
and! if i create an another button to pause, or something like that, should I use the same answer?
my code in a button:
testme.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if(nombre.matches("Kaminomi")) { //ignore this
try {
mp.setDataSource(nombreSong);
mp.prepare();
} catch (IOException e) {
e.printStackTrace();
}
if (validar == false) {
validar = true;
mp.start();
Toast.makeText(getApplicationContext(), "Reproduciendo ahora: \n" + nombreSong, Toast.LENGTH_LONG).show();
testme.setText("Stop :D");
testme.setCompoundDrawablesWithIntrinsicBounds(R.drawable.nisekoi1,0,0,0);
} else {
validar = false;
Toast.makeText(getApplicationContext(), "Deteniendo: \n" + nombreSong, Toast.LENGTH_LONG).show();
mp.stop();
testme.setText("Play :D");
}
}else{
Toast.makeText(getApplicationContext(), "Algo mas creo", Toast.LENGTH_LONG).show(); //ignore this too
}
}
Put this in your manifest xml file:
<activity android:name="MainActivity"
android:configChanges="keyboardHidden|orientation">
i.e. add android:configChanges="keyboardHidden|orientation" to the activity xml element.
Whats happening is that when your screen orientation changes, a configuration change occurs and this causes Android to destroy and recreate your activity.
The above code in my answer will prevent a configuration change from happening when an orientation change or a keyboard change occurs.
However this is just a workaround. A configuration change can occur at any time (e.g. placing the phone in a docking station) and therefore just disabling configuration changes for orientation changes and keyboard changes is not enough.
To properly maintain the state of objects during configuration changes, Fragments are a good approach.

Waiting for GPS location before proceeding Android

I am aware there are a number of similar questions floating around but could not find a suitable answer in my searches.
My App has an activity which relies on the GPS location to function. The app will crash if it is run immediately after start up due to null pointer exceptions etc where the location is null. I am aware these are my programming errors and I should handle the exceptions, but the activity is still useless until a GPS fix is found.
When the app crashes I get the "Searching for GPS" icon, and if this is left for long enough a GPS location is found and the app can be run with no issue.
I have created another activity to act as a home screen which will enable the button to link to the above activity when a GPS location is found. The problem is that it doesn't seem to find or be looking for a GPS signal. By this i mean that no "Searching for GPS" icon appears and the button is never enabled. The code for this home activity is below, have I missed something?
My activity implements LocationListener, and the code below is in the Activity "onCreate" method. "startExplore" starts my GPS reliant activity.
exploreButton = (Button) findViewById(R.id.button1);
exploreButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startExplore();
}
});
// Get the location manager
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Define the criteria how to select the location provider -> use
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null) {
System.out.println("Provider " + provider + " has been selected.");
onLocationChanged(location);
} else {
exploreButton.setEnabled(false);
exploreButton.setText("Finding location . . .");
}
This is my "onLocationChanged" method. As i said above, unlike my other activity I do not get the "Searching for GPS" icon and the location does not appear to be found despite this being the same method used in my other Activity. So is this the correct technique for waiting until a location is found, and can anyone identify any mistakes?
public void onLocationChanged(Location location) {
exploreButton.setEnabled(true);
exploreButton.setText("Found signal");
}
Call the
locationManager.requestLocationUpdates(locationProvider, 0, 0, this)
to get the updated location.. It might be the source of the problem.. Because of this only "Searching for GPS" wasn't initiated I think..
Move it out the onCreate methode or put it in a handler or so.
Example:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//methods you want.
}
}, 100);

Categories

Resources