二、编写代码
1. 获取当前所在位置信息
先修改activity_main.xml文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!--显示详细定位信息--> <TextView android:id="@+id/tv_address_detail" android:padding="20dp" android:gravity="center" android:textColor="#000" android:textSize="18sp" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello World!" /> </LinearLayout>
① 绑定控件
然后进入到MainActivity.java
鼠标右键点击布局文件activity_main 选择Generate
现在就可以用这个插件,点击红色边框中的Generate ButterKnife Iniertions
然后Confirm提交即可
② Android版本判断
之前提到Android6.0之后有运行时权限这么一说,所以要先判断是什么版本。在这之前先写一个Toast工具类。
新建了一个utils包用于存放工具类。
工具类代码如下:
package com.llw.goodweather.utils; import android.content.Context; import android.widget.Toast; /** * 消息提示工具类 */ public class ToastUtils { public static void showLongToast(Context context, CharSequence llw) { Toast.makeText(context.getApplicationContext(), llw, Toast.LENGTH_LONG).show(); } public static void showShortToast(Context context, CharSequence llw) { Toast.makeText(context.getApplicationContext(), llw, Toast.LENGTH_SHORT).show(); } }
然后在代码中做版本业务逻辑的判断。
//权限判断 private void permissionVersion(){ if(Build.VERSION.SDK_INT >= 23){//6.0或6.0以上 //动态权限申请 }else {//6.0以下 //发现只要权限在AndroidManifest.xml中注册过,均会认为该权限granted 提示一下即可 ToastUtils.showShortToast(this,"你的版本在Android6.0以下,不需要动态申请权限。"); } }
之后在onCreate方法中调用
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); permissionVersion();//权限判断 }
③ 权限申请
private RxPermissions rxPermissions;//权限请求框架
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); rxPermissions = new RxPermissions(this);//实例化这个权限请求框架,否则会报错 permissionVersion();//权限判断 }
//动态权限申请 private void permissionsRequest() { rxPermissions.request(Manifest.permission.ACCESS_FINE_LOCATION) .subscribe(granted -> { if (granted) {//申请成功 //得到权限之后开始定位 } else {//申请失败 ToastUtils.showShortToast(this, "权限未开启"); } }); }
接下来在 permissionVersion 方法里面进行权限的申请
这个思路就相当的清晰了,一环扣一环,这样写的好处是便于理解,千万不要把什么东西都往onCreate里面塞,那样不仅增加代码阅读难度,也会提高BUG出现的频率。
④ 初始化LocationClient类
请在主线程中声明LocationClient类对象,该对象初始化需传入Context类型参数。
//定位器 public LocationClient mLocationClient = null; private MyLocationListener myListener = new MyLocationListener();
//开始定位 private void startLocation() { //声明LocationClient类 mLocationClient = new LocationClient(this); //注册监听函数 mLocationClient.registerLocationListener(myListener); LocationClientOption option = new LocationClientOption(); //如果开发者需要获得当前点的地址信息,此处必须为true option.setIsNeedAddress(true); //可选,设置是否需要最新版本的地址信息。默认不需要,即参数为false option.setNeedNewVersionRgc(true); //mLocationClient为第二步初始化过的LocationClient对象 //需将配置好的LocationClientOption对象,通过setLocOption方法传递给LocationClient对象使用 mLocationClient.setLocOption(option); //启动定位 mLocationClient.start(); }
这时,你会发现myListener会有红线报错,是因为我们没有实现这个接口,下面来实现,这个方法和onCreate是平级的,你只要是写在MainActivity的{}里面,想放那里就放那里
⑤ 实现BDAbstractLocationListener接口
/** * 定位结果返回 */ private class MyLocationListener extends BDAbstractLocationListener { @Override public void onReceiveLocation(BDLocation location) { double latitude = location.getLatitude(); //获取纬度信息 double longitude = location.getLongitude(); //获取经度信息 float radius = location.getRadius(); //获取定位精度,默认值为0.0f String coorType = location.getCoorType(); //获取经纬度坐标类型,以LocationClientOption中设置过的坐标类型为准 int errorCode = location.getLocType();//161 表示网络定位结果 //获取定位类型、定位错误返回码,具体信息可参照类参考中BDLocation类中的说明 String addr = location.getAddrStr(); //获取详细地址信息 String country = location.getCountry(); //获取国家 String province = location.getProvince(); //获取省份 String city = location.getCity(); //获取城市 String district = location.getDistrict(); //获取区县 String street = location.getStreet(); //获取街道信息 String locationDescribe = location.getLocationDescribe(); //获取位置描述信息 tvAddressDetail.setText(addr);//设置文本显示 } }
⑥ 显示定位结果
在 permissionsRequest() 方法中得到权限后调用定位方法,定位得到数据后在监听器里返回详细地址。
运行一下,请运行在自己的手机上,别使用虚拟机和模拟器(PS: 如果你运行报错了,请把你的错误信息贴出来,我好判断是什么问题)
点击 仅使用期间允许或者始终允许 之后就可以得到定位地址了。
现在位置已经拿到了,接下来就是通过这个位置来查询当天的天气了。如果你运行之后没有拿到地址,并且你已经打开了手机的定位开关和网络连接。那么此时你肯定是用模拟器或者虚拟机运行的,定位SDK中不适配模拟器和虚拟机,所以请使用真机运行。