📜  Android-基于位置的服务

📅  最后修改于: 2021-01-05 05:00:58             🧑  作者: Mango


Android位置API使您可以轻松构建支持位置的应用程序,而无需关注基础定位技术的细节。

借助Google Play服务,这将成为可能,该服务可通过自动的位置跟踪,地理围栏和活动识别功能,为您的应用添加位置感知功能。

本教程向您展示如何在APP中使用定位服务来获取当前位置,获取定期的位置更新,查找地址等。

位置对象

Location对象代表一个地理位置,可以由纬度,经度,时间戳和其他信息(例如方位,高度和速度)组成。您可以将以下重要方法与Location对象一起使用,以获取特定于位置的信息-

Sr.No. Method & Description
1

float distanceTo(Location dest)

Returns the approximate distance in meters between this location and the given location.

2

float getAccuracy()

Get the estimated accuracy of this location, in meters.

3

double getAltitude()

Get the altitude if available, in meters above sea level.

4

float getBearing()

Get the bearing, in degrees.

5

double getLatitude()

Get the latitude, in degrees.

6

double getLongitude()

Get the longitude, in degrees.

7

float getSpeed()

Get the speed if it is available, in meters/second over ground.

8

boolean hasAccuracy()

True if this location has an accuracy.

9

boolean hasAltitude()

True if this location has an altitude.

10

boolean hasBearing()

True if this location has a bearing.

11

boolean hasSpeed()

True if this location has a speed.

12

void reset()

Clears the contents of the location.

13

void setAccuracy(float accuracy)

Set the estimated accuracy of this location, meters.

14

void setAltitude(double altitude)

Set the altitude, in meters above sea level.

15

void setBearing(float bearing)

Set the bearing, in degrees.

16

void setLatitude(double latitude)

Set the latitude, in degrees.

17

void setLongitude(double longitude)

Set the longitude, in degrees.

18

void setSpeed(float speed)

Set the speed, in meters/second over ground.

19

String toString()

Returns a string containing a concise, human-readable description of this object.

获取当前位置

要获取当前位置,请创建一个位置客户端(即LocationClient对象),使用connect()方法将其连接到Location Services,然后调用其getLastLocation()方法。此方法以Location对象的形式返回最近的位置,该对象包含纬度和经度坐标以及其他信息,如上所述。要在您的活动中具有基于位置的功能,您将必须实现两个接口-

  • GooglePlayServicesClient.ConnectionCallbacks
  • GooglePlayServicesClient.OnConnectionFailedListener

这些接口提供以下重要的回调方法,您需要在活动类中实现它们-

Sr.No. Callback Methods & Description
1

abstract void onConnected(Bundle connectionHint)

This callback method is called when location service is connected to the location client successfully. You will use connect() method to connect to the location client.

2

abstract void onDisconnected()

This callback method is called when the client is disconnected. You will use disconnect() method to disconnect from the location client.

3

abstract void onConnectionFailed(ConnectionResult result)

This callback method is called when there was an error connecting the client to the service.

您应该在活动类的onCreate()方法中创建位置客户端,然后在onStart()中将其连接,以便位置服务在您的活动完全可见时维护当前位置。您应该使用onStop()方法断开客户端的连接,这样当您的应用程序不可见时,Location Services不会维护当前位置。这样可以最大程度地节省电池电量。

获取更新的位置

如果您愿意进行位置更新,那么除了上面提到的接口之外,您还需要实现LocationListener接口。该接口提供以下回调方法,您需要在活动类中实现该方法:

Sr.No. Callback Method & Description
1

abstract void onLocationChanged(Location location)

This callback method is used for receiving notifications from the LocationClient when the location has changed.

位置服务质量

所述LocationRequest对象用于请求的服务质量(QoS),用于从LocationClient位置更新一个质量。您可以使用以下有用的设置方法来处理QoS。您可以在Android官方文档中查看等效的getter方法。

Sr.No. Method & Description
1

setExpirationDuration(long millis)

Set the duration of this request, in milliseconds.

