Open noorbakerally opened 1 year ago
It is not currently possible to do that et the moment. I had this problem too while working on my project and i have a workaround that involve a bit of work.
I start an isolate that contains an HttpServer
(see here) that serve the json file.
I only bind the http server to the local loopback
await HttpServer.bind(InternetAddress.loopbackIPv4, arg.port, shared: true);
HttpResponse res = (await server.first).response
..headers.contentType = arg.contentType
..statusCode = 200
..write(arg.fileContent);
await res.close();
await server.close();
Here, arg.contentType
is application/json and arg.fileContent
is the json file content.
Is it possible to do that on Android? I'm getting the following error:
SocketException: Failed to create server socket (OS Error: Permission denied, errno = 13), address = 127.0.0.1, port = 80
My codes are:
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 80, shared: true);
HttpResponse res = (await server.first).response
..headers.contentType = ContentType.json
..statusCode = 200
..write(styleFileContent);
await res.close();
await server.close();
you're missing some permission on your manifest.
cf: https://github.com/flutter/flutter/issues/32602#issuecomment-494178777
@mariusvn,
I'm not missing the permission, could something else be causing this?
the fact that the style need to be served via HTTP, is it a requirement of the native libraries also?
Can you send me the content of android/app/src/main/AndroidManifest.xml
?
@mariusvn,
I'm not missing the permission, could something else be causing this?
the fact that the style need to be served via HTTP, is it a requirement of the native libraries also?
In the original mapbox library, every style, even the main map style was recovered over http in the native library. The download has not yet been updated to get it from a string
Hmm weird, it should work with this 🤔
@mariusvn you ever tried this on Android?
yeah, I actually use this on my app i am developping right now, the code I sent you is extracted from it
@mariusvn from the codes you provided above, i changed the port to 8080, im no longer getting this problem, but is hanging on the line HttpResponse res = (await server.first).response................
, make sense because it is waiting for requests i suppose, so we cannot define this in the order i suppose,
So, im defining it this way:
HttpServer.bind(InternetAddress.loopbackIPv4, 8080, shared: true).then((server){
server.first.then((req) async {
final file = File('assets/styles/style.json');
final contents = await file.readAsString();
HttpResponse res = (await server.first).response
..headers.contentType = ContentType.json
..statusCode = 200
..write(contents);
await res.close();
await server.close();
});
}).whenComplete(() async {
LatLngBounds latLngBounds = await maplibreMapController.getVisibleRegion();
var metadata = {
"date":formatDate(DateTime.now(),[dd, '/', mm, '/', yyyy, ' ',HH, ':',hh])
};
await downloadOfflineRegion(
OfflineRegionDefinition(bounds: latLngBounds,
mapStyleUrl: "http://127.0.0.1:8080", minZoom: zoomFrom.toDouble(), maxZoom: 15),
onEvent:downloadNotifier,
metadata:metadata
);
});
The idea is:
downloadOfflineRegion
is called with reference to the mapStyleUrlHowever, im getting the following error:
D/Mbgl-HttpRequest( 4451): Request failed due to a temporary error: timeout
D/Mbgl-HttpRequest( 4451): [HTTP] This request was cancelled (http://127.0.0.1:8080/). This is expected for tiles that were being prefetched but are no longer needed for the map to render.
E/OfflineManagerUtils( 4451): onError reason: REASON_SERVER
E/OfflineManagerUtils( 4451): onError message: timeout
If you do it with an Http Server, you should create an isolate for him
Thats why I'm able to continue to do other things while it waits
my code for the server is actually this
class HttpServerService extends Service {
int _port = 8633;
int get port {
return _port;
}
set port(int value) {
if (value < 1 || value > 65536) {
throw InvalidPortException();
}
_port = value;
}
Future<void> host(String content, {ContentType? contentType}) async {
contentType ??= ContentType.json;
ReceivePort receivePort = ReceivePort();
await Isolate.spawn(HttpServerService._startServerSingleRequest, _HttpServerArgs(content, contentType, _port, receivePort.sendPort));
await receivePort.first;
}
static void _startServerSingleRequest(_HttpServerArgs arg) async {
const Logger isolateLogger = Logger('HttpServerServiceIsolate');
final HttpServer server = await HttpServer.bind(InternetAddress.loopbackIPv4, arg.port, shared: true);
isolateLogger.info('Server running on port ${arg.port}');
arg.sendPort.send(1);
HttpResponse res = (await server.first).response
..headers.contentType = arg.contentType
..statusCode = 200
..write(arg.fileContent);
await res.close();
isolateLogger.info('Response done, stopping server ...');
await server.close();
isolateLogger.info('Server closed');
arg.sendPort.send(2);
}
}
class _HttpServerArgs {
const _HttpServerArgs(this.fileContent, this.contentType, this.port, this.sendPort);
final String fileContent;
final ContentType contentType;
final int port;
final SendPort sendPort;
}
When downloading an offline region using
downloadOfflineRegion
, is it obligatory to supply a style file throughmapStyleUrl
that is served through HTTP, is it possible to use a file from the assets directory or application document directory?