判断应用的状态是在前台还是后台,以及获取应用是否联网,是wifi或流量连接等这些基本应用信息在APP开发中是十分常见的功能。今天就分别介绍AppState(获取应用状态信息),NetInfo(获取网络信息)这两个模块。
AppState
AppState可以获取当前APP是在前台还是在后台运行,并且当APP的运行状态发生改变的时会收到通知。AppState通常在处理推送通知的时候用来决定内容和对应的行为。例如,判断应用在后台时通知栏显示并通过声音和振动提醒用户。当应用在前台时直接透传消息。
AppState应用的状态
App一般存在以下三种状态:
- active - 应用正在前台运行
- background - 应用正在后台运行。此时用户既可能在使用别的应用,也可能在桌面(Home界面)。
- inactive - 此状态表示应用正在前后台的切换过程中,或是处在系统的多任务视图,又或是处在来电状态中。属于过渡状态,通常不会出现在React Native应用中,因此可暂不考虑。
AppState属性方法
currentState:TypeCastExpression
:标志当前状态类型static addEventListener(type: string, handler: Function)
:添加监听应用状态(AppState)变化的方法。参数应填type:'change'
以及处理方法。static removeEventListener(type: string, handler: Function)
:移除监听应用状态(AppState)变化的方法。参数同上。
实例
我们可以通过AppState.currentState
要获取当前的状态,这个变量会一直保持更新。不过当App在启动的过程中,currentState可能为null,直到AppState从原生代码得到通知更新为止。
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
AppState, } from 'react-native';
export default class AppStateDemo extends Component {
constructor(props) {
super(props);
this.state = {
currentAppState: AppState.currentState,
};
}
componentDidMount() {
AppState.addEventListener('change', this._handleAppStateChange);
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (appState) => {
console.log('当前状态为:'+appState);
if (this.state.currentAppState.match(/inactive|background/) && appState === 'active') {
console.log('App has come to the foreground!')
}
this.setState({currentAppState: appState});
}
render() {
return (
<Text>Current state is: {this.state.currentAppState}</Text>
);
}
}
运行结果如下:
该实例只会显示”Current state is: active”,这是因为应用只有在active状态下才能被用户看到。并且null状态只会在一开始的一瞬间出现。如果想看到当应用在后台时的状态,可以通过log日志查看。
NetInfo
NetInfo可以获知设备联网/离线的网络状态信息。由于iOS与Android本身的平台差异,导致其获取的网络状态信息有所不同。
iOS
在iOS平台上,NetInfo通过异步方式去检测设备是否联网还是连接移动数据网络。可能的网络状态值为:
- none - 设备处于离线状态。
- wifi - 设备处于联网状态且通过wifi连接,或者当前设备是一个iOS的模拟器。
- cell - 设备是通过Edge、3G、WiMax或是LTE网络联网的。
- unknown - 发生错误,网络状况不可知。
Android
请求网络信息需要先在应用的AndroidManifest.xml文件中添加如下权限字段:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
其也是通过异步方法来检测设备是否联网以及连接的网络的细节信息。
Android的联网类型:
- NONE - 设备处于离线状态
- BLUETOOTH - 蓝牙数据连接
- DUMMY - 模拟数据连接
- ETHERNET - 以太网数据连接
- MOBILE - 移动网络数据连接
- MOBILE_DUN - 拨号移动网络数据连接
- MOBILE_HIPRI - 高优先级移动网络数据连接
- MOBILE_MMS - 彩信移动网络数据连接
- MOBILE_SUPL - 安全用户面定位(SUPL)数据连接
- VPN - 虚拟网络连接。需要Android5.0以上
- WIFI - WIFI数据连接
- WIMAX - WiMAX数据连接
- UNKNOWN - 未知数据连接
其他的连接状态已被Android API隐藏,但可以在需要时使用。
NetInfo属性方法
isConnected: ObjectExpression
:当前网络是否连接的属性,此属性为一个对象。static addEventListener(eventName, handler)
:在网络状况/类型发生变化时调用此监听函数。回调的参数为上面列出的网络状况/类型。static removeEventListener(eventName, handler)
:移除网络状况/类型变化的监听函数。static fetch()
:返回一个promise,用于获取当前的网络状况/类型。static isConnectionExpensive()
:检测当前连接的网络是否需要计费,该方法只适合Android平台。例如当用户连接的是移动数据网络,那么会判断成该网络是需要计费的。具体判断代码如下:
NetInfo.isConnectionExpensive((isConnectionExpensive) => {
console.log('Connection is ' + (isConnectionExpensive ? 'Expensive' : 'Not Expensive'));
});
实例
下面用实例演示一下NetInfo的实际使用。在写之前千万不要忘记Android项目中的权限配置,在android/app/src/AndroidManifest.xml中加入:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
下例演示了NetInfo基本用法,检测当前设备的网络连接状态,网络详细信息以及是否计费:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
NetInfo, } from 'react-native';
export default class NetInfoDemo extends Component {
constructor(props){
super(props);
this.state = {
isConnected: null,
connectionInfo:null,
};
}
componentDidMount() {
NetInfo.isConnected.addEventListener(
'change',
this._handleConnectivityChange
);
//检测网络是否连接
NetInfo.isConnected.fetch().done(
(isConnected) => { this.setState({isConnected}); }
);
//检测网络连接信息
NetInfo.fetch().done(
(connectionInfo) => { this.setState({connectionInfo}); }
);
}
componentWillUnmount() {
NetInfo.isConnected.removeEventListener(
'change',
this._handleConnectivityChange
);
}
_handleConnectivityChange(isConnected) {
console.log((isConnected ? 'online' : 'offline'));
}
render() {
return (
<View >
<Text>
当前的网络状态:{this.state.isConnected ? '网络在线' : '离线'}
</Text>
<Text >
当前网络连接类型:{this.state.connectionInfo}
</Text>
<Text >
当前连接网络是否计费:{NetInfo.isConnectionExpensive === true ? '需要计费' : '不需要'}
</Text>
</View>
);
}
}
结果如下: