React Native中的地理跟踪

移动应用程序可以充当员工的“工作场所”,而可能需要传输地理坐标和其他数据。在iOS和Android上的跨平台应用程序开发中,诸如Flutter或React Native之类的框架通常用于此任务。在本文中,我们以案例为例讨论在React Native中使用地理定位的功能。



开发人员有时会批评React Native的可靠性,速度和成熟度,大约在三年前,这种怀疑可以说是合理的。但是,在这段时间里,技术变得更加先进,React Native被公认为是创建广泛应用程序的实用工具。特别是,React Native适用于使用地理坐标的应用程序,例如各种跟踪器,快递公司的应用程序等。

还在商店中开发在线商店,餐厅菜单,新闻提要,交付应用程序,社交网络客户的React Native应用程序-因此,大量的React Native一直在使用,甚至都没有考虑它。简单的例子是Facebook,Instagram,Skype,Uber Eats,Wallmart。根据预测,Microsoft可以补充此列表,并将其移动应用程序转移到React Native,尤其是在实现对Windows平台的支持之后。尽管QtmacOS和“内置” weechat应用程序的支持仍然很匮乏,但React Native 对此提供了支持。

React Native几乎可以执行与本地应用程序相同的所有操作。例如,像Java / Kotlin或ObjC / Swift应用程序一样,从设备传感器接收信息,或者使用Foreground Service或Background fetch在后台发送数据。唯一的区别是,在React Native中,您需要实现一个接口,以实现本机部分与Javascript之间的交互。对于日常任务,这些接口通常已经实现。这也适用于在后台跟踪Javascript的位置和操作:已经有独立开源库形式的解决方案。碰巧的是,社区独立地“向前拉” JavaScript,程序员和公司都在积极使用开放源代码解决方案。很少有语言社区拥有相同数量的库,框架,质量实用程序。但是,在React Native中,本机开发中存在的某些功能仍然受到限制,应该记住这一点。

使用React Native


考虑一些确保React Native上跨平台应用程序开发速度的关键因素:

通用代码库


一旦编写了逻辑,布局屏幕和组件在不同平台上的工作原理和外观就尽可能相同(例如,在Android上,它们使用兴高采烈的概念,而不是通常的阴影)。对于使用旧版本的开发人员,几乎没有永恒的头痛-例如,即使在实践中也很容易添加对Android 4.4的支持,尽管在实践中,此任务的实现还取决于使用其他本机模块。

最佳工作流程


通常,React提供最佳的工作流程,使新功能的开发速度比使用本地语言快几倍。这适用于布局,组件方法,依赖项安装,React的通用架构解决方案。

热装


开发人员无需每次都重建应用程序即可查看更改。借助热重装,只需几秒钟即可将应用程序更新到当前状态。在版本0.61中,还额外考虑了实时刷新(现在是快速刷新),现在在编辑排版更改时可以“即时”进行,而无需重置组件的当前状态。

创建应用程序时,需要特别注意以下几个关键领域:

1)Javascript

React Native旨在使用Javascript,使您能够快速描述逻辑和接口。 Web和Node.js领域有许多现成的模块可以按常规方式使用(自然地,如果它们未连接到DOM或服务器端)。尽管速度很快,但Javascript有时不如本地语言。没有多线程。在React Native中,我们可能无法直接访问Native API,尽管该限制可能很快就会被消除。 Javascript主要描述了本机部分需要完成和呈现的内容。

2)桥

总线通过react-native库提供的特殊接口接受Javascript调用。呼叫是常规的序列化消息。对于每个组件-一个简单的视图,一个输入字段或对系统对话框的调用-都有一个用Javascript描述的接口,其逻辑在本机部分中实现。总线是最慢的部分,它是异步的,在Javascript和本机之间传输数据需要时间(很可能,Facebook可以完全摆脱它)。通常,React Native上应用程序的性能问题通常是由网桥的操作引起的,但是如果正确使用它(将数据来回传输减少到最低限度),那么React Native应用程序中的性能不会有太大差异。

3)本机部分

React Native上的应用程序最初是一个普通的本机应用程序。特殊之处在于,所有必需的库都已连接到其中,因此您可以在React JS中编写所有逻辑。在这里,我们可以编写自己的本机逻辑,以便在JS中使用(或不使用它),添加常用的本机库(例如,以支持KitKat和更早版本的TLS v1.2)。在现成的本机应用程序中,您可以添加对React Native的支持。

在React Native中使用地理跟踪


在其中一个项目中,我们需要为客户的员工开发一个“移动工作场所”,尤其是要确保在后台转移他们的地理坐标。

在React Native中有几种用于地理定位的工具。例如,这是来自React Native @ react-native-community / geolocation社区的软件包,它涵盖了大多数用,但是在后台无法使用。

为了实现我们的任务,我们使用了几种解决方案,包括一个名称为@ mauron85 / react-native-background-geolocation的库。。最初,该库是Cordova的插件,但后来作者分离了基础,并为React Native制作了单独的包装。还有一个来自晶体管软件的同名付费库,但在我们从事该项目时,它仅凭其文档获得了成功。

该库使我们能够为跟踪位置设置灵活的设置。例如,以什么频率查询系统服务,如何在后台精确工作,在哪个半径位置将位置视为静止。可以“开箱即用”使用将这些坐标发送到服务器的设置和方法,但是我们决定不发送垃圾邮件请求,而是将接收到的坐标汇总到存储库中并以​​较大的间隔发送。同时,该库允许我们以前台活动的形式启动我们的应用程序,从而使我们免于不必要的麻烦,因为在许多Android设备上,后台应用程序只能与其他设置一起使用(最近使用的是华为,MIUI,三星)。

