本节目标

  • 创建 ios flutter 插件流程
  • 集成百度定位功能

视频

https://www.bilibili.com/video/BV1HT4y1L73i/

代码

https://github.com/ducafecat/flutter_baidu_plugin_ducafecat/releases/tag/v1.0.3

百度平台部分

设置 AK

https://lbsyun.baidu.com/apiconsole/key#/home

  • 添加应用
  • 查看 Bundle Identifier

IOS 部分

自动部署 CocoaPods

  • 安装工具
1
sudo gem install cocoapods
  • ios/flutter_baidu_plugin_ducafecat.podspec
1
2
3
4
5
6
7
8
9
  ...
s.dependency 'Flutter'
s.platform = :ios, '8.0'

s.dependency 'BMKLocationKit'

# Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
end
  • 安装百度 sdk 包
1
pod install
  • 升级
1
pod repo update
  • pod search 无法搜索到类库的解决办法(找不到类库)
1
2
3
4
5
6
7
8
9
10
11
(1)执行pod setup

(2)删除~/Library/Caches/CocoaPods目录下的search_index.json文件

pod setup成功后会生成~/Library/Caches/CocoaPods/search_index.json文件

终端输入rm ~/Library/Caches/CocoaPods/search_index.json

删除成功后再执行pod search

(3)执行pod search

Info.plist 定位授权

example/ios/Runner/Info.plist

1
2
3
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要定位</string>

消息通知 BdmapFlutterStreamManager

  • ios/Classes/BdmapFlutterStreamManager.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//
// Header.h
// bdmap_location_flutter_plugin
//
// Created by Wang,Shengzhan on 2020/2/4.
//


#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>

NS_ASSUME_NONNULL_BEGIN
@class BdmapFlutterStreamHandler;
@interface BdmapFlutterStreamManager : NSObject
+ (instancetype)sharedInstance ;
@property (nonatomic, strong) BdmapFlutterStreamHandler* streamHandler;

@end

@interface BdmapFlutterStreamHandler : NSObject<FlutterStreamHandler>
@property (nonatomic, strong) FlutterEventSink eventSink;

@end
NS_ASSUME_NONNULL_END
  • ios/Classes/BdmapFlutterStreamManager.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//
// BdmapFlutterStreamManager.m
// bdmap_location_flutter_plugin
//
// Created by Wang,Shengzhan on 2020/2/4.
//

#import "BdmapFlutterStreamManager.h"

@implementation BdmapFlutterStreamManager

+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static BdmapFlutterStreamManager *manager = nil;
dispatch_once(&onceToken, ^{
manager = [[BdmapFlutterStreamManager alloc] init];
BdmapFlutterStreamHandler * streamHandler = [[BdmapFlutterStreamHandler alloc] init];
manager.streamHandler = streamHandler;
});

return manager;
}

@end


@implementation BdmapFlutterStreamHandler

- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
self.eventSink = eventSink;
return nil;
}

- (FlutterError*)onCancelWithArguments:(id)arguments {

return nil;
}

@end

地图接口业务 FlutterBaiduPluginDucafecatPlugin

  • ios/Classes/FlutterBaiduPluginDucafecatPlugin.h
1
2
3
4
#import <Flutter/Flutter.h>

@interface FlutterBaiduPluginDucafecatPlugin : NSObject<FlutterPlugin>
@end
  • ios/Classes/FlutterBaiduPluginDucafecatPlugin.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#import "FlutterBaiduPluginDucafecatPlugin.h"
#import "BMKLocationkit/BMKLocationComponent.h"
#import "BdmapFlutterStreamManager.h"

@interface FlutterBaiduPluginDucafecatPlugin()<BMKLocationManagerDelegate>

@property (nonatomic,strong) BMKLocationManager *locManager;

@property (nonatomic, copy) FlutterResult flutterResult;

@end



@implementation FlutterBaiduPluginDucafecatPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
// FlutterMethodChannel* channel = [FlutterMethodChannel
// methodChannelWithName:@"flutter_baidu_plugin_ducafecat"
// binaryMessenger:[registrar messenger]];
// FlutterBaiduPluginDucafecatPlugin* instance = [[FlutterBaiduPluginDucafecatPlugin alloc] init];
// [registrar addMethodCallDelegate:instance channel:channel];

FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"flutter_baidu_plugin_ducafecat"
binaryMessenger:[registrar messenger]];

FlutterBaiduPluginDucafecatPlugin* instance = [[FlutterBaiduPluginDucafecatPlugin alloc] init];

[registrar addMethodCallDelegate:instance channel:channel];

FlutterEventChannel *eventChanel = [FlutterEventChannel eventChannelWithName:@"flutter_baidu_plugin_ducafecat_stream" binaryMessenger:[registrar messenger]];

[eventChanel setStreamHandler:[[BdmapFlutterStreamManager sharedInstance] streamHandler]];

}

// - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
// if ([@"getPlatformVersion" isEqualToString:call.method]) {
// result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
// }
// else if ([@"duAddOne" isEqualToString:call.method]) {
// NSInteger val = 100;
// val += [[call.arguments objectForKey:@"num"] intValue];
// result([NSNumber numberWithLong:val]);
// }
// else {
// result(FlutterMethodNotImplemented);
// }
// }


- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {

if ([@"getPlatformVersion" isEqualToString:call.method]) {

result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);

} else if ([@"startLocation" isEqualToString:call.method]){ // 开始定位

// NSLog((@"\n[bdmap_loc_flutter_plugin:%s]"), "startLocation...");
[self startLocation:result];

}else if ([@"stopLocation" isEqualToString:call.method]){ // 停止定位

// NSLog((@"\n[bdmap_loc_flutter_plugin:%s]"), "stopLocation...");
[self stopLocation];
result(@YES);

} else if ([@"updateOption" isEqualToString:call.method] ) { // 设置定位参数

result(@([self updateOption:call.arguments]));

} else if ([@"setApiKey" isEqualToString:call.method]){ // 设置ios端ak
// NSLog((@"\n[bdmap_loc_flutter_plugin:%s]"), "setApiKey...");
[[BMKLocationAuth sharedInstance] checkPermisionWithKey:call.arguments authDelegate:self];
result(@YES);
} else {

result(FlutterMethodNotImplemented);
}
}

/**
获取设置的期望定位精度
*/
-(double)getDesiredAccuracy:(NSString*)str{

if([@"kCLLocationAccuracyBest" isEqualToString:str]) {
return kCLLocationAccuracyBest;
} else if ([@"kCLLocationAccuracyNearestTenMeters" isEqualToString:str]) {
return kCLLocationAccuracyNearestTenMeters;
} else if ([@"kCLLocationAccuracyHundredMeters" isEqualToString:str]) {
return kCLLocationAccuracyHundredMeters;
} else if ([@"kCLLocationAccuracyKilometer" isEqualToString:str]) {
return kCLLocationAccuracyKilometer;
} else {
return kCLLocationAccuracyBest;
}
}

/**
获取设置的经纬度坐标系类型
*/
-(int)getCoordinateType:(NSString*)str{

if([@"BMKLocationCoordinateTypeBMK09LL" isEqualToString:str]) {
return BMKLocationCoordinateTypeBMK09LL;
} else if ([@"BMKLocationCoordinateTypeBMK09MC" isEqualToString:str]) {
return BMKLocationCoordinateTypeBMK09MC;
} else if ([@"BMKLocationCoordinateTypeWGS84" isEqualToString:str]) {
return BMKLocationCoordinateTypeWGS84;
} else if ([@"BMKLocationCoordinateTypeGCJ02" isEqualToString:str]) {
return BMKLocationCoordinateTypeGCJ02;
} else {
return BMKLocationCoordinateTypeGCJ02;
}


}


