I'm trying to make an application that works with the user's location.
First, I did a little test app to return the user's location at getLastKnownLocation assigning permission control requested by API 23.
The control of location is made by the condition
if (location != null){
Log.i("LogX","Got Location!");
} else{ Log.i("LogX","It has location");}
The problem is that at all times, returns "It has location".
I think that should be something related to the use of getLastKnownLocation.
My MainActivity
public class MainActivity extends AppCompatActivity implements LocationListener{
LocationManager locationManager;
String provider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
permissaoMapa();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
provider = locationManager.getBestProvider(new Criteria(), false);
Location location = locationManager.getLastKnownLocation(provider);
if (location != null){
Log.i("LogX","Got Location!");
} else{ Log.i("LogX","It has location");}
}
private void permissaoMapa(){
if(ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
if(ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.ACCESS_COARSE_LOCATION)){
}else{
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},0);
}
}else {
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
for (int result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
return;
} else {
if (grantResults.length ==1) {
}
}
}
}
#Override
public void onLocationChanged(Location location) {
Double lat = location.getLatitude();
Double lon = location.getLatitude();
Log.i("LogX",lat.toString());
Log.i("LogX", lon.toString());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
protected void onResume() {
super.onResume();
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
#Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
}
}
For the getLastKnownLocation work, I did the following steps:
I open the terminal and typed the command "telnet localhost 5554" where 5554 refers to the AVD port
Open the Maps application that comes installed on AVD
Input the command line "geo fix 12 45" in the terminal . In this example you can type any latitude and longitude information.
There, after it managed to get the location.
Related
As you can tell from this question topic, when Run my program on the emulator it works perfectly on the first time, but when I run it again without any changes, It shows "(Project name) has Stop Working.
I really don't know how to fix this, I tried cleaning the project, building the APK again, but still there is no solution.
any help please, will be appreciated.
This is my code:
public class MainActivity extends AppCompatActivity {
LocationManager locationManager;
LocationListener locationListener;
TextView latitude;
TextView longitude;
TextView accuracy;
TextView altitude;
TextView address;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latitude = (TextView) findViewById(R.id.latitude);
longitude = (TextView) findViewById(R.id.longitude);
accuracy = (TextView) findViewById(R.id.accuracy);
altitude = (TextView) findViewById(R.id.altitude);
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Check if we already have a location access permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// this mean we don't have permissions, so we need to ask for it.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); // 1 here is some sort of id to identify this request, its called request code
} else {
// we do have permission
// 0 , 0 mean always keep track of user location changes, we can change it to be every 10 seconds or something like that.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
latitude.setText("Latitude: " + location.getLatitude());
longitude.setText("Longitude: " + location.getLongitude());
accuracy.setText("Accuracy: " + location.getAccuracy());
altitude.setText("Alitiude: " + location.getAltitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
}
#Override // this controls the dialog that asks user for location access permission
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// check if user clicked on the dialog and choose allow.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// if we have permission, then update user location. we need this check to make the code run!
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// 0 , 0 mean always keep track of user location changes, we can change it to be every 10 seconds or something like that.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
}
}
Even when I copy this code and put it in a new project, it works but again, same problem when I run it again it doesnt work.
I got this error
09-10 21:35:37.936 2588-2588/com.example.qubayel.test2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.qubayel.test2, PID: 2588
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.qubayel.test2/com.example.qubayel.test2.MainActivity}: java.lang.IllegalArgumentException: invalid listener: null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
I found the solution, the problem was that I'm using locationListener before defining it. on this line of code:
// 0 , 0 mean always keep track of user location changes, we can change it to be every 10 seconds or something like that.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
This definition should've been on top of my locationListener call:
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
latitude.setText("Latitude: " + location.getLatitude());
longitude.setText("Longitude: " + location.getLongitude());
accuracy.setText("Accuracy: " + location.getAccuracy());
altitude.setText("Alitiude: " + location.getAltitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
final code should be like this:
public class MainActivity extends AppCompatActivity {
LocationManager locationManager;
LocationListener locationListener;
TextView latitude;
TextView longitude;
TextView accuracy;
TextView altitude;
TextView address;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latitude = (TextView) findViewById(R.id.latitude);
longitude = (TextView) findViewById(R.id.longitude);
accuracy = (TextView) findViewById(R.id.accuracy);
altitude = (TextView) findViewById(R.id.altitude);
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
latitude.setText("Latitude: " + location.getLatitude());
longitude.setText("Longitude: " + location.getLongitude());
accuracy.setText("Accuracy: " + location.getAccuracy());
altitude.setText("Alitiude: " + location.getAltitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
// Check if we already have a location access permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// this mean we don't have permissions, so we need to ask for it.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); // 1 here is some sort of id to identify this request, its called request code
} else {
// we do have permission
// 0 , 0 mean always keep track of user location changes, we can change it to be every 10 seconds or something like that.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
#Override // this controls the dialog that asks user for location access permission
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// check if user clicked on the dialog and choose allow.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// if we have permission, then update user location. we need this check to make the code run!
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// 0 , 0 mean always keep track of user location changes, we can change it to be every 10 seconds or something like that.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
}
}
Hi I am creating an android map application that will get the user location, but when users open their map sometimes the location is not accurate and will slowly pinpoint your location.
I have tried this. But It still calls the handler and the TOASTS won't stop.
private LocationManager locationManager;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps_page);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
handler.postDelayed(runnable,3000);
}
#Override
public void onProviderDisabled(String provider) {
handler.removeCallbacks(runnable);
}
});
private Runnable runnable = new Runnable() {
#Override
public void run() {
getCurrentLocation();
Toast.makeText(mapsPage.this, "GETTING LOCATION", Toast.LENGTH_SHORT).show();
handler.postDelayed(this, 3000);
}
};
private void getCurrentLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
longitude = location.getLongitude();
latitude = location.getLatitude();
moveMap();
Integer loc = Math.round(location.getAccuracy());
textings.setText(Integer.toString(loc));
if(loc <= 100)
{
handler.removeCallbacks(runnable);
Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
}
}
}
//Function to move the map
private void moveMap() {
LatLng latLng = new LatLng(latitude, longitude);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(17));
mMap.addMarker(new MarkerOptions().position(latLng).draggable(false));
}
I have added a handler that will run every 5 seconds checking the users location, and when the getAccuracy data is either equal or lesser than 100 it will stop. How would I do this?
getCurrentLocation may call handler.removeCallbacks(runnable);, but then the runnable will always call handler.postDelayed(this, 3000); right after.
To fix this there has to be some condition for the Runnable to check to see if it should post itself again.
A solution would be to make getCurrentLocation return a boolean indicating if it was successful (enough):
private boolean getCurrentLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
longitude = location.getLongitude();
latitude = location.getLatitude();
moveMap();
Integer loc = Math.round(location.getAccuracy());
textings.setText(Integer.toString(loc));
if(loc <= 100) {
handler.removeCallbacks(runnable);
Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
return true;
}
}
return false;
}
Then in your Runnable check if you need to have another run:
#Override
public void run() {
if(!getCurrentLocation()) {
handler.postDelayed(this, 3000);
}
}
However, all of that being said, you should just check the Location in onLocationChanged of your LocationListener and do something if that location is accurate enough. Then you don't need the Runnable at all.
You should definitely accept RobCo's answer as the correct one because it addresses your question directly and also offers an additional key insight (i.e. you don't really need the Runnable at all).
But, I was curious what RobCo's approach would look like, so I created one possible implementation of it.
It turns out that if we avoid the Runnable and rely on Google's callbacks instead, we can get away with using only the newer location provider API (LocatonServices.FusedLocationApi). The older LocationManager API can just be eliminated.
So, in this implementation, I let the Google location service trigger callbacks if/when the location changes (instead of using a periodic poll from the client):
public class MainActivity extends AppCompatActivity implements
ActivityCompat.OnRequestPermissionsResultCallback, GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks,
com.google.android.gms.location.LocationListener {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int PERMISSION_REQUEST_CODE = 10001;
public static final int LOCATION_UPDATE_INTERVAL = 5000; // milliseconds
private GoogleApiClient googleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
googleApiClient = new GoogleApiClient.Builder(this, this, this)
.enableAutoManage(this, this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
private void requestPermission() {
ActivityCompat.requestPermissions(this,
new String[]{ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE);
}
private void initLocationServices() {
try {
// make initial, synchronous request for current location
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
moveMap(location);
}
// request future location updates which will come in as callbacks later, when available
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
} catch (SecurityException se) {
Log.w(TAG, "App does not have sufficient permission to request location. " +
"Requesting permission now...");
requestPermission();
}
}
private void moveMap(Location location) {
Log.v(TAG, "moveMap");
// TODO: actual map moving code goes here
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e(TAG, "Connection failed:" + connectionResult.getErrorMessage());
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) {
Log.v(TAG, "User granted permission. Will request current location.");
initLocationServices();
} else {
Log.w(TAG, "User did not grant permission. Cannot request location. Cannot proceed.");
}
}
#Override
public void onLocationChanged(Location newLocation) {
Log.v(TAG, "onLocationChanged:" + newLocation.toString());
moveMap(newLocation);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if ((ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED)
&& (ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED)) {
initLocationServices();
} else {
Log.w(TAG, "onCreate: requesting sufficient permission from user");
requestPermission();
}
}
#Override
public void onConnectionSuspended(int i) {
Log.v(TAG, "onConnectionSuspended");
}
}
A downside of this particular implementation is that the MainActivity implements several interfaces and that adds some confusion (what are all these methods doing here?, etc)
Dunno. Maybe it's useful. In any event, good luck with your app.
I'm building a friend tracking android app. While my friend activated the app and goes away along with his GPS and cellular data on, I need to track him on my device. That's the concept.
I've implemented LocationListener class and now I can get the last updated location either from Gps or Network but is not updated unless I launch Google Maps and return to my application. After googling, I learned that location cache is updated only by GMaps.!
Is there an alternate way to continuously update location?
What if when I need to get continues location after the device locked without making use of Wakelock?
This is my location listener class:
package com.amazinginside;
/** AMAZING LOCATION SUPPORT CLASS, Devoloped By SANGEETH NANDAKUMAR */
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
public class AmazingLocation extends Service implements LocationListener
{
private final Context mContext;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
double latitude=0.0;
double longitude=0.0;
//MINIMUM DISTANCE FOR UPDATE (meters)
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 Meters
//MINIMUM TIME BETWEEN UPDATES
private static final long MIN_TIME_BW_UPDATES = 1000 * 0; // 0 Seconds
//LOCATION MANAGER
protected LocationManager locationManager;
//CONSTRUCTOR
public AmazingLocation(Context context)
{
this.mContext = context;
getLocation();
}
//LOCATION PROVISION
public Location getLocation()
{
try
{
//GET LOCATION MANAGER
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
//CHECK GPS STATE
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
//CHECK NETWORK STATE
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled)
{
//NO LOCATION PROVIDERS
}
else
{
this.canGetLocation = true;
/** GET LOCATION FROM NETWORK */
//FIRST GET LOCATION FROM NETWORK
if (isNetworkEnabled)
{
//REQUEST LOCATION
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
//START WITH LAST KNOWN LOCATION
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//EXTRACT LOCATION
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
/** GET LOCATION FROM GPS SENSOR */
//THEN GET LOCATION FROM GPS
if (isGPSEnabled)
{
if (location == null)
{
//REQUEST GPS LOCATION
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null)
{
//EXTRACT LAST KNOWN LOCATION
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//RETURN LOCATION
if (location != null)
{
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return location;
}
//STOP GPS SENSOR
public void stopUsingGPS()
{
if(locationManager != null)
{
locationManager.removeUpdates(AmazingLocation.this);
}
}
//EXTRACT LATTITUDE
public double getLatitude()
{
if(location != null)
{
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
//EXTACT LONGITUDE
public double getLongitude()
{
if(location != null)
{
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
//CAN I GET THE LOCATION.?
public AmazingStatus canGetLocation()
{
AmazingStatus status=new AmazingStatus();
if(this.canGetLocation)
{
status.setStatus(true);
status.setErrorcode(0);
status.setErrormsg("Task completed");
}
else
{
status.setStatus(false);
status.setErrorcode(145);
status.setErrormsg("Please turn on GPS access manually");
}
return status;
}
//SHOW LOCATION SETTINGS
public AmazingStatus showSettingsAlert()
{
final AmazingStatus status=new AmazingStatus();
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("REQUIRES LOCATION ACCESS");
alertDialog.setMessage("Please allow GPS access to this app");
//POSSITIVE REPLY
alertDialog.setPositiveButton("Allow", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int which)
{
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
status.setStatus(true);
status.setErrorcode(0);
status.setErrormsg("Task completed");
}
});
//NEGATIVE REPLY
alertDialog.setNegativeButton("Deny", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
status.setStatus(false);
status.setErrorcode(408);
status.setErrormsg("User denied permission");
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
return status;
}
//UNUSED OVERRIDE METHORDS...
#Override
public void onLocationChanged(Location location)
{
getLocation();
}
#Override
public void onProviderDisabled(String provider)
{
}
#Override
public void onProviderEnabled(String provider)
{
getLocation();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
getLocation();
}
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
}
This my onCreate() method:
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//CREATE A BUTTON HANDLER
Button start_btn=(Button)findViewById(R.id.start_location_streaming);
//ON BUTTON CLICK EVENT
start_btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//REPEAT A METHORD AT SPECIFIC INTERVALS
Timer myTimer = new Timer();
myTimer.schedule(new TimerTask()
{
#Override
public void run()
{
TimerMethod();
}
}, 0, 8000);
}
}); }
These are other methods:
private void TimerMethod()
{
//START METHORD
this.runOnUiThread(Timer_Tick);
}
//LOCATION REPORTING METHORD
private Runnable Timer_Tick = new Runnable()
{
public void run()
{
Toast.makeText(MainActivity.this, "Current latitude : "+Double.toString(getLocation().latitude), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, "Current longitude : "+Double.toString(getLocation().longitude), Toast.LENGTH_SHORT).show();
}
};
private LatLng getLocation()
{
//CREATE A LOCATION CLASS INSTANCE
AmazingLocation gps = new AmazingLocation(this);
//RETRIVE LOCATION
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
//RETURN LOCATION
LatLng loc=new LatLng(latitude,longitude);
return loc;
}
Now the problem is, the toast just shows previously known the location and not updating unless I opened Google Maps and returned.
Any help will be great for me.
Use Fused location provider in Android set your interval in that:
For an example create your activity like this:
public class LocationActivity extends Activity implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationActivity";
private static final long INTERVAL = 1000 * 10;
private static final long FASTEST_INTERVAL = 1000 * 5;
Button btnFusedLocation;
TextView tvLocation;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
String mLastUpdateTime;
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate ...............................");
//show error dialog if GoolglePlayServices not available
if (!isGooglePlayServicesAvailable()) {
finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
setContentView(R.layout.activity_main);
tvLocation = (TextView) findViewById(R.id.tvLocation);
btnFusedLocation = (Button) findViewById(R.id.btnShowLocation);
btnFusedLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
updateUI();
}
});
}
#Override
public void onStart() {
super.onStart();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
#Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop fired ..............");
mGoogleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
startLocationUpdates();
}
protected void startLocationUpdates() {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Connection failed: " + connectionResult.toString());
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
private void updateUI() {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
tvLocation.setText("At Time: " + mLastUpdateTime + "\n" +
"Latitude: " + lat + "\n" +
"Longitude: " + lng + "\n" +
"Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
"Provider: " + mCurrentLocation.getProvider());
} else {
Log.d(TAG, "location is null ...............");
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}
Google play services required:
To get continiuos location update, you can refer to the above provided answers .
But You can also make use of LocationServices which is faster than other approaches and much easy and efficient to get location.
This approach is quit long but kindly follow all the provided steps
So let me provide a brief working :
Add these two dependencies in your gradle app file
implementation 'com.google.android.gms:play-services-maps:17.0.0'
implementation 'com.google.android.gms:play-services-location:17.0.0'
Add these permissions in the manifest file outside applicationtag
Declare variable outside onCreate
private FusedLocationProviderClient fusedLocationClient;
private LocationRequest mLocationRequest;
private LocationCallback mlocationCallback;
private LocationSettingsRequest.Builder builder;
private static final int REQUEST_CHECK_SETTINGS = 102;
Now inside onCreate :
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
fetchLastLocation();
mlocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
// Update UI with location data
// ...
Log.e("CONTINIOUSLOC: ", location.toString());
}
};
};
mLocationRequest = createLocationRequest();
builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
checkLocationSetting(builder);
No define fetchLastLocation method
private void fetchLastLocation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
// Toast.makeText(MainActivity.this, "Permission not granted, Kindly allow permission", Toast.LENGTH_LONG).show();
showPermissionAlert();
return;
}
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
Log.e("LAST LOCATION: ", location.toString()); // You will get your last location here
}
}
});
}
Now define other two method for permission request
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 123: {
// If request is cancelled, the result arrays are empty.
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// permission was denied, show alert to explain permission
showPermissionAlert();
}else{
//permission is granted now start a background service
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fetchLastLocation();
}
}
}
}
}
private void showPermissionAlert(){
if (ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(MainHomeActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainHomeActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 123);
}
}
now define createLocationRequest method and checkLocationSetting method :
protected LocationRequest createLocationRequest() {
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(30000);
mLocationRequest.setFastestInterval(10000);
mLocationRequest.setSmallestDisplacement(30);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
return mLocationRequest;
}
private void checkLocationSetting(LocationSettingsRequest.Builder builder) {
SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
startLocationUpdates();
return;
}
});
task.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull final Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
AlertDialog.Builder builder1 = new AlertDialog.Builder(mContext);
builder1.setTitle("Continious Location Request");
builder1.setMessage("This request is essential to get location update continiously");
builder1.create();
builder1.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ResolvableApiException resolvable = (ResolvableApiException) e;
try {
resolvable.startResolutionForResult(MainHomeActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e1) {
e1.printStackTrace();
}
}
});
builder1.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(mContext, "Location update permission not granted", Toast.LENGTH_LONG).show();
}
});
builder1.show();
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if (requestCode == REQUEST_CHECK_SETTINGS) {
if (resultCode == RESULT_OK) {
// All location settings are satisfied. The client can initialize
// location requests here.
startLocationUpdates();
}
else {
checkLocationSetting(builder);
}
}
}
now atlast define startLocationUpdates and stopLocationUpdates method :
public void startLocationUpdates() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
return;
}
}
fusedLocationClient.requestLocationUpdates(mLocationRequest,
mlocationCallback,
null /* Looper */);
}
private void stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(mlocationCallback);
}
Note : Replace context with your class context and call stopLocationUpdates() inside onDestroy method of your class
Note : For any futher information or doubt you can refer to :
https://developer.android.com/training/location/retrieve-current
https://developer.android.com/training/location/change-location-settings
https://developer.android.com/training/location/receive-location-updates
You will get your location in Logcat.
Hope this will hope you or somebody else !
I believe rather than reinventing the wheel, you can use one of the third party libraries that are easy to implement and in this case, battery efficient. One of the library I found is SmartLocation. You can add the following dependency in your build.gradle (app) to start using the library.
compile 'io.nlopez.smartlocation:library:3.2.9'
After adding the dependency, you should rebuild the project to get the references.
As an example you can try the following code in your Activity.
Button start_btn=(Button)findViewById(R.id.start_location_streaming);
Context context = start_btn.getContext();
Handler handler = new Handler();
start_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SmartLocation.with(context).location().start(locationListener);
}
});
OnLocationUpdatedListener locationListener = new OnLocationUpdatedListener({
#Override
public void onLocationUpdated(Location location) {
double lat = location.getLatitude();
double lng = location.getLongitude();
handler.postDelayed(locationRunnable,8000);
}
});
Runnable locationRunnable = new Runnable({
#Override
public void run() {
SmartLocation.with(context).location().start(locationListener);
}
});
You can stop location tracking in onStop() method
#Override
public void onStop() {
SmartLocation.with(context).location().stop();
super.onStop();
}
SmartLocation library will give you more than what is expected, just try that once.
Note: Make sure your application does have ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION (both) to have accurate results. Don't forget to ask for permissions at runtime for Android 6.0 and above.
You should use android services, rather than the app itself. This way you will achieve to run code continuously in the background and you will receive the location even if the app closes.
https://www.tutorialspoint.com/android/android_services.htm
I am not getting GPS location in my code, while Google maps is showing current location and even its updating, I am starting a service, inside service registering locationListener to the locationManager, handling onLocationChanged callback method, doing entry in the AndroidManifest.xml even. The logs onCreate methods is showing.
below is my code, could you guys please let me know where i am doing wrong...
public class LocationService extends Service implements LocationListener {
private static final long MIN_TIME_INTERVAL_FOR_GPS_LOCATION = 100;
private static final float MIN_DISTANCE_INTERVAL_FOR_GPS_LOCATION = 1.0f;
private static String TAG = LocationService.class.getSimpleName();
private LocationManager locationManager;
private static Location mCurrentLocation;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate...");
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_INTERVAL_FOR_GPS_LOCATION, MIN_DISTANCE_INTERVAL_FOR_GPS_LOCATION, this);
mCurrentLocation = getBestLocation();
}
private Location getBestLocation() {
Log.i(TAG, "getBestLocation...");
Location location_gps = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location location_network = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// If both are available, get the most recent
if (location_gps != null && location_network != null) {
return (location_gps.getTime() > location_network.getTime()) ? location_gps : location_network;
} else if (location_gps == null && location_network == null) {
return null;
} else {
return (location_gps == null) ? location_network : location_gps;
}
}
#Override
public void onLocationChanged(Location location) {
Log.i(TAG, "onLocationChanged...");
Toast.makeText(LocationService.this, "Location Found", Toast.LENGTH_SHORT).show();
mCurrentLocation = location;
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public static Location getmCurrentLocation() {
return mCurrentLocation;
}
public static void setmCurrentLocation(Location mCurrentLocation) {
LocationService.mCurrentLocation = mCurrentLocation;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy...");
locationManager.removeUpdates(this);
}
}
Your locationManager called requestLocationUpdates using GPS provider only.
I think your device could not catch GPS satellite signal, in-door sate.
So, you should call requestLocationUpdates using Network provider too.
Next two links are may helpful to you.
http://developer.android.com/guide/topics/location/strategies.html
http://developer.android.com/training/location/receive-location-updates.html
i need to find current location, either with network or gps.
i searched over internet and in stackoverflow but i cann't find what's wrong with this code.
i also set this parameter in manifest:
uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
so here is my code:
LocationManager locationManager;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
findCurrentLocation();
//some other stuff here
}
public void findCurrentLocation()
{
boolean networkEnabled = false;
boolean gpsEnabled = false;
currentLocation = getLastKnownLocation();
if(currentLocation == null)
{
currentLocation = new Location("sometext");
locationFindDialog = ProgressDialog.show(this, "Find Your Location", "Please Wait", false);
try
{
networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
catch(Exception e)
{
}
try
{
gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
catch(Exception e)
{
}
if((networkEnabled == false) && (gpsEnabled == false))
{
locationFindDialog.dismiss();
showMessage("we need gps or sim card(or network) to find your location");
//show message
//you need at least one provider
return;
}
if(networkEnabled)
{
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, networkLocationListener);
}
if(gpsEnabled)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLocationListener);
}
}
private final LocationListener networkLocationListener = new LocationListener()
{
#Override
public void onLocationChanged(Location location)
{
currentLocation.set(location);
//unregister listener
locationManager.removeUpdates(this);
locationManager.removeUpdates(gpsLocationListener);
locationFindDialog.dismiss();
}
#Override
public void onProviderDisabled(String provider)
{
}
#Override
public void onProviderEnabled(String provider)
{
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
};
private final LocationListener gpsLocationListener = new LocationListener()
{
#Override
public void onLocationChanged(Location location)
{
currentLocation.set(location);
//unregister listener
locationManager.removeUpdates(this);
locationManager.removeUpdates(networkLocationListener);
locationFindDialog.dismiss();
}
#Override
public void onProviderDisabled(String provider)
{
}
#Override
public void onProviderEnabled(String provider)
{
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
};
private Location getLastKnownLocation()
{
Location location = null;
List<String> providers = locationManager.getAllProviders();
for(String provider : providers)
{
location = locationManager.getLastKnownLocation(provider);
if(location != null)
{
return location;
}
}
return null;
}
no mater how much i wait, the app don't give me the location.
what's wrong with this code and how i can fix it?
finally i found a solution for this problem, the idea is finding cellId and lac manually, then send them to google secret API, and find latitude and longitude of cell tower, it's not too accurate (because it's cell tower location not user location), but enough for me.
refer to this address for more info:
http://sunil-android.blogspot.com/2013/01/convert-celllocation-to-real-location.html