安装后,您可以创建组件或仅用于管理服务的助手。我们决定使用该组件将其安装在路由器中,并根据条件将其轻松连接到Redux。设置我们的服务:

import BackgroundGeolocation, {
  Location,
} from '@mauron85/react-native-background-geolocation';
 
class ForegroundService extends PureComponent<Props> {
//...
startBackgroundService = (config: GeotrackerConfig) => {
     //    
	BackgroundGeolocation.configure({
  	desiredAccuracy: BackgroundGeolocation.HIGH_ACCURACY,
  	stationaryRadius: 50,
  	distanceFilter: config.distance,
  	notificationTitle: Strings.Geolocation.NOTIFICATION_TITLE,
  	notificationText: Strings.Geolocation.NOTIFICATION_DESCRIPTION,
  	debug: false,
  	startOnBoot: false,
  	stopOnTerminate: true,
  	locationProvider: BackgroundGeolocation.ACTIVITY_PROVIDER,
  	interval: this.runnerInterval,
  	fastestInterval: 10000,
  	activitiesInterval: 30000,
  	stopOnStillActivity: false,
  	notificationIconColor: Colors.primary,
  	notificationIconSmall: 'notification_icon',
	});
 
     //    start()      
                    	BackgroundGeolocation.on('authorization', status => {
  	if (status !== BackgroundGeolocation.AUTHORIZED) {
    	//   
  	} else if (status.hasPermissions) {
        // hasPermission -  ,    
  	}
	});
 
     //  
                    	BackgroundGeolocation.start();
};


我们看到,您还可以在此处设置通知的设置,即图标(来自本地资产)。权限呢?对于Android,安装软件包后,不需要任何操作,该库将接管访问系统地理位置的请求。但是,要在Xcode上的iOS上正常运行,还需要在项目的“签名和功能”选项卡中启用后台处理和位置更新。



我们以相同的方法实现了在on(“位置”)事件中保存和发送坐标的主要方法。它可以在活动应用程序和最小化状态下工作:

BackgroundGeolocation.on('location', location => {
    BackgroundGeolocation.startTask(async taskKey => {
     //       ,
     //     iOS-
      const batteryLevel = this.isSimulator
        ? 100
        : (await DeviceInfo.getBatteryLevel()) * 100;
      const updateDelta = location.time - this.lastUpdateAt;

     //      
      this.props.locationUpdate(location);
      this.props.locationAddTrackerData({
        altitude: location.altitude,
        batteryChargeLevel: batteryLevel,
        latitude: location.latitude,
        longitude: location.longitude,
        course: location.bearing,
        accuracy: location.accuracy,
        speed: location.speed,
        timestamp: Number(String(location.time).substr(0, 10)),
        isAlertOn: false,
      });

     //  ?
      if (updateDelta / 1000 > config.sendInterval) {
        this.syncDataWithInterval();
        this.lastUpdateAt = location.time;
      }

     //    AsyncStorage,    
      Storage.setLastKnownLocation(location);
      BackgroundGeolocation.endTask(taskKey);  //   !
    });
});


在这里,我们从商店调用动作,在商店中,我们以自定义格式传输坐标数据,并使用react-native-device-info库将数据另外存储在电池读数上。当应用程序处于活动状态或在后台运行时,所有这些在Android和iOS上均能很好地运行。

此外,还有一些获取当前位置的方法(但这仅在服务运行时有效),订阅应用程序状态从活动状态到后台的转换,切换到应用程序的系统设置。但是,总的来说,在这些示例中给出了最必要的。

结果是一个可以安装的组件,例如,只能安装在授权零件上:

class ForegroundService extends PureComponent<Props> {
	//...
	componentDidMount() {
		this.startBackgroundService(this.props.config);
	}

	componentWillUnmount() {
    BackgroundGeolocation.stop();
    BackgroundGeolocation.removeAllListeners();
  }

	startBackgroundService = (config: GeotrackerConfig) => {
    BackgroundGeolocation.configure({
		// ...
	};

	render() {
    return null;
  }
} 


如果使用react-navigation,则可以为授权零件创建导航,如下所示:

//  StackNavigator   
const Navigator = createStackNavigator(RouteConfigs, NavigatorConfig);


class AppNavigator extends PureComponent<Props> {
  static router: NavigationRouter = Navigator.router;

  componentDidMount(): void {
    SplashScreen && SplashScreen.hide();
  }

  render() {
    return (
      <>
        <ForegroundService navigation={this.props.navigation} />
        <Navigator {...this.props} />
      </>
    );
  }
}

export default AppNavigator;


此外,可以在根导航器中以通常的方式使用此导航器:

const RootNavigator = createSwitchNavigator(
  {
    Auth: AuthNavigator,
    App: AppNavigator,
  },
  {
    initialRouteName: 'Auth',
  },
);

export default createAppContainer(RootNavigator);


因此,地理位置和数据交换服务将仅在应用程序的授权部分中工作。

总结一下


在本文中,我们研究了在地理定位应用程序中使用React Native的功能。我们发现,使用此框架,开发人员现在可以轻松跟踪设备的地理坐标,例如在自行车跟踪器,快递员和货运代理的应用程序,房地产选择应用程序等中。该库涵盖了大多数与地理位置跟踪有关的案例,尤其是它允许您调整间隔并节省设备费用,在两种平台上均可在后台稳定运行,并支持在Android上自动运行。同时,通常,对于复杂的应用程序,本机开发更适合(例如,如我们在一篇文章中已经写过的那样,用于处理计算和小部件)。

感谢您的关注,我们希望本文对您有所帮助!

All Articles