Solve the stubborn problem of Android GPS not locating completely

Keywords: Android SDK Mobile network

You go online to search for Android location for null, there is no legal positioning problem, it is estimated that there are a lot of articles on how to solve, but finally you find it basically useless. This paper will analyze the reasons for the lack of positioning from the principle of Android positioning implementation and propose a real solution. Before we analyze it, we must first look at the positioning SDK officially provided by Android.

Default Android GPS positioning example

Get Location Manager:

mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

Select Location Provider:

There are many provider s in Android system.

GPS_PROVIDER:

This is a mobile phone with a GPS chip, which can then use satellites to get their own location information. But indoors, GPS positioning is basically useless and difficult to locate.

NETWORK_PROVIDER:

This is the use of network location, usually using the addresses of mobile base stations and WIFI nodes to roughly locate the location.

This location depends on the server, that is, the ability of the server to translate the information of base station or WIF node into location information. Because most Android phones currently do not have the official location manager Library of google installed, and the mainland network is not allowed, that is, there is no server to do this thing, naturally this method can not basically achieve positioning.

PASSIVE_PROVIDER:

Passive positioning means that when other applications update the positioning information using positioning, the system will be saved, and the application can read the message directly after receiving it. For example, if Baidu Map and Gaode Map have been installed in the system, you can get more accurate location information in your program by using them only after positioning.

Users can specify a provider directly

String provider = mLocationManager.getProvider(LocationManager.GPS_PROVIDER);

Configuration can also be provided, with the system choosing a provider closest to the user's needs based on the user's configuration

Criteria crite = new Criteria();  
crite.setAccuracy(Crite.ACCURACY_FINE); //accuracy
crite.setPowerRequirement(Crite.POWER_LOW); //Selection of Power Consumption Types
String provider = mLocationManager.getBestProvider(crite, true);

Get Location

Location location = mLocationManager.getLocation(provider);

Then you will find that the location returned is always null, and you naturally have no legal status. Then there is a lot of consultation on the Internet about why the location is null, and the same network is full of so-called solutions to this problem.

 

The so-called solution

Some people on the Internet say that location is likely to be null at first, because the program has never asked for it, just re-request the update location and register the listener to receive the updated location information.

LocationListener locationListener = new LocationListener() {
	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}
	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onLocationChanged(Location location) {
	    longitude = location.getLongitude();
	    latitude  = location.getLatitude();
	    Log.d(TAG,"Location longitude:"+ longitude +" latitude: "+ latitude );
	}
};
mLocationManager.requestLocationUpdates(serviceProvider, 10000, 1, this);

Then you find that onLocation Changed will never be invoked, and you still can't get location information.

 

Why can't you get location?

In fact, as I mentioned above, all the solutions above do not solve the fundamental problem, that is, when you develop indoors, your mobile phone can not get location information at all, you ask the system how to inform you of the location information program. So in order to solve this problem fundamentally, we need to solve the problem of location information acquisition. As mentioned earlier, only NETWORK_PROVIDER is a reliable way to locate indoors, but because of the strange network in the mainland, and most vendors will not use google's services, this way of locating is not available by default. What can we do? Easy to handle, find an alternative service provider, Baidu location information sdk can solve this problem. Its basic principle has been mentioned above, which is to collect your wifi node information and your mobile base station information to locate.

The real solution is to use Baidu location to locate SDK

SDK download:

         http://pan.baidu.com/s/1i3xGMih

Of course, you can download it on the official website, so that you can download the latest sdk.

         http://lbsyun.baidu.com/sdk/download

SDK use:

1. To apply for Baidu's service key, see the official website for the specific operation steps:

       http://api.map.baidu.com/lbsapi/cloud/geosdk.htm

2. Copy the above downloaded sdk file locSDK_4.1.jar to your project libs

3. Modify the Android Manifest file and add the following configuration to it

        

<service
	android:name="com.baidu.location.f"
	android:enabled="true"
	android:process=":remote" >
        </service>
        <meta-data
	android:name="com.baidu.lbsapi.API_KEY"
	android:value="xxxxx " />
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Change the value in meta-data above to your own key

