Polyline disappears when orientation changes - Android - GMaps V2 - java

My MapActivity records a polyline just fine however when I tip the screen on it's side and the orientation changes the polyline disappears? What could be causing this? Here is my code that is recording the polyline:
Location lastLocationloc;
private GoogleMap myMap;
#Override
public void onLocationChanged(Location location) {
if (lastLocationloc == null) {
lastLocationloc = location;
}
LatLng lastLatLng = locationToLatLng(lastLocationloc);
LatLng thisLatLng = locationToLatLng(location);
//Log.e(TAG, "Last LatLng is :"+lastLatLng);
//Log.e(TAG, "Last LatLng is :"+thisLatLng);
myMap.addPolyline(new PolylineOptions().add(lastLatLng).add(thisLatLng).width(10).color(Color.RED));
lastLocationloc = location;
}
How can I prevent this from happening?

You have to save your points and restore them later. One simple way is to use onSaveInstanceState which will keep your data across configuration changes and process being killed. Other options are files and DB. More info here: http://developer.android.com/guide/topics/data/data-storage.html

Related

HMS Map Kit - How to set camera zoom to current location?

I would like to make the map auto-focus to the current location and I've obtained the location via Location Kit.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
Now, I was trying to set the latitude and longitude of the camera in OnMapReady() function, but how to retrieve them?
#Override
public void onMapReady(HuaweiMap huaweiMap) {
float zoom = 12.0f;
LatLng latLng = new LatLng(***mLat***, ***mLong***);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
.
.
.
}
I really need your assistance!!
Update
There is a official demo show how to realize this:
use location kit to get the current location
use map kit to show current location point in map
You can try to use the function moveCamera or animateCamera to make the map move to the location you want :
#Override
public void onMapReady(HuaweiMap huaweiMap) {
float zoom = 12.0f;
LatLng latLng = new LatLng(***mLat***, ***mLong***);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, zoom);
huaweiMap.moveCamera(cameraUpdate);
}

How to show polylines on map [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I tried to show the polylines and it shows the correct line when I put it in onLocationResult.
However, I only want it to show polylines when the user clicks on the start button.
So I tried to put the code into onClickListener, the screen only displays the marker but not the lines.
Location mLastLocation;
LocationRequest mLocationRequest;
private SupportMapFragment mapFragment;
private FusedLocationProviderClient mFusedLocationClient;
private FirebaseAuth myAuth;
private FirebaseDatabase mDatabase;
private DatabaseReference myRef;
private Marker currentUserLocationMarker;
private ArrayList<LatLng> points; //added
Polyline line;
private Button btnStartRun;
LatLng latLng;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_googls_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
points = new ArrayList<LatLng>();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
btnStartRun=findViewById(R.id.btnStartRun);
btnStartRun.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
points.add(latLng);//add points to the array
redrawLine();
myAuth=FirebaseAuth.getInstance();
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference().child("OnlineUsers");//.child("OnlineUser");
DatabaseReference currentUserDB=mDatabase.child(myAuth.getCurrentUser().getUid());
currentUserDB.child("CurrentLatitude").setValue(mLastLocation.getLatitude());
currentUserDB.child("CurrentLongitude").setValue(mLastLocation.getLongitude());
}
});
}
Here is my onLocationResult
LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
mLastLocation = location;
latLng = new LatLng(location.getLatitude(), location.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(15));
}
}
};
Here is my redrawline()
private void redrawLine(){
mMap.clear(); //clears all Markers and Polylines
PolylineOptions options = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);//set the colour and width of the polyline
for (int i = 0; i < points.size(); i++) {
LatLng point = points.get(i);
options.add(point);
}
addMarker(); //add Marker in current position
line = mMap.addPolyline(options); //add Polyline
}
Thank you.
You are only adding to points on the button click, but that is incorrect. You should be adding to points every time you get an onLocationChanged (or perhaps your location callback), otherwise, you don't have any line to draw.
Your onLocationChanged (or callback) should call the redrawLine method every time.
Your redrawLine method should have a flag, such as hasStarted. If hasStarted = false, then clear the map, but don't draw the line. If hasStarted = true, then clear the map and DO draw the line.
In the onClick listener, simply set hasStarted = true (or, if you want it to be a toggle, say hasStarted = !hasStarted).