2

setExpirationTime(long millis)

Set the request expiration time, in millisecond since boot.

3

setFastestInterval(long millis)

Explicitly set the fastest interval for location updates, in milliseconds.

4

setInterval(long millis)

Set the desired interval for active location updates, in milliseconds.

5

setNumUpdates(int numUpdates)

Set the number of location updates.

6

setPriority(int priority)

Set the priority of the request.

现在,例如,如果您的应用程序需要高精度位置,则应创建一个位置请求,将setPriority(int)设置为PRIORITY_HIGH_ACCURACY并将setInterval(long)设置为5秒。您也可以使用更大的间隔和/或其他优先级(例如PRIORITY_LOW_POWER)来请求“城市”级别的准确性,或者使用PRIORITY_BALANCED_POWER_ACCURACY来获取“阻止”级别的准确性。

活动应该强烈考虑在进入后台时删除所有位置请求(例如,在onPause()处),或者至少将请求交换为较大的间隔和较低的质量以节省功耗。

显示位置地址

一旦有了Location对象,就可以使用Geocoder.getFromLocation()方法来获取给定纬度和经度的地址。此方法是同步的,可能需要很长时间才能完成工作,因此您应该从AsyncTask类的doInBackground()方法中调用该方法。

必须使用AsyncTask的子类,并且子类将重写doInBackground(Params …)方法以在后台执行任务,并且在后台计算完成后(此时要执行以下操作)在UI线程上调用onPostExecute(Result)方法。显示结果。 AyncTask中还有一个更重要的方法execute(Params … params) ,该方法使用指定的参数执行任务。

以下示例以实用方式向您展示了如何在应用中使用定位服务来获取当前位置及其等效地址等。

要试验此示例,您将需要配备最新的Android OS的实际移动设备,否则,您将不得不使用可能无法正常工作的仿真器。

创建Android应用程序

Step Description
1 You will use Android studio IDE to create an Android application and name it as Tutorialspoint under a package com.example.tutorialspoint7.myapplication.
2 add src/GPSTracker.java file and add required code.
3 Modify src/MainActivity.java file and add required code as shown below to take care of getting current location and its equivalent address.
4 Modify layout XML file res/layout/activity_main.xml to add all GUI components which include three buttons and two text views to show location/address.
5 Modify res/values/strings.xml to define required constant values
6 Modify AndroidManifest.xml as shown below
7 Run the application to launch Android emulator and verify the result of the changes done in the application.

以下是修改后的主要活动文件MainActivity.java的内容

package com.example.tutorialspoint7.myapplication;

import android.Manifest;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.test.mock.MockPackageManager;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

   Button btnShowLocation;
   private static final int REQUEST_CODE_PERMISSION = 2;
   String mPermission = Manifest.permission.ACCESS_FINE_LOCATION;

   // GPSTracker class
   GPSTracker gps;

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
        
      try {
         if (ActivityCompat.checkSelfPermission(this, mPermission)
            != MockPackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this, new String[]{mPermission}, 
               REQUEST_CODE_PERMISSION);

            // If any permission above not allowed by user, this condition will
               execute every time, else your else part will work
         }
      } catch (Exception e) {
         e.printStackTrace();
      }

      btnShowLocation = (Button) findViewById(R.id.button);

      // show location button click event
      btnShowLocation.setOnClickListener(new View.OnClickListener() {

         @Override
         public void onClick(View arg0) {
            // create class object
            gps = new GPSTracker(MainActivity.this);

            // check if GPS enabled
            if(gps.canGetLocation()){

               double latitude = gps.getLatitude();
               double longitude = gps.getLongitude();

               // \n is for new line
               Toast.makeText(getApplicationContext(), "Your Location is - \nLat: "
                  + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
            }else{
               // can't get location
               // GPS or Network is not enabled
               // Ask user to enable GPS/network in settings
               gps.showSettingsAlert();
            }

         }
      });
   }
}

以下是修改后的主要活动文件GPSTracker.java的内容

