努力尽今夕,少年犹可夸。这篇文章主要讲述Android:在服务中使用网络相关的知识,希望能为你提供帮助。
【Android(在服务中使用网络)】在我的android应用程序的Service类中调用REST WebService会创建NetworkOnMainThreadException
。
我理解为什么在Activity中引发这个异常:同步通过网络获取内容是一种非常糟糕的做法,但我很惊讶在服务类中看到同样的错误。所以我的问题是:
- 在这种特殊情况下,我应该使用StrictMode.setThreadPolicy()
来允许这个电话。 (对于那些因为在活动中遇到此错误而读取此内容的人,请不要使用StrictMode来隐藏此错误,请使用AsyncTask)
- 或者我应该使用AsyncTask?在那种情况下,这里的问题是什么?线程上的服务不是与Activity分开的吗?
答案即使Service用于后台处理,它们也可以在主线程中运行。
来自documentation的简短引用:
警告:默认情况下,服务在与声明它的应用程序相同的进程中运行,并在该应用程序的主线程中运行。因此,如果您的服务在用户与同一应用程序中的活动进行交互时执行密集或阻止操作,则该服务将降低活动性能。为避免影响应用程序性能,您应该在服务中启动一个新线程。“后台处理”意味着服务没有用户界面,即使用户没有直接与应用程序交互,它也可以运行。但默认情况下,所有后台处理仍然在主线程中发生。
那么,如何解决它并摆脱异常呢?正如文档所示,您必须使用后台线程。在您的服务中,您可以使用
AsyncTask
或直接创建线程。但我想IntentService可能是最适合你的情况。 IntentService
在后台线程中处理请求(这是您正在寻找的服务类型)。另一答案服务在主线程中运行,这就是你需要做的事情
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);
}
}
推荐阅读
- Linux到Android蓝牙网络共享(PAN)
- 邮件发送到.herokuapp.com域
- Facebook AppRequests +浏览器兼容性
- Android中SVG和VectorDrawable的区别
- 有人可以帮我理解appendChild方法实际发生了什么吗()
- 线程“JavaFX Application Thread”中的异常java.lang.NoClassDefFoundError
- Android GSON使用POST方法
- 必须使用app access_token调用此方法
- Facebook通知API(“必须使用app access_token调用此方法”)