2015-04-05 10 views
13

To pytanie jest bezpośrednio związane z tym samym przeważającym pytaniem o stackoverflow w "Android: get current location of user without using gps or internet", gdzie zaakceptowana odpowiedź w rzeczywistości nie odpowiada na pytanie.Uzyskaj nazwę bieżącej lokalizacji użytkownika bez użycia GPS lub Internetu, ale używając Network_Provider w Androidzie

Powinienem być w stanie uzyskać aktualną nazwę lokalizacji (np. Nazwę miasta, nazwę wioski) urządzenia za pośrednictwem operatora sieci, a nie z GPS lub Internetu. Oto akceptowana odpowiedź w tym pytaniu. (Następujące części Kodeksu powinny być uwzględnione w metodzie onCreate())

// 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); 

Zmieniłem powyższy kod podany w połączonej odpowiedzi w następujący sposób, ale bez powodzenia.

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); 
    } 

} 

Jak osiągnąć to, co chcę, poprawiając powyższy kod lub jakąkolwiek inną metodę? Zwróć uwagę, że chcę uzyskać nazwę lokalizacji, ale nie długość i szerokość geograficzną. Czy ktoś mógłby mi pomóc.

+0

Nie jestem całkowicie wolny od tego, o co prosisz, możesz opisać dokładnie to, co próbujesz osiągnąć, jaki rodzaj zachowania próbujesz uzyskać, przewidywany czas między aktualizacjami lokalizacji, itp. – Kai

+0

Chcę tylko uzyskać bieżące lokalizacja użytkownika bez korzystania z GPS lub Internetu. –

+0

@Kai Czy wiesz, co to jest problem? Zrobiłem też małą zmianę w pytaniu na końcu. –

Odpowiedz

4

Co masz na myśli tutaj (pokazuje nazwę lokalizacji na starszych telefonach) odbywa się za pomocą "Cell Broadcast" (lub "CB"). Nie ma to absolutnie nic wspólnego z interfejsem API lokalizacji ani z żadnymi jego odmianami.

Komórki wieżowe mogą wysyłać informacje rozgłoszeniowe, które mogą być odbierane przez urządzenia (np. "Jeden do wielu SMS-ów"). Niektórzy operatorzy wykorzystali Cell Broadcast do nadania nazwy lokalizacji, w której znajduje się wieża komórek. Niektórzy operatorzy wykorzystali Cell Broadcast do nadawania lokalizacji (szerokość/długość) wieży celi. Niektórzy operatorzy wykorzystali Cell Broadcast do wysyłania pasków reklamowych. Nie istnieją żadne standardy dotyczące informacji zawartych w komunikacie rozgłoszeniowym CB, a każdy operator sieci komórkowej może wybrać, czy chce tego użyć, czy nie.

Ponieważ większość operatorów nie wysyła tych wiadomości, prawdopodobnie nie ma sensu inwestować w żaden czas, próbując je odbierać i dekodować. Ale jeśli chcesz spróbować, możesz zarejestrować słuchanie dla tej BroadcastReceiver: android.provider.Telephony.SMS_CB_RECEIVED. Więcej informacji na temat danych zawartych w Intent można znaleźć na stronie the documentation.

+0

Wielkie dzięki ... To jest właśnie odpowiedź, z którą walczyłem ... w 100% poprawne ... Przepraszam, nie mogłem zaakceptować odpowiedzi przed zakończeniem okresu nagród, ponieważ nie mogłem sprawdzić na koniec moment .. –

+0

Daj mi znać, jeśli masz szczęście z Cell Broadcast –

+0

OK, odpowiem po wypróbowaniu ... –

1

Według android docs korzystających LocationManager nie jest obecny Zalecanych API (patrz 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. 

Aby dowiedzieć się, jak skonfigurować bibliotekę klienta Google Services, zobacz Setup w Google Play przewodnika.

Po połączeniu biblioteki klienta Google Services do aplikacji można osiągnąć lokalizacji użytkownika za pomocą 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 
     } 

