我有用golang编写的web服务器,它使用graphql包格尔根和戈姆作为数据库。
由于golang可以在android上编译和运行,所以我想创建我的应用程序的离线版本,其中sqlite可以用于离线存储,并将我的整个服务器导入为aar。
我已经成功地构建了aar,并按照指示这里将它添加到我的颤振上。
当我运行我的应用程序时,服务器是在android上启动的,它似乎工作得很好。当在模拟器的铬应用程序上打开http://localhost:8080/时,我看到graphql操场运行时没有任何问题,就像我在windows浏览器上看到的那样。
我面临的唯一问题是,当服务器在后台运行时,颤振应用程序只显示一个空白屏幕。以下是启动app时打印的日志
Launching lib\main.dart on sdk gphone64 x86 64 in debug mode...
Running Gradle task 'assembleDebug'...
√ Built build\app\outputs\flutter-apk\app-debug.apk.
Installing build\app\outputs\flutter-apk\app.apk...
Debug service listening on ws://127.0.0.1:62561/DyGpOhyuekw=/ws
Syncing files to device sdk gphone64 x86 64...
I/GoLog ( 6295): connect to http://localhost:8080/ for GraphQL playground
W/ux.offline( 6295): type=1400 audit(0.0:38): avc: denied { read } for name="somaxconn" dev="proc" ino=74990 scontext=u:r:untrusted_app:s0:c149,c256,c512,c768 tcontext=u:object_r:proc_net:s0 tclass=file permissive=0 app=com.nux.offline我认为问题可能在上面的日志上,avc: denied { read } for name="somaxconn"或者其他什么东西导致了ui线程的阻塞,因为它就像颤振,不呈现任何东西。
我使用颤振插件启动服务器,这是ServerPlugin.kt
package com.mahesabu.server.server
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import lib.Lib.startServer
/** ServerPlugin */
class ServerPlugin : FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel: MethodChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "server")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "startServer") {
try {
val port = startServer() //from golang bindings
result.success(port)
} catch (e: Exception) {
e.printStackTrace();
result.error("Error in starting server", "${e.message}", null);
}
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}这是飞镖代码
class Server {
static const MethodChannel _channel = MethodChannel('server');
static Future<String?> startServer() async {
try {
final String? port = await _channel.invokeMethod('startServer');
return port;
} catch (e) {
log('startServer error: ${e.toString()}');
return null;
}
}
}我的应用程序的主要内容如下
import 'package:flutter/material.dart';
import 'package:server/server.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final port = await Server.startServer(); //problem
print('port $port'); //This don't print
runApp(const MyApp());
}站在这一边,我如何启动服务器
//start.go
package util
import (
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground"
"log"
"my-project/graph"
"my-project/graph/generated"
"net/http"
"os"
)
const defaultPort = "8080"
// StartServer This way so that it can be invoked via libs
func StartServer(Offline bool) string {
port := os.Getenv("PORT")
if port == "" {
port = defaultPort
}
db := InitDB(Offline)
config := generated.Config{Resolvers: &graph.Resolver{
DB: db,
}}
srv := handler.NewDefaultServer(generated.NewExecutableSchema(config))
http.Handle("/", playground.Handler("GraphQL playground", "/query"))
http.Handle("/query", srv)
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
return port
}这是用来生成gomobile绑定的lib。
//lib.go
package lib
import "my-project/util"
// StartServer This way so that it can be invoked via libs
func StartServer() string {
return util.StartServer(true)
}如对此有任何帮助,将不胜感激。
编辑
我认为当嵌入式服务器试图创建一个新端口时会出现问题。我不知道一个应用程序是否有可能像nodejs一样在android上打开一个新的端口,戈朗会打开像http://localhost:8080这样的东西。
现在,我想,如果有一种方法来创建端口,那么我可以成功地运行我的应用程序,但我不知道具体如何。
我在想,如果我能在android上找到任何可用的端口,并使用它启动服务器,也许这个堆栈是可能的。在科特林,像这样的东西可能会在寻找港口方面起作用。
import java.net.ServerSocket
fun main() {
val serverPort = ServerSocket(0)
print(serverPort.toString())
}但当我尝试类似的东西时,它会在android应用程序上崩溃。
我已经在GitHub上上传了一个存储库,展示了我打算做的事情。它只是一个简单的golang服务器,使用gin和android应用程序(没有颤音) 这里可以买到。
发布于 2022-04-16 05:40:52
“我不知道一个应用程序是否有可能像nodejs一样在android上打开一个新端口,golang可以打开localhost:8080之类的东西。”
要找出根本原因,请尝试在android中运行HTTP,例如如何在Android中创建HTTP服务器?。如果成功,试着找出它们如何处理端口的不同之处。
此外,请确保您在androidmanifest.xml中拥有正确的权限。
(从我的评论中重新措辞)
https://stackoverflow.com/questions/71809021
复制相似问题