/**
获取设置的应用位置类型
*/
-(int)getActivityType:(NSString*)str{

if ([@"CLActivityTypeOther" isEqualToString:str]) {
return CLActivityTypeOther;
} else if ([@"CLActivityTypeAutomotiveNavigation" isEqualToString:str]) {
return CLActivityTypeAutomotiveNavigation;
} else if ([@"CLActivityTypeFitness" isEqualToString:str]) {
return CLActivityTypeFitness;
} else if ([@"CLActivityTypeOtherNavigation" isEqualToString:str]) {
return CLActivityTypeOtherNavigation;
} else {
return CLActivityTypeAutomotiveNavigation;
}


}

/**
解析flutter端所设置的定位SDK参数
*/
-(BOOL)updateOption:(NSDictionary*)args {
if(self.locManager) {

// NSLog(@"定位参数配置:%@",args);

self.locManager.isNeedNewVersionReGeocode = YES;

// 设置期望定位精度
if ([[args allKeys] containsObject:@"desiredAccuracy"]) {
[self.locManager setDesiredAccuracy:[ self getDesiredAccuracy: args[@"desiredAccuracy"]]];
}

// 设置定位的最小更新距离
if ([[args allKeys] containsObject:@"distanceFilter"]) {
self.locManager.distanceFilter = [args[@"distanceFilter"] doubleValue];
// NSLog(@"最小更新距离值:%f", [args[@"distanceFilter"] doubleValue]);
}

// 设置返回位置坐标系类型
if ([[args allKeys] containsObject:@"BMKLocationCoordinateType"]) {
[self.locManager setCoordinateType:[ self getCoordinateType: args[@"desiredAccuracy"]]];
}

// 设置应用位置类型
if ([[args allKeys] containsObject:@"activityType"]) {
[self.locManager setActivityType:[ self getActivityType: args[@"desiredAccuracy"]]];
}

// 设置是否需要返回新版本rgc信息
if ([[args allKeys] containsObject:@"isNeedNewVersionRgc"]) {
if ((bool)args[@"desiredAccuracy"]) {
// NSLog(@"需要返回新版本rgc信息");
self.locManager.isNeedNewVersionReGeocode = YES;
} else {
// NSLog(@"不需要返回新版本rgc信息");
self.locManager.isNeedNewVersionReGeocode = NO;
}

}

// 指定定位是否会被系统自动暂停
if ([[args allKeys] containsObject:@"pausesLocationUpdatesAutomatically"]) {
if ((bool)args[@"pausesLocationUpdatesAutomatically"]) {
// NSLog(@"设置定位被系统自动暂停");
self.locManager.isNeedNewVersionReGeocode = YES;
} else {
// NSLog(@"设置定位不能被系统自动暂停");
self.locManager.isNeedNewVersionReGeocode = NO;
}

}

// 设置是否允许后台定位
if ([[args allKeys] containsObject:@"allowsBackgroundLocationUpdates"]) {
if ((bool)args[@"allowsBackgroundLocationUpdates"]) {
// NSLog(@"设置允许后台定位");
self.locManager.isNeedNewVersionReGeocode = YES;
} else {
// NSLog(@"设置不允许后台定位");
self.locManager.isNeedNewVersionReGeocode = NO;
self.locManager.distanceFilter = kCLDistanceFilterNone;
}

}

// 设置定位超时时间
if ([[args allKeys] containsObject:@"locationTimeout"]) {
[self.locManager setLocationTimeout:[args[@"locationTimeout"] integerValue]];
self.locManager.coordinateType = BMKLocationCoordinateTypeGCJ02;
}

// 设置逆地理超时时间
if ([[args allKeys] containsObject:@"reGeocodeTimeout"]) {
[self.locManager setReGeocodeTimeout:[args[@"reGeocodeTimeout"] integerValue]];
}

return YES;

}
return NO;
}
/**
启动定位
*/
- (void)startLocation:(FlutterResult)result
{
self.flutterResult = result;
[self.locManager startUpdatingLocation];
}

/**
停止定位
*/
- (void)stopLocation
{
self.flutterResult = nil;
[self.locManager stopUpdatingLocation];
}

