1

我试图了解 Android 位置,在网上发现了很多代码,它们看起来都不同,而且它们以不同的方式处理库,这让我感到困惑。我找不到常用的方法。

基本上我需要使用GPS获取位置,如果使用GPS在90秒内没有成功检索到位置,则获取网络提供的位置。最简单的方法是什么?

我测试了以下代码段,但设备上的结果并不可靠,有时不清楚如何确保 getLastKnownLocation() 没有获取不是当前的旧存储位置。谢谢!

location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
    if (location != null) {
    gps_latitude = location.getLatitude();
    gps_longitude = location.getLongitude();
    gps_timestamp = location.getTime();
    gps_accuracy = location.getAccuracy();
    gps_provider = location.getProvider();
    gps_speed = location.getSpeed();
}
4

4 回答 4

3

尝试使用LocationCLient来获得最近已知的最佳位置。此类使用 GPS、WiFi 和传感器的组合来自动为您检测当前位置。因此不再需要在 GPS 或网络之间做出选择。

这是如何使用它的指南。

编辑:您必须使用与 API 8 兼容的Google Play Services库。

于 2013-07-18T20:40:12.510 回答
1

派对有点迟到,但认为值得为 2016 年(或以后)阅读本文的人发布更新。

正如其他答案所建议的那样,如今最好的方法是使用Google Play Services Location API。除非您确实需要对位置提供程序进行细粒度控制,否则 Google API 一定会在更短的时间内为您提供更好的位置估计,仅使用每个位置实际需要的资源(GPS、WiFi、蜂窝塔、蓝牙)用户的设备。

不幸的是,订阅位置更新仍然很麻烦(正如Matthias指出的那样,API 有点复杂)。您需要执行以下部分或全部操作:

  • 一次:请求位置许可(棉花糖及以上)
  • 连接到 API,处理不同的错误和极端情况
  • 检查并可能启用所需的位置提供程序
  • 请求位置更新

我努力在几个不同的项目中设置位置更新,并决定编写一个实用程序类来为您完成大部分工作:

LocationAssistant - Android 上的无忧位置更新

我还写了一篇关于在各种 Android 版本上设置 Android 位置的详细博客文章,您可以在此处阅读


因此,要解决您最初的问题(尽快获得具有 GPS 精度的最新位置):

public class MyActivity extends Activity implements LocationAssistant.Listener {

    private LocationAssistant assistant;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // You can specify a different accuracy and interval here, depending on the needs of your app
        assistant = new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, true);
    }

    @Override
    protected void onResume() {
        super.onResume();
        assistant.start();
    }

    @Override
    protected void onPause() {
        assistant.stop();
        super.onPause();
    }

    @Override
    public void onNewLocationAvailable(Location location) {
        // Do something with the location
    }

    ...
}

onNewLocationAvailable()在第一个有效位置可用时立即调用。您需要实现更多的侦听器方法来处理未授予权限或关闭位置提供程序的情况。但本质上就是这样。

LocationAssistant还允许您可靠地拒绝模拟位置(如果这是您的应用程序的要求)。

于 2016-06-05T12:07:50.323 回答
0

使用下面的代码。它对我来说很好。它为我提供了 gps 和网络上的位置

package com.fudiyo.LocationTracker;

import android.app.Dialog;
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;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;

import com.fudiyo.R;

public class GPSLocationNetwork 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
    public LocationManager locationManager;

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

    @SuppressWarnings("static-access")
    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(mContext.LOCATION_SERVICE);

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

            // getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            //
            if (!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) {
                    this.canGetLocation = true;
                    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(GPSLocationNetwork.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() {



        final Dialog gpsDialog = new Dialog(mContext);
        gpsDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

        gpsDialog.setContentView(R.layout.gps_enable_dialog);
        gpsDialog.setCancelable(true);

        Button gpsSettingBtn = (Button) gpsDialog
                .findViewById(R.id.btn_setting_gps_dialog);
        Button gpsCancelBtn = (Button) gpsDialog
                .findViewById(R.id.btn_cancel_gps_dialog);

        gpsSettingBtn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {


                gpsDialog.dismiss();
                Intent intent = new Intent(
                        Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });

        gpsCancelBtn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                gpsDialog.dismiss();
            }
        });

        gpsDialog.show();
    }

    @Override
    public void onLocationChanged(Location location) {
        this.location = location;
        getLatitude();
        getLongitude();
    }

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

}
于 2015-12-03T14:54:32.697 回答
0

你确定你需要如此努力地优先考虑 GPS 位置吗?对 GPS 提供商提出硬性要求有几个缺点:

  1. 您必须使用最旧的 API,因为这是唯一可以显式强制检索的修复“类型”的 API。(“位置管理器”)

  2. 从用户体验的角度来看,它通常要差得多,因为获得 GPS 定位需要更长的时间,它在室内无法工作等。

  3. 较新的 API 有很多漂亮的逻辑,可以权衡电池寿命、速度、准确性等。

当然,我对您的申请一无所知,只是提示您考虑一下您的真正要求是什么。

“新” api 还有其他好处,这是我在大约 18 个月前切换到我们的应用程序时第一手发现的:

它更快更可靠。它的错误更少。例如,在旧 API 中,我们有时可以得到一个带有新时间戳的“旧”修复。这再也不会发生了。还有更多,但这将是一个更长的帖子。它肯定会消耗更少的电池。例如,当您打开地图视图时,GPS 一直在运行,并且 GPS 图标可见。新的情况并非如此。这让用户想知道发生了什么。这不再是一个大问题。因此,当涉及到位置输出和工作时,一切都会更好。但也有一些缺点:

您必须安装 Google Play 服务,这意味着它不适用于任何“未经谷歌批准”的手机型号,在某些情况下,您必须告诉用户他们需要安装它。

API 本身是更复杂的 IMO,部分原因是第 1 点。除了“常规”回调,即等待位置修复等。您现在有一个参与的过程,然后才能开始,您必须检查播放服务可用,并“连接”locationclient。这是额外的代码,掌握起来有点复杂。代码中还要考虑更多错误条件(如果您可能会被打扰......)

Google Play 服务本身至少需要 2.2,因此它不适用于比这更旧的设备。我们不得不告诉一些客户他们必须升级......

希望这可以帮助!

于 2015-11-04T17:00:28.583 回答