Android Location API跟踪您当前的位置

本教程介绍了如何使用Android Location API开发一个应用程序,以编程方式获取和显示用户的当前位置。内容涉及LocationListener接口、LocationManager类,以及如何通过GPS_PROVIDER和NETWORK_PROVIDER获取位置更新。示例代码展示了如何实现定位服务,包括请求运行时权限、处理位置变化以及在模拟器中模拟GPS位置。
摘要由CSDN通过智能技术生成

Android Location API can be used to track your mobile current location and show in the app. In this tutorial, we’ll develop an application that fetches the user’s current location programmatically.

Android Location API可用于跟踪您的移动设备当前位置并在应用程序中显示。 在本教程中,我们将开发一个应用程序,该程序以编程方式获取用户的当前位置。

Android Location API (Android Location API)

There are two ways to get a users location in our application:

有两种方法可以在应用程序中获取用户位置:

  • android.location.LocationListener : This is a part of the Android API.

    android.location.LocationListener :这是Android API的一部分。
  • com.google.android.gms.location.LocationListener : This is present in the Google Play Services API. (We’ll look into this in the next tutorial)

    com.google.android.gms.location.LocationListener :它存在于Google Play服务API中。 (我们将在下一个教程中对此进行研究)

Android Location Services is available since Android API 1.
Google officially recommends using Google Play Location Service APIs. Android Location Services API is still used to develop location-based apps for devices that don’t support Google Play Services.

自Android API 1起即可使用Android定位服务。
Google正式建议使用Google Play定位服务API。 Android Location Services API仍用于为不支持Google Play服务的设备开发基于位置的应用。

LocationListener (LocationListener)

The LocationListener interface, which is part of the Android Locations API is used for receiving notifications from the LocationManager when the location has changed. The LocationManager class provides access to the systems location services.

LocationListener接口是Android Locations API的一部分,用于在位置更改后从LocationManager接收通知。 LocationManager类提供对系统位置服务的访问。

The LocationListener class needs to implement the following methods.

LocationListener类需要实现以下方法。

  • onLocationChanged(Location location) : Called when the location has changed.

    onLocationChanged(位置位置) :位置更改时调用。
  • onProviderDisabled(String provider) : Called when the provider is disabled by the user.

    onProviderDisabled(String provider) :当用户禁用提供程序时调用。
  • onProviderEnabled(String provider) : Called when the provider is enabled by the user.

    onProviderEnabled(String provider) :当用户启用了提供程序时调用。
  • onStatusChanged(String provider, int status, Bundle extras) : Called when the provider status changes.

    onStatusChanged(String provider,int status,Bundle extras) :当提供者状态更改时调用。

The android.location has two means of acquiring location data:

android.location有两种获取位置数据的方法:

  • LocationManager.GPS_PROVIDER: Determines location using satellites. Depending on the conditions, this provider may take a while to return a location fix

    LocationManager.GPS_PROVIDER :使用卫星确定位置。 根据条件,此提供商可能需要一段时间才能返回位置信息
  • LocationManager.NETWORK_PROVIDER: Determines location based on the availability of nearby cell towers and WiFi access points. This is faster than GPS_PROVIDER

    LocationManager.NETWORK_PROVIDER :根据附近的手机信号塔和WiFi接入点的可用性来确定位置。 这比GPS_PROVIDER快

In this tutorial, we’ll create a Service that implements the LocationListener class to receive periodic location updates via GPS Providers or Network Providers.

在本教程中,我们将创建一个服务,该服务实现LocationListener类,以通过GPS提供商或网络提供商定期接收位置更新。

Android Location API项目结构 (Android Location API Project Structure)

The project consists of a MainActivity.java class which displays a Get Location and a LocationTrack.java Service class.

该项目包含一个MainActivity.java类,该类显示一个Get Location和一个LocationTrack.java Service类。

Android Location APICode ( Android Location APICode)

The activity_main.xml layout is defined below.

下面定义了activity_main.xml布局。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.journaldev.gpslocationtracking.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn"
        android:layout_centerInParent="true"
        android:text="GET LOCATION" />
</RelativeLayout>

The MainActivity.java class is defined below.

MainActivity.java类在下面定义。