Call sdk in the code:

public class LocationUtil {
	private final static boolean DEBUG = true;
	private final static String TAG = "LocationUtil";
	private static LocationUtil mInstance;
	private BDLocation mLocation = null;
	private MLocation  mBaseLocation = new MLocation();

	public static LocationUtil getInstance(Context context) {
		if (mInstance == null) {
			mInstance = new LocationUtil(context);
		}
		return mInstance;
	}

	Context mContext;
	String mProvider;
	public BDLocationListener myListener = new MyLocationListener();
	private LocationClient mLocationClient;
	
	public LocationUtil(Context context) {
	    mLocationClient = new LocationClient(context.getApplicationContext());
		initParams();
		mLocationClient.registerLocationListener(myListener);
	}

	public void startMonitor() {
		if (DEBUG) Log.d(TAG, "start monitor location");
		if (!mLocationClient.isStarted()) {
			mLocationClient.start();
		}
		if (mLocationClient != null && mLocationClient.isStarted()) {
			mLocationClient.requestLocation();
		} else {
			 Log.d("LocSDK3", "locClient is null or not started");
		}
	}

	public void stopMonitor() {
		if (DEBUG) Log.d(TAG, "stop monitor location");
		if (mLocationClient != null && mLocationClient.isStarted()) {
			mLocationClient.stop();
		}
	}
	
	public BDLocation getLocation() {
		if (DEBUG) Log.d(TAG, "get location");
		return mLocation;
	}
	
	public MLocation getBaseLocation() {
		if (DEBUG) Log.d(TAG, "get location");
		return mBaseLocation;
	}
	
	private void initParams() {
		LocationClientOption option = new LocationClientOption();
		option.setOpenGps(true);
		//option.setPriority(LocationClientOption.NetWorkFirst);
		option.setAddrType("all");//The location result returned contains address information
		option.setCoorType("bd09ll");//The location result returned is Baidu longitude and latitude, default value gcj02
		option.setScanSpan(5000);//Set the interval for initiating location requests to 5000ms
		option.disableCache(true);//Disable Cache Location
		option.setPoiNumber(5);    //Maximum number of POI s returned   
		option.setPoiDistance(1000); //poi query distance        
		option.setPoiExtraInfo(true); //Do you need POI phone and address details?        
		mLocationClient.setLocOption(option);
	}


	public class MyLocationListener implements BDLocationListener {
		@Override
		public void onReceiveLocation(BDLocation location) {
			if (location == null) {
				return ;
			}
			mLocation = location;
			mBaseLocation.latitude = mLocation.getLatitude();
			mBaseLocation.longitude = mLocation.getLongitude();
			
			StringBuffer sb = new StringBuffer(256);
			sb.append("time : ");
			sb.append(location.getTime());
			sb.append("\nerror code : ");
			sb.append(location.getLocType());
			sb.append("\nlatitude : ");
			sb.append(location.getLatitude());
			sb.append("\nlontitude : ");
			sb.append(location.getLongitude());
			sb.append("\nradius : ");
			sb.append(location.getRadius());
			sb.append("\ncity : ");
			sb.append(location.getCity());
			if (location.getLocType() == BDLocation.TypeGpsLocation){
				sb.append("\nspeed : ");
				sb.append(location.getSpeed());
				sb.append("\nsatellite : ");
				sb.append(location.getSatelliteNumber());
			} else if (location.getLocType() == BDLocation.TypeNetWorkLocation){
				sb.append("\naddr : ");
				sb.append(location.getAddrStr());
			}
			if (DEBUG) Log.d(TAG, "" + sb);
		}

		public void onReceivePoi(BDLocation poiLocation) {
		}
	}
	
	public class MLocation {
		public double latitude;
		public double longitude;
	}
}

Of course, don't forget to turn on the gps positioning in setting s

Posted by meir4u on Sat, 30 Mar 2019 20:24:28 -0700