访问RSS源中的URL时出错

时间:2013-02-20 07:11:11

标签: android rss

我无法运行我非常简单的RSS阅读器。当试图运行app force关闭时,我的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.

2 个答案:

答案 0 :(得分:1)

你得到 android.os.NetworkOnMainThreadException

  

应用程序尝试执行时抛出的异常   在其主线程上进行网络操作。

     

这仅适用于针对Honeycomb SDK或。的应用程序   更高。允许使用早期SDK版本的应用程序   他们的主要事件循环线程上的网络,但它是很重要的   泄气。请参阅文档设计响应性。

来自the documentation

因此,您需要将与网络一起使用的try {下的块移动到与主网络不同的线程。阅读painless threading以获取简单的方法。

答案 1 :(得分:0)

从Android 3开始,主要线程中禁止使用http请求以防止冻结设备。 由于没有超时请求和服务器没有回答,一些请求转向无限循环,当用户触摸他的设备屏幕时,系统要求他杀死应用程序,因为它没有响应...为了防止这种不好的方式做事情,系统抛出这个 NetworkOnMainThreadException 来警告开发人员。

我的建议是使用AsyncTask。 AsyncTask将执行你在线程中的 doInBackground 函数中放入的代码,并将在线程端自动调用其 onPostExecute 函数,为此函数提供 doInBackground < / strong>返回。 onPostExecute 与MainThread同步,并且可以更新它。

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);
    }
}

然后要在你的活动中使用它,你只需要像这样使用你的asynctask:

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

并实现 RSSFeedAsyncTaskListener 接口函数 setText ,以便在AsynTask完成其工作后更新UI。