一.GPS定位:android 的三种定位方式
1.GPS定位: 需要GPS硬件支持,直接和卫星交互来获取当前经纬度。
优点:速度快、精度高、可在无网络情况下使用。
缺点:首次连接时间长、只能在户外已经开阔地使用,设备上方有遮挡物就不行了、比较耗电。
2.Network定位: 又细分为WIFI定位和基站定位
(1)基站定位:一般手机附近的三个基站进行三角定位,由于每个基站的位置是固定的,利用电磁波在这三个基站间中转所需要时间来算出手机所在的坐标
a.优点:受环境的影响情况较小,不管在室内还是人烟稀少的地方都能用,只要有基站。
b.缺点:首先需要消耗流量、其实精度没有GPS那么准确,大概在十几米到几十米之间
(2)WIFI定位:
a.优点:和基站定位一样,它的优势在于收环境影响较小,只要有Wifi的地方可以使用。
b.缺点:需要有wifi、精度不准
3.AGPS定位: AssistedGPS(辅助全球卫星定位系统),是结合GSM或GPRS与传统卫星定位
GPS常用的类:
LocationManager: 位置信息管理类。
Android为定位系统提供了LocationManager管理类。通过LocationManager和其他几个辅助类,开发人员可以方便开发出GPS应用:
LocationManager lm = getSystemService(Context.LOCATION_SERVICE);
LocationProvider: 提供定位信息的类。
LocationManager 提供了方法getAllProviders()获取所有的LocationProvider;
也可以通过名称获取指定的LocationProvider。
(1) GPS定位:通过卫星实现的
LocationProvider lProvider = locationManager.getProvider(LocationManager.GPS_PROVIDER);
(2) 网络定位:通过WI-FI 或者信号塔进行定位
LocationProvider lProvider = locationManager.getProvider(LocationManager.NETWORK_PROVIDER);
Location:位置类
double getLatitude()获取维度值
double getLongtitude()获取经度值
double getAltitude(); 获得海拔
在设备位置发生改变的时候获取到最新的位置信息。
void requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, new LocationListener{
void onLocationChanged();
}) 获取GPS定位信息。
第一个参数:位置提供器的类型。
第二个参数:监听位置变化的时间间隔,以毫秒为单位。
第三个参数:监听位置变化的距离间隔,以米为单位。
第四个参数:LocationListener 监听器。
如上,LocationManager 每隔 3 秒钟会检测一下位置的变化情况,当移动距离超过 3000米的时候,就会调用 LocationListener 的 onLocationChanged() 方法,并把新的位置信息作为参数传入。
二.GPS定位代码:
<!--用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!--用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
public class MainActivity extends AppCompatActivity {
private String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_NETWORK_STATE};
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//安卓6.0以后需要动态获取权限
checkPermisson();
//获得LocationManager
LocationManager manager = (LocationManager) getSystemService(LOCATION_SERVICE);
//判断是否得到定位的权限
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
//LocationListener->位置监听器->位置改变进入
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 0, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
//Location->封装经度纬度海拔等信息->javabean
Log.e("ZXY","海拔:"+location.getAltitude());
Log.e("ZXY","纬度:"+location.getLatitude());
Log.e("ZXY","经度:"+location.getLongitude());
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
});
}
@RequiresApi(api = Build.VERSION_CODES.M)
public void checkPermisson(){
boolean flag=true;//默认全部被申请过
for(int i=0;i<permissions.length;i++){//只要有一个没有申请成功
if(!(ActivityCompat.checkSelfPermission(this,permissions[i])== PackageManager.PERMISSION_GRANTED)){
flag=false;
}
}
if(!flag){
//动态申请权限
requestPermissions(permissions,100);
}
}
//动态申请权限的疾厄宫
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==100){
boolean flag=true;
for(int i=0;i<grantResults.length;i++){
if(grantResults[i]!=PackageManager.PERMISSION_GRANTED){
flag=false;
}
}
if(flag){
Toast.makeText(this, "ok ", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
}
}
}
}
三.使用高德地图:
添加依赖
implementation ‘com.amap.api:map2d:latest.integration’
implementation ‘com.amap.api:search:latest.integration’
//清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.day09_work1">
<!--允许程序打开网络套接字-->
<uses-permission android:name="android.permission.INTERNET" />
<!--允许程序设置内置sd卡的写权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--允许程序获取网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--允许程序访问WiFi网络信息-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许程序读写手机状态和身份-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--允许程序访问CellID或WiFi热点来获取粗略的位置-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data android:name="com.amap.api.v2.apikey" android:value="7e029f9a727587c05226dbfb5305b7bc">
</meta-data>
</application>
</manifest>
//布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<SearchView
android:id="@+id/sear"
android:layout_width="match_parent"
android:layout_height="50dp">
</SearchView>
<ListView android:layout_width="match_parent"
android:background="#98DCF8"
android:visibility="gone"
android:id="@+id/list"
android:layout_height="match_parent">
</ListView>
<com.amap.api.maps2d.MapView
android:layout_width="match_parent"
android:id="@+id/map_view"
android:layout_height="match_parent">
</com.amap.api.maps2d.MapView>
</LinearLayout>
//主类
//北京市地图 搜索网吧 将北京城有名的网吧 存入listview中,点击会直接规划路线
public class MainActivity extends AppCompatActivity {
MapView mapView;
MyLocationStyle myLocationStyle;
AMap aMap;
ListView listView;
SearchView searchView;
ArrayAdapter<PoiItem> arrayAdapter;
LatLonPoint start=new LatLonPoint(0,0);//经纬度
LatLonPoint end=new LatLonPoint(0,0);//经纬度
ArrayList<PoiItem> pois;
ArrayList<PoiItem> arrayList=new ArrayList<>();
String[] strings = new String[]{
Manifest.permission.INTERNET,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 23) {
for (int i = 0; i < strings.length; i++) {
int permission = ActivityCompat.checkSelfPermission(this, strings[i]);
if (permission == PackageManager.PERMISSION_DENIED) {
requestPermissions(strings, 101);
break;
}
}
}
listView=findViewById(R.id.list);
searchView=findViewById(R.id.sear);
mapView = findViewById(R.id.map_view);
mapView.onCreate(savedInstanceState);
arrayAdapter = new ArrayAdapter<PoiItem>(this,android.R.layout.simple_expandable_list_item_1,arrayList);
listView.setAdapter(arrayAdapter);
if (aMap == null) {
aMap = mapView.getMap();
}
landian();
// 设置该SearchView显示搜索按钮
searchView.setSubmitButtonEnabled(true);
// 设置该SearchView内默认显示的提示文本
searchView.setQueryHint("查找");
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
if (query.length()>0){
Toast.makeText(MainActivity.this, query+"", Toast.LENGTH_SHORT).show();
PoiSearch.Query querys = new PoiSearch.Query(query, "", "北京市");
querys.setPageSize(50);
querys.setPageNum(1);
PoiSearch poiSearch=new PoiSearch(MainActivity.this,querys);
poiSearch.setOnPoiSearchListener(new PoiSearch.OnPoiSearchListener() {
@Override
public void onPoiSearched(PoiResult poiResult, int i) {
if (i==1000){
pois= poiResult.getPois();
aMap.clear();
arrayList.clear();
for (int i1 = 0; i1 < pois.size(); i1++) {
arrayList.add(pois.get(i1));
}
// arrayList.clear();
for (int i2 = 0; i2 < arrayList.size(); i2++) {
Log.e("###",arrayList.get(i2).getTitle()+"");
}
Log.e("###0",arrayList.size()+"");
arrayAdapter.notifyDataSetChanged();
PoiOverlay poiOverlay = new PoiOverlay(aMap,pois);
poiOverlay.removeFromMap();
poiOverlay.addToMap();
poiOverlay.zoomToSpan();
}
}
@Override
public void onPoiItemSearched(PoiItem poiItem, int i) {
}
});
poiSearch.searchPOIAsyn();
}
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)){
arrayList.clear();
arrayAdapter.notifyDataSetChanged();
listView.setVisibility(View.GONE);
}else {
listView.setVisibility(View.VISIBLE);
}
return true;
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(final AdapterView<?> parent, View view, int position, long id) {
listView.setVisibility(View.GONE);
//TODO 1:创建RouteSearch对象
RouteSearch routeSearch = new RouteSearch(MainActivity.this);
//TODO 2:设置监听,得到结果,画出路线
routeSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
//公交录像
@Override
public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {
}
//驾驶
@Override
public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
//获得路径的集合
List<DrivePath> paths = driveRouteResult.getPaths();
//画驾驶路线
DrivingRouteOverlay drivingRouteOverlay = new DrivingRouteOverlay(
MainActivity.this, aMap, paths.get(0),
start,
end, null);
//设置节点marker是否显示:
//drivingRouteOverlay.setNodeIconVisibility(true);
//drivingRouteOverlay.setThroughPointIconVisibility(true);
drivingRouteOverlay.removeFromMap();//将之前的路径移除
drivingRouteOverlay.addToMap();//画上新的路径w
drivingRouteOverlay.zoomToSpan();//放大
}
//走路
@Override
public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {
//获得路径的集合
List<WalkPath> paths = walkRouteResult.getPaths();
//画驾驶路线
WalkRouteOverlay walkRouteOverlay = new WalkRouteOverlay(MainActivity.this,aMap,paths.get(0),start,end);
//设置节点marker是否显示:
// drivingRouteOverlay.setNodeIconVisibility(true);
// drivingRouteOverlay.setThroughPointIconVisibility(true);
walkRouteOverlay.removeFromMap();//将之前的路径移除
walkRouteOverlay.addToMap();//画上新的路径
walkRouteOverlay.zoomToSpan();//放大
}
//骑车
@Override
public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {
}
});
//TODO 3:设置参数
//当前用户的位置
double longitude = aMap.getMyLocation().getLongitude();//精度
double latitude = aMap.getMyLocation().getLatitude();//维度
start.setLongitude(longitude);
start.setLatitude(latitude);
//获得用户选择的重点
PoiItem poiItem = arrayList.get(position);
end= poiItem.getLatLonPoint();
RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(start,end);
RouteSearch.DriveRouteQuery driveRouteQuery = new RouteSearch.DriveRouteQuery(fromAndTo,0,null,null,"");
//TODO 4:计算
routeSearch.calculateDriveRouteAsyn(driveRouteQuery);
//步行
RouteSearch.WalkRouteQuery walkRouteQuery = new RouteSearch.WalkRouteQuery(fromAndTo,RouteSearch.WALK_DEFAULT);
routeSearch.calculateWalkRouteAsyn(walkRouteQuery);
}
});
}
private void landian() {
myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。
myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
//aMap.getUiSettings().setMyLocationButtonEnabled(true);设置默认定位按钮是否显示,非必需设置。
aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
四.使用高德地图获取定位数据:
添加依赖:implementation ‘com.amap.api:location:4.2.0’
public class GaodeActivity extends AppCompatActivity implements AMapLocationListener {
private TextView mLocation;
private AMapLocationClient client;//定位客户端
private AMapLocationClientOption op;//参数设置
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gaode);
mLocation = findViewById(R.id.location_Tv);
initLocation();
}
private void initLocation(){
client = new AMapLocationClient(getApplicationContext());
op = new AMapLocationClientOption();
//设置定位回调监听
client.setLocationListener(this);
//配置定位参数
op.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
// op.setOnceLocation(true);//定位一次
op.setInterval(1000);//每隔1s定位1次
op.setNeedAddress(true);//是否需要返回地点
op.setMockEnable(true);//允许虚拟定位
client.setLocationOption(op);
client.startLocation();
}
//定位结果回调进入当前方法
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
Log.e("ZXY","errorCode"+aMapLocation.getErrorCode());
Log.e("ZXY","errorInfo"+aMapLocation.getErrorInfo());
Log.e("ZXY","地址:"+aMapLocation.getAddress());
Log.e("ZXY","纬度:"+aMapLocation.getLatitude());
Log.e("ZXY","经度:"+aMapLocation.getLongitude());
mLocation.setText("定位地址:"+aMapLocation.getAddress());
}
}