flutter中获取当前位置周围信息
实现方式
- 获取到当前定位的经纬度(可以参考我之前的博客)
- 根据经纬度获取周围信息
- 可以根据关键字进行搜索
第一步可以查看博客 这里就不讲了
博主使用的是高德官方提供的POI搜索接口(官网提供了大量的接口都可以使用 根据自己需要的可以去官网查看)https://developer.amap.com/api/webservice/guide/api/search
使用高德的接口的前提需要自己去 注册一个key
使用高德的搜索是申请Web服务API类型KEY 千万不要注册错了
注册好之后就是使用高德的接口查询数据
1.关键字搜索
接口地址:https://restapi.amap.com/v3/place/text
参数:key :你刚刚注册的web服务的key 必须传
keywords:查询关键字
city:查询城市
citylimit:仅返回指定城市数据(默认false) 可以改
offset:每页记录数据 强烈建议不超过25,若超过25可能造成访问报错
page:当前页数 最大翻页数100
更多参数可以查看查看文档
查看json可以直接复制下面的连接进去
https://restapi.amap.com/v3/place/text?key=fef4e35be05e2337119aeb3b4e57388d&keywords=%E6%B8%AF%E6%83%A0&city=%E6%83%A0%E5%B7%9E%E5%B8%82&offset=20&page=1&citylimit=true
2.根据经纬度获取附近信息
接口地址 : https://restapi.amap.com/v3/place/around
参数:key :你刚刚注册的web服务的key 必须传
keywords:查询关键字
city:查询城市
citylimit:仅返回指定城市数据(默认false) 可以改
offset:每页记录数据 强烈建议不超过25,若超过25可能造成访问报错
page:当前页数 最大翻页数100
location:中心点坐标(根据当前位置搜索附近的信息) 规则: 经度和纬度用","分割,经度在前,纬度在后,经纬度小数点后不得超过6位
更多参数可以查看查看文档
查看json可以直接复制下面的连接进去
https://restapi.amap.com/v3/place/around?key=fef4e35be05e2337119aeb3b4e57388d&keywords=&city=%E6%83%A0%E5%B7%9E%E5%B8%82&location=114.40497230523532,23.11071494684081&offset=20&page=1&citylimit=true
目前博主就使用了高德的搜索POI的这两个接口 有小伙伴需要使用其他的可以查看文档 都是一样的
使用的插件有 如果有报错 可能是使用的flutter版本不一样 博主的是flutter1.1.12.13
#状态管理
rxdart: ^0.21.0
random_string: ^1.1.0
modal_progress_hud: ^0.1.3
# 本地存储
shared_preferences: ^0.5.6+2
flutter_i18n: ^0.8.2
# 同步插件
synchronized: ^2.1.0+1
# 吐司插件
fluttertoast: ^3.1.0
#日期选择
flutter_cupertino_date_picker: ^1.0.7
date_format: ^1.0.6
#图片多选插件
multi_image_picker: ^4.5.9
#下拉菜单
dropdown_menu: ^1.1.1
#下拉菜单
gzx_dropdown_menu: ^1.0.3
#搜索
amap_search_fluttify: ^0.8.2+1
#权限
permission_handler: ^3.2.0
#定位
amap_location: ^0.2.0
provider: ^3.1.0
# 网络请求插件
dio: ^2.1.7
# 上拉下拉
flutter_easyrefresh: ^2.1.1
intl: ^0.16.0
另外代码贴上 复制到项目中可以直接使用
test.dart
import 'package:amap_location/amap_location.dart';
import 'package:amap_location/amap_location_option.dart';
import 'package:carbutlerflutter/http/http.dart';
import 'package:carbutlerflutter/model/peripheral_information_entity.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:permission_handler/permission_handler.dart';
class TestWidget extends StatefulWidget {
@override
_TestWidgetState createState() => _TestWidgetState();
}
class _TestWidgetState extends State<TestWidget> {
@override
void initState() {
// TODO: implement initState
super.initState();
init();
}
init() async {
/flutter定位
await AMapLocationClient.startup(new AMapLocationOption( desiredAccuracy: CLLocationAccuracy.kCLLocationAccuracyHundredMeters));
getLocation();
}
AMapLocation currentAddressInfo = AMapLocation(); //当前位置的信息
TextEditingController searchController = TextEditingController(); //搜索关键字控制器
// List<model> modelList = [];
int pageSize = 20; //一页大小
int pageIndex = 1; //当前页
int pages = 1; //总页数
List<PeripheralInformationPoi> pois; //返回页面显示的数据集合
String androidAMapKey = "fef4e35be05e2337119aeb3b4e57388d"; //安卓高德key 搜索POI需要
bool cityLimit = true; //仅返回指定城市数据
getLocation() async {
// 申请权限 定位权限
Map<PermissionGroup, PermissionStatus> permissions =
await PermissionHandler()
.requestPermissions([PermissionGroup.location]);
// 申请结果
PermissionStatus permission = await PermissionHandler()
.checkPermissionStatus(PermissionGroup.location);
print('PermissionStatus.granted${PermissionStatus.granted}');
if (permission == PermissionStatus.granted) {
await AMapLocationClient.getLocation(true).then((_) {
print('获取定位成功');
print('获取的latitude${_.latitude}');
print('获取的longitude${_.longitude}');
currentAddressInfo = _; //获取到当前定位的信息
aroundHttp();
Fluttertoast.showToast(msg: "定位成功");
});
} else {
Fluttertoast.showToast(msg: "权限申请被拒绝");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('附近信息'),
),
body:Container(
child: Column(
children: <Widget>[
//搜索框
Container(
width: MediaQuery.of(context).size.width,
height: 44,
margin: EdgeInsets.symmetric(
vertical: 12,
),
padding: EdgeInsets.symmetric(
horizontal:12,
),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
//当前城市
InkWell(
child: Container(
padding: EdgeInsets.only(left: 10),
margin: EdgeInsets.only(right: 5),
child: Row(
children: <Widget>[
Container(
child: Text(
'${currentAddressInfo.city ?? " "}',
style: TextStyle(fontSize: 13),
),
),
Icon(
Icons.arrow_drop_down,
color: Colors.grey[400],
size: 20,
)
],
),
),
onTap: () {
//点击跳转到选择城市页面
},
),
//线
Container(
width: 1,
color: Colors.grey[400],
margin: EdgeInsets.symmetric(vertical: 9),
),
//输入框
Container(
padding: EdgeInsets.only(left: 10),
child: TextField(
decoration: InputDecoration(
hintText: "点击输入",
hintStyle: TextStyle(
fontSize: 14,
color: Colors.grey[400],
),
border: InputBorder.none,
suffix: InkWell(
child: Container(
child: Image.asset(
'images/clear.png',
width: 16,
height: 16,
fit: BoxFit.cover,
),
),
onTap: () {
searchController.text = "";
searchHttp();
},
),
),
controller: searchController,
onSubmitted: (val) {
//调用搜索接口
if (val == null || val == "" || val.length == 0) {
return;
} else {
print('调用搜索接口');
searchHttp();
}
},
onChanged: (val) {
setState(() {
});
},
style: TextStyle(
fontSize: 14,
color: Colors.grey[400],
),
),
width: MediaQuery.of(context).size.width * 0.55,
),
//搜索按钮
InkWell(
child: Container(
alignment: Alignment.centerRight,
child: Center(
child: Text(
'搜索',
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
),
),
width: MediaQuery.of(context).size.width * 0.17,
decoration: BoxDecoration(
color: Color(0xff2EA5F1),
borderRadius: BorderRadius.circular(2)),
),
onTap: () {
//调用搜索接口
print('调用搜索接口');
searchHttp();
},
),
],
),
decoration: BoxDecoration(
color: Color(0xffF0F0F0),
borderRadius: BorderRadius.circular(4)),
),
),
//数据列表
Expanded(
child: Container(
color: Colors.white,
child: EasyRefresh(
child: ListView(
children: List.generate(pois.length, (index) {
return InkWell(
child: Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(
left: 12,
bottom: 10,
top: 10),
margin: EdgeInsets.symmetric(vertical: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Image.asset(
'images/currentaddress.png',
width: 12,
height: 12,
),
Container(
width: 3,
),
Expanded(
child: Text(
'${pois[index].name}',
style: TextStyle(
fontSize:13,
color: Color(0xff333333)),
softWrap: true,
)),
],
),
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey[100], width: 1),
),
),
onTap: () {
//获取数据返回
},
);
}),
),
//todo:刷新
onRefresh: () async {
print('下拉刷新');
searchHttp();
},
//todo:加载更多
onLoad: () async {
print('加载更多');
onLoadMore();
},
)),
)
],
),
color: Colors.white,
),
);
}
//调用接口
Future<Null> searchHttp() async {
pois = [];
PeripheralInformationEntity locationInformationEntity =
await searchForHttp(1);
if (locationInformationEntity.status == "1") {
print('请求成功');
pageIndex = 1;
pois = locationInformationEntity.pois;
int total = int.parse(locationInformationEntity.count);
//整页
if (total % pageSize == 0) {
pages = (total / pageSize).floor();
} else {
pages = (total / pageSize).floor() + 1;
}
setState(() {
});
} else {
Fluttertoast.showToast(msg: "请求失败");
}
}
//加载更多
Future<Null> onLoadMore() async {
if (pageIndex < pages) {
PeripheralInformationEntity locationInformationEntity =
await searchForHttp(pageIndex + 1);
if (locationInformationEntity.status == "1") {
print('请求成功');
pageIndex++;
pois.addAll(locationInformationEntity.pois);
} else {
Fluttertoast.showToast(msg: "请求失败");
}
} else {
Fluttertoast.showToast(msg: "没有更多数据了");
}
}
//高德接口获取周边数据---不使用插件
aroundHttp() async {
PeripheralInformationEntity locationInformationEntity =
await aroundForHttp();
if (locationInformationEntity.status == "1") {
print('请求成功');
pois = locationInformationEntity.pois;
int total = int.parse(locationInformationEntity.count); //总数量
//算页数
if (total % pageSize == 0) {
pages = (total / pageSize).floor();
} else {
pages = (total / pageSize).floor() + 1;
}
} else {
Fluttertoast.showToast(msg: "没有更多数据了");
}
}
//高德接口搜索---不使用插件
Future<PeripheralInformationEntity> searchForHttp(pageIndex) async {
String BaseUrl = "https://restapi.amap.com/v3/place/text";
Map<String, dynamic> map = Map();
map["key"] = androidAMapKey;
map["keywords"] = searchController.text;
map["city"] = currentAddressInfo.city; //搜索的城市
map["offset"] = pageSize; //每页记录数据
map["page"] = pageIndex; //每页记录数据
map["citylimit"] = cityLimit; //仅返回指定城市数据
Response resp = await Http.getInstance()
.dio
.get(
BaseUrl,
queryParameters: map,
)
.catchError((e) {
print(e);
});
PeripheralInformationEntity baseBean =
PeripheralInformationEntity.fromJson(resp.data);
return baseBean;
}
//高德接口获取当前位置周边信息---不使用插件
Future<PeripheralInformationEntity> aroundForHttp() async {
String BaseUrl = "https://restapi.amap.com/v3/place/around";
Map<String, dynamic> map = Map();
map["key"] = androidAMapKey;
map["keywords"] = searchController.text;
map["city"] = currentAddressInfo.city; //搜索的城市
map["location"] = "${currentAddressInfo.longitude},${currentAddressInfo.latitude}"; //中心点坐标 经度和纬度用","分割,经度在前,纬度在后,经纬度小数点后不得超过6位
map["offset"] = pageSize; //每页记录数据
map["page"] = pageIndex; //每页记录数据
map["citylimit"] = cityLimit; //仅返回指定城市数据
Response resp = await Http.getInstance().dio.get( BaseUrl, queryParameters: map, ).catchError((e) {
print(e);
});
PeripheralInformationEntity baseBean = PeripheralInformationEntity.fromJson(resp.data);
return baseBean;
}
}
peripheral_information_entity.dart
class PeripheralInformationEntity {
PeripheralInformationSuggestion suggestion;
String count;
String infocode;
List<PeripheralInformationPoi> pois;
String status;
String info;
PeripheralInformationEntity({this.suggestion, this.count, this.infocode, this.pois, this.status, this.info});
PeripheralInformationEntity.fromJson(Map<String, dynamic> json) {
suggestion = json['suggestion'] != null ? new PeripheralInformationSuggestion.fromJson(json['suggestion']) : null;
count = json['count'];
infocode = json['infocode'];
if (json['pois'] != null) {
pois = new List<PeripheralInformationPoi>();(json['pois'] as List).forEach((v) { pois.add(new PeripheralInformationPoi.fromJson(v)); });
}
status = json['status'];
info = json['info'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.suggestion != null) {
data['suggestion'] = this.suggestion.toJson();
}
data['count'] = this.count;
data['infocode'] = this.infocode;
if (this.pois != null) {
data['pois'] = this.pois.map((v) => v.toJson()).toList();
}
data['status'] = this.status;
data['info'] = this.info;
return data;
}
}
class PeripheralInformationSuggestion {
List<Null> keywords;
List<Null> cities;
PeripheralInformationSuggestion({this.keywords, this.cities});
PeripheralInformationSuggestion.fromJson(Map<String, dynamic> json) {
if (json['keywords'] != null) {
keywords = new List<Null>();
}
if (json['cities'] != null) {
cities = new List<Null>();
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.keywords != null) {
data['keywords'] = [];
}
if (this.cities != null) {
data['cities'] = [];
}
return data;
}
}
class PeripheralInformationPoi {
List<Null> parent;
dynamic address;
List<Null> distance;
PeripheralInformationPoisBizExt bizExt;
String pname;
List<Null> importance;
List<Null> bizType;
String cityname;
String type;
List<PeripheralInformationPoisPhoto> photos;
String typecode;
String shopinfo;
List<Null> poiweight;
List<Null> childtype;
String adname;
String name;
String location;
String tel;
List<Null> shopid;
String id;
PeripheralInformationPoi({this.parent, this.address, this.distance, this.bizExt, this.pname, this.importance, this.bizType, this.cityname, this.type, this.photos, this.typecode, this.shopinfo, this.poiweight, this.childtype, this.adname, this.name, this.location, this.tel, this.shopid, this.id});
PeripheralInformationPoi.fromJson(Map<String, dynamic> json) {
if (json['parent'] != null) {
parent = new List<Null>();
}
address = json['address'];
if (json['distance'] != null) {
distance = new List<Null>();
}
bizExt = json['biz_ext'] != null ? new PeripheralInformationPoisBizExt.fromJson(json['biz_ext']) : null;
pname = json['pname'];
cityname = json['cityname'];
type = json['type'];
typecode = json['typecode'];
shopinfo = json['shopinfo'];
adname = json['adname'];
name = json['name'];
location = json['location'];
id = json['id'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.parent != null) {
data['parent'] = [];
}
data['address'] = this.address;
if (this.distance != null) {
data['distance'] = [];
}
if (this.bizExt != null) {
data['biz_ext'] = this.bizExt.toJson();
}
data['pname'] = this.pname;
if (this.importance != null) {
data['importance'] = [];
}
if (this.bizType != null) {
data['biz_type'] = [];
}
data['cityname'] = this.cityname;
data['type'] = this.type;
if (this.photos != null) {
data['photos'] = this.photos.map((v) => v.toJson()).toList();
}
data['typecode'] = this.typecode;
data['shopinfo'] = this.shopinfo;
if (this.poiweight != null) {
data['poiweight'] = [];
}
if (this.childtype != null) {
data['childtype'] = [];
}
data['adname'] = this.adname;
data['name'] = this.name;
data['location'] = this.location;
data['tel'] = this.tel;
if (this.shopid != null) {
data['shopid'] = [];
}
data['id'] = this.id;
return data;
}
}
class PeripheralInformationPoisBizExt {
List<Null> cost;
String rating;
PeripheralInformationPoisBizExt({this.cost, this.rating});
PeripheralInformationPoisBizExt.fromJson(Map<String, dynamic> json) {
if (json['cost'] != null) {
cost = new List<Null>();
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.cost != null) {
data['cost'] = [];
}
data['rating'] = this.rating;
return data;
}
}
class PeripheralInformationPoisPhoto {
List<Null> provider;
List<Null> title;
String url;
PeripheralInformationPoisPhoto({this.provider, this.title, this.url});
PeripheralInformationPoisPhoto.fromJson(Map<String, dynamic> json) {
if (json['provider'] != null) {
provider = new List<Null>();
}
if (json['title'] != null) {
title = new List<Null>();
}
url = json['url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.provider != null) {
data['provider'] = [];
}
if (this.title != null) {
data['title'] = [];
}
data['url'] = this.url;
return data;
}
}
请求框架 http.dart
import 'dart:io';
import 'package:carbutlerflutter/constant/constant.dart';
import 'package:dio/dio.dart';
import 'config.dart';
class Config {
// String base_url = "http://chenhongye1.qicp.io:55118";
String base_url = "https://restapi.amap.com/v3/place/text";
int connectTimeout = 60000;
int receiveTimeout = 60000;
}
/**
* 通过网络请求工具
*/
class Http{
static Http instance;
static String token;
Config _config = new Config();
Dio _dio;
static Http getInstance(){
if(instance == null){
instance = new Http();
}
return instance;
}
Http(){
// 初始化 Options
_dio = new Dio();
_dio.options.baseUrl =_config.base_url;
_dio.options.connectTimeout = _config.connectTimeout;
_dio.options.receiveTimeout = _config.receiveTimeout;
//https证书校验
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
client.badCertificateCallback=(X509Certificate cert, String host, int port){
return true;
};
};
_dio.interceptors.add(InterceptorsWrapper(
onRequest:(RequestOptions options){
// 在请求被发送之前做一些事情
Map<String,dynamic> _headers = options.headers??{};
print("\n================== 请求数据 ==========================");
print("url = ${options.uri.toString()}");
print("headers = ${options.headers}");
return options; //continue
// 如果你想完成请求并返回一些自定义数据,可以返回一个`Response`对象或返回`dio.resolve(data)`。
// 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义数据data.
//
// 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象,或返回`dio.reject(errMsg)`,
// 这样请求将被中止并触发异常,上层catchError会被调用。
},
onResponse:(Response response) {
// 在返回响应数据之前做一些预处理
print("================== 响应数据 ==========================");
print("statusCode:${response.statusCode}");
print("response.data:${response.data}");
return response;
},
onError: (DioError e) {
// 当请求失败时做一些预处理
return e;//continue
}
));
}
Dio get dio {
return _dio;
}
}
谢谢观看 oVo