0

我无法运行我非常简单的 RSS 阅读器。当尝试运行应用程序强制关闭时,我的 logcat 在这一行给我一个错误:

InputSource myInputSource = new InputSource(rssUrl.openStream());

这是我的 MainActivity.java:

package com.banagas.polypost;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

String streamTitle = "";

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    TextView result = (TextView)findViewById(R.id.result);

    try {
        URL rssUrl = new URL("http://www.thepolypost.com/search/?q=&t=article&l=10&d=&d1=&d2=&s=start_time&sd=desc&c[]=news,news/*&f=rss");
        SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
        SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
        XMLReader myXMLReader = mySAXParser.getXMLReader();
        RSSHandler myRSSHandler = new RSSHandler();
        myXMLReader.setContentHandler(myRSSHandler);
        InputSource myInputSource = new InputSource(rssUrl.openStream());
        myXMLReader.parse(myInputSource);

        result.setText(streamTitle);

    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    } catch (ParserConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    } catch (SAXException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    }


}

private class RSSHandler extends DefaultHandler
{
    final int stateUnknown = 0;
    final int stateTitle = 1;
    int state = stateUnknown;

    int numberOfTitle = 0;
    String strTitle = "";
    String strElement = "";

    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        strTitle = "--- Start Document ---\n";
    }

    @Override
    public void endDocument() throws SAXException {
        // TODO Auto-generated method stub
        strTitle += "--- End Document ---";
        streamTitle = "Number Of Title: " + String.valueOf(numberOfTitle) + "\n"
            + strTitle;
    }

    @Override
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes) throws SAXException {
        // TODO Auto-generated method stub
        if (localName.equalsIgnoreCase("title"))
        {
            state = stateTitle;
            strElement = "Title: ";
            numberOfTitle++;
        }
        else
        {
            state = stateUnknown;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
    throws SAXException {
        // TODO Auto-generated method stub
        if (localName.equalsIgnoreCase("title"))
        {
            strTitle += strElement + "\n";
        }
        state = stateUnknown;
    }

    @Override
    public void characters(char[] ch, int start, int length)
    throws SAXException {
        // TODO Auto-generated method stub
        String strCharacters = new String(ch, start, length);
        if (state == stateTitle)
        {
            strElement += strCharacters;
        }
    }

}
}

这是我的清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest         xmlns:android="http://schemas.android.com/apk/res/android"
package="com.banagas.polypost"
android:versionCode="1"
android:versionName="1.0" >

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:label="@string/app_name"
        android:name=".MainActivity" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />

<uses-sdk 
    android:minSdkVersion="4" 
    android:targetSdkVersion="11" />

</manifest>

编辑:这是我的日志:

02-19 23:18:22.103 I/ActivityManager(  539): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.banagas.polypost/.MainActivity bnds=[540,922][540,922] u=0} from pid 1411
02-19 23:18:22.153 I/ActivityManager(  539): Start proc com.banagas.polypost for activity com.banagas.polypost/.MainActivity: pid=10710 uid=10225 gids={3003, 1028}
02-19 23:18:22.313 E/EmbeddedLogger(  539): App crashed! Process: com.banagas.polypost
02-19 23:18:22.313 E/EmbeddedLogger(  539): App crashed! Package: com.banagas.polypost v1 (1.0)
02-19 23:18:22.313 E/AndroidRuntime(10710): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.banagas.polypost/com.banagas.polypost.MainActivity}: android.os.NetworkOnMainThreadException
02-19 23:18:22.313 E/AndroidRuntime(10710):     at com.banagas.polypost.MainActivity.onCreate(MainActivity.java:40)
02-19 23:18:22.313 W/ActivityManager(  539):   Force finishing activity com.banagas.polypost/.MainActivity
02-19 23:18:22.864 W/ActivityManager(  539): Activity pause timeout for ActivityRecord{42908170 com.banagas.polypost/.MainActivity}
02-19 23:18:23.475 I/ActivityManager(  539): Process com.banagas.polypost (pid 10710) has died.
4

2 回答 2

1

你得到android.os.NetworkOnMainThreadException

当应用程序尝试在其主线程上执行网络操作时引发的异常。

这仅针对面向 Honeycomb SDK 或更高版本的应用程序抛出。允许以早期 SDK 版本为目标的应用程序在其主事件循环线程上进行网络连接,但非常不鼓励这样做。请参阅文档设计响应性。

文档

因此,您需要将try {与网络一起工作的块移动到与主线程不同的线程。阅读无痛线程以获得简单的方法。

于 2013-02-20T07:41:46.217 回答
0

Since Android 3, http requests are just forbidden in the main thread to prevent freezing devices. Because of without timeout requests and servers that do not answer, some requests turns to infinite loops and when the user touch his device screen, the system ask him to kill the app because it is not responding... To prevent this bad way to do things, the system throw this NetworkOnMainThreadException to alert developers.

My suggestion is to use an AsyncTask. The AsyncTask will execute the code you put in its doInBackground function in a Thread and will automatically call its onPostExecute function on the thread end giving this function what the doInBackground returned. The onPostExecute is synchronized with the MainThread and will be able to update it.

class RSSFeedAsyncTask extends AsyncTask<URL, Void, String>
{
    public interface RSSFeedAsyncTaskListener
    {
        public void setText(String text);
    }

    private RSSFeedAsyncTaskListener listener;

    public RSSFeedAsyncTask(RSSFeedAsyncTaskListener listener)
    {
        this.listener = listener;
    }

    protected Long doInBackground(URL... urls)
    {
        String streamTitle = "";
        URL url = urls[0];
        try
        {
            // Download and parse the feed
            ...
            streamTitle = XX;
        }
        // Will catch MalformedURLException,
        // ParserConfigurationException,
        // SAXException and
        // IOException
        catch(Exception exception)
        {
            streamTitle = "Cannot connect RSS!";
        }
    }

    protected void onPostExecute(String result)
    {
        this.listener.setText(result);
    }
}

Then to use it in your activity, you will just have to use your asynctask like this :

RSSFeedAsyncTask rssFeedAsyncTask = new RSSFeedAsyncTask(this);
rssFeedAsyncTask.execute(new URL("http://..."));

and implement the RSSFeedAsyncTaskListener interface function setText to update the UI after the AsynTask did his job.

于 2013-02-20T15:52:58.987 回答