package com.example.tutorialspoint7.myapplication;

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;

public class GPSTracker extends Service implements LocationListener {

   private final Context mContext;

   // flag for GPS status
   boolean isGPSEnabled = false;

   // flag for network status
   boolean isNetworkEnabled = false;

   // flag for GPS status
   boolean canGetLocation = false;

   Location location; // location
   double latitude; // latitude
   double longitude; // longitude

   // The minimum distance to change Updates in meters
   private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

   // The minimum time between updates in milliseconds
   private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

   // Declaring a Location Manager
   protected LocationManager locationManager;

   public GPSTracker(Context context) {
      this.mContext = context;
      getLocation();
   }

   public Location getLocation() {
      try {
         locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);

         // getting GPS status
         isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

         // getting network status
         isNetworkEnabled = locationManager
            .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

         if (!isGPSEnabled && !isNetworkEnabled) {
            // no network provider is enabled
         } else {
            this.canGetLocation = true;
            // First get location from Network Provider
            if (isNetworkEnabled) {
               locationManager.requestLocationUpdates(
                  LocationManager.NETWORK_PROVIDER,
                  MIN_TIME_BW_UPDATES,
                  MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        
               Log.d("Network", "Network");
               if (locationManager != null) {
                  location = locationManager
                     .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                            
                  if (location != null) {
                     latitude = location.getLatitude();
                     longitude = location.getLongitude();
                  }
               }
            }
                
            // if GPS Enabled get lat/long using GPS Services
            if (isGPSEnabled) {
               if (location == null) {
                  locationManager.requestLocationUpdates(
                     LocationManager.GPS_PROVIDER,
                     MIN_TIME_BW_UPDATES,
                     MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                            
                  Log.d("GPS Enabled", "GPS Enabled");
                  if (locationManager != null) {
                     location = locationManager
                        .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                                
                     if (location != null) {
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                     }
                  }
               }
            }
         }

      } catch (Exception e) {
         e.printStackTrace();
      }

      return location;
   }

   /**
      * Stop using GPS listener
      * Calling this function will stop using GPS in your app
   * */
    
   public void stopUsingGPS(){
      if(locationManager != null){
         locationManager.removeUpdates(GPSTracker.this);
      }
   }

   /**
      * Function to get latitude
   * */
    
   public double getLatitude(){
      if(location != null){
         latitude = location.getLatitude();
      }

      // return latitude
      return latitude;
   }

   /**
      * Function to get longitude
   * */
    
   public double getLongitude(){
      if(location != null){
         longitude = location.getLongitude();
      }

      // return longitude
      return longitude;
   }

   /**
      * Function to check GPS/wifi enabled
      * @return boolean
   * */
    
   public boolean canGetLocation() {
      return this.canGetLocation;
   }

   /**
      * Function to show settings alert dialog
      * On pressing Settings button will lauch Settings Options
   * */
    
   public void showSettingsAlert(){
      AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

      // Setting Dialog Title
      alertDialog.setTitle("GPS is settings");

      // Setting Dialog Message
      alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

      // On pressing Settings button
      alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
         public void onClick(DialogInterface dialog,int which) {
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            mContext.startActivity(intent);
         }
      });

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

      // Showing Alert Message
      alertDialog.show();
   }

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

以下是res / layout / activity_main.xml文件的内容-





   


下面将RES /值的内容/字符串.XML定义两个新常量-



   Tutorialspoint

以下是AndroidManifest.xml的默认内容-



   
   
   
        
      
         
            

            
         
      
   


让我们尝试运行您的Tutorialspoint应用程序。我假设您已将实际的Android Mobile设备与计算机连接。要从Android Studio运行该应用,请打开您项目的活动文件之一,然后点击运行Eclipse运行图标工具栏中的图标。在启动应用程序之前,Android Studio安装程序将显示以下窗口,以选择要在其中运行Android应用程序的选项。

Android行动装置

现在要查看位置,请选择“获取位置”按钮,它将显示位置信息,如下所示:

Android移动位置信息