Como usar o GPS no Android


Como usar o GPS para obter informações de localização no Android? Uma pequena demonstração é a seguinte

Introdução ao GPS

Sistema de Posicionamento Gobal, Sistema de Posicionamento Global, é um sistema de posicionamento de navegação por rádio de alta precisão baseado em satélites terrestres artificiais desenvolvidos pelos Estados Unidos na década de 1970. Ele pode fornecer localização geográfica precisa em qualquer lugar do mundo e espaço próximo à Terra, velocidade do veículo e informações de tempo precisas; é uma nova geração de sistema de navegação e posicionamento por satélite com navegação tridimensional em tempo real e funções de posicionamento no mar, terra e ar.

O sistema de posicionamento usado na China é o Sistema de Navegação por Satélite Beidou, ou abreviado BDS.BDS, GPS, GLONASS da Rússia e GALILEO da União Européia são fornecedores aprovados pela Comissão de Navegação por Satélite das Nações Unidas.

A função de posicionamento de telefones celulares é amplamente utilizada.Neste capítulo, aprenderemos o desenvolvimento de aplicativos de GPS.

APIs comuns para GPS

O sistema GPS consiste em três partes, a parte espacial do satélite, a parte de monitoramento terrestre e a parte do equipamento do usuário.

Para a máquina Android, é a parte do equipamento do usuário e o receptor do sistema de posicionamento GPS, ou seja, o posicionamento GPS requer hardware para suportar a função GPS. Para desenvolvedores Android, os aplicativos de GPS podem ser desenvolvidos por meio de alguns métodos das três APIs, LocationManager, LocationProvider e Location.

O objeto LocationManger do programa não pode ser criado diretamente, mas deve ser obtido através do método Context.getSystemService

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

Ao perguntar ao chatGPT, esse formulário é resolvido. O método e a função do LocationManger são os seguintes:

nome do método

valor de retorno

efeito

getLastKnownLocation(Provedor de string)

Localização

Obtenha as informações de localização mais recentes do provedor especificado

requestLocationUpdates (Provedor de string, long minTime, float minDistance, ouvinte LocationListener)

vazio

Registre um ouvinte de localização para obter atualizações de localização do provedor. Os parâmetros minTime e minDistance representam o intervalo de tempo mínimo e o intervalo de distância mínima de atualização de localização, respectivamente

removeUpdates(LocationListener listener)

vazio

Cancelar o registro do ouvinte de localização

isProviderEnabled(Fornecedor de string)

boleano

Determine se o provedor especificado está disponível

addProximityAlert(latitude dupla, longitude dupla, raio flutuante, expiração longa, intenção PendingIntent)

vazio

Registre uma "cerca geográfica" que aciona uma intenção quando o dispositivo entra em uma área circular com um raio especificado

removeProximityAlert (intenção PendingIntent)

vazio

Cancelamento do registro de "geofence"

Ao usar o LocationManager, você precisa solicitar as permissões apropriadas, como as permissões ACCESS_FINE_LOCATION ou ACCESS_COARSE_LOCATION.

Outra API é LocationProvider, que não é uma classe no Android, mas uma classe abstrata no sistema Android, que define a interface padrão do provedor de localização e sua classe de implementação é usada para fornecer informações de localização. A classe de implementação de LocationProvider pode ser obtida através do serviço de sistema LocationManager. Quando um aplicativo solicita a obtenção de informações de localização, o LocationManager seleciona um provedor de localização apropriado para obter informações de localização e seleciona diferentes provedores de localização de acordo com as diferentes necessidades.

nome do método

valor de retorno

efeito

getNome()

Corda

Obtenha o nome do provedor de localização (locationProvider)

obterPrecisão()

int

Obtenha a precisão deste provedor de localização

getPowerRequirement()

int

Obtenha o consumo de bateria deste provedor de localização

hasMonetaryCost()

boleano

Determine se o provedor de localização precisa pagar uma taxa

requerCélula()

boleano

Determine se o provedor de localização precisa usar a rede móvel

requerRede()

boleano

Determine se o provedor de localização precisa usar a rede de dados

requerSatélite()

boleano

Determine se o provedor de localização precisa usar satélites

suportaAltitude()

boleano

Determine se o provedor de localização suporta informações de altitude

suportaRolamento()

boleano

Determine se o provedor de localização suporta informações de direção

suportaVelocidade()

boleano

Determine se o provedor de localização oferece suporte a informações de velocidade

Outra API é Location, que é uma classe usada para representar informações de localização no Android, que inclui informações de localização como longitude, latitude, altitude, velocidade e direção. O objeto Location é fornecido pelo LocationProvider, e o LocationManager é responsável por obter as informações de localização fornecidas pelo LocationProvider, encapsulando-as em um objeto Location e, em seguida, fornecendo-as ao aplicativo. Métodos como abaixo:

nome do método

valor de retorno

efeito

getLatitude()

dobro

Obtenha a latitude do local

getLongitude()

dobro

Obter a longitude do local

getAltitude()

dobro

Obter a altitude do local

obterPrecisão()

flutuador

Obtenha a precisão desta posição

getBearing()

flutuador

Obter direções para este local

getSpeed()

flutuador

Obter a velocidade nesta posição

consiga tempo()

longo

Obtenha o carimbo de data/hora das informações de localização

temPrecisão()

boleano

Determine se as informações de localização contêm informações de precisão

hasAltitude()

boleano

Determine se as informações de localização contêm informações de altitude

hasbearing()

boleano

Determine se as informações de localização contêm informações de direção

hasSpeed()

boleano

Determine se as informações de posição contêm informações de velocidade

Deve-se observar que um valor nulo pode aparecer ao obter o objeto Location, portanto é necessário fazer um julgamento não nulo antes de usar o objeto Location. Além disso, a obtenção de informações de localização requer a solicitação de permissões apropriadas, como as permissões ACCESS_FINE_LOCATION ou ACCESS_COARSE_LOCATION.

As três APIs acima são as três principais APIs suportadas pelo posicionamento GPS do Android. Os passos a usar são os seguintes:

1 Obtenha o objeto LocationManger do 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的就讲完了,想开发出具体的导航系统还要结合地图功能。

Acho que você gosta

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