package com.journaldev.gpslocationtracking;

import android.annotation.TargetApi;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.util.ArrayList;

import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;

public class MainActivity extends AppCompatActivity {


    private ArrayList permissionsToRequest;
    private ArrayList permissionsRejected = new ArrayList();
    private ArrayList permissions = new ArrayList();

    private final static int ALL_PERMISSIONS_RESULT = 101;
    LocationTrack locationTrack;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        permissions.add(ACCESS_FINE_LOCATION);
        permissions.add(ACCESS_COARSE_LOCATION);

        permissionsToRequest = findUnAskedPermissions(permissions);
        //get the permissions we have asked for before but are not granted..
        //we will store this in a global list to access later.


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


            if (permissionsToRequest.size() > 0)
                requestPermissions(permissionsToRequest.toArray(new String[permissionsToRequest.size()]), ALL_PERMISSIONS_RESULT);
        }


        Button btn = (Button) findViewById(R.id.btn);


        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                locationTrack = new LocationTrack(MainActivity.this);


                if (locationTrack.canGetLocation()) {


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

                    Toast.makeText(getApplicationContext(), "Longitude:" + Double.toString(longitude) + "\nLatitude:" + Double.toString(latitude), Toast.LENGTH_SHORT).show();
                } else {

                    locationTrack.showSettingsAlert();
                }

            }
        });

    }


    private ArrayList findUnAskedPermissions(ArrayList wanted) {
        ArrayList result = new ArrayList();

        for (String perm : wanted) {
            if (!hasPermission(perm)) {
                result.add(perm);
            }
        }

        return result;
    }

    private boolean hasPermission(String permission) {
        if (canMakeSmores()) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                return (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
            }
        }
        return true;
    }

    private boolean canMakeSmores() {
        return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
    }


    @TargetApi(Build.VERSION_CODES.M)
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

        switch (requestCode) {

            case ALL_PERMISSIONS_RESULT:
                for (String perms : permissionsToRequest) {
                    if (!hasPermission(perms)) {
                        permissionsRejected.add(perms);
                    } 
                }

                if (permissionsRejected.size() > 0) {


                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {
                            showMessageOKCancel("These permissions are mandatory for the application. Please allow access.",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                requestPermissions(permissionsRejected.toArray(new String[permissionsRejected.size()]), ALL_PERMISSIONS_RESULT);
                                            }
                                        }
                                    });
                            return;
                        }
                    }

                }

                break;
        }

    }

    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(MainActivity.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        locationTrack.stopListener();
    }
}

In the above code, we’re implementing runtime permissions that are used in Android 6.0+ devices.
We’ve added the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in the AndroidManifest.xml file.
Clicking the button invokes the LocationTrack.java service class. If the location returned is NULL in the case of GPS Provider, we call the showSettingsAlert() method from the LocationTrack.java class that we’ll be seeing shortly. When the activity is destroyed stopLocationTrack() method is called to turn off the location updates.

在上面的代码中,我们正在实现Android 6.0+设备中使用的运行时权限。
我们已经在AndroidManifest.xml文件中添加了ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION权限。
单击按钮将调用LocationTrack.java服务类。 如果在GPS Provider的情况下返回的位置为NULL, showSettingsAlert()不久将要看到的LocationTrack.java类中调用showSettingsAlert()方法。 活动销毁后,将调用stopLocationTrack()方法关闭位置更新。

The LocationTrack.java class is defined below.

LocationTrack.java类在下面定义。

public class LocationTrack extends Service implements LocationListener {

    private final Context mContext;


    boolean checkGPS = false;


    boolean checkNetwork = false;

    boolean canGetLocation = false;

    Location loc;
    double latitude;
    double longitude;


    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;


    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
    protected LocationManager locationManager;

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

    private Location getLocation() {

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

            // get GPS status
            checkGPS = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // get network provider status
            checkNetwork = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!checkGPS && !checkNetwork) {
                Toast.makeText(mContext, "No Service Provider is available", Toast.LENGTH_SHORT).show();
            } else {
                this.canGetLocation = true;

                // if GPS Enabled get lat/long using GPS Services
                if (checkGPS) {

                    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                    }
                    locationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    if (locationManager != null) {
                        loc = locationManager
                                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        if (loc != null) {
                            latitude = loc.getLatitude();
                            longitude = loc.getLongitude();
                        }
                    }


                }


