最近把 老的项目重新跑起来,无论如何都不能跑起来,折腾了好几天,记录一下心路历程,都是坑! 满满干货
android studio 运行老项目
- 不能识别flutter版本
E/flutter (14355): [ERROR:flutter/shell/common/shell.cc(242)] Dart Error: Can't load Kernel binary: Invalid kernel binary: Indicated size is invalid. E/flutter (14355): [ERROR:flutter/runtime/dart_isolate.cc(169)] Could not prepare isolate. E/flutter (14355): [ERROR:flutter/runtime/runtime_controller.cc(401)] Could not create root isolate. E/flutter (14355): [ERROR:flutter/shell/common/shell.cc(571)] Could not launch engine with configuration.
杀掉进程,重启项目就可以
2.神坑的问题 报错插件未注册
I/flutter (17872): [INFO] J: Serving on 0.0.0.0:55588
E/flutter (17872): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)
E/flutter (17872):
E/flutter (17872): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)
E/flutter (17872):
报错 shared_preferences 插件注册没成功
可以尝试
flutter clean flutter pub get/ flutter packages get
不行,往下看: 参照网上的资料
1.shared_preferences 0.2.4及更高版本,可直接在flutter项目的main方法中添加以下内容
import 'package:shared_preferences/shared_preferences.dart';
void main() {
SharedPreferences.setMockInitialValues({});
runApp(MyApp());
}
对于早期版本,可以改为:
const MethodChannel('plugins.flutter.io/shared_preferences')
.setMockMethodCallHandler((MethodCall methodCall) async {
if (methodCall.method == 'getAll') {
return <String, dynamic>{}; // set initial values here if desired
}
return null;
});
上面这个方法 确实能进入项目,能解决此问题,但是有两个问题 1.如果是项目中如果采用webView,跳转webView 页面会报错,项目报错 path_provider 未注册,2. 每次重启之前保存的数据都没了,实际的项目中肯定是不行的,用户每次进入APP 都是需要重新登录。
如果是没有报错其他的插件未注册,可以试试:
flutter pub cache repair
上述所有的方法不能解决问题,中间尝试了很多方法,还是不能不能解决问题,尝试了升级flutter版本,尝试改动android源码均不能解决这个问题。
网上查找资料无意中看到一句话,flutter项目如果有一个插件有问题,会导致其他的插件注册也会不成功。 无意中看到希望的曙光!
开始新建一个项目,跑最简单的闭环,思路是把原项目的依赖都安装了
以下是我这个项目的 pubspec.yaml文件 插件依赖部分
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
dio: ^3.0.10
provider: ^4.3.2+3
rxdart: ^0.25.0
cookie_jar: ^1.0.1
dio_cookie_manager: ^1.0.0
flutter_screenutil: ^4.0.2+3
fluro: ^1.7.8
shared_preferences: ^2.0.0
crypto: ^2.1.5
logger: ^0.9.4
webview_flutter:
path: plugins/webview_flutter
# webview_flutter: ^2.0.8
jaguar: ^2.4.46
jaguar_flutter_asset: ^2.2.0
fluwx_no_pay: ^2.4.0+1
permission_handler: ^5.0.1+1
flutter_easyloading: ^2.2.2
get_it: ^5.0.3
image_picker: ^0.6.7+20
contacts_service: ^0.4.6
path_provider: ^2.0.0
package_info: ^0.4.3+2
device_info: ^1.0.0
circular_check_box: ^1.0.4
flutter_bloc: ^6.1.1
equatable: ^1.2.5
flutter_aliyun_captcha: ^1.0.1
flutter_channel: ^0.0.1
uuid: ^2.2.2
store_redirect: ^1.0.2
open_file: ^3.0.3
tpns_flutter_plugin:
path: plugins/TPNS-Flutter-Plugin
flutter_picker: ^1.1.0
barcode_scan: ^1.0.0
# amap_flutter_location: ^2.0.0
# amap_location_muka: ^0.1.1
jwt_decoder: ^2.0.1
然后main.dart 文件
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
// import 'package:uuid/uuid.dart';
void main() {
runApp(MyApp());
initUuid();
}
void initUuid() async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
}
步骤是 pubspec.yaml 依赖插件全部注释,再flutter clean ,flutter pub get 启动项目,再逐个放开执行此过程,终于定位到当放开 amap_location_muka: ^0.1.1 这个插件的时候,就会看到开头说的报错,至此终于定位到问题了,flutter这个机制实在是坑!
最后 我换成下面这个插件
amap_location_fluttify: ^0.20.0
原文例子如下:
/// !注意: 只要是返回Future的方法, 一律使用`await`修饰, 确保当前方法执行完成后再执行下一行, 在不能使用`await`修饰的环境下, 在`then`方法中执行下一步.
/// 初始化 iOS在init方法中设置, android需要去AndroidManifest.xml里去设置, 详见 https://lbs.amap.com/api/android-sdk/gettingstarted
await AmapCore.init('ios key');
// 单次定位
if (await requestPermission()) {
final location = await AmapLocation.fetchLocation();
setState(() => _location = location);
}
// 连续定位
if (await requestPermission()) {
AmapLocation.listenLocation()
.listen((location) => setState(() => _location = location));
}
因为我的项目是webView链接远端的h5项目,基本的业务都是h5上面的,所以flutter这里只需要某个时刻单词定位就可以了,利用flutter定位的经纬度,传入到h5项目中,h5项目也引入了web的高德地图(这里有坑,vue的移动端项目,没有对应的高德地图的插件,自己手撸了一个两个组件,一个是定位的,一个是可以输入地图检索位置,如果有谁需要看实现可以私聊我)
下面是flutter 调用定位(配置高德key我会写一篇,附带安卓签名)
Future<Map<String, dynamic>> _getLocation(data) async {
await AmapLocation.instance.init(iosKey: ''); //https://console.amap.com/dev/key/app 去配置项目的key
// return null; // 用于调试
if (Platform.isAndroid
? await Permission.location.isPermanentlyDenied
: await Permission.location.isDenied) {
DialogUtil.buildDialog(context, S.of(context).permissionTitle,
S.of(context).locationPermissionDesc, openAppSettings);
return {"permission": false};
}
if (await Permission.locationWhenInUse.request().isGranted) {
try {
Location _location = await AmapLocation.instance.fetchLocation();
Map locationMap = <String, dynamic> {
"address" : _location.address,
"latitude" : _location.latLng.latitude,
"longitude": _location.latLng.longitude
};
// print(_location.toJson());
final res = <String, dynamic>{
"api": "getLocation",
"data": locationMap
};
_controller.then((v) => v.evaluateJavascript(
"window.jsBridge.receiveMessage(${json.encode(res)})")); //与嵌套的h5页面通信
//停止定位
// if (await Permission.locationWhenInUse.request().isGranted) {
// await AmapLocation.instance.stopLocation();
// }
return res;
}catch(e){
DialogUtil.buildToast(e);// toast 提示,这里是DialogUtil自己封装的提示插件
}
} else {
DialogUtil.buildToast(S.of(context).contactPermission); // toast 提示
}
}
我看了网上很多的资料flutter webview 与 web项目通信,讲的很简单,实际项目肯定需要一套对应的中间桥接插件,但是这个就没有,如果是有对flutter 和 web页面通信有疑问的,我可以单独写一篇文章。
原文 有道云笔记:note.youdao.com/s/deIDli2G