本模块讲述的是自动获取当前位置,并获取当前天气
思路:1.获取到当前位置;2.根据当前位置去获取天气
第一步:获取到当前位置
我这里用的是高德地图react-native-smart-amap-location这个组件获取当前位置
具体操作:
Android部分:
需要用到两个组件,
安装:
npm install react-native-smart-amap-location --save
npm install react-native-smart-app-event-listener-enhance --save
配置:
1.在 android\settings.gradle 中添加
include ':react-native-smart-amap-location' project(':react-native-smart-amap-location').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-smart-amap-location/android')
2.在 android\app\build.gradle 中
dependencies { compile project(':react-native-smart-amap-location')//添加此行 }
3.在 MainApplication.java 中 添加
import com.reactnativecomponent.amaplocation.RCTAMapLocationPackage;//添加此行
.............
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( .......... new RCTAMapLocationPackage(),//添加此行 ....... ); }
4.在 AndroidManifest.xml 中添加权限
<!--*************************高德地图-定位所需要权限*************************--> <!-- Normal Permissions 不需要运行时注册 --> <!--用于访问wifi网络信息,wifi信息会用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!--这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位--> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> <!-- 请求网络 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 不是SDK需要的权限,是示例中的后台唤醒定位需要的权限 --> <!--<uses-permission android:name="android.permission.WAKE_LOCK" />--> <!-- 需要运行时注册的权限 --> <!--用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!--用于访问GPS定位--> <uses-permission android:name="android.permission.ACCESS_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!--用于提高GPS定位速度--> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <!--写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!--读取缓存数据--> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!--用于读取手机当前的状态--> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 更改设置 --> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!--*************************高德地图-定位所需要权限*************************-->
并 在 application 中添加如下代码,并把从 高德地图API申请的key 填写到下面value处
<application 。。。。。。。。 "> <!-- 高德地图 --> <meta-data android:name="com.amap.api.v2.apikey" android:value="从高德地图API申请的key"/> <service android:name="com.amap.api.location.APSService" > </service>
</application>
可能出现的错误:
1.No resource found that matches the given name: attr 'android:keyboardNavigationCluster'
解决方法:
到相应组件的 android\bulid.gradle 中 ,改为26 及 26.0.1
compileSdkVersion 26 buildToolsVersion "26.0.1"
和 依赖也改为 26.0.1
dependencies { compile 'com.android.support:appcompat-v7:26.0.1' }
2.在运行中可能出现一个在 node_modules\react-native-smart-amap-location\android\src\main\java\com\reactnativecomponent\amaplocation\RCTAMapLocationPackage.java 中 第22行 @Override 的错误,
此时需要将 这个方法删掉即可
例子代码:
import React, { Component } from 'react'; import { View, TextInput, Keyboard, Text, KeyboardAvoidingView, Image, StyleSheet, NetInfo, Platform, Alert, ImageBackground, ScrollView, DeviceEventEmitter, TouchableOpacity, StatusBar, NativeAppEventEmitter, ProgressBarAndroid, ActivityIndicator, Dimensions } from 'react-native'; import { InputItem, Button, WingBlank, Toast, Checkbox, Modal } from 'antd-mobile-rn'; import AMapLocation from 'react-native-smart-amap-location'; import AppEventListenerEnhance from 'react-native-smart-app-event-listener-enhance' const duration = 20000; //fetch扩展,加入超时功能. const fetchPlus = (url, config) => { let fetch_promise = fetch(url, config); let time_promise = new Promise((resolve, reject) => { setTimeout(() => { reject(new Error('请求超时')); }, duration); }); return Promise.race([fetch_promise, time_promise]); } const width = Dimensions.get('window').width; class Test extends Component { static navigationOptions = ({navigation,screenProps}) => ({ // 这里面的属性和App.js的navigationOptions是一样的。 header : null }); constructor(props) { super(props); this.state = { addLoading:true, weaLoading:true, address:'', weather:'', }; } async show(district){ console.log("地区;",district); try{ let url = `http://wthrcdn.etouch.cn/weather_mini?city=${district}`; let response = await fetchPlus(url); let result = await response.json(); console.log("singleGetList result:",result); debugger; this.setState({ weather:result, weaLoading:false, }) return result; }catch (e){ Toast.info('发生未知错误') this.setState({ weaLoading:false, }) } } componentDidMount() { AMapLocation.init(null); this._showReGeocode(); this.addAppEventListener( NativeAppEventEmitter.addListener('amap.location.onLocationResult', this._onLocationResult) ) } componentWillUnmount () { //停止并销毁定位服务 AMapLocation.cleanUp() } //单次定位并返回逆地理编码信息 _showReGeocode = () => { console.log("bbbbbbbbb"); this.setState({ loading: true, }) AMapLocation.getReGeocode() } _onLocationResult = (result) => { this.setState({ addLoading:false, }) if(result.error) { Alert.alert(`错误代码: ${result.error.code}, 错误信息: ${result.error.localizedDescription}`) } else { if(result.formattedAddress) { console.log("地址:"+result.city+"-"+result.district); let r =''; if(result.district){ r= this.show(result.district); }else{ r= this.show(result.city); } this.setState({ address:result, addLoading:false, }) } else { Alert.alert(`纬度 = ${result.coordinate.latitude}, 经度 = ${result.coordinate.longitude}`) } } } showWeather(item,key){ console.log("aaa") if(key!==0){ return( <View key = {key}> <View style={{ width:width, justifyContent:'space-between', flexDirection:'row', alignItems:'center', height:40, paddingLeft:10, paddingRight:10, }}> <Text style={{fontSize:13}}>{item.date}</Text> <Text style={{fontSize:13}}>{item.type}</Text> <Text style={{fontSize:13}}>{item.high.split(' ')[1]+' / '+item.low.split(' ')[1]}</Text> </View> <View style={{height:1,width:width,backgroundColor:'#F5F5F5'}}/> </View> ) } } render() { let address = this.state.address; let weather = this.state.weather; debugger return ( <ScrollView style={{flex:1,backgroundColor:'#FFFFFF'}}> <View style={{flex:1}}> { this.state.addLoading? <View sytle={{flex:1,justifyContent:'center',alignItems:'center',}}> <ActivityIndicator size="large"/> <Text>定位中......</Text> </View> : <View sytle={{flex:1,justifyContent:'center',alignItems:'center',}}> <Text style={{fontSize:30,color:'#333333'}}>{address!==''&&(address.city+"-"+address.district)}</Text> </View> } </View> <View sytle={{flex:6}}> { !this.state.weaLoading? <View> <View style={{height:80,justifyContent:'center',alignItems:'center'}}> <Text style={{fontSize:45,color:'#333333'}}>{weather!==''&&weather.data.wendu+' ℃'}</Text> </View> <View style={{height:40,justifyContent:'center',alignItems:'center'}}> <Text style={{fontSize:30,color:'#333333'}}>{weather!==''&&weather.data.forecast[0].type}</Text> </View> <View style={{height:40,justifyContent:'center',alignItems:'center'}}> <Text style={{fontSize:20,color:'#666666'}}>{weather!==''&&weather.data.forecast[0].high.split(' ')[1]+' / '+weather.data.forecast[0].low.split(' ')[1]}</Text> </View> <View style={{height:40,justifyContent:'center',alignItems:'center'}}> <Text style={{fontSize:15,color:'#666666'}}>{weather!==''&&weather.data.forecast[0].fengxiang+weather.data.forecast[0].fengli.split(']')[0].slice(9)}</Text> </View> <View style={{height:40,justifyContent:'center',alignItems:'center',paddingLeft:10,paddingRight:10}}> <Text style={{fontSize:13,color:'#999999'}}>{weather!==''&&weather.data.ganmao}</Text> </View> </View> : <View style={{height:240,justifyContent:'center',alignItems:'center'}} > <ActivityIndicator size="large"/> <Text>正在获取天气......</Text> </View> } </View> <View sytle={{flex:1}}> <View style={{width:width,height:1,backgroundColor:'#f5f5f5'}}/> { weather!==''&& weather.data.forecast.map((item,key)=> this.showWeather(item,key)) } </View> </ScrollView> ); } } export default AppEventListenerEnhance(Test);