首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用颤振嵌入golang服务器

用颤振嵌入golang服务器
EN

Stack Overflow用户
提问于 2022-04-09 14:37:21
回答 1查看 638关注 0票数 9

我有用golang编写的web服务器,它使用graphql包格尔根戈姆作为数据库。

由于golang可以在android上编译和运行,所以我想创建我的应用程序的离线版本,其中sqlite可以用于离线存储,并将我的整个服务器导入为aar

我已经成功地构建了aar,并按照指示这里将它添加到我的颤振上。

当我运行我的应用程序时,服务器是在android上启动的,它似乎工作得很好。当在模拟器的铬应用程序上打开http://localhost:8080/时,我看到graphql操场运行时没有任何问题,就像我在windows浏览器上看到的那样。

我面临的唯一问题是,当服务器在后台运行时,颤振应用程序只显示一个空白屏幕。以下是启动app时打印的日志

代码语言:javascript
复制
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

代码语言:javascript
复制
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)
    }
}

这是飞镖代码

代码语言:javascript
复制
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;
    }
  }
}

我的应用程序的主要内容如下

代码语言:javascript
复制
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());
}

站在这一边,我如何启动服务器

代码语言:javascript
复制
//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。

代码语言:javascript
复制
//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上找到任何可用的端口,并使用它启动服务器,也许这个堆栈是可能的。在科特林,像这样的东西可能会在寻找港口方面起作用。

代码语言:javascript
复制
import java.net.ServerSocket

fun main() {
   val serverPort = ServerSocket(0)
   print(serverPort.toString())
}

但当我尝试类似的东西时,它会在android应用程序上崩溃。

我已经在GitHub上上传了一个存储库,展示了我打算做的事情。它只是一个简单的golang服务器,使用gin和android应用程序(没有颤音) 这里可以买到

EN

回答 1

Stack Overflow用户

发布于 2022-04-16 05:40:52

“我不知道一个应用程序是否有可能像nodejs一样在android上打开一个新端口,golang可以打开localhost:8080之类的东西。”

要找出根本原因,请尝试在android中运行HTTP,例如如何在Android中创建HTTP服务器?。如果成功,试着找出它们如何处理端口的不同之处。

此外,请确保您在androidmanifest.xml中拥有正确的权限。

(从我的评论中重新措辞)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71809021

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档