Cómo usar el GPS en Android


¿Cómo usar el GPS para obtener información de ubicación en Android? Una pequeña demostración es la siguiente

Introducción al GPS

El Sistema de Posicionamiento Global, Sistema de Posicionamiento Global, es un sistema de posicionamiento de navegación por radio de alta precisión basado en satélites terrestres artificiales desarrollados por los Estados Unidos en la década de 1970. Puede proporcionar una ubicación geográfica precisa en cualquier parte del mundo y en el espacio cercano a la Tierra, la velocidad del vehículo y información de tiempo precisa; es una nueva generación de sistema de posicionamiento y navegación por satélite con funciones de posicionamiento y navegación tridimensional en tiempo real en mar, tierra y aire.

El sistema de posicionamiento utilizado en China es Beidou Navigation Satellite System, o BDS para abreviar.BDS, GPS, GLONASS de Rusia y GALILEO de la Unión Europea son proveedores aprobados por la Comisión de Navegación por Satélite de las Naciones Unidas.

La función de posicionamiento de los teléfonos móviles es ampliamente utilizada.En este capítulo, aprenderemos el desarrollo de aplicaciones de GPS.

API comunes para GPS

El sistema GPS consta de tres partes, la parte del espacio satelital, la parte de monitoreo en tierra y la parte del equipo del usuario.

Para la máquina Android, es la parte del equipo de usuario y el receptor del sistema de posicionamiento GPS, es decir, el posicionamiento GPS requiere hardware para soportar la función GPS. Para los desarrolladores de Android, las aplicaciones de GPS se pueden desarrollar a través de algunos métodos de las tres API, LocationManager, LocationProvider y Location.

El objeto LocationManger del programa no se puede crear directamente, sino que se debe obtener a través del método Context.getSystemService

