Android:在服务中使用网络

问题描述 投票:10回答:2

在我的Android应用程序的Service类中调用REST WebService会创建NetworkOnMainThreadException

我理解为什么在Activity中引发这个异常:同步通过网络获取内容是一种非常糟糕的做法,但我很惊讶在服务类中看到同样的错误。所以我的问题是:

- 在这种特殊情况下,我应该使用StrictMode.setThreadPolicy()来允许这个电话。 (对于那些因为在活动中遇到此错误而读取此内容的人,请不要使用StrictMode来隐藏此错误,请使用AsyncTask)

- 或者我应该使用AsyncTask?在那种情况下,这里的问题是什么?线程上的服务不是与Activity分开的吗?

android networking service
2个回答
15
投票

即使Service用于后台处理,它们也可以在主线程中运行。

来自documentation的简短引用:

警告:默认情况下,服务在与声明它的应用程序相同的进程中运行,并在该应用程序的主线程中运行。因此,如果您的服务在用户与同一应用程序中的活动进行交互时执行密集或阻止操作,则该服务将降低活动性能。为避免影响应用程序性能,您应该在服务中启动一个新线程。

“后台处理”意味着服务没有用户界面,即使用户没有直接与应用程序交互,它也可以运行。但默认情况下,所有后台处理仍然在主线程中发生。

那么,如何解决它并摆脱异常呢?正如文档所示,您必须使用后台线程。在您的服务中,您可以使用AsyncTask或直接创建线程。但我想IntentService可能是最适合你的情况。 IntentService在后台线程中处理请求(这是您正在寻找的服务类型)。


0
投票

服务在主线程中运行,这就是你需要做的事情

public class ServiceDownloadSomething extends Service {

private static final String TAG = ServiceDownloadSomething.class.getSimpleName();

private boolean isRunning;
private Thread backgroundThread;

private Runnable myTask = new Runnable() {
    public void run() {
        while (true) {

            //sleep 30 seconds
            long sleepTime = System.currentTimeMillis() + (15 * 1000);

            try {
                Thread.sleep(sleepTime - System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            try {
                //perform network action
                downloadSomething();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
};

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    this.isRunning = false;
    this.backgroundThread = new Thread(myTask);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if(!this.isRunning) {
        this.isRunning = true;
        this.backgroundThread.start();
    }

    return START_STICKY;
}

@Override
public void onDestroy() {
    this.isRunning = false;
}

private void downloadSomething() throws IOException {

    URL url = new URL("http://192.168.197.101:8080/api/medias/");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setReadTimeout(10000 /* milliseconds */);
    conn.setConnectTimeout(15000 /* milliseconds */);
    conn.setRequestMethod("POST");
    conn.setDoInput(true);
    // Starts the query
    conn.connect();

    InputStream is = conn.getInputStream();
    StringBuilder sb = new StringBuilder();
    int r;
    do {
        r = is.read();

        if (r != -1){
            sb.append((char) r);
        }

    } while (r != -1);

    String json = sb.toString();
    Log.d(TAG, json);

}

}

© www.soinside.com 2019 - 2024. All rights reserved.