13

This question is directly related to the same prevailing stackoverflow question at "Android: get current location of user without using gps or internet" where the accepted answer is actually not answering the question.

I should be able to get the current location name (eg:city name, village name) of the device via network provider not with GPS or internet. Following is the accepted answer in that question. (The following code parts should be included in the onCreate() method)

// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
      // Called when a new location is found by the network location provider.
      makeUseOfNewLocation(location);
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {}

    public void onProviderEnabled(String provider) {}

    public void onProviderDisabled(String provider) {}
  };

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

I changed the above code given in the linked answer as following but no success.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final TextView txtView = (TextView) findViewById(R.id.tv1);
    txtView.setText("ayyo samitha");
    ////

    // Acquire a reference to the system Location Manager
    LocationManager locationManager;
   locationManager= (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

    // Define a listener that responds to location updates
    LocationListener locationListener = new LocationListener() {
        public void onLocationChanged(Location location) {
            // Called when a new location is found by the network location provider.
            makeUseOfNewLocation(location);

        }

        private void makeUseOfNewLocation(Location location) {
            txtView.setText("sam came in");
            txtView.append(location.toString());
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {}

        public void onProviderEnabled(String provider) {
           // makeUseOfNewLocation(location);
        }

        public void onProviderDisabled(String provider) {}
    };

    // Register the listener with the Location Manager to receive location updates
    if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
    }

}

How to accomplish what I want by correcting above code or any other method? Note that I want to get the location name, but not the longitudes and latitudes. Can somebody please help me.

Community
  • 1
  • 1
Samitha Chathuranga
  • 1,689
  • 5
  • 30
  • 57
  • I am not entirely clear of what you are asking, can you describe exactly what you are trying to accomplish, what kind of behavior you are trying to get, the expected time between location updates, etc – Kai May 02 '15 at 01:47
  • I just want to get current location of user without using gps or internet. – Samitha Chathuranga May 02 '15 at 03:39
  • @Kai Are you clear what the problem is? I did a small edit in the question at the end too. – Samitha Chathuranga May 03 '15 at 12:01
  • 1
    The problem is that the code you tried does work, probably just not as well as you wished. For example, the accuracy such a method provides on Samsung Galaxy S3 is 2000m, meaning my actual position is anywhere within a circle of 2 kilometers radius. Additional it would probably take quite a large change in location before your app would be informed of a location change since the margin of error is so big. The answer provided by Ruben would give you better result many times, though you do have to change the priority to `LocationRequest.PRIORITY_LOW_ENERGY` to satisfy your no GPS requirement. – Kai May 03 '15 at 12:21
  • @Kai I want to get the location without a location change occur. That is my objective. It means that I want to get the fresh current location when I start the app while my phone location is never changed. If my objective cannot be fulfilled by above code, how to change it to do it. – Samitha Chathuranga May 03 '15 at 12:31
  • I believe a GPS or `LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY` (if Google Play Services is used) is required to get a reasonably good location. This does require `android.permission.ACCESS_FINE_LOCATION`, however unless you only require _km_ level accuracy, otherwise this permission is a must. Note that using Google Play Services with `LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY` I can get location data as accurate as 10m _without_ turning on GPS, so this should still satisfy your requirement. – Kai May 03 '15 at 13:19
  • @Kai I want to get the location without turning on GPS or internet in the phone. I do not care about the accuracy. I just want to get the location via the signal tower. And I'm not clear where to use that LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY in the program. Do u suppose to to use it instead of LocationRequest.PRIORITY_HIGH_ACCURACY in Ruben's program. Anyway does this enable to get the location without turning on internet ? – Samitha Chathuranga May 03 '15 at 16:30
  • @Kai And what is mLocationProviderApi in Ruben's code? As I see LocationProviderApi variable is not initialized. – Samitha Chathuranga May 03 '15 at 16:32

6 Answers6

4

What you are referring to here (showing location name on older phones) is done using "Cell Broadcast" (or "CB"). This has absolutely nothing to do with the Location API or any variations on that.

Cell towers can send out broadcast information that can be received by devices (something like "one to many SMS"). Some operators have used Cell Broadcast to broadcast the name of the location where the cell tower is. Some operators have used Cell Broadcast to broadcast the location (lat/long) of the cell tower. Some operators have used Cell Broadcast to send advertising tickers. There are no standards for the information contained in a CB broadcast message and each mobile operator can choose to use this or not.

