赞
踩
在不使用第三方地图SDK的情况下,也可以借助Android
本身的 location api 来实现获取地理位置相关信息功能,官方介绍见这里(需要翻墙):https://developer.android.com/reference/android/location/LocationManager
废话不多说,先看最终效果图:
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))) {
Toast.makeText(this, "请打开网络或GPS定位功能!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, 0);
return;
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 100);
} else {
initLocation();
}
回调函数处理
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { // 相机权限 case 100: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //用户点击了同意授权 initLocation(); } else { //用户拒绝了授权 Toast.makeText(MainActivity.this, "权限被拒绝", Toast.LENGTH_SHORT).show(); } break; } }
优先获取gps定位结果,没有的话再获取网络定位结果,并添加2个listener
long minSecond = 2 * 1000;
long minDistance = 2;
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location == null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
updateLocation(location);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minSecond, minDistance, listener);//LocationManager.GPS_PROVIDER
mGPSStatusImpl = new GPSStatusImpl();
locationManager.addGpsStatusListener(mGPSStatusImpl);
public final LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location location) { updateLocation(location); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { switch (status) { // GPS状态为可见时 case LocationProvider.AVAILABLE: Log.i("xml", "当前GPS状态为可见状态"); break; // GPS状态为服务区外时 case LocationProvider.OUT_OF_SERVICE: Log.i("xml", "当前GPS状态为服务区外状态"); break; // GPS状态为暂停服务时 case LocationProvider.TEMPORARILY_UNAVAILABLE: Log.i("xml", "当前GPS状态为暂停服务状态"); break; } } @Override public void onProviderEnabled(String provider) { @SuppressLint("MissingPermission") Location location = locationManager.getLastKnownLocation(provider); updateLocation(location); } @Override public void onProviderDisabled(String provider) { } };
在requestLocationUpdates方法后add监听器,在onDestroy或者onStop方法中remove该监听器
private class GPSStatusImpl implements GpsStatus.Listener { @Override public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_FIRST_FIX: //第一次定位 break; case GpsStatus.GPS_EVENT_SATELLITE_STATUS: //卫星状态改变 { //获取当前状态 @SuppressLint("MissingPermission") GpsStatus gpsStatus = locationManager.getGpsStatus(null); //获取卫星颗数的默认最大值 int maxSatellites = gpsStatus.getMaxSatellites(); //创建一个迭代器保存所有卫星 Iterator<GpsSatellite> iters = gpsStatus.getSatellites().iterator(); int count = 0; while (iters.hasNext() && count <= maxSatellites) { GpsSatellite s = iters.next(); // 只有信噪比不为0时才算合格的卫星 if (s.getSnr() != 0) { count++; } } stars = count; SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String curTime = dateFormat.format(new Date()); System.out.println(curTime + "-----卫星数量nun----" + stars); textView2.setText("实时卫星数量:" + stars); break; } case GpsStatus.GPS_EVENT_STARTED: //定位启动 break; case GpsStatus.GPS_EVENT_STOPPED: //定位结束 break; } } }
关键核心代码,把结果展示在textview并写入本地文件中
private void updateLocation(Location location) { String result; double lat; double lon; if (location != null) { lat = location.getLatitude(); lon = location.getLongitude(); if (location.hasSpeed()) { speed = location.getSpeed() * 3.6; } else { if( lastLocation != null) { speed = getMySpeed(lastLocation, location); } } result = "纬度:" + lat + "\n经度:" + lon + "\n速度:" + String.format("%.2f", speed) + " km/h\n卫星数量:" + stars; Log.i("xml", "显示结果 = " + result); lastLocation = location; } else { result = "无法获取经纬度信息"; } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat dateFormatDate = new SimpleDateFormat("yyyyMMdd"); String curTime = dateFormat.format(new Date()); String curDate = dateFormatDate.format(new Date()); // 把结果展示在界面上 textView.setText(curTime + "\n" + result); // 把结果写入文件 Utils.writeFileAppend(Utils.BASE_PROJECT_IMAGE_PATH + "log_" + curDate + ".txt", curTime + "\n" + result.replace("\n", " ")); }
使用LocationManager需要注意以下几个点:
(1)在开启网络定位的前提下,经过测试,如果只根据时间来定位的话,发现允许的最短时间是20秒,代码中设置低于这个时间的话,还是会以20秒作为定位间隔,与此同时,最小距离还必须设置为0,如果非0的话监听器就无法再被回调来获取网络定位经纬度。
(2)获取卫星数量时(简称搜星),尽量要在户外空旷的地方,同时搜星一般比较慢,而且代码中要实现GpsStatus.Listener接口,不然数量可能为0,同时要添加信噪比判断,不然容易获取较多的卫星数量
(3)在Manifest添加了相关权限并且代码中已经做了运行时权限处理代码,主要是以下两个权限:
Manifest.permission.ACCESS_COARSE_LOCATION
Manifest.permission.ACCESS_FINE_LOCATION
如果requestLocationUpdates这个方法还是报红的话,那么只有添加注解来解决了
@SuppressLint("MissingPermission")
(4)在获取gps速度的时候,getSpeed方法要乘以3.6,这是为了把单位米每秒转换成千米每小时
(5)由于网络定位误差较大,建议只开启GPS定位,当hasSpeed为false的时候,使用两个经纬度之差和时间之差来获取实时速度
下载地址见这里,https://download.csdn.net/download/diyangxia/11219445
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。