Android Studio JSoup 服务
Android Studio JSoup Service
我 运行 Android Studio 2.3.2,我想制作一个应用程序,通过服务检查网站上的字符串。在没有后台服务 运行ning 的情况下使用 JSoup 库正常执行此操作工作正常,但将其作为服务尝试会在 LogCat 中出现错误并且无法正常工作。
public class BackgroundCheck extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String myurl = "http://s503426938.online.de/untis/Heute/subst_001.htm";
try {
// Connect to the web site
Document document = Jsoup.connect(myurl).get();
Element innerTable = document.getElementsByClass("mon_list").first();
Elements rows = innerTable.select("tr");
for (Element row : rows) {
Elements cells = row.select("td");
for (Element cell : cells) {
if (cell.className().equals("list")) {
if (cell.text().contains("10A")){
int notifID = 33;
int color = getResources().getColor(R.color.colorAccent);
long[] pattern = {0, 300, 200, 300};
PendingIntent settingsIntent = null;
String text = "es fällt bald etwas aus!";
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(BackgroundCheck.this)
.setSmallIcon(R.drawable.ic_notifications_black_24dp)
.setContentTitle("Vertretungsplan")
.setContentText(text)
.setColor(color)
.addAction(new NotificationCompat.Action(R.drawable.ic_menu_manage, "Settings", settingsIntent))
.setLights(color, 500, 500)
.setDefaults(Notification.DEFAULT_SOUND)
.setVibrate(pattern);
Notification notification = mBuilder.build();
Toast.makeText(BackgroundCheck.this,"10A",Toast.LENGTH_SHORT).show();
NotificationManagerCompat.from(BackgroundCheck.this).notify(notifID, notification);
}
}
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
Toast.makeText(BackgroundCheck.this,"Test",Toast.LENGTH_SHORT).show(); //Works Fine
Log.d("Vertretungsplan", "Checked: String");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
在我的 MainActivity 中,我将这些行添加到 OnCreate 方法中,以便在启动应用程序后创建后台服务 运行:
AlarmManager alarmManager = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
Intent check = new Intent(MainActivity.this, BackgroundCheck.class);
PendingIntent startServicependingIntent = PendingIntent.getService(MainActivity.this,0,check,0);
Calendar calendar = Calendar.getInstance();
int intervall = 1000*60;
calendar.setTimeInMillis(System.currentTimeMillis() + intervall);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),intervall,startServicependingIntent);`
现在 Logcat 在尝试从 table 中的服务器获取字符串时抛出以下错误:
> 06-11 19:51:45.639 18293-18293/org.ddnss.jojeker.vertretungsplan D/Vertretungsplan: Checked: String
06-11 19:52:45.617 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: android.os.NetworkOnMainThreadException
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.net.InetAddress.getAllByName(InetAddress.java:752)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:187)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:156)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:98)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:346)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:247)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:439)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:424)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:178)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection.get(HttpConnection.java:167)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.ddnss.jojeker.vertretungsplan.BackgroundCheck.onStartCommand(BackgroundCheck.java:35)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3366)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread.-wrap21(ActivityThread.java)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1612)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.os.Looper.loop(Looper.java:154)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6236)
06-11 19:52:45.619 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.lang.reflect.Method.invoke(Native Method)
06-11 19:52:45.619 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
06-11 19:52:45.619 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
通常我使用 AsyncTask 来执行 JSoup 的操作,但我认为这不是必需的服务。我用 Toast 来确保我没有犯任何基本错误。
所以我的问题是:这是通过 JSoup 获取数据即服务的 "right" 方式,还是我在这种情况下使用它做错了什么。
是否有其他更易于使用的库,或者 JSoup 是此类工作的正确选择?
先谢谢你了!
您仍然需要生成一个线程。根据 Android Services 文档:
Caution: A service runs in the main thread of its hosting process; the service does not create its own thread and does not run in a separate process unless you specify otherwise. If your service is going to perform any CPU-intensive work or blocking operations, such as MP3 playback or networking, you should create a new thread within the service to complete that work.
堆栈跟踪中也提到了这个问题:
W/System.err: android.os.NetworkOnMainThreadException
我 运行 Android Studio 2.3.2,我想制作一个应用程序,通过服务检查网站上的字符串。在没有后台服务 运行ning 的情况下使用 JSoup 库正常执行此操作工作正常,但将其作为服务尝试会在 LogCat 中出现错误并且无法正常工作。
public class BackgroundCheck extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String myurl = "http://s503426938.online.de/untis/Heute/subst_001.htm";
try {
// Connect to the web site
Document document = Jsoup.connect(myurl).get();
Element innerTable = document.getElementsByClass("mon_list").first();
Elements rows = innerTable.select("tr");
for (Element row : rows) {
Elements cells = row.select("td");
for (Element cell : cells) {
if (cell.className().equals("list")) {
if (cell.text().contains("10A")){
int notifID = 33;
int color = getResources().getColor(R.color.colorAccent);
long[] pattern = {0, 300, 200, 300};
PendingIntent settingsIntent = null;
String text = "es fällt bald etwas aus!";
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(BackgroundCheck.this)
.setSmallIcon(R.drawable.ic_notifications_black_24dp)
.setContentTitle("Vertretungsplan")
.setContentText(text)
.setColor(color)
.addAction(new NotificationCompat.Action(R.drawable.ic_menu_manage, "Settings", settingsIntent))
.setLights(color, 500, 500)
.setDefaults(Notification.DEFAULT_SOUND)
.setVibrate(pattern);
Notification notification = mBuilder.build();
Toast.makeText(BackgroundCheck.this,"10A",Toast.LENGTH_SHORT).show();
NotificationManagerCompat.from(BackgroundCheck.this).notify(notifID, notification);
}
}
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
Toast.makeText(BackgroundCheck.this,"Test",Toast.LENGTH_SHORT).show(); //Works Fine
Log.d("Vertretungsplan", "Checked: String");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
}
在我的 MainActivity 中,我将这些行添加到 OnCreate 方法中,以便在启动应用程序后创建后台服务 运行:
AlarmManager alarmManager = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
Intent check = new Intent(MainActivity.this, BackgroundCheck.class);
PendingIntent startServicependingIntent = PendingIntent.getService(MainActivity.this,0,check,0);
Calendar calendar = Calendar.getInstance();
int intervall = 1000*60;
calendar.setTimeInMillis(System.currentTimeMillis() + intervall);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),intervall,startServicependingIntent);`
现在 Logcat 在尝试从 table 中的服务器获取字符串时抛出以下错误:
> 06-11 19:51:45.639 18293-18293/org.ddnss.jojeker.vertretungsplan D/Vertretungsplan: Checked: String
06-11 19:52:45.617 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: android.os.NetworkOnMainThreadException
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.net.InetAddress.getAllByName(InetAddress.java:752)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.Network.resolveInetAddresses(Network.java:29)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:187)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:156)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:98)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:346)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:247)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:439)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:424)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:178)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.jsoup.helper.HttpConnection.get(HttpConnection.java:167)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at org.ddnss.jojeker.vertretungsplan.BackgroundCheck.onStartCommand(BackgroundCheck.java:35)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3366)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread.-wrap21(ActivityThread.java)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1612)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.os.Looper.loop(Looper.java:154)
06-11 19:52:45.618 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6236)
06-11 19:52:45.619 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at java.lang.reflect.Method.invoke(Native Method)
06-11 19:52:45.619 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
06-11 19:52:45.619 18293-18293/org.ddnss.jojeker.vertretungsplan W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
通常我使用 AsyncTask 来执行 JSoup 的操作,但我认为这不是必需的服务。我用 Toast 来确保我没有犯任何基本错误。 所以我的问题是:这是通过 JSoup 获取数据即服务的 "right" 方式,还是我在这种情况下使用它做错了什么。 是否有其他更易于使用的库,或者 JSoup 是此类工作的正确选择?
先谢谢你了!
您仍然需要生成一个线程。根据 Android Services 文档:
Caution: A service runs in the main thread of its hosting process; the service does not create its own thread and does not run in a separate process unless you specify otherwise. If your service is going to perform any CPU-intensive work or blocking operations, such as MP3 playback or networking, you should create a new thread within the service to complete that work.
堆栈跟踪中也提到了这个问题:
W/System.err: android.os.NetworkOnMainThreadException