Object: Get 1 set of Longitude and Lattitude coordinates from url JSON results. Load maps and add a marker and camera zoom to those coordinates.
Problem: Everything works, only on 1st load of the app and the fragment that has the map in it. When you click on a different nav button and then click on the button to go back to the fragment with the map on it, or if you click on the nav button for the map fragment and then click on it again, the map will only load with values directly in the OnMapReady. You then have to close out the app and reopen it in order for that fragment to load correctly.
We have in the fragment the following:
Textview and the Map.
We have commented out everything in the OnMapReady to ensure that we are getting the right data.
Steps we have taken to verify data:
- Open App
- Clicked on Nav button to open fragment with map.
- Looked at textview to make sure it pulled the right data from url.
- Opened up phpmyadmin, changed data.
- Clicked on button to load different fragment.
- Clicked on button to load fragment with map on it.
Results: Textview is populated with correct data.
Next test was to see if the maps will load and if we are getting data to the markers.
We added all map info back to the OnMapReady. We temporarily used hard coded longitude and lattitude for the marker and camera zoom. We then added a toast to display textview.gettext.tostring().
RESULTS: 1st run or load data is there and correct. Each load after that it is null / empty displaying an empty toast message.
Below is the code that we use to call the fragment with the map on it in MainActivity:
getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.bottom_nav_enter, R.anim.bottom_nav_exit)
.add(R.id.container, frg)
//.replace(R.id.container, frg)
//.attach(frg)
.commitNow();
I have tried detach / attach / remove / add / replace and does not make a difference.
Below is the full code for my fragment that has the map on it.
package com.app.restaurant.bowzers.fragments;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.app.restaurant.bowzers.GetJSON;
import com.app.restaurant.bowzers.R;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class TruckFragment extends Fragment implements OnMapReadyCallback {
Activity mactivity;
public static TextView textviewlocation;
GoogleMap mGoogleMap;
String strlong, strlat;
String longitudestring;
String lattitudestring, mySB;
MapView mMapView;
View mView;
double locationlong, locationlat;
public TruckFragment() {
// Required empty public constructor
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mactivity = getActivity();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_truck, container, false);
if(this.getArguments()!=null) {
Log.d("hey", "hey");
String[] longlat =textviewlocation.getText().toString().split(",");
locationlong = Double.parseDouble(longlat [0]);
locationlat = Double.parseDouble(longlat [1]);
}
return mView;
}
TextView textView;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
textviewlocation = view.findViewById(R.id.textviewlocation);
getJSON("https://bowzershotdogstand.com/app/get_location.php");
// String[] longlat =textviewlocation.getText().toString().split(",");
// locationlong = Double.parseDouble(longlat [0]);
// locationlat = Double.parseDouble(longlat [1]);
mMapView = mView.findViewById(R.id.truckmap);
if (mMapView != null) {
mMapView.onCreate(null);
mMapView.onResume();
mMapView.getMapAsync(this);
}
}
private void getJSON(final String urlWebService) {
class GetJSON extends AsyncTask<Void, Void, String> {
protected void onPreExecute() {
super.onPreExecute();
}
protected void onPostExecute(String s) {
super.onPostExecute(s);
mySB = s;
textviewlocation.setText(mySB);
}
protected String doInBackground(Void... Voids) {
try {
URL url = new URL(urlWebService);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String json;
while ((json = bufferedReader.readLine()) != null) {
sb.append((json + "n"));
}
mySB = String.valueOf(sb);
JSONArray JA = new JSONArray(mySB);
for(int i =0 ;i <JA.length(); i++){
JSONObject JO = (JSONObject) JA.get(i);
switch (JO.getString("id")){
case "1":
strlong = JO.getString("longitude");
strlat = JO.getString("lattitude");
break;
}
}
//return sb.toString().trim();
return strlong + "," + strlat;
} catch (Exception e) {
return null;
}
}
}
GetJSON getJSON = new GetJSON();
getJSON.execute();
}
@Override
public void onMapReady(@NonNull GoogleMap googleMap) {
LatLng bowzers = new LatLng(locationlat, locationlong);
Toast.makeText(getContext(),textviewlocation.getText().toString(), Toast.LENGTH_SHORT).show();
mGoogleMap = googleMap;
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.addMarker(new MarkerOptions().position(new LatLng(39.918837, -82.831853)).title("Bowzers").snippet("Where Our Dogs Are NOT JUST A DOG"));
// googleMap.addMarker(new MarkerOptions().position(new LatLng(locationlat, locationlong)).title("Bowzers").snippet("Where Our Dogs Are NOT JUST A DOG"));
//googleMap.addMarker(new MarkerOptions().position(bowzers).title("Marker"));
// googleMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Bowzers").snippet("Where Our Dogs Are NOT JUST A DOG"));
CameraPosition Bowzers = CameraPosition.builder().target(new LatLng(39.918837, -82.831853)).zoom(16).bearing(0).tilt(45).build();
// CameraPosition Bowzers = CameraPosition.builder().target(new LatLng(locationlat, locationlong)).zoom(16).bearing(0).tilt(45).build();
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(Bowzers));
}
@Override
public void onResume() {
super.onResume();
Log.i("IsRefresh", "Yes");
getJSON("https://bowzershotdogstand.com/app/get_location.php");
Toast.makeText(getContext(),textviewlocation.getText().toString(), Toast.LENGTH_SHORT).show();
}
As you can see I even tried doing detach, attach in the onResume as well and it does not make a difference. detach / attach in the way I went about it should of refreshed the whole fragment I thought. However it does not refresh it.
What am I doing wrong, or what am I missing that when the fragment resumes that it does not refresh as if it were the first time loading and OnMapReady being able to access the data from the textview after the first load of the fragment.
I double check logcat and it does get to OnResume and it does log it to let me know.
So why does OnMapready not seeing or able to access global variables or the data in the textview after the first load?
I can not figure it out for the life of me, I am ready to pull my hair out trying to get it to work properly on every load not just the first one.
2
Answers
This is now solved. Using a totally different code. For those that are looking for something similar or the same issues that I have had for something so simple here is my current solution, although far from perfect, however it does work.
This is a sample code from one of the fragment that loads on BottomNavigationItem click. Switching between those fragments also preserves the value. Considering this fragment to be equivalent of the TruckFragment,modify your TruckFragment code like below to get the result from async task.