简体   繁体   English

在不使用gps或互联网的情况下获取用户的当前位置名称,但在android中使用Network_Provider

[英]Get current location name of user without using gps or internet but by using Network_Provider in android

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. 这个问题与“ Android:在不使用gps或互联网时获取用户的当前位置 ”相同的主流stackoverflow问题直接相关,其中接受的答案实际上没有回答问题。

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. 我应该能够通过网络提供商而不是GPS或互联网获取设备的当前位置名称(例如:城市名称,村庄名称)。 Following is the accepted answer in that question. 以下是该问题的公认答案。 (The following code parts should be included in the onCreate() method) (以下代码部分应包含在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);

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. 有人能帮帮我吗。

What you are referring to here (showing location name on older phones) is done using "Cell Broadcast" (or "CB"). 你在这里指的是什么(在旧手机上显示位置名称)是使用“小区广播”(或“CB”)完成的。 This has absolutely nothing to do with the Location API or any variations on that. 这与Location API或其任何变体完全无关。

Cell towers can send out broadcast information that can be received by devices (something like "one to many SMS"). 小区塔可以发送可以由设备接收的广播信息(诸如“一对多SMS”之类的东西)。 Some operators have used Cell Broadcast to broadcast the name of the location where the cell tower is. 一些运营商使用Cell Broadcast来广播蜂窝塔所在位置的名称。 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. 一些运营商使用Cell Broadcast发送广告代码。 There are no standards for the information contained in a CB broadcast message and each mobile operator can choose to use this or not. CB广播消息中包含的信息没有标准,每个移动运营商都可以选择是否使用。

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 . 但是如果你想尝试,你可以注册一个BroadcastReceiver监听这个Intent动作: android.provider.Telephony.SMS_CB_RECEIVED See the documentation for more details about what data is contained in the Intent . 有关Intent包含哪些数据的更多详细信息,请参阅文档

According to android docs using LocationManager is not the current recomended API (see reference ): 根据Android文档使用LocationManager不是当前推荐的API(参见参考资料 ):

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. 要了解如何设置的谷歌服务客户端库,请参阅安装在谷歌Play服务指南。

Once you have linked Google Services client library to your app you can achieve user location using FusedLocationProviderApi : 将Google服务客户端库链接到应用后,您可以使用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. 希望这对你有所帮助。

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. 例如,三星Galaxy S3上提供的这种方法的准确度是2000m,这意味着实际位置是在2公里半径范围内的任何位置。 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. 需要GPS或LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY (如果使用Google Play服务)才能获得相当不错的位置。 This does require android.permission.ACCESS_FINE_LOCATION , however unless you only require km level accuracy, otherwise this permission is a must. 这确实需要android.permission.ACCESS_FINE_LOCATION ,但是除非你只需要km级精度,否则这个权限是必须的。

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. 最后请注意,使用带有LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY Google Play服务,我可以在打开GPS的情况下获得精确到10米的位置数据,因此这仍然可以满足您的要求。

Below is a complete example: 以下是一个完整的例子:

AndroidManifest.xml AndroidManifest.xml中

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

MainActivity.java 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());
        }
    }
}

You can try getting a country level accuracy using the Locale object or using the Telephony service. 您可以尝试使用Locale对象或使用Telephony服务获得国家/地区级别的准确性。 No internet or GPS required. 无需互联网或GPS。

Getting country code from Locale: 从Locale获取国家/地区代码:

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

Getting country code from Android's Telephony service: 从Android的电话服务获取国家/地区代码:

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 . 更好的代码示例和讨论在这里

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 并且给出了此用户权限

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

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 https://developer.android.com/training/location/display-address.html

How to get city name from latitude and longitude coordinates in Google Maps? 如何从谷歌地图中的纬度和经度坐标获取城市名称?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM