我正在构建一个颤振应用程序,并在运行时收到以下错误:
颤振运行-风味开发
出现的错误如下:
NoSuchMethodError:方法'of‘在null上被调用。我不知道这是否与丢失插件带来的抛出有关。
详细的跟踪显示如下:
The following MissingPluginException was thrown while activating platform stream on channel
myapp.io/receive_share:
MissingPluginException(No implementation found for method listen on channel myapp.io/receive_share)
When the exception was thrown, this was the stack:
#0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:294:7)
<asynchronous suspension>
#1 EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:637:9)
<asynchronous suspension>
════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter ( 8965): type 'Null' is not a subtype of type 'String'
I/flutter ( 8965): #0 new Environment.fromJson (package:myapp/services/environment_loader.dart:50:34)
I/flutter ( 8965): #1 EnvironmentLoader.load.<anonymous closure> (package:myapp/services/environment_loader.dart:13:45)
I/flutter ( 8965): #2 _rootRunUnary (dart:async/zone.dart:1399:47)
I/flutter ( 8965): #3 _CustomZone.runUnary (dart:async/zone.dart:1300:19)
I/flutter ( 8965): <asynchronous suspension>
I/flutter ( 8965): In dev mode. Not sending report to Sentry.io.
I/flutter ( 8965): Clearing prompted user for permission
The Flutter DevTools debugger and profiler on sdk gphone64 x86 64 is available at: http://127.0.0.1:9106?uri=http://127.0.0.1:59439/1DkvGghzJD8=/
E/MethodChannel#maido.io/intercom( 8965): Failed to handle method call
E/MethodChannel#maido.io/intercom( 8965): java.lang.IllegalStateException: Please call Intercom.initialize() before requesting the client.
E/MethodChannel#maido.io/intercom( 8965): at io.intercom.android.sdk.Intercom$Companion.client(Intercom.kt:622)
E/MethodChannel#maido.io/intercom( 8965): at io.maido.intercom.IntercomFlutterPlugin.onMethodCall(IntercomFlutterPlugin.kt:130)
E/MethodChannel#maido.io/intercom( 8965): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262)
E/MethodChannel#maido.io/intercom( 8965): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/MethodChannel#maido.io/intercom( 8965): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319)
E/MethodChannel#maido.io/intercom( 8965): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/MethodChannel#maido.io/intercom( 8965): at android.os.Handler.handleCallback(Handler.java:942)
E/MethodChannel#maido.io/intercom( 8965): at android.os.Handler.dispatchMessage(Handler.java:99)
E/MethodChannel#maido.io/intercom( 8965): at android.os.Looper.loopOnce(Looper.java:201)
E/MethodChannel#maido.io/intercom( 8965): at android.os.Looper.loop(Looper.java:288)
E/MethodChannel#maido.io/intercom( 8965): at android.app.ActivityThread.main(ActivityThread.java:7898)
E/MethodChannel#maido.io/intercom( 8965): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#maido.io/intercom( 8965): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
E/MethodChannel#maido.io/intercom( 8965): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
I/flutter ( 8965): <asynchronous suspension>
I/flutter ( 8965): #1 KNHomePageState._logout (package:myapp/pages/home/home.dart:340:7)I/flutter ( 8965): <asynchronous suspension>
I/flutter ( 8965): In dev mode. Not sending report to Sentry.io.
httpie.dart
import 'dart:convert';
import 'dart:io';
import 'dart:async';
import 'package:myapp/services/localization.dart';
import 'package:myapp/services/utils_service.dart';
// ignore: depend_on_referenced_packages
import 'package:crypto/crypto.dart';
import 'package:http/http.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';
// ignore: depend_on_referenced_packages
import 'package:http_parser/http_parser.dart';
import 'package:http_retry/http_retry.dart';
export 'package:http/http.dart';
class HttpieService {
late LocalizationService _localizationService;
late UtilsService _utilsService;
String? authorizationToken;
String? magicHeaderName;
String? magicHeaderValue;
late Client client;
HttpieService() {
client = IOClient();
client = RetryClient(client,
when: _retryWhenResponse, whenError: _retryWhenError);
}
bool _retryWhenResponse(BaseResponse response) {
return response.statusCode >= 503 && response.statusCode < 600;
}
bool _retryWhenError(error, StackTrace stackTrace) {
return error is SocketException || error is ClientException;
}
void setAuthorizationToken(String token) {
authorizationToken = token;
}
String? getAuthorizationToken() {
return authorizationToken;
}
void removeAuthorizationToken() {
authorizationToken = null;
}
void setLocalizationService(LocalizationService localizationService) {
_localizationService = localizationService;
}
void setUtilsService(UtilsService utilsService) {
_utilsService = utilsService;
}
void setMagicHeader(String name, String value) {
magicHeaderName = name;
magicHeaderValue = value;
}
void setProxy(String proxy) {
var overrides = HttpOverrides.current as HttpieOverrides?;
if (overrides != null) {
overrides.setProxy(proxy);
}
}
Future<HttpieResponse> post(url,
{Map<String, String>? headers,
body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) async {
var finalHeaders = _getHeadersWithConfig(
headers: headers,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
Response? response;
try {
response = await client.post(Uri.parse(url),
headers: finalHeaders, body: body, encoding: encoding);
} catch (error) {
_handleRequestError(error);
}
return HttpieResponse(response);
}
Future<HttpieResponse> put(url,
{Map<String, String>? headers,
body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) async {
var finalHeaders = _getHeadersWithConfig(
headers: headers,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
Response? response;
try {
response = await client.put(Uri.parse(url),
headers: finalHeaders, body: body, encoding: encoding);
} catch (error) {
_handleRequestError(error);
}
return HttpieResponse(response);
}
Future<HttpieResponse> patch(url,
{Map<String, String>? headers,
body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) async {
var finalHeaders = _getHeadersWithConfig(
headers: headers,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
Response? response;
try {
response = await client.patch(Uri.parse(url),
headers: finalHeaders, body: body, encoding: encoding);
} catch (error) {
_handleRequestError(error);
}
return HttpieResponse(response);
}
Future<HttpieResponse> delete(url,
{Map<String, String>? headers,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) async {
var finalHeaders = _getHeadersWithConfig(
headers: headers,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
Response? response;
try {
response = await client.delete(Uri.parse(url), headers: finalHeaders);
} catch (error) {
_handleRequestError(error);
}
return HttpieResponse(response);
}
Future<HttpieResponse> postJSON(url,
{Map<String, String> headers = const {},
body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) {
String jsonBody = json.encode(body);
Map<String, String> jsonHeaders = _getJsonHeaders();
jsonHeaders.addAll(headers);
return post(url,
headers: jsonHeaders,
body: jsonBody,
encoding: encoding,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
}
Future<HttpieResponse> putJSON(url,
{Map<String, String> headers = const {},
body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) {
String jsonBody = json.encode(body);
Map<String, String> jsonHeaders = _getJsonHeaders();
jsonHeaders.addAll(headers);
return put(url,
headers: jsonHeaders,
body: jsonBody,
encoding: encoding,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
}
Future<HttpieResponse> patchJSON(url,
{Map<String, String> headers = const {},
body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) {
String jsonBody = json.encode(body);
Map<String, String> jsonHeaders = _getJsonHeaders();
jsonHeaders.addAll(headers);
return patch(url,
headers: jsonHeaders,
body: jsonBody,
encoding: encoding,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
}
Future<HttpieResponse> get(url,
{Map<String, String>? headers,
Map<String, dynamic>? queryParameters,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) async {
var finalHeaders = _getHeadersWithConfig(
headers: headers,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
// ignore: prefer_is_empty
if (queryParameters != null && queryParameters.keys.length > 0) {
url = url + _makeQueryString(queryParameters);
}
Response? response;
try {
response = await client.get(Uri.parse(url), headers: finalHeaders);
} catch (error) {
_handleRequestError(error);
}
return HttpieResponse(response);
}
Future<HttpieStreamedResponse> postMultiform(String url,
{Map<String, String>? headers,
Map<String, dynamic>? body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) {
return _multipartRequest(url,
method: 'POST',
headers: headers,
body: body,
encoding: encoding,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
}
Future<HttpieStreamedResponse> patchMultiform(String url,
{Map<String, String>? headers,
Map<String, dynamic>? body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) {
return _multipartRequest(url,
method: 'PATCH',
headers: headers,
body: body,
encoding: encoding,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
}
Future<HttpieStreamedResponse> putMultiform(String url,
{Map<String, String>? headers,
Map<String, dynamic>? body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) {
return _multipartRequest(url,
method: 'PUT',
headers: headers,
body: body,
encoding: encoding,
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
}
Future<HttpieStreamedResponse> _multipartRequest(String url,
{Map<String, String>? headers,
required String method,
Map<String, dynamic>? body,
Encoding? encoding,
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) async {
var request = http.MultipartRequest(method, Uri.parse(url));
var finalHeaders = _getHeadersWithConfig(
headers: headers ?? {},
appendLanguageHeader: appendLanguageHeader,
appendAuthorizationToken: appendAuthorizationToken);
request.headers.addAll(finalHeaders);
List<Future> fileFields = [];
List<String>? bodyKeys = body?.keys.toList();
if (bodyKeys != null) {
for (final String key in bodyKeys) {
dynamic value = body![key];
if (value is String || value is bool) {
request.fields[key] = value.toString();
} else if (value is List) {
request.fields[key] =
value.map((item) => item.toString()).toList().join(',');
} else if (value is File) {
String fileMimeType = await _utilsService.getFileMimeType(value);
String? fileExtension =
_utilsService.getFileExtensionForMimeType(fileMimeType);
var bytes = utf8.encode(value.path);
var digest = sha256.convert(bytes);
String newFileName = fileExtension == null
? digest.toString()
: '$digest.$fileExtension';
MediaType fileMediaType = MediaType.parse(fileMimeType);
var fileFuture = http.MultipartFile.fromPath(key, value.path,
filename: newFileName, contentType: fileMediaType);
fileFields.add(fileFuture);
} else {
throw const HttpieArgumentsError('Unsupported multiform value type');
}
}
}
var files = await Future.wait(fileFields);
// ignore: avoid_function_literals_in_foreach_calls
files.forEach((file) => request.files.add(file));
// ignore: prefer_typing_uninitialized_variables
var response;
try {
response = await client.send(request);
} catch (error) {
_handleRequestError(error);
}
return HttpieStreamedResponse(response);
}
String _getLanguage() {
return _localizationService.getLocale().languageCode.toLowerCase();
}
Map<String, String> _getHeadersWithConfig(
{Map<String, String>? headers = const {},
bool? appendLanguageHeader,
bool? appendAuthorizationToken}) {
headers = headers ?? {};
Map<String, String> finalHeaders = Map.from(headers);
appendLanguageHeader = appendLanguageHeader ?? true;
appendAuthorizationToken = appendAuthorizationToken ?? false;
if (appendLanguageHeader) finalHeaders['Accept-Language'] = _getLanguage();
if (appendAuthorizationToken && authorizationToken != null) {
finalHeaders['Authorization'] = 'Token $authorizationToken';
}
if (magicHeaderName != null && magicHeaderValue != null) {
finalHeaders[magicHeaderName!] = magicHeaderValue!;
}
return finalHeaders;
}
void _handleRequestError(error) {
if (error is SocketException) {
var errorCode = error.osError?.errorCode;
if (errorCode == 61 ||
errorCode == 60 ||
errorCode == 111 ||
// Network is unreachable
errorCode == 101 ||
errorCode == 104 ||
errorCode == 51 ||
errorCode == 8 ||
errorCode == 113 ||
errorCode == 7 ||
errorCode == 64) {
// Connection refused.
throw HttpieConnectionRefusedError(error);
}
}
throw error;
}
Map<String, String> _getJsonHeaders() {
return {
'Content-type': 'application/json',
'Accept': 'application/json',
};
}
String _makeQueryString(Map<String, dynamic> queryParameters) {
String queryString = '?';
queryParameters.forEach((key, value) {
if (value != null) {
queryString += '$key=' + _stringifyQueryStringValue(value) + '&';
}
});
return queryString;
}
String _stringifyQueryStringValue(dynamic value) {
if (value is String) return value;
if (value is bool || value is int || value is double) {
return value.toString();
}
if (value is List) {
return value
.map((valueItem) => _stringifyQueryStringValue(valueItem))
.join(',');
}
throw 'Unsupported query string value';
}
}
abstract class HttpieBaseResponse<T extends http.BaseResponse> {
final T _httpResponse;
HttpieBaseResponse(this._httpResponse);
bool isInternalServerError() {
return _httpResponse.statusCode == HttpStatus.internalServerError;
}
bool isBadRequest() {
return _httpResponse.statusCode == HttpStatus.badRequest;
}
bool isOk() {
return _httpResponse.statusCode == HttpStatus.ok;
}
bool isUnauthorized() {
return _httpResponse.statusCode == HttpStatus.unauthorized;
}
bool isForbidden() {
return _httpResponse.statusCode == HttpStatus.forbidden;
}
bool isAccepted() {
return _httpResponse.statusCode == HttpStatus.accepted;
}
bool isCreated() {
return _httpResponse.statusCode == HttpStatus.created;
}
bool isNotFound() {
return _httpResponse.statusCode == HttpStatus.notFound;
}
int get statusCode => _httpResponse.statusCode;
}
class HttpieResponse extends HttpieBaseResponse<http.Response> {
// ignore: no_leading_underscores_for_local_identifiers
HttpieResponse(_httpResponse) : super(_httpResponse);
String get body {
return utf8.decode(_httpResponse.bodyBytes);
}
Map<String, dynamic> parseJsonBody() {
return json.decode(body);
}
http.Response get httpResponse => _httpResponse;
}
class HttpieStreamedResponse extends HttpieBaseResponse<http.StreamedResponse> {
// ignore: no_leading_underscores_for_local_identifiers
HttpieStreamedResponse(_httpResponse) : super(_httpResponse);
Future<String> readAsString() {
var completer = Completer<String>();
var contents = StringBuffer();
_httpResponse.stream.transform(utf8.decoder).listen((String data) {
contents.write(data);
}, onDone: () {
completer.complete(contents.toString());
});
return completer.future;
}
}
class HttpieRequestError<T extends HttpieBaseResponse> implements Exception {
static String convertStatusCodeToHumanReadableMessage(int statusCode) {
String readableMessage;
if (statusCode == HttpStatus.notFound) {
readableMessage = 'Not found';
} else if (statusCode == HttpStatus.forbidden) {
readableMessage = 'You are not allowed to do this';
} else if (statusCode == HttpStatus.badRequest) {
readableMessage = 'Bad request';
} else if (statusCode == HttpStatus.internalServerError) {
readableMessage =
'We\'re experiencing server errors. Please try again later.';
} else if (statusCode == HttpStatus.serviceUnavailable ||
statusCode == HttpStatus.serviceUnavailable) {
readableMessage =
'We\'re experiencing server errors. Please try again later.';
} else {
readableMessage = 'Server error';
}
return readableMessage;
}
final T response;
const HttpieRequestError(this.response);
@override
String toString() {
String statusCode = response.statusCode.toString();
String stringifiedError = 'HttpieRequestError:$statusCode';
if (response is HttpieResponse) {
var castedResponse = response as HttpieResponse;
stringifiedError = '$stringifiedError | ${castedResponse.body}';
}
return stringifiedError;
}
Future<String> body() async {
late String body;
if (response is HttpieResponse) {
HttpieResponse castedResponse = response as HttpieResponse;
body = castedResponse.body;
} else if (response is HttpieStreamedResponse) {
HttpieStreamedResponse castedResponse =
response as HttpieStreamedResponse;
body = await castedResponse.readAsString();
}
return body;
}
Future<String?> toHumanReadableMessage() async {
String errorBody = await body();
try {
dynamic parsedError = json.decode(errorBody);
if (parsedError is Map) {
if (parsedError.isNotEmpty) {
if (parsedError.containsKey('detail')) {
return parsedError['detail'];
} else if (parsedError.containsKey('message')) {
return parsedError['message'];
} else {
dynamic mapFirstValue = parsedError.values.toList().first;
dynamic value = mapFirstValue is List ? mapFirstValue[0] : null;
if (value != null && value is String) {
return value;
} else {
return convertStatusCodeToHumanReadableMessage(
response.statusCode);
}
}
} else {
return convertStatusCodeToHumanReadableMessage(response.statusCode);
}
} else if (parsedError is List && parsedError.isNotEmpty) {
return parsedError.first;
}
return null;
} catch (error) {
return convertStatusCodeToHumanReadableMessage(response.statusCode);
}
}
}
class HttpieConnectionRefusedError implements Exception {
final SocketException socketException;
const HttpieConnectionRefusedError(this.socketException);
@override
String toString() {
String address = socketException.address.toString();
String port = socketException.port.toString();
return 'HttpieConnectionRefusedError: Connection refused on $address and port $port';
}
String toHumanReadableMessage() {
return 'No internet connection.';
}
}
class HttpieArgumentsError implements Exception {
final String msg;
const HttpieArgumentsError(this.msg);
@override
String toString() => 'HttpieArgumentsError: $msg';
}
// These overrides are used by the standard dart:http/HttpClient to change how
// it behaves. All settings changed here will apply to every single HttpClient
// used by any other package, as long as they're running inside a zone with
// these set.
class HttpieOverrides extends HttpOverrides {
String? _proxy;
final HttpOverrides? _previous = HttpOverrides.current;
HttpieOverrides();
void setProxy(String proxy) {
_proxy = proxy;
}
@override
HttpClient createHttpClient(SecurityContext? context) {
if (_previous != null) return _previous!.createHttpClient(context);
return super.createHttpClient(context);
}
@override
String findProxyFromEnvironment(Uri uri, Map<String, String>? environment) {
if (_proxy != null) return _proxy!;
if (_previous != null) {
return _previous!.findProxyFromEnvironment(uri, environment);
}
return super.findProxyFromEnvironment(uri, environment);
}
}
我解决不了上面的问题,我花了很长时间在上面。帮帮忙吧。
发布于 2022-11-17 16:15:06
来自intercom_flutter使用(https://pub.dev/packages/intercom_flutter#usage)
//确保从您的对讲机工作区中添加密钥。
await Intercom.instance.initialize('appIdHere', iosApiKey: 'iosKeyHere', androidApiKey: 'androidKeyHere');
我认为你已经错过了这一点,从你共享的堆栈痕迹中可以明显看出这一点。
java.lang.IllegalStateException: Please call Intercom.initialize() before requesting the client.
https://stackoverflow.com/questions/74384353
复制相似问题