Android - Displaying Polyline - java

The concept of my application is that a a path is drawn every time a user sets two markers on a map and that path is shown in another activity. I have saved the path (waypoints) as an Array list in my FireBase database and I have also retrieved the way points in the second activity, but I am having problems displaying the poly line in the second activity. My database:
My POJO classes:
public static class Route {
private ArrayList<Location> locations;
public Route() {
}
#PropertyName("route")
public ArrayList<Location> getLocations() {
return locations;
}
#PropertyName("route")
public void setLocations(ArrayList<Location> locations) {
this.locations = locations;
}
}
public static class Location {
private Double latitude;
private Double longitude;
public Location() {
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
}
Retrieval of waypoints:
userRef.child("Route").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Route route = dataSnapshot.getValue(Route.class);
for (Location location : route.getLocations()) {
points = new ArrayList();
double lat = location.getLatitude();
double lng = location.getLongitude();
position = new LatLng(lat, lng);
points.add(position);
}
}
To add the polyline to the map I do this:
PolylineOptions lineOptions = null;
lineOptions.add(position);
lineOptions.width(12);
lineOptions.color(Color.RED);
mMap.addPolyline(lineOptions);
But I get this exception :
"NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.PolylineOptions com.google.android.gms.maps.model.PolylineOptions.add(com.google.android.gms.maps.model.LatLng)' on a null object reference"

What about writing
PolylineOptions lineOptions = new PolylineOptions();
instead of
PolylineOptions lineOptions = null;
Also you are adding a single point in the polyline. Loop through your list points and add all of them.
for (LatLng point: points){
lineOptions.add(point);
}
mMap.addPolyline(lineOptions);
Your another mistake:
You are recreating the ArrayList as points = new ArrayList(); inside for loop. Use it before for loop.
points = new ArrayList();
for (Location location : route.getLocations()) {
//your code
}

Related

Current Location with Geocoder not working for non activities

I am currently building an Android app and my main problem is that I have a class that retrieves the current latitude and longitude of my current location.
Whenever I make an activity out of it, it works fine. However, now that I;m trying to make it a class that will just retrieve the latitude and longitude and will set it to a setter, it doesn't work.
Namely, I am using FusedLocationProviderClient and Geocoder in order to retrieve those two elements.
The problem is that both of them won't take the current object as an argument (context, since it's a non activity class), whereas they work just fine with activities. In other words, this doesn't apply whenever I apply this for the context. Below is my class, with the problems that I am facing.
I would appreciate some help here thank you in advance.
public class CurrentLocationFinder {
FusedLocationProviderClient fusedLocationProviderClient;
double lagitudeValue, longitudeValue;
private final static int REQUEST_CODE = 100;
public CurrentLocationFinder() {
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);//*******doesn't accept 'this' in method
getLastLocation();
}
private void getLastLocation() { //doesn't accept 'this'
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(location -> {
if (location != null) {
Geocoder geocoder = new Geocoder(this, Locale.getDefault()); //doesn't accept 'this'
List<Address> addressList = null;
try {
addressList = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
System.out.println("********************" + addressList.get(0).getLatitude());
setLagitude(addressList.get(0).getLatitude());
setLongitude(addressList.get(0).getLongitude());
System.out.println("=====================" + addressList.get(0).getLatitude());
} catch (IOException e) {
e.printStackTrace();
}
}
});
} else {
//askPermission();
}
}
public double getLagitude() {
return this.lagitudeValue;
}
public double getLongitude() {
return this.longitudeValue;
}
public void setLagitude(double lagitude) {
this.lagitudeValue = lagitude;
}
public void setLongitude(double longitude) {
this.longitudeValue = longitude;
}
}