Android studio get last known location for maps and using a spinner to set circle radius

I am creating an app with a google maps and a circle radius centered on the user’s location. I want the user to choose the desired radius of the circle with a spinner (1-10 km radius). But when I use the value from my spinner the radius circle doesn't appear.
For the location I can get the blue dot showing my appearance by: map.setMyLocationEnabled(true); and I can manually enter a location for map to zoom into. But when I try to zoom into and set center of circle on the device location I get a nullpointerexception error. Below is my code for the location and the toast is just for me to see that I get the actual location.
private void getDeviceLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
return;
}
Task<Location> task = mFusedLocationClient.getLastLocation();
task.addOnSuccessListener(MainActivity.this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
currentLocation = location;
Toast.makeText(MainActivity.this, "Current Position " + currentLocation.getLongitude(), Toast.LENGTH_LONG).show(); //Just to make sure we have a value
SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map2);
supportMapFragment.getMapAsync(MainActivity.this);
}
}
});
}
Then I use userPosition for map to zoom into and set center of circle
public void onMapReady(GoogleMap map) {
LatLng userPosition = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
mGoogleMap = map;
map.setMyLocationEnabled(true);
map.animateCamera(CameraUpdateFactory.newLatLngZoom(userPosition, 10f));
map.addCircle(new CircleOptions()
.center(userPosition)
.radius(mapRadius)
.strokeColor(0x330073FF)
.fillColor(0x330073FF)
.strokeWidth(2));
map.getUiSettings().setZoomControlsEnabled(true);
map.getUiSettings().setMyLocationButtonEnabled(true);
}
But here I get the error on the line userPosition: java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference
at com.example.test.MainActivity.onMapReady(MainActivity.java:362).
I got the code from a tutorial and it seems to work for them and tried many different tutorials as well with slightly different code so not sure what I do wrong. I have tried searching and know others had similar problems but still haven't gotten it to work.
As for the radius, it works fine when I set a manual location and write It works well if I write the radius myself in meters. But if I try to use my spinner and the mapRadius value, the radius circle doesn’t show up at all when I run the emulator. This is the code that is in onCreate
spinnerRadius = findViewById(R.id.spinner_radius);
ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(this,
R.array.spinner_radius_option, android.R.layout.simple_spinner_item);
spinnerRadius.setAdapter(spinnerAdapter);
spinnerRadius.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mapRadiusInput = parent.getItemAtPosition(position).toString();
mapRadius = Double.parseDouble(mapRadiusInput)*1000; //converting to meters
Toast.makeText(MainActivity.this, ""+mapRadius, Toast.LENGTH_LONG).show();
}
I am a beginner when it comes to programming and android and I spent quite a bit on time on these two problem and it wouldn’t surprise me if it is easy to solve. Any help or pointers would be greatly appreciated.
When you add the circle, save the return value (Circle) in a field variable, Circle myCircle.
Then in the onItemSelected update the circle radius with the value (in meters).
So, first declare the variable as a class field variable (for scope visibility later). I'm assuming this is all in one class - if not you'll need to make this variable accessible to the onItemSelected callback instance.
private Circle myCircle;
Then when adding the circle, save it:
myCircle = map.addCircle(new CircleOptions()
.center(userPosition)
.radius(mapRadius)
.strokeColor(0x330073FF)
.fillColor(0x330073FF)
.strokeWidth(2));
And in your onItemSelected, update the circle (in meters)
myCircle.setRadius(mapRadius);
Here's another example showing same thing: https://stackoverflow.com/a/38454501/2711811
And API doc: https://developers.google.com/android/reference/com/google/android/gms/maps/model/Circle.html#setRadius(double)
The key is to save the Circle when it's created. And as you can see from the API, with the Circle reference there are other setters which can be used.