LocationManager locationManager= (LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> allProviders = locationManager.getAllProviders();

Al preguntar a chatGPT, se resuelve dicho formulario. El método y la función de LocationManger son los siguientes:

nombre del método

valor devuelto

efecto

getLastKnownLocation(proveedor de cadena)

Ubicación

Obtenga la información de ubicación más reciente del proveedor especificado

requestLocationUpdates (proveedor de cadenas, minTime largo, minDistance flotante, oyente LocationListener)

vacío

Registre un detector de ubicación para obtener actualizaciones de ubicación del proveedor. Los parámetros minTime y minDistance representan el intervalo de tiempo mínimo y el intervalo de distancia mínima de actualización de ubicación, respectivamente.

removeUpdates (escucha LocationListener)

vacío

Anular el registro del oyente de ubicación

isProviderEnabled (proveedor de cadena)

booleano

Determinar si el proveedor especificado está disponible

addProximityAlert(doble latitud, doble longitud, radio de flotación, caducidad larga, intención de PendingIntent)

vacío

Registre una "geocerca" que active una intención cuando el dispositivo ingrese a un área circular con un radio específico

removeProximityAlert(PendingIntent intent)

vacío

Cancelación del registro de "geocerca"

Al usar LocationManager, debe solicitar los permisos apropiados, como los permisos ACCESS_FINE_LOCATION o ACCESS_COARSE_LOCATION.

Otra API es LocationProvider, que no es una clase en Android, sino una clase abstracta en el sistema Android, que define la interfaz estándar del proveedor de ubicación y su clase de implementación se usa para proporcionar información de ubicación. La clase de implementación de LocationProvider se puede obtener a través del servicio del sistema LocationManager. Cuando una aplicación solicita obtener información de ubicación, LocationManager seleccionará un proveedor de ubicación apropiado para obtener información de ubicación y seleccionará diferentes proveedores de ubicación según las diferentes necesidades.

nombre del método

valor devuelto

efecto

obtenerNombre()

Cadena

Obtener el nombre del proveedor de ubicación (providerubicación)

obtenerPrecisión()

En t

Obtenga la precisión de este proveedor de ubicación

getPowerRequirement()

En t

Obtener el consumo de batería de este proveedor de ubicación

tieneCoste Monetario()

booleano

Determinar si el proveedor de ubicación debe pagar una tarifa

requiere celda()

booleano

Determinar si el proveedor de ubicación necesita usar la red móvil

requiere Red()

booleano

Determinar si el proveedor de ubicación necesita usar la red de datos

requiereSatélite()

booleano

Determinar si el proveedor de ubicación necesita usar satélites

apoyaAltitud()

booleano

Determinar si el proveedor de ubicación admite información de altitud

apoyaRodamiento()

booleano

Determinar si el proveedor de ubicación admite información de dirección

soportaVelocidad()

booleano

Determinar si el proveedor de ubicación admite información de velocidad

Otra API es Location, que es una clase utilizada para representar información de ubicación en Android, que incluye información de ubicación como longitud, latitud, altitud, velocidad y dirección. LocationProvider proporciona el objeto Location, y LocationManager es responsable de obtener la información de ubicación proporcionada por LocationProvider, encapsularla en un objeto Location y luego proporcionarla a la aplicación. Métodos de la siguiente manera:

nombre del método

valor devuelto

efecto

obtenerLatitud()

doble

Obtener la latitud de la ubicación

obtenerLongitud()

doble

Obtener la longitud de la ubicación

getAltitude()

doble

Obtener la altitud de la ubicación

obtenerPrecisión()

flotar

Obtener la precisión de esta posición

obtenerRumbo()

flotar

Obtener indicaciones para llegar a esta ubicación

obtenerVelocidad()

flotar

Obtener la velocidad en esta posición

consigue tiempo()

largo

Obtener la marca de tiempo de la información de ubicación

tiene precisión ()

booleano

Determinar si la información de ubicación contiene información de precisión

tieneAltitud()

booleano

Determinar si la información de ubicación contiene información de altitud

tiene rodamiento()

booleano

Determinar si la información de ubicación contiene información de dirección

tieneVelocidad()

booleano

Determinar si la información de posición contiene información de velocidad

Cabe señalar que puede aparecer un valor nulo al obtener el objeto Ubicación, por lo que es necesario hacer un juicio no nulo antes de usar el objeto Ubicación. Además, obtener información de ubicación requiere solicitar los permisos apropiados, como los permisos ACCESS_FINE_LOCATION o ACCESS_COARSE_LOCATION.

Las tres API anteriores son las tres API principales compatibles con el posicionamiento GPS de Android. Los pasos a utilizar son los siguientes:

1 Obtenga el objeto LocationManger del sistema.

2 使用LocationManger,通过指定的locationProvider来获取定位信息,定位信息由Location表示。

3 从Location对象中获取定位信息。

locationProvider

写一个简单的demo来获取当前系统所有的locationProvider

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    private ListView listView;
    private LocationManager locationManager;

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

        listView = findViewById(R.id.list);
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        //获取所有的locationProvider名称
        List<String> allProviders = locationManager.getAllProviders();
        ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1,allProviders);
        listView.setAdapter(adapter);
    }
}

在真机上运行可以看到该系统上有如下四个LocationProvider

移动端通常通过WIFI、GPS、基站这三种方式来定位设备。

以下这四种provider分别来介绍一下

    public static final String NETWORK_PROVIDER = "network";
    public static final String GPS_PROVIDER = "gps";
    public static final String PASSIVE_PROVIDER = "passive";
    public static final String FUSED_PROVIDER = "fused";

NETWORK_PROVIDER:通过移动网络的基站或者 Wi-Fi 来获取地理位置;优点:只要有网络,就可以快速定位,室内室外都可;缺点:精确度不高;

GPS_PROVIDER:通过 GPS 来获取地理位置的经纬度信息;优点:获取地理位置信息精确度高;缺点:只能在户外使用,获取经纬度信息耗时,耗电;