java.lang.NullPointerException Can't set text from class to activity [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I'm rather new to coding and my long term goal is to create an android weather app. I've created the main activity and a class, plus I'm using Weatherlib to make things a bit easier.
The main activity asks for permission and grabs the location using GPS. Those coords are sent to the getweather method which grabs the information using OpenWeatherMap. When the data is retrieved, in this case, cloud percentage, what I want it to do is pass that to the main activity to setText for the TextView clouds. My issue is that it's throwing a NullPointerException when I try to do that from onWeatherRetrieved.
public class MainActivity extends AppCompatActivity {
private double latitude;
private double longitude;
private FusedLocationProviderClient fusedLocationClient;
private String response;
private TextView clouds;
private Context context;
private Context x;
private WeatherOWM weatherOWM;
//Get location
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
clouds = findViewById(R.id.clouds);
x = this;
context = getApplicationContext();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
requestPermissions();
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
return;
}
fusedLocationClient.getLastLocation().addOnSuccessListener (this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null){
double latitude = location.getLatitude();
double longitude = location.getLongitude();
System.out.println(latitude + " " + longitude);
WeatherOWM loc = new WeatherOWM(latitude, longitude, context);
loc.getWeather();
}
}
});
}
public void setClouds(Integer cloud) {
clouds.setText(cloud);
}
private void requestPermissions(){
ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION}, 1);
}
}
public class WeatherOWM{
private double latitude;
private double longitude;
private Context ma;
WeatherConfig config = new WeatherConfig();
private Object WeatherConfig;
private Object hourForecast;
private Object MainActivity;
private MainActivity mainActivity;
public WeatherOWM(double latitude, double longitude, Context ma){
this.latitude = latitude;
this.longitude = longitude;
this.ma = ma;
}
public void getWeather() {
TextView clouds = new TextView(ma);
//Init client
WeatherClient client = null;
config.ApiKey = "REDACTED";
try {
client = (new WeatherClient.ClientBuilder()).attach(ma)
.httpClient(WeatherDefaultClient.class)
.provider(new OpenweathermapProviderType())
.config(config)
.build();
} catch (WeatherProviderInstantiationException e) {
e.printStackTrace();
}
client.getHourForecastWeather(new WeatherRequest(latitude, longitude), new WeatherClient.HourForecastWeatherEventListener() {
#Override
public void onWeatherRetrieved(WeatherHourForecast weatherHourForecast) {
List<HourForecast> hourList = weatherHourForecast.getHourForecast();
for (HourForecast hourForecast: hourList) {
Weather weather = hourForecast.weather;
long timestamp = hourForecast.timestamp;
mainActivity.setClouds(hourForecast.weather.clouds.getPerc());
System.out.println(hourForecast.weather.clouds.getPerc());
}
}
#Override
public void onWeatherError(WeatherLibException wle) {
System.out.println("ERROR");
}
#Override
public void onConnectionError(Throwable t) {
System.out.println("ERROR");
}
});
}
}
In the WeatherOWM class , you have created an instance of MainActivity as here :
private MainActivity mainActivity;
and in the method , you have written :
mainActivity.setClouds(hourForecast.weather.clouds.getPerc());
the problem is that the variable "mainActivity" has no value and is empty so you have to give value to it.
so in the WeatherOWM class , write this code :
mainActivity = new MainActivity();
please reply is solved your problem

I am trying to create a search query “How far my users are with respect to the current user who is online”. I have lat and Long values for all

