Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/221.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将简单的Go脚本作为Android服务运行?_Android_Go_Service_Gomobile - Fatal编程技术网

如何将简单的Go脚本作为Android服务运行?

如何将简单的Go脚本作为Android服务运行?,android,go,service,gomobile,Android,Go,Service,Gomobile,我有以下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:

我有以下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);
    }
}
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;
    }
}
<?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>
我的GoNativeService.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);
    }
}
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;
    }
}
<?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>
我的AndroidManifest.xml文件如下所示:

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);
    }
}
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;
    }
}
<?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>
这就是我的$GOPATH/src/testapp目录的外观:

testapp/
    assets/
        icon.png
    AndroidManifest.xml
    testapp.go
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
这是我的$GOPATH/src/golang.org/x/mobile/app目录的外观:

testapp/
    assets/
        icon.png
    AndroidManifest.xml
    testapp.go
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
处于活动状态时,我可以很好地运行脚本,但我想知道如何构建启动后台服务的本机应用程序


任何能给我指出正确方向的回答或尝试都将不胜感激

首先,有一个普遍的看法是,你真的不应该按自己的要求去做。正确的方法是使用AlarmManager发送广播,以唤醒单个请求的服务。这样系统可以更好地优化功耗。为此,让您的go代码只处理一个请求,并在广播时从Java端调用它

然而,要真正持久地运行服务,您需要启动一个“前台服务”,如前所述。这反过来需要在服务运行时显示通知。在这种情况下,您可能会发现设备本身也关闭了电源,在这种情况下,您需要考虑购买一个新的。除非你非常小心,否则这样做会大大缩短电池寿命

我发现以这种方式启动go代码对于Android上长时间运行的web服务器(包括使用WebSocket)来说已经足够了