                /*if (checkNetwork) {


                    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                    }
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    if (locationManager != null) {
                        loc = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                    }

                    if (loc != null) {
                        latitude = loc.getLatitude();
                        longitude = loc.getLongitude();
                    }
                }*/

            }


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

        return loc;
    }

    public double getLongitude() {
        if (loc != null) {
            longitude = loc.getLongitude();
        }
        return longitude;
    }

    public double getLatitude() {
        if (loc != null) {
            latitude = loc.getLatitude();
        }
        return latitude;
    }

    public boolean canGetLocation() {
        return this.canGetLocation;
    }

    public void showSettingsAlert() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);


        alertDialog.setTitle("GPS is not Enabled!");

        alertDialog.setMessage("Do you want to turn on GPS?");


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


        alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });


        alertDialog.show();
    }


    public void stopListener() {
        if (locationManager != null) {

            if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            locationManager.removeUpdates(LocationTrack.this);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) {

    }

    @Override
    public void onProviderEnabled(String s) {

    }

    @Override
    public void onProviderDisabled(String s) {

    }
}

Few inferences drawn from the above code are:

从以上代码得出的推论很少是:

  • In the above code isProviderEnabled(String provider) is called upon the locationManager object and is used to check whether GPS/Network Provider is enabled or not.

    在上面的代码中,对locationManager对象调用了isProviderEnabled(String provider) ,用于检查是否启用了GPS / Network Provider。
  • If the Providers aren’t enabled we’re calling the method showSettingsAlert() that shows a prompt to enable GPS.

    如果未启用提供者,我们将调用showSettingsAlert()方法,该方法显示启用GPS的提示。
  • requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) method of the LocationManager class is used to register the current activity to be notified periodically by the named provider.

    LocationManager类的requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)方法用于注册要由命名提供者定期通知的当前活动。
  • onLocationChanged is invoked periodically based upon the minTime and minDistance, whichever comes first.

    onLocationChanged调用定期于minTime和minDistance才会,以先到者为准为主。
  • Location class hosts the latitude and longitude.
    To get the current location the following code snippet is used.
    Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

    On the above Location object, getters are called to store the double values of latitude and longitude. These double values are then disabled as a Toast message on the screen.

    位置类别主持纬度和经度。
    要获取当前位置,请使用以下代码段。

    在上面的Location对象上,调用getter来存储纬度和经度的双精度值。 然后,将这些双精度值作为Toa​​st消息在屏幕上禁用。

  • To stop location updates removeUpdates method is called on the LocationManager instance.

    要停止位置更新,请在LocationManager实例上调用removeUpdates方法。

The output of the above application in action on an emulator is:

android location api, android location tracking

在模拟器上运行的上述应用程序的输出为:

Our emulators can’t fetch locations, hence it’s returning 0.0 for lat/lng. You can connect your smartphone and run the application in debug mode to check your current location.
To emulate GPS Locations in an emulator we can pass fixed Latitude and Longitude values from Android Studio. Besides the emulator window, you can see a list of options. The one at the bottom (which has three dots) is our Extended Controls options. Open that and send a dummy location. Your application should look like this:

android location manager

我们的仿真器无法提取位置,因此纬度/经度返回0.0。 您可以连接智能手机并以调试模式运行该应用程序以检查您的当前位置。
要在模拟器中模拟GPS位置,我们可以从Android Studio中传递固定的纬度和经度值。 除了模拟器窗口,您还可以看到选项列表。 底部的一个(有三个点)是我们的扩展控件选项。 打开该地址并发送一个虚拟位置。 您的应用程序应如下所示:

This brings an end to this tutorial. We’ll be implementing Location API using Google Play Services in a later tutorial. You can download the Android GPSLocationTracking Project from the link below.

本教程到此结束。 在稍后的教程中,我们将使用Google Play服务实现Location API。 您可以从下面的链接下载Android GPSLocationTracking项目

翻译自: https://www.journaldev.com/13325/android-location-api-tracking-gps

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值