PASSIVE_PROVIDER:被动接收更新地理位置信息,而不用自己请求地理位置信息。

PASSIVE_PROVIDER 返回的位置是通过其他 providers 产生的,可以查询 getProvider() 方法决定位置更新的由来,需要 ACCESS_FINE_LOCATION 权限,但是如果未启用 GPS,则此 provider 可能只返回粗略位置匹配;

FUSED_PROVIDER:已经被废弃了

通过名称获取指定的locationProvider

LocationProvider provider = locationManager.getProvider(LocationManager.GPS_PROVIDER);

使用GPS获取位置信息

代码如下:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    private LocationManager locationManager;
    private TextView showInfo;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        showInfo = findViewById(R.id.show_location);
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},0x123);
    }

    private void updateView(Location location) {
        if (location != null) {
            Log.d(TAG, "updateView: 222");
            String res = "实时位置:\n" +
                    "经度:" + location.getLongitude() +
                    "\n纬度:" + location.getLatitude() +
                    "\n高度:" + location.getAltitude() +
                    "\n速度:" + location.getSpeed()
                    + "\n方向:" + location.getBearing();
            showInfo.setText(res);
        } else {
            Log.d(TAG, "updateView: 111");
            showInfo.setText("");
        }
    }
    @SuppressLint("MissingPermission")
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 0x123 && grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //创建locationManger对象
            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            //获取最新的定位信息
            Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            updateView(lastKnownLocation);
            //每隔三秒获取一次GPS信息
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 8f, new LocationListener() {
                @Override
                public void onLocationChanged(@NonNull Location location) {
                    updateView(location);
                }
            });
        }
    }
}

这里代码也很简单,我布局文件只写了一个textView来展示经纬度信息,首先在onCreate方法里动态申请权限。在Android6.0以上不仅仅要在声明文件里静态注册,还有动态申请,否则会出现安全异常。然后就是一个更新UI的方法,通过传入的location获取经纬度高度等信息。选择完获取权限后,会执行onRequestPermissionsResult回调函数,然后就是获取定位信息更新UI。

最后需要在声明文件里静态注册权限。

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

我获取到的是北京市内某地区的经纬度,把该程序和地图功能结合,就能反映出该经纬度在地图上的具体位置,即可开发出GPS导航系统。

室内WIFI定位

室内WIFI定位主要根据WIFI路由器所在的位置进行定位,主要应用于室内较小的空间的精准定位。

Android 9 添加了WiFi 室内定义功能(RTT),以下内容来自 developer.android.com

Android 9 添加了对 IEEE 802.11mc Wi-Fi 协议(也称为 Wi-Fi Round-Trip-Time (RTT))的平台支持,从而让您的应用可以利用室内定位功能。
在运行 Android 9 且具有硬件支持的设备上,应用可以使用 RTT API 来测量与附近支持 RTT 的 Wi-Fi 接入点 (AP) 的距离。 设备必须已启用位置服务并开启 Wi-Fi 扫描(在 Settings > Location 下),同时您的应用必须具有 ACCESS_FINE_LOCATION 权限。

设备无需连接到接入点即可使用 RTT。 为了保护隐私,只有手机可以确定与接入点的距离;接入点无此信息。

如果您的设备测量与 3 个或更多接入点的距离,您可以使用一个多点定位算法来预估与这些测量值最相符的设备位置。 结果通常精准至 1 至 2 米。

室内WIFI定位的管理器是WifiRttManager,获取方式如下,由于在Android9后才增加该功能,所以需要先判断。

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
    WifiRttManager wifiRttManager= (WifiRttManager) getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
}

获取到wifirttmanger对象后,可以用startRanging开始定位,该方法里有三个参数。

startRanging(@NonNull RangingRequest request, @NonNull Executor executor, @NonNull RangingResultCallback callback)

RangingRequest:该参数代表一个定位请求,该参数管理本次定位是基于哪个WIFI节点进行访问的