Since most operators do not send these messages, it probably doesn't make sense to invest any time in trying to receive and decode them. But if you want to try, you can register a BroadcastReceiver listening for this Intent action: android.provider.Telephony.SMS_CB_RECEIVED. See the documentation for more details about what data is contained in the Intent.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Thanks a lot... This is exactly the answer I was struggling for... 100% correct... Sorry I couldn't accept the answer before ending the bounty period as I couldn't check at the last moment.. – Samitha Chathuranga May 10 '15 at 15:28
  • Let me know if you have any luck with the Cell Broadcast. – David Wasser May 11 '15 at 05:39
  • I tried to get cell broadcast messages. But could not find a correct way. Can u mention a way if u know please. – Samitha Chathuranga Jun 12 '15 at 13:23
  • Do you know if your operator is sending cell broadcasts? Have you confirmed this? – David Wasser Jun 12 '15 at 14:07
  • Yes, I confirmed it. When I turn on cell broadcast messages in my phone those messages are received with location names. – Samitha Chathuranga Jun 12 '15 at 14:39
  • You set up a `BroadcastReceiver` to listen for SMS_CB_RECEIVED events. Have you done that? Is the receiver's `onReceive()` being called? Do you have the permission `android.permission.RECEIVE_SMS`? – David Wasser Jun 12 '15 at 14:56
  • Yes, both mentioned requirements are ok. I tried this code actually. http://stackoverflow.com/questions/7118378/how-to-get-cell-broadcast-message But I am stuck at a certain point.. The problem is mentioned as a comment in the accepted answer of that question. – Samitha Chathuranga Jun 14 '15 at 07:12
1

According to android docs using LocationManager is not the current recomended API (see reference):

The Google Play services location APIs are preferred over the 
Android framework location APIs (android.location) as a way of
adding location awareness to your app.

To learn how to set up the Google Services client library, see Setup in the Google Play services guide.

Once you have linked Google Services client library to your app you can achieve user location using FusedLocationProviderApi:

    import android.location.Location;
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.util.Log;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.Toast;

    import com.google.android.gms.common.ConnectionResult;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
    import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
    import com.google.android.gms.common.api.PendingResult;
    import com.google.android.gms.common.api.ResultCallback;
    import com.google.android.gms.common.api.Status;
    import com.google.android.gms.location.FusedLocationProviderApi;
    import com.google.android.gms.location.LocationListener;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationServices;

    public class MainActivity extends ActionBarActivity
            implements ConnectionCallbacks, OnConnectionFailedListener {

        // ..

        private GoogleApiClient mGoogleAPIClient;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // create google api client object
            mGoogleAPIClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        }

        @Override
        protected void onStart() {
            super.onStart();

            mGoogleAPIClient.connect();
        }

        @Override
        protected void onStop() {
            super.onStop();

            mGoogleAPIClient.disconnect();
        }

        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            Toast.makeText(this,
                "Could not connect to Google Play Services",
                Toast.LENGTH_SHORT).show();

            finish();
        }

        @Override
        public void onConnected(Bundle bundle) {
            Log.i(TAG,
                "Successfuly connect to Google Play Services");

            // retrieve last location once connected
            Location lastLocation = LocationServices.FusedLocationApi
                .getLastLocation(mGoogleAPIClient);

            if (lastLocation == null) {
                // should request new one
                // location should be enabled
                Log.i(TAG,
                    "No location data previously acquired.. should request!");

                Toast.makeText(this,
                    "Requesting location data ..",
                    Toast.LENGTH_SHORT).show();

                LocationRequest locationRequest = LocationRequest.create();
                locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                locationRequest.setInterval(5000);

                PendingResult<Status> result = LocationServices.FusedLocationApi
                    .requestLocationUpdates(mGoogleAPIClient,
                        locationRequest,
                        new LocationListener() {

                    @Override
                    public void onLocationChanged(Location location) {
                        makeUseOfNewLocation(location);
                    }
                });

                // TODO: use result to retrieve more info

            } else {
                makeUseOfNewLocation(lastLocation);
            }
        }

        @Override
        public void onConnectionSuspended(int i) {
        }

        private void makeUseOfNewLocation(Location location) {
             // do your stuff here
        }

I have tested the code above and it works without internet connection but it requires that user enable location feature on device. Also it requires that the user have already enabled Location History feature into location feature.