Ja testowałem powyższy kod i działa bez połączenia z Internetem, ale wymaga, aby użytkownik włączyć funkcję lokalizacji Na urządzeniu. Ponadto wymaga, aby użytkownik włączył już funkcję Historii lokalizacji do funkcji lokalizacji.

Mam nadzieję, że to ci pomoże.

+0

Dzięki stary, przetestuję to. –

+0

co to jest mLocationProviderApi? Jak widzę zmienna mLocationProviderApi nie jest zainicjalizowana. I pls wymieniają listę importów. –

+0

Przepraszam, mój błąd. Poprawiłem kod, proszę spojrzeć. Kiedy po raz pierwszy zaimplementowałem kod, tworzę instancję instancji 'FusedLocationProviderApi', którą nazwałem ** mLocationProviderApi **, ale dowiedziałem się, że mogę uzyskać dostęp do referencji' FusedLocationProviderApi' bezpośrednio z 'LocationServices.FusedLocationApi'. –

1

Problem polega na tym, że kod, który wypróbowałeś, działa, prawdopodobnie nie tak dobrze, jak chciałeś. Na przykład dokładność takiej metody zapewnia, że ​​Samsung Galaxy S3 ma 2000 m, co oznacza, że ​​rzeczywista pozycja znajduje się w dowolnym miejscu w promieniu 2 km. Dodatkowo prawdopodobnie trzeba by było sporo zmienić lokalizację, zanim aplikacja zostanie poinformowana o zmianie lokalizacji, ponieważ margines błędu jest tak duży.

GPS lub LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY (jeśli usługa Google Play jest używana) jest wymagana, aby uzyskać względnie dobrą lokalizację. To jednak wymaga android.permission.ACCESS_FINE_LOCATION, chyba że potrzebujesz tylko dokładności na poziomie kilometrów, w przeciwnym razie to uprawnienie jest koniecznością.

Pamiętaj, że korzystając z Usług Google Play z LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY mogę uzyskać dane o lokalizacji tak dokładne jak 10m bez włączania GPS, więc to powinno spełnić Twoje wymagania.

Poniżej znajduje się pełna przykład:

AndroidManifest.xml

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

główną działalność.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()); 
     } 
    } 
} 
+0

Czy to działa dobrze bez Internetu? –

+0

Tak, możesz wyłączyć GPS i dowolne połączenie internetowe i wypróbować dla siebie – Kai

+0

, ale to nie może dać mi nazwy lokalizacji (np. Londyn). Daje to tylko szerokości i długości geograficzne. Próbowałem również używać geokodera, ale potrzebuje on internetu. –

0

spróbuj tego kodu ..

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; 
} 

}

i następna klasa jest

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; 
} 

} i to uprawnienie użytkownik podane

<!-- 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" /> 
+0

również zmieniasz swój plik XML .. w razie potrzeby.Dzięki i Pozdrawiam –

+0

Widzę to również nie podam lokalizacji NAZWA .. !!! To też daje tylko długie i długie. –

+0

Tak, tak długo. na tak długo, aby uzyskać adres –

0

Powodzenia z tym. Nazywa się geocoder. A dokładniej odwrotne geokodowanie, aby zmienić współrzędne w czytelne dla człowieka wyjście. Jestem całkiem pewien, że jeden google zapewnia usługę płatną, ale dostajesz garść za darmo. Dlatego planuj buforowanie wyników i używanie wyników z pamięci podręcznej, kiedy tylko jest to możliwe.

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?

+0

To wymaga internetu .. !!! Więc to nie jest to, co chcę –

+0

Do jakiego urządzenia podłączono wieżę? – danny117

+0

Tak. W każdy sposób nazwa obszaru znajduje się wieża .. !! –

1

Możesz spróbować uzyskać dokładność na poziomie kraju za pomocą obiektu Locale lub za pomocą usługi Telefonia. Nie jest wymagany internet ani GPS.

Uzyskiwanie kod kraju z Locale:

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

Uzyskiwanie kod kraju z usługi Android Telephony:

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(); 

Lepsze próbki kodu i dyskusja here.

+1

Ale potrzebuję dokładności na poziomie miasta. –

Powiązane problemy