Not showing desired map

When I run the app, I get the world map, where you can see all the countries. But this is not what I want, I want it to show the map of my country or city as an example. Is there a way to do this? This is my code so far. I don't think the xml code should be necassary for this?
public class MainActivity extends Activity {
private GoogleMap gMap;
private LocationManager locationManager;
private Location location, g;
private double lati, longi;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
// gMap.setMyLocationEnabled(true);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
System.out.println("Last known location: " + location);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void showUsersPosition(View v) {
gMap.setMyLocationEnabled(true);
if(location != null) {
lati = location.getLatitude();
longi = location.getLongitude();
}
gMap.addMarker(new MarkerOptions().position(new LatLng(lati, longi)).title("You are here"));
}
}
I also have added a button, where I want to show the users location when this button is clicked. This happens in the method "showUsersPosition". But at this point, Location is null, even though I try to set it when the app is beeing started. Can anyone see why it is null? When the gMap.setMyLocation(true) is called, a symbole appears at the right corner, and if I click on this, it will show me my position. But I want it so that it does this when I click the button.
So the questions again are:
1. How to show the map of my country or city, and not the world map?
2. Why is Location null?
3. How do I make it show my exact location when the button is clicked
1)
You can use this on your fragment declaration to set the default latitude and longitude.
map:cameraTargetLat="Your Latitude"
map:cameraTargetLng="Your Longitude"
Do not forget to put xmlns:map="http://schemas.android.com/apk/res-auto" on your fragment if it is not there.
2) From the docs:
If the provider is currently disabled, null is returned.
Is the GPS turned on?. Also, you should use the new Location API.
3) The exactness of your Location will be based on the Provider used to get the Location. One of the advantages of using the new Fused Provider is that the system will try to get the best Location possible for you.

Android GPS takes a while to be accurate

I have made an Android app that gets location by longitude and latitude on a button click.
At first I get the last known location reading, which is, for argument sake, inaccurate when I first load up the app/turn on gps.
What I would like to know is how to wait for it to be accurate, like in Google maps when you get the toast message 'waiting for location'.
If you see any way the code can be improved it would also be helpful.
Code for reference:
public class Clue extends Activity {
public static double latitude;
public static double longitude;
Criteria criteria;
LocationManager lm;
LocationListener ll;
Location location;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.questions);
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
ll = new MyLocationListener();
lm.requestLocationUpdates(lm.getBestProvider(criteria, true), 0, 0, ll);
}
private boolean weAreThere() {
location = getLocation();
longitude = location.getLongitude();
latitude = location.getLatitude();
return inCorrectPlace(param);
}
private Location getLocation() {
lm.requestLocationUpdates(lm.getBestProvider(criteria, true), 0, 0, ll);
return lm.getLastKnownLocation(lm.getBestProvider(criteria, true));
}
}
public class MyLocationListener implements LocationListener
{
public void onLocationChanged(Location loc)
{
Clue.longitude = loc.getLongitude();
Clue.latitude = loc.getLatitude();
}
}
Thanks for reading, all replies will be appreciated.
Ben
If Location.hasAccuracy() returns true, you could call Location.getAccuracy() to retrieve the accuracy in meters, then filter the ones you don't consider enough accurate.
Notice you are not using LocationManager.GPS_PROVIDER so your fixes could also be obtained by other means (like WiFi).
Usually expect about a minute for the GPS chip to get "hot"* before getting GPS fixes (outdoors).
*By hot I mean having satellites coverage. Some chipsets get disconnected ("cold") after some time to preserve battery. The Time To First Fix (TTFF) is greater when the chip is cold.
Here is an excellent explanation,
http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html
helps you understand exactly how to implement it.
Initially , u should get fix using getlastknownLocation ()
In addition, U can use a background service that updates location using NETWORK.PROVIDER... which shall not drain ur battery if used judiciously...and also works if GPS is turned off
If there is no network provider, then u should try and ask user to turn on GPS.
If u r using 2.2 try PASSIVE PROVIDER

Categories

Resources