Hope that this helps you.

  • what is mLocationProviderApi ? As I see mLocationProviderApi variable is not initialized. And pls mention the imports list. – Samitha Chathuranga May 02 '15 at 15:26
  • Sorry, my mistake. I edited the code, please take a look. When I first implemented the code I create an attribute instance of `FusedLocationProviderApi` that I called **mLocationProviderApi**, but I found out that I can access a reference of `FusedLocationProviderApi` directly from `LocationServices.FusedLocationApi`. – Ruben O. Chiavone May 04 '15 at 01:49
  • Thanks, What do u mean by "enable location feature on device"? I guess this doesn't mean I should turn on gps. – Samitha Chathuranga May 04 '15 at 13:49
  • Ok, This run without error but this cannot give me the location name (eg. London). This only gives latitudes and logitudes.. OMG,,,!!! – Samitha Chathuranga May 04 '15 at 14:27
  • I think u have seen a most primitive phone such as "nokia 1110" shows the location name from the signal tower.(without internet or gps) I want to get that data. But as I see this approach cannot get it as Location class no method to get the location name – Samitha Chathuranga May 04 '15 at 15:27
  • I mean enable the location services, maybe it will use gps but only if you make a request. The thing is that if you use Google Play Services you can use Location history which retrieves the user last location and I checked that it was not necessary to have an internet connection. I did not see that you needed a location name but with lat and lng you can work it out. – Ruben O. Chiavone May 04 '15 at 17:36
  • What I actually want is location name, but not lat and lng. As I know to get location name by lat and lng we need internet connection. – Samitha Chathuranga May 04 '15 at 17:43
1

The problem is that the code you tried does work, probably just not as well as you wished. For example, the accuracy such a method provides on Samsung Galaxy S3 is 2000m, meaning the actual position is anywhere within a circle of 2 kilometers radius. Additional it would probably take quite a large change in location before your app would be informed of a location change since the margin of error is so big.

A GPS or LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY (if Google Play Services is used) is required to get a reasonably good location. This does require android.permission.ACCESS_FINE_LOCATION, however unless you only require km level accuracy, otherwise this permission is a must.

Finally note that using Google Play Services with LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY I can get location data as accurate as 10m without turning on GPS, so this should still satisfy your requirement.

Below is a complete example:

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

MainActivity.java

import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