Executor:创建一个新的线程来执行WIFI定位,避免阻塞UI线程。

RangingResultCallback:定位成功或失败的时候触发该对象内的特定方法

写一个具体的案例来实现室内WIFI定位,代码如下:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    WifiRttManager mWifiRttManager;

    //定义监听WIFI状态改变的BroadcastReceiver
    public class WIfiChangeReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
                //开始执行wifi定位
                startWifiLoc();
            }
        }

    }


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

        //定义一个监听网络状态的改变 WIFI状态改变的intentFilter
        IntentFilter wifiFilter = new IntentFilter();
        wifiFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        wifiFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        wifiFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
        registerReceiver(new WIfiChangeReceiver(), wifiFilter);
    }

    @SuppressLint("MissingPermission")
    private void startWifiLoc() {
        //获取wifi管理器
        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        //判断是否支持室内wifi定位功能
        boolean hasRtt = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
        Log.d(TAG, "startWifiLoc: 是否具有室内WIFI定位功能:" + hasRtt);
        //Android版本大于9才能使用
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            //获取室内WiFi定位管理器
            mWifiRttManager = (WifiRttManager) getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
            RangingRequest request = new RangingRequest.Builder()
                    .addAccessPoints(wifiManager.getScanResults())//添加WiFi扫描结果
                    .build();//创建RangingRequest对象
            Log.d(TAG, "startWifiLoc: request:"+request);
            //开始请求执行室内WIFI定位
            mWifiRttManager.startRanging(request, Executors.newCachedThreadPool(), new RangingResultCallback() {
                @Override
                public void onRangingFailure(int i) {
                    //WIFI定位出错执行的方法
                    Log.d(TAG, "onRangingFailure:错误码是: "+i);
                }

                @Override
                public void onRangingResults(@NonNull List<RangingResult> list) {
                    //室内WiFi定位返回结果时触发
                    for (RangingResult rr : list){
                        Log.d(TAG, "onRangingResults:与 "+rr.getMacAddress()+" WIFI的距离是:"+rr.getDistanceMm());
                    }
                }
            });
        }
    }

}

运行后报错了

 查询了一下原因是我设备硬件不支持WIFIRTT功能。

总结WIFI定位的步骤:

1 获取WifiRttManger对象

2 通过RangingRequest.Builder来创建对象,创建之前应该先添加WiFi扫描得到WiFi访问点的信息

3 调用WifiRttManger对象的startRanging方法

近距离警报

之前学习的API方法中有一个函数:

addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent)

代码:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    private LocationManager locationManager;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0x123);

    }


    @SuppressLint("MissingPermission")
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 0x123 && grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            //定义靠近点的经纬度信息
            double lon = 116.00;
            double lat = 46.00;
            float radius = 500F; //定义半径500M
            Intent intent = new Intent(this, ProxAlertReciever.class);
            //将intent封装成pendingIntent
            PendingIntent pendingIntent = PendingIntent.getBroadcast(this, -1, intent, 0);
            //添加临近警告
            locationManager.addProximityAlert(lat, lon, radius, -1, pendingIntent);
        }
    }
}

注册一个广播监听变化:

public class ProxAlertReciever extends BroadcastReceiver {
    private static final String TAG = "ProxAlertReciever";

    @Override
    public void onReceive(Context context, Intent intent) {
       boolean isEnter= intent.getBooleanExtra(LocationManager.KEY_PROXIMITY_ENTERING,false);
       if (isEnter){
           //靠近提示
           Log.d(TAG, "onReceive: 快靠近了!!");
       }else {
           Log.d(TAG, "onReceive: 离开了!!");
       }
    }
}

至此 Android中的GPS的就讲完了,想开发出具体的导航系统还要结合地图功能。

Supongo que te gusta

Origin blog.csdn.net/m0_56366502/article/details/130512358
Recomendado
Clasificación