So I am using Firebase realtime database where the Nodes go a bit like this.
Company-> Users-> Registered Tutors ->All the data like longitude, latitude, name, dob, gender etc...
The idea behind it is, that when the user searches for the registered tutors, the latitude and longitude values of all registered tutors are retrieved, the latitude and longitude values of current user are also retrieved, and only the distance between them is shown in the search query.
I am using a FirebaseRecyclerAdapter. Sorry I am terrible with words, maybe the code and a few pictures would help.
This is my Activity (section of it)
private FirebaseAuth mAuth;
private DatabaseReference allUsersDatabaseRef, currentUserRefLong, currentUserRef;
allUsersDatabaseRef = FirebaseDatabase.getInstance().getReference().child("oxtuition").child("Users").child("Registered Tutors");
mAuth = FirebaseAuth.getInstance();
currentUserID = mAuth.getCurrentUser().getUid();
currentUserRef = FirebaseDatabase.getInstance().getReference().child("oxtuition").child("Users").child(currentUserID);
SearchResultList = (RecyclerView) findViewById(R.id.search_result_list);
SearchResultList.setHasFixedSize(true);
SearchResultList.setLayoutManager(new LinearLayoutManager(this));
SearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String searchBoxInput = SearchInputText.getText().toString();
SearchPeopleAndFriends(searchBoxInput);
}
});
}
private void SearchPeopleAndFriends(String searchBoxInput) {
Toast.makeText(this, "Searching....", Toast.LENGTH_LONG).show();
Query searchPeopleAndFriendsQuery = allUsersDatabaseRef.orderByChild("fullname").startAt(searchBoxInput).endAt(searchBoxInput + "\uf8ff");
FirebaseRecyclerAdapter<FindFriends, FindFriendsViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<FindFriends, FindFriendsViewHolder>(FindFriends.class,
R.layout.all_tutors_display_layout,
FindFriendsViewHolder.class,
searchPeopleAndFriendsQuery) {
#Override
protected void populateViewHolder(FindFriendsViewHolder findFriendsViewHolder, FindFriends model, int i) {
findFriendsViewHolder.setLocation(model.getLocation());
}
};
SearchResultList.setAdapter(firebaseRecyclerAdapter);
}
public static class FindFriendsViewHolder extends RecyclerView.ViewHolder {
View mView;
public FindFriendsViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setLocation(String location) {
TextView mylocation = (TextView) mView.findViewById(R.id.all_users_profile_how_far);
mylocation.setText(location);
}
}
}
Now it's the problem page, the FindFriends.class where the constructor and the setters and getters are.
public class FindFriends
{
public double longitude;
public double latitude, location;
public FindFriends(){
}
public FindFriends(String fullname, String profilimage, String subjects, String addresspostcode, String shortdescription, double longitude, double latitude) {
this.longitude = Double.parseDouble(String.valueOf(longitude));
this.latitude = Double.parseDouble(String.valueOf(latitude));
}
public double getLongitude() {
return longitude; //Longitude Getter
}
public void setLongitude(double longitude) {
this.longitude = longitude; //Longitude Setter
}
public void setLatitude(double latitude) {
this.latitude = latitude; //Latitude Setter
}
public double getLatitude() {
return latitude; //Latitude Getter
}
public String getLocation() {// Location getter doesn't exist in Firebase, it's calculated based upon the latitude and the longitude
final double lon1 = this.longitude;
final double lat1 = this.latitude;
FirebaseAuth mAuth = FirebaseAuth.getInstance();
String CurrentUserID = mAuth.getCurrentUser().getUid();
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("oxtuition").child("Users").child(CurrentUserID);
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String lon2S = dataSnapshot.child("longitude").getValue().toString();
String lat2S = dataSnapshot.child("latitude").getValue().toString();
//This is the mathematics behind calculating the distance between two latitude //and longitude values
double lon2 = Double.valueOf(lon2S);
double lat2 = Double.valueOf(lat2S);
System.out.println("Print OK" + lon2 + lat2);
double thetaLong = (lon2 - lon1)*Math.PI/180;
double thetaLat = (lat2 - lat1)*Math.PI/180;
double lat1Rad = lat1*Math.PI/180;
double lat2Rad = lat2*Math.PI/180;
double a = Math.sin(thetaLat/2)*Math.sin(thetaLat/2) + Math.cos(lat1Rad)*Math.cos(lat2Rad)*Math.sin(thetaLong/2)*Math.sin(thetaLong/2);
double c = 2*Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double R = 6371;
double d = (R*c);
location = d; //the double location is the "DISTANCE" calculated //between two latitude and longitude points.
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed");
}
});
return Double.toString(location);
//This returns the location calculated (hopefully, I feel like the problem is here)
}
public void setLocation() {
//don't really think this is even necessary.
}
}
In the end I am returning a calculated location which is sent to the main activity. The problem is:
I am having problems reading the latitude and longitude values from the current user ID. I have tried using arbitary values by simply doing:
double lat1 = 1.234556;
double lon1 = 1.233467;
and i get the correct answer, but I can't do that when reading the current user ID location. Please help, I am really stuck! I get values of 0! That's it for all of them. I can give more information, don't really know what else to include in this thread really.
After this i am hoping I can arrange the results according to the distance. But that's a challenge for the future. I'll be happy if anyone has any inputs on that as well.
Thankyou in Advance!

Adding markers to a hashmap without adding them to the map