public class MainActivity extends Activity implements
        com.google.android.gms.location.LocationListener, ConnectionCallbacks,
        OnConnectionFailedListener {
    private final FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
    private GoogleApiClient mGoogleAPIClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mGoogleAPIClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API).addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
    }

    @Override
    protected void onResume() {
        super.onResume();

        mGoogleAPIClient.connect();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mGoogleAPIClient != null) {
        mGoogleAPIClient.disconnect();
        }
    }

    @Override
    public void onConnected(Bundle arg0) {
        final LocationRequest locationRequest = LocationRequest.create();
        locationRequest
                .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        locationRequest.setInterval(30 * 1000);
        locationRequest.setFastestInterval(5 * 1000);
        fusedLocationProviderApi.requestLocationUpdates(mGoogleAPIClient,
                locationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onConnectionFailed(ConnectionResult arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onLocationChanged(Location location) {
        // the location is no more than 10 min old, and with reasonable
        // accurarcy (50m), done
        if (System.currentTimeMillis() < location.getTime() + 10 * 60 * 1000
                && location.getAccuracy() < 50) {
            mGoogleAPIClient.disconnect();
            mGoogleAPIClient = null;
            ((TextView) findViewById(R.id.test)).setText(location.toString());
        }
    }
}
Kai
  • 15,284
  • 6
  • 51
  • 82
  • yes, you can turn off GPS and any internet connection and try it for yourself – Kai May 04 '15 at 14:33
  • but this cannot give me the location name (eg. London). This only gives latitudes and longitudes.. I tried also using geocoder, but it does need internet. – Samitha Chathuranga May 04 '15 at 15:21
  • I think u have seen a most primitive phone such as "nokia 1110" shows the location name from the signal tower.(without internet or gps) I want to get that data. But as I see this approach cannot get it as Location class no method to get the location name – Samitha Chathuranga May 04 '15 at 15:25
  • You've mentioned **nothing** about getting the location _name_ which is entirely separate from the location info itself. That cannot be done without internet connection. – Kai May 04 '15 at 15:33
  • Sorry, I didn't thought I should mention that. [I will edit the question.] But I don't think that it is impossible as most primitive phones such as "nokia 1110" shows the location name by default from the signal tower.(without internet or gps). So if such a simple phone could do that, I guess android too could do that. – Samitha Chathuranga May 04 '15 at 16:31
1

You can try getting a country level accuracy using the Locale object or using the Telephony service. No internet or GPS required.

Getting country code from Locale:

String locale = context.getResources().getConfiguration().locale.getCountry();

Getting country code from Android's Telephony service:

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
// Will work on all networks. Only provide the SIM card's country
String countryCode = tm.getSimCountryIso();

// Might not work well on CDMA networks. Will provide the country code
// for the country the device is currently in.
String currentCountryCode = tm.getNetworkCountryIso();

Better code samples and discussion here.

Community
  • 1
  • 1
Hassaan
  • 932
  • 8
  • 16
0

try this code..

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;

public class AppLocationService extends Service implements LocationListener         {

protected LocationManager locationManager;
Location location;

private static final long MIN_DISTANCE_FOR_UPDATE = 10;
private static final long MIN_TIME_FOR_UPDATE = 1000 * 60 * 2;

public AppLocationService(Context context) {
    locationManager = (LocationManager) context
            .getSystemService(LOCATION_SERVICE);
}

public Location getLocation(String provider) {
    if (locationManager.isProviderEnabled(provider)) {
        locationManager.requestLocationUpdates(provider,
                MIN_TIME_FOR_UPDATE, MIN_DISTANCE_FOR_UPDATE, this);
        if (locationManager != null) {
            location = locationManager.getLastKnownLocation(provider);
            return location;
        }
    }
    return null;
}

@Override
public void onLocationChanged(Location location) {
}

@Override
public void onProviderDisabled(String provider) {
}

@Override
public void onProviderEnabled(String provider) {
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}

@Override
public IBinder onBind(Intent arg0) {
    return null;
}

}

and next class is

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class AndroidLocationActivity extends Activity {

Button btnGPSShowLocation;
Button btnNWShowLocation;

AppLocationService appLocationService;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    appLocationService = new AppLocationService(
            AndroidLocationActivity.this);

    btnGPSShowLocation = (Button) findViewById(R.id.btnGPSShowLocation);
    btnGPSShowLocation.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {

            Location gpsLocation = appLocationService
                    .getLocation(LocationManager.GPS_PROVIDER);

            if (gpsLocation != null) {
                double latitude = gpsLocation.getLatitude();
                double longitude = gpsLocation.getLongitude();
                Toast.makeText(
                        getApplicationContext(),
                        "Mobile Location (GPS): \nLatitude: " + latitude
                                + "\nLongitude: " + longitude,
                        Toast.LENGTH_LONG).show();
            } else {
                showSettingsAlert("GPS");
            }

        }
    });

    btnNWShowLocation = (Button) findViewById(R.id.btnNWShowLocation);
    btnNWShowLocation.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View arg0) {

            Location nwLocation = appLocationService
                    .getLocation(LocationManager.NETWORK_PROVIDER);

            if (nwLocation != null) {
                double latitude = nwLocation.getLatitude();
                double longitude = nwLocation.getLongitude();
                Toast.makeText(
                        getApplicationContext(),
                        "Mobile Location (NW): \nLatitude: " + latitude
                                + "\nLongitude: " + longitude,
                        Toast.LENGTH_LONG).show();
            } else {
                showSettingsAlert("NETWORK");
            }

        }
    });

}

public void showSettingsAlert(String provider) {
    AlertDialog.Builder alertDialog = new AlertDialog.Builder(
            AndroidLocationActivity.this);

    alertDialog.setTitle(provider + " SETTINGS");

    alertDialog
            .setMessage(provider + " is not enabled! Want to go to settings menu?");

    alertDialog.setPositiveButton("Settings",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    Intent intent = new Intent(
                            Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    AndroidLocationActivity.this.startActivity(intent);
                }
            });

    alertDialog.setNegativeButton("Cancel",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });

    alertDialog.show();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

    }

and this user permission given At Manifest File

<!-- to get location using GPS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- to get location using NetworkProvider -->
<uses-permission android:name="android.permission.INTERNET" />
Hardik Parmar
  • 712
  • 2
  • 13
  • 28
0

Good luck with this. It's called geocoder. Or more specifically reverse geocoding to turn coordinates into a human readable output. I'm fairly sure the one google provides is a pay service but you get a bunch free. So plan on caching the results and using your cached results when ever possible.

List<Address> list = geoCoder.getFromLocation(location
            .getLatitude(), location.getLongitude(), 1);
    if (list != null & list.size() > 0) {
        Address address = list.get(0);
        result = address.getLocality();
        return result;

https://developer.android.com/training/location/display-address.html

How to get city name from latitude and longitude coordinates in Google Maps?

Community
  • 1
  • 1
danny117
  • 5,581
  • 1
  • 26
  • 35