Introduction to this section:
Speaking of the term GPS, I believe everyone is familiar with it. GPS global positioning technology, well, there are generally four positioning methods in Android: GPS positioning, WIFI positioning, base station positioning, and AGPS positioning (base station + GPS);
This series of tutorials only explains the basic use of GPS positioning! GPS obtains the current latitude and longitude of the device by interacting with satellites. The accuracy is high, but there are also some disadvantages. The biggest disadvantage is that it is almost impossible to use indoors ... Need to receive 4 or more satellite signals to ensure accurate GPS positioning ! But if you are outdoors and there is no network, GPS can still be used!
In this section, we will discuss the basic usage of GPS in Android~
1. Some APIs related to positioning
1)LocationManager
Official API documentation: LocationManager
This thing comes from a system service and cannot be directly new. It needs:
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
In addition, don't forget to add permissions when using GPS positioning:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Ok, after getting the LocationManager object, we can call the following common methods:
- addGpsStatusListener (GpsStatus.Listener listener): Add a GPS status listener
- addProximityAlert (double latitude, double longitude, float radius, long expiration, PendingIntent intent): Add a critical warning
- getAllProviders (): Get a list of all LocationProviders
- getBestProvider (Criteria criteria, boolean enabledOnly): returns the best LocationProvider according to the specified conditions
- getGpsStatus (GpsStatus status): Get GPS status
- getLastKnownLocation (String provider): Get the last known Location according to LocationProvider
- getProvider (String name): Get the LocationProvider according to the name
- getProviders (boolean enabledOnly): Get all available LocationProviders
- getProviders (Criteria criteria, boolean enabledOnly): Get all LocationProviders that meet the conditions according to the specified conditions
- isProviderEnabled (String provider): Determine whether the LocationProvider with the specified name is available
- removeGpsStatusListener (GpsStatus.Listener listener): remove the GPS status listener
- removeProximityAlert (PendingIntent intent): removes a proximity alert
- requestLocationUpdates (long minTime, float minDistance, Criteria criteria, PendingIntent intent): periodically obtain location information through the specified LocationProvider, and start the corresponding components through Intent
- requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener): Obtain location information periodically through the specified LocationProvider, and trigger the trigger corresponding to the listener
2) LocationProvider (location provider)
Official API documentation: LocationProvider
This is an abstract representation of the GPS positioning component, and the relevant information of the positioning component can be obtained by calling the following method!
Commonly used methods are as follows:
- getAccuracy (): returns LocationProvider accuracy
- getName (): Returns the LocationProvider name
- getPowerRequirement (): Get the power requirements of LocationProvider
- hasMonetaryCost (): Returns whether the LocationProvider is charged or free
- meetsCriteria (Criteria criteria): Determine whether the LocationProvider meets the Criteria conditions
- requiresCell (): Determine whether the LocationProvider needs to access the network base station
- requiresNetwork (): Determine whether the LocationProvider needs to access network data
- requiresSatellite (): Determine whether the LocationProvider needs to access a satellite-based positioning system
- supportsAltitude (): Determine whether the LocationProvider supports height information
- supportsBearing (): Determine whether the LocationProvider supports direction information
- supportsSpeed (): Determine whether the LocationProvider supports speed information
3) Location (location information)
Official API documentation: Location
The abstract class of location information, we can call the following methods to obtain related location information!
Common methods are as follows:
- float getAccuracy (): Get the accuracy of positioning information
- double getAltitude (): Get the height of the positioning information
- float getBearing (): Obtain the direction of positioning information
- double getLatitude (): Get the latitude of the positioning information
- double getLongitude (): Get the accuracy of positioning information
- String getProvider (): Get the LocationProvider that provides the location information
- float getSpeed (): Get the speed of positioning information
- boolean hasAccuracy (): Determine whether the positioning information contains accuracy information
4) Criteria (filter conditions)
Official API documentation: Criteria
When obtaining the LocationProvider, you can set the filter conditions, which is to set the relevant conditions through this class~
Common methods are as follows:
- setAccuracy (int accuracy): Set the accuracy requirement for the pair
- setAltitudeRequired (boolean altitudeRequired): Set whether to require LocationProvider to provide altitude information
- setBearingRequired (boolean bearingRequired): Set whether to ask LocationProvider to provide direction information
- setCostAllowed (boolean costAllowed): Set whether to require LocationProvider to provide direction information
- setPowerRequirement (int level): Set the power consumption required by LocationProvider
- setSpeedRequired (boolean speedRequired): Set whether to require LocationProvider to provide speed information
2. Get an example of LocationProvider
Running effect diagram :
As can be seen from the figure, there are three currently available LocationProviders, namely:
- passive : Passively provided, provided by other programs
- gps : Obtain location information through GPS
- network : Obtain location information through the network
Implementation code :
Layout file: activity_main.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btn_one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="获得系统所有的LocationProvider" /> <Button android:id="@+id/btn_two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Get LocationProvider according to conditions" /> android:id="@+id/btn_three" <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="获取指定的LocationProvider" /> <TextView android:id="@+id/tv_result" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="10dp" android:background="#81BB4D" android:padding="5dp" android:textColor="#FFFFFF" android:textSize="20sp" android:textStyle="bold" /> </LinearLayout>
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btn_one; private Button btn_two; private Button btn_three; private TextView tv_result; private LocationManager lm; private List<String> pNames = new ArrayList<String>(); // 存放LocationProvider名称的集合 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); bindViews(); } private void bindViews() { btn_one = (Button) findViewById(R.id.btn_one); btn_two = (Button) findViewById(R.id.btn_two); btn_three = (Button) findViewById(R.id.btn_three); tv_result = (TextView) findViewById(R.id.tv_result); btn_one.setOnClickListener(this); btn_two.setOnClickListener(this); btn_three.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_one: pNames.clear(); pNames = lm.getAllProviders(); tv_result.setText(getProvider()); break; case R.id.btn_two: pNames.clear(); Criteria criteria = new Criteria(); criteria.setCostAllowed(false); //free criteria.setAltitudeRequired(true); //can provide height information criteria.setBearingRequired(true); //can provide direction information pNames = lm.getProviders( criteria, true); tv_result.setText(getProvider()); break; case R.id.btn_three: pNames.clear(); pNames.add(lm.getProvider(LocationManager.GPS_PROVIDER).getName()); //Specify Name tv_result.setText(getProvider()); break; } } //The method of traversing the array and returning the string private String getProvider(){ StringBuilder sb = new StringBuilder(); for (String s : pNames) { sb.append(s + "\n"); } return sb.toString() ; } }
3. Two ways to judge whether GPS is turned on and to turn it on
The first thing before we use GPS positioning should be to determine whether the GPS has been turned on or available, otherwise we need to turn on the GPS to complete the positioning! The case of AGPS is not considered here~
1) Determine whether GPS is available
private boolean isGpsAble(LocationManager lm){ return lm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)?true:false; }
2) Detect that the GPS is not turned on, turn on the GPS
Method 1 : Force GPS to be turned on, it is useless after Android 5.0....
//强制帮用户打开GPS 5.0以前可用 private void openGPS(Context context){ Intent gpsIntent = new Intent(); gpsIntent.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); gpsIntent.addCategory("android.intent.category.ALTERNATIVE"); gpsIntent.setData(Uri.parse("custom:3")); try { PendingIntent.getBroadcast(LocationActivity.this, 0, gpsIntent, 0).send(); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); } }
Method 2 : Open the GPS location information setting page and let the user open it by himself
//Open the location information setting page and let the user set up private void openGPS2(){ Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivityForResult(intent,0); }
4. Dynamically obtain location information
This is very simple, just call the requestLocationUpdates method to set up a LocationListener to regularly detect the location!
The sample code is as follows:
Layout: activity_location.xml :
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv_show" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="5dp" android:textSize="20sp" android:textStyle="bold" /> </LinearLayout>
LocationActivity.java:
/** * Created by Jay on 2015/11/20 0020. */ public class LocationActivity extends AppCompatActivity { private LocationManager lm; private TextView tv_show; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_location); tv_show = (TextView) findViewById(R.id.tv_show); lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); if (!isGpsAble(lm)) { Toast.makeText(LocationActivity.this, "请打开GPS~", Toast.LENGTH_SHORT).show(); openGPS2(); } //从GPS获取最近的定位信息 Location lc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER); updateShow(lc); //Set an interval of two seconds to obtain GPS location information lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 8, new LocationListener() { @Override public void onLocationChanged (Location location) { // When the GPS location information changes, update the location updateShow(location); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { // When GPS LocationProvider is available, update the location updateShow(lm.getLastKnownLocation(provider)); } @Override public void onProviderDisabled(String provider) { updateShow(null); } }); } //Define a method for updating display private void updateShow(Location location) { if (location != null) { StringBuilder sb = new StringBuilder(); sb.append("Current location information:\n"); sb.append("Accuracy: " + location.getLongitude() + "\n"); sb .append("Latitude: " + location.getLatitude() + "\n"); sb.append("Height: " + location.getAltitude() + "\n"); sb.append("Speed: " + location.getSpeed() + "\n"); sb.append("Direction: " + location.getBearing() + "\n"); sb.append("Positioning Accuracy: " + location.getAccuracy() + "\n"); tv_show.setText(sb.toString ()); } else tv_show.setText(""); } private boolean isGpsAble(LocationManager lm) { return lm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER) ? true : false; } //Open the settings page for the user Settings private void openGPS2() { Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivityForResult(intent, 0); } }
Okay, it’s very simple, because the GPS needs to be used outdoors, so I took this opportunity to trot out to the convenience store to buy a cup of milk tea, and screenshot the picture below~
requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
When the time exceeds minTime (unit: milliseconds), or the position moves beyond minDistance (unit: meters), the method in the listener will be called to update the GPS information. It is recommended that the minTime be no less than 60000, that is, 1 minute, which will be more efficient and save power , adding that you need to update the GPS in real time as much as possible, you can set minTime and minDistance to 0
By the way, don't forget, you also need a permission:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
5. Proximity warning (geofencing)
Well, it is to fix a point, and when the distance between the mobile phone and the point is less than the specified range, the corresponding processing can be triggered! Kind of like a geofence...we can call the LocationManager's addProximityAlert method to add proximity alerts! The complete method is as follows:
addProximityAlert(double latitude,double longitude,float radius,long expiration,PendingIntent intent)
Property description:
- latitude : specifies the longitude of the fixed point
- longitude : specifies the latitude of the fixed point
- radius : Specifies the radius length
- expiration : Specifies how many milliseconds after which the approach warning will expire, -1 means it will never expire
- intent : This parameter specifies the component that triggers the intent when approaching the fixed point
The sample code is as follows :
ProximityActivity.java:
/** * Created by Jay on 2015/11/21 0021. */ public class ProximityActivity extends AppCompatActivity { private LocationManager lm; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_proximity); lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); //定义固定点的经纬度 double longitude = 113.56843; double latitude = 22.374937; float radius = 10; //定义半径,米 Intent intent = new Intent(this, ProximityReceiver.class); PendingIntent pi = PendingIntent.getBroadcast(this, -1, intent, 0); lm.addProximityAlert(latitude, longitude, radius, -1, pi); } }
You also need to register a broadcast receiver: ProximityReceiver.java :
/** * Created by Jay on 2015/11/21 0021. */ public class ProximityReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { boolean isEnter = intent.getBooleanExtra( LocationManager.KEY_PROXIMITY_ ENTERING, false); if(isEnter) Toast.makeText(context, "You have arrived near Building B1 of Nanruan", Toast.LENGTH_LONG).show(); else Toast.makeText(context, "You have left near Building B1 of Nanruan", Toast. LENGTH_LONG). show(); } }
Don't forget to register:
<receiver android:name=".ProximityReceiver"/>
Running effect diagram :
PS: Well, I set 10m, but I walked from B1 to D1, it was more than 10m... and it happened to be raining