我在Android应用程序上使用JSoup时遇到问题,因为我有一个NetworkOnMainThreadException。我使用AsyncTask来获取我的网站标签的信息,但我不知道我是否正确操作,所以我需要帮助才能做到这一点。这是代码:
主要活动:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
tagsSP = (Spinner) findViewById(R.id.spinner);
String myPage = "http://www.mypage.com";
TagGetter tG = new TagGetter();
ArrayList<Tag> a;
tG.setPage(myPage);
try {
a = tG.execute(myPage).get();
this.fillSpinner(a);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void fillSpinner(ArrayList<Tag> a) {
String[] numTags = new String[a.size()];
for(int i=0;i<a.size();i++){
numTags[i] = a.get(i).getTitle();
}
arrayAdapterTags = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item,numTags);
tagsSP.setAdapter(arrayAdapterTags);
}
这是AsyncTask代码:
public class TagGetter extends AsyncTask<String, Void, ArrayList<Tag>> {
Document html;
String className, page;
ArrayList<Tag> tags;
/**
* This method is from the AsyncTask class. It will run with the method "execute"
*
* @param params
* @return
*/
@Override
protected ArrayList<Tag> doInBackground(String... params) {
this.tags = getTags();
return this.tags;
}
/**
* This method allows to you to set a url where you can get the tags.
*
* @param url
*/
public void setPage(String url) {
this.page = url;
}
/**
* This method gives to you an ArrayList of tags.
*
* @return
*/
public ArrayList<Tag> getTags() {
ArrayList<Tag> tgs = new ArrayList<Tag>();
try {
html = getConnect(page);
className = "tag_col_0";
Elements items = html.getElementsByClass(className);
String[] col_0 = getValuesTag(html, "tag_col_0", "b");
String[] col_1 = getValuesTag(html, "tag_col_1", "b");
String[] col_2 = getValuesTag(html, "tag_col_2", "b");
String[] col_3 = getValuesTag(html, "tag_col_3", "b");
String[] tag_names = new String[col_0.length + col_1.length + col_2.length + col_3.length];
tag_names = appendArrayString(col_0, col_1, tag_names);
tag_names = appendArrayString(tag_names, col_2, tag_names);
tag_names = appendArrayString(tag_names, col_3, tag_names);
String[] url_0 = getURL(html, "tag_col_0", "href");
String[] url_1 = getURL(html, "tag_col_1", "href");
String[] url_2 = getURL(html, "tag_col_2", "href");
String[] url_3 = getURL(html, "tag_col_3", "href");
String[] tag_links = new String[col_0.length + col_1.length + col_2.length + col_3.length];
tag_links = appendArrayString(url_0, url_1, tag_links);
tag_links = appendArrayString(tag_links, url_2, tag_links);
tag_links = appendArrayString(tag_links, url_3, tag_links);
int n = tag_names.length;
for (int i = 0; i < n; i++) {
tgs.add(new Tag(tag_names[i], page+"/"+ tag_links[i]));
}
} catch (IOException e) {
e.printStackTrace();
}
return tgs;
}
/**
* This method returns the conection to a web page.
*
* @param link
* @return
* @throws IOException
*/
public Document getConnect(String link) throws IOException {
return Jsoup.connect(link).get();
}
/**
* This method allows to you to append two arrays.
*
* @param arrayX
* @param arrayY
* @param build
* @return
*/
public String[] appendArrayString(String[] arrayX, String[] arrayY, String[] build) {
int x = arrayX.length;
int y = arrayY.length;
int n = 0;
build = new String[x + y];
for (int i = 0; i < x; i++) {
build[i] = arrayX[i];
n = i;
}
for (int i = 0; i < y; i++) {
build[i + n] = arrayY[i];
}
return build;
}
/**
* This method returns the url of a tag.
*
* @param item = the connection
* @param name = the name of the main class (or tag)
* @param prin = the name of the attribute you're looking for
* @return
*/
public String[] getURL(Document item, String name, String prin) {
Elements e = item.getElementsByClass(name);
int n = e.size();
String[] elements = new String[n];
if (e != null && n > 0) {
for (int i = 0; i < n; i++) {
Element element = (Element) e.get(i);
elements[i] = element.getElementsByAttribute(prin).text();
}
}
return elements;
}
/**
* This method returns the name of the tag.
*
* @param item = the connection
* @param name = the name of the main class (or tag)
* @param prin = the name of the tag you're looking for
* @return
*/
public String[] getValuesTag(Document item, String name, String prin) {
Elements e = item.getElementsByClass(name);
int n = e.size();
String[] elements = new String[n];
if (e != null && n > 0) {
for (int i = 0; i < n; i++) {
Element element = (Element) e.get(i);
elements[i] = element.getElementsByTag(prin).text();
}
}
return elements;
}
Tag对象的构造函数只需要标记名称和标记url。
问题出在哪里?
PD:我在清单中有 android.permission.ACCESS_NETWORK_STATE 和 android.permission.INTERNET 。
答案 0 :(得分:0)
当应用程序尝试在其主线程上执行网络操作时引发的异常。
仅针对Honeycomb SDK或更高版本的应用程序进行此操作。针对早期SDK版本的应用程序可以在其主要事件循环线程上进行联网,但是非常不鼓励。
因此,尝试使用AsyncTask如下:
public class ForgotPasswordTask extends AsyncTask<String, String, String> {
protected void onPreExecute() {}
@Override
protected String doInBackground(String... urls) {
HttpURLConnection urlConnection = null;
StringBuilder builder = new StringBuilder();
try {
/* forming th java.net.URL object */
URL url = new URL("http://www.mypage.com");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
int statusCode = urlConnection.getResponseCode();
/* 200 represents HTTP OK */
if (statusCode == 200) {
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
builder.append(inputLine);
}
in.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
return builder.toString();
}
protected void onPostExecute(String result) {
//get result/response generated from onPostExecute()
}
}