I want to add google map markers to this hashmap:
private HashMap<Marker, MyMarker> mMarkersHashMap;
without adding them to the google map. This is the code I currently have:
MarkerOptions markerOption = new MarkerOptions().position(new LatLng(myMarker.getmLatitude(), myMarker.getmLongitude()));
Marker currentMarker = mMap.addMarker(markerOption);
mMarkersHashMap.put(currentMarker, myMarker);
This code adds the markers to the hashmap but also adds the markers to the map(using addMarker), which I don't want. Any suggestions
Here is the function I am working on:
private void plotMarkers(ArrayList<MyMarker> markers)
{
if(markers.size() > 0)
{
for (final MyMarker myMarker : markers)
{
MarkerOptions markerOption = new MarkerOptions().position(new LatLng(myMarker.getmLatitude(), myMarker.getmLongitude()));
Marker currentMarker = mMap.addMarker(markerOption);
//Passes markers into hashmap so they can be used by the information window methods
mMarkersHashMap.put(currentMarker, myMarker);
mMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
Intent ListIntent = new Intent(getApplicationContext(), InfoWindowList.class);
MyMarker myMarker = mMarkersHashMap.get(marker);
String title = myMarker.getmLabel();
ListIntent.putExtra("COUNTY", title);
startActivity(ListIntent);
}
});
mMap.setInfoWindowAdapter(new MarkerInfoWindowAdapter());
}
}
mClusterManager.addItems(markers);
}
I want mClusterManager.addItems(markers); to add the markers to the map.
Here is my information window function which needs the hashmap to set information windows on the markers in the hashmap:
public class MarkerInfoWindowAdapter implements GoogleMap.InfoWindowAdapter
{
public MarkerInfoWindowAdapter()
{
}
#Override
public View getInfoWindow(Marker marker)
{
return null;
}
#Override
public View getInfoContents(Marker marker)
{
View v = getLayoutInflater().inflate(R.layout.infowindow_layout, null);
MyMarker myMarker = mMarkersHashMap.get(marker);
ImageView markerIcon = (ImageView) v.findViewById(R.id.marker_icon);
TextView markerLabel = (TextView)v.findViewById(R.id.marker_label);
TextView anotherLabel = (TextView)v.findViewById(R.id.another_label);
//anotherLabel.setOnClickListener(newsfeed);
markerIcon.setImageResource(manageMarkerIcon(myMarker.getmIcon()));
anotherLabel.setText("Newsfeed");
markerLabel.setText(myMarker.getmLabel());
return v;
}
}
The MyMarker class:
public class MyMarker implements ClusterItem {
private String mLabel;
private String mIcon;
private Double mLatitude;
private Double mLongitude;
private final LatLng mPosition;
public MyMarker(String label, String icon, Double latitude, Double longitude)
{
this.mLabel = label;
this.mLatitude = latitude;
this.mLongitude = longitude;
this.mIcon = icon;
mPosition = new LatLng(latitude, longitude);
}
//mPosition = LatLng(mLatitude, mLongitude);
#Override
public LatLng getPosition() {
return mPosition;
}
public String getmLabel()
{
return mLabel;
}
public void setmLabel(String mLabel)
{
this.mLabel = mLabel;
}
public String getmIcon()
{
return mIcon;
}
public void setmIcon(String icon)
{
this.mIcon = icon;
}
public Double getmLatitude()
{
return mLatitude;
}
public void setmLatitude(Double mLatitude)
{
this.mLatitude = mLatitude;
}
public Double getmLongitude()
{
return mLongitude;
}
public void setmLongitude(Double mLongitude)
{
this.mLongitude = mLongitude;
}
}
A "Marker" is created when you give MarkerOptions to the map and call addMarker so you cannot get a marker without first adding it to the map first.
if you are just trying to not have the marker visible then change its visibility
You can add the marker to the map, but then hide it using
currentMarker.setVisible(false);
Not sure that is the most efficient route, though.. Depends on your use-case.
edit based on commments
If maintaining a HashMap of markers is all you need to do, have you tried using a ClusterRenderer?
Here's an example:
clusterManager.setRenderer(new DefaultClusterRenderer<MyMarker>(activity, map, clusterManager) {
#Override
protected void onClusterItemRendered(MyMarker myMarker, Marker marker) {
super.onClusterItemRendered(mobileMarker, marker);
// add to hashmap here
}
... override other methods as needed
});
clusterManager.addItems(markers)

Using value of abstract method called at runtime

I'm trying to use MyLocation class from here. In code below I need to access variable currentLat and currentLon anywhere inside the class instantiating MyLocation. I don't know how to access value of currentLat and currentLon
LocationResult locationResult = new LocationResult(){
#Override
public void gotLocation(Location location){
currentLat = location.getLatitude();
currentLon = location.getLongitude();
};
}
MyLocation myLocation = new MyLocation();
myLocation.getLocation(this, locationResult);
Suppose I want here
Double x =currentLoc;
how to I get that? Any help would be appreciated
instead of anonymous class use your own that extends/implments LocationResult class/interface and add getter like this
class MyLocationResult extends/implments LocationResult{
double currentLat;
double currentLon;
#Override
public void gotLocation(Location location){
currentLat = location.getLatitude();
currentLon = location.getLongitude();
};
public double getCurrentLat(){
return currentLat;
}
public double getCurrentLon (){
return currentLon ;
}
}
then you can write
MyLocationResult locationResult = new MyLocationResult();
MyLocation myLocation = new MyLocation();
myLocation.getLocation(this, locationResult);
and whenever you need currentLat or currentLon you can write
locationResult.getCurrentLat();
You can use static modifiers for your variables and define them globally..
public static double currentLat; // defined globally...
public static double currentLon;
LocationResult locationResult = new LocationResult(){
#Override
public void gotLocation(Location location){
currentLat =location.getLatitude(); // assuming getLatitude() returns double or int
currentLon = location.getLongitude();
};
}
MyLocation myLocation = new MyLocation();
myLocation.getLocation(this, locationResult);
Now you can access them anywhere
double x =currentLon;
double y =currentLat;

Categories

Resources