- (BMKLocationManager *)locManager {
if (!_locManager) {
_locManager = [[BMKLocationManager alloc] init];
_locManager.locatingWithReGeocode = YES;
_locManager.delegate = self;
}
return _locManager;
}

/**
* @brief 连续定位回调函数
* @param manager 定位 BMKLocationManager 类。
* @param location 定位结果。
*/
- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error

{
if (error)
{
// NSLog(@"locError:{%ld - %@};", (long)error.code, error.localizedDescription);
} if (location) { // 得到定位信息,添加annotation
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:1];

if (location) {

if (location.location.timestamp) {
[dic setObject:[self getFormatTime:location.location.timestamp] forKey:@"locTime"]; // 定位时间
}


if (location.location.horizontalAccuracy) {
[dic setObject:@(location.location.horizontalAccuracy) forKey:@"radius"]; // 定位精度
}


if (location.location.coordinate.latitude) {
[dic setObject:@(location.location.coordinate.latitude) forKey:@"latitude"]; // 纬度
}

if (location.location.coordinate.longitude) {
[dic setObject:@(location.location.coordinate.longitude) forKey:@"longitude"]; // 经度
}

if (location.location.altitude) {
// NSLog(@"返回海拔高度信息");
[dic setObject:@(location.location.altitude) forKey:@"altitude"];// 高度
}


if (location.rgcData) {
[dic setObject:[location.rgcData country] forKey:@"country"]; // 国家
[dic setObject:[location.rgcData province] forKey:@"province"]; // 省份
[dic setObject:[location.rgcData city] forKey:@"city"]; // 城市
if (location.rgcData.district) {
[dic setObject:[location.rgcData district] forKey:@"district"]; // 区县
}

if (location.rgcData.street) {
[dic setObject:[location.rgcData street] forKey:@"street"]; // 街道
}

if (location.rgcData.description) {
// 地址信息
[dic setObject:[location.rgcData description] forKey:@"address"];
}


if (location.rgcData.poiList) {

NSString* poilist;

if (location.rgcData.poiList.count == 1) {

for (BMKLocationPoi * poi in location.rgcData.poiList) {
poilist = [[poi name] stringByAppendingFormat:@",%@,%@", [poi tags], [poi addr]];
}

} else {
for (int i = 0; i < location.rgcData.poiList.count - 1 ; i++) {
poilist = [poilist stringByAppendingFormat:@"%@,%@,%@|", location.rgcData.poiList[i].name,location.rgcData.poiList[i].tags,location.rgcData.poiList[i].addr];
}

poilist = [poilist stringByAppendingFormat:@"%@,%@,%@",
location.rgcData.poiList[location.rgcData.poiList.count-1].name,location.rgcData.poiList[location.rgcData.poiList.count-1].tags,location.rgcData.poiList[location.rgcData.poiList.count-1].addr];

}
[dic setObject: poilist forKey:@"poiList"]; // 周边poi信息

}
}
} else {
[dic setObject: @1 forKey:@"errorCode"]; // 定位结果错误码
[dic setObject:@"location is null" forKey:@"errorInfo"]; // 定位错误信息
}

// 定位结果回调时间
[dic setObject:[self getFormatTime:[NSDate date]] forKey:@"callbackTime"];

[[BdmapFlutterStreamManager sharedInstance] streamHandler].eventSink(dic);
// NSLog(@"x=%f,y=%f",location.location.coordinate.latitude,location.location.coordinate.longitude);
}
}

/**
格式化时间
*/
- (NSString *)getFormatTime:(NSDate*)date
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
NSString *timeString = [formatter stringFromDate:date];
return timeString;
}

@end

Flutter 部分

设置 AK

1
2
3
4
5
6
7
8
9
10
@override
void initState() {
super.initState();
_requestPermission(); // 执行权限请求

if (Platform.isIOS == true) {
FlutterBaiduPluginDucafecat.setApiKeyForIOS(
"dkYT07blcAj3drBbcN1eGFYqt16HP1pR");
}
}

其它代码和 android 同接口 无影响

参考


© 猫哥

https://ducafecat.tech

https://ducafecat.gitee.io