我有以下的Go脚本(testapp.go),我希望将其作为后台服务持续运行:
package main
import(
"net/http"
"time"
"log"
"golang.org/x/mobile/app"
)
func main() {
app.Main(func(a app.App) {
for {
req, err := http.NewRequest( "GET", "http://0.0.0.0:88/fetch_news", strings.NewReader("topic.title") )
if err != nil {
log.Print(err)
}
cli := &http.Client{}
res, err := cli.Do(req)
if err != nil {
log.Print(err)
} else {
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
returnStr := string(body)
// Do something with returnStr
}
time.Sleep(8 * time.Second)
}
})
}
我的 GoNativeActivity.java 文件如下:
package org.golang.app;
import android.app.Activity;
import android.app.NativeActivity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyCharacterMap;
public class GoNativeActivity extends NativeActivity {
private static GoNativeActivity goNativeActivity;
public GoNativeActivity() {
super();
goNativeActivity = this;
}
String getTmpdir() {
return getCacheDir().getAbsolutePath();
}
int getRune(int deviceId, int keyCode, int metaState) {
try {
int rune = KeyCharacterMap.load(deviceId).get(keyCode, metaState);
if (rune == 0) {
return -1;
}
return rune;
} catch (KeyCharacterMap.UnavailableException e) {
return -1;
} catch (Exception e) {
Log.e("Go", "exception reading KeyCharacterMap", e);
return -1;
}
}
private void load() {
// Interestingly, NativeActivity uses a different method
// to find native code to execute, avoiding
// System.loadLibrary. The result is Java methods
// implemented in C with JNIEXPORT (and JNI_OnLoad) are not
// available unless an explicit call to System.loadLibrary
// is done. So we do it here, borrowing the name of the
// library from the same AndroidManifest.xml metadata used
// by NativeActivity.
try {
ActivityInfo ai = getPackageManager().getActivityInfo(
getIntent().getComponent(), PackageManager.GET_META_DATA);
if (ai.metaData == null) {
Log.e("Go", "loadLibrary: no manifest metadata found");
return;
}
String libName = ai.metaData.getString("android.app.lib_name");
System.loadLibrary(libName);
} catch (Exception e) {
Log.e("Go", "loadLibrary failed", e);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
load();
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, org.golang.app.GoNativeService.class);
startService(intent);
}
}
我的GoNativeService.java文件看起来像这样:
package org.golang.app;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class GoNativeService extends IntentService {
@Override
public void onStart(Intent intent, int startId) {
Toast.makeText(this,"Service started. onStart()", Toast.LENGTH_SHORT).show();
handleCommand(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this,"Service started. onStartCommand()", Toast.LENGTH_SHORT).show();
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
}
我的 AndroidManifest.xml 文件长这样:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="org.golang.todo.testapp"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<application android:label="Testapp" android:debuggable="true">
<activity android:name="org.golang.app.GoNativeActivity"
android:label="Testactivity"
android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.lib_name" android:value="testapp" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="org.golang.app.GoNativeService"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
这是我的工作环境:
GOARCH="amd64"
GOBIN="/root/go/bin"
GOCACHE="/root/.cache/go-build"
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GOROOT="/usr/lib/go-1.10"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.10/pkg/tool/linux_amd64"
这是我的$GOPATH/src/testapp目录的样子:
testapp/
assets/
icon.png
AndroidManifest.xml
testapp.go
这是我的$GOPATH/src/golang.org/x/mobile/app 目录的样子:
app/
android.c
app_test.go
darwin_armx.go
GoNativeActivity.java
GoNativeService.java
internal/
x11.go
android.go
darwin_amd64.go
darwin_armx.m
shiny.go
app.go
darwin_amd64.m
doc.go
x11.c
如何在Android上将我的Go脚本作为后台服务运行,以便当应用程序退出(MainActivity关闭)时,后台服务将继续获取新闻消息?
注意:我正在监视端口88上的Web服务器请求。当GoNativeActivity
处于活动状态时,我可以正常运行脚本,但我想知道如何构建一个启动后台服务的原生应用程序。
如果有任何答案或指向正确方向的尝试,将不胜感激!