Android 3.0 проблема сота при разборе RSS-канала - PullRequest
1 голос
/ 08 июня 2011

Я пытаюсь проанализировать RSS-канал в сотах 3.0, но выдает ошибку следующим образом.

ОШИБКА / AndroidNews :: PullFeedParser (444): android.os.NetworkOnMainThreadException

Я пробовал тот же код в более низкой версии Android, он работает, но он не работает в Honeycomb.Пожалуйста, предложите некоторую помощь

Это в основной деятельности

try{
    FeedParser parser = new XmlPullFeedParser(feedUrl);
    messages = parser.parse();
    titles = new ArrayList<String>(messages.size());
    String description ="";//= new ArrayList<String>(messages.size());
    for (Message msg : messages){
        description = msg.getDescription().toString();
        Log.v("Desc", description);
            titles.add(description);
        }
    } catch (Throwable t){
    Log.e("AndroidNews",t.getMessage(),t);
}

Я использую XmlPullFeedParser, который расширяет BaseFeedParser

public class XmlPullFeedParser extends BaseFeedParser {

    public XmlPullFeedParser(String feedUrl) {
        super(feedUrl);
    }

    public List<Message> parse() {
        List<Message> messages = null;
        XmlPullParser parser = Xml.newPullParser();
        try {
            // auto-detect the encoding from the stream
            parser.setInput(this.getInputStream(), null);
            int eventType = parser.getEventType();
            Message currentMessage = null;
            boolean done = false;
            while (eventType != XmlPullParser.END_DOCUMENT && !done){
                String name = null;
                switch (eventType){
                    case XmlPullParser.START_DOCUMENT:
                        messages = new ArrayList<Message>();
                        break;
                    case XmlPullParser.START_TAG:
                        name = parser.getName();
                        if (name.equalsIgnoreCase(ITEM)){
                            currentMessage = new Message();
                        } else if (currentMessage != null){
                            if (name.equalsIgnoreCase(LINK)){
                                currentMessage.setLink(parser.nextText());
                            } else if (name.equalsIgnoreCase(DESCRIPTION)){
                                currentMessage.setDescription(parser.nextText());
                            } else if (name.equalsIgnoreCase(PUB_DATE)){
                                currentMessage.setDate(parser.nextText());
                            } else if (name.equalsIgnoreCase(TITLE)){
                                currentMessage.setTitle(parser.nextText());
                            }   
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        name = parser.getName();
                        if (name.equalsIgnoreCase(ITEM) && currentMessage != null){
                            messages.add(currentMessage);
                        } else if (name.equalsIgnoreCase(CHANNEL)){
                            done = true;
                        }
                        break;
                }
                eventType = parser.next();
            }
        } catch (Exception e) {
            Log.e("AndroidNews::PullFeedParser", e.getMessage(), e);
            throw new RuntimeException(e);
        }
        return messages;
    }
}

Это BaseFeedParser:

public class BaseFeedParser implements FeedParser {

    // names of the XML tags
    static final String CHANNEL = "channel";
    static final String PUB_DATE = "pubDate";
    static final  String DESCRIPTION = "description";
    static final  String LINK = "link";
    static final  String TITLE = "title";
    static final  String ITEM = "item";
    static final  String BODY = "body";

    private final URL feedUrl;

    protected BaseFeedParser(String feedUrl){
        try {
            this.feedUrl = new URL(feedUrl);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }

    protected InputStream getInputStream() {
        try {
            return feedUrl.openConnection().getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public List<Message> parse() {
        // TODO Auto-generated method stub
        return null;
    }
}

Это FeedParser:

public interface FeedParser {
    List<Message> parse();
}

Это класс сообщения:

public class Message implements Comparable<Message>{
    static SimpleDateFormat FORMATTER = 
        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
    private String title;
    private URL link;
    private String description;
    private Date date;
    private String body;

    public String getTitle() {
        return title;
    }

    public String getBody() {
        return body;
    }

    public void setTitle(String title) {
        this.title = title.trim();
    }
    // getters and setters omitted for brevity 
    public URL getLink() {
        return link;
    }

    public void setLink(String link) {
        try {
            this.link = new URL(link);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description.trim();
    }

    public String getDate() {
        return FORMATTER.format(this.date);
    }

    public void setDate(String date) {
        // pad the date if necessary
        while (!date.endsWith("00")){
            date += "0";
        }
        try {
            this.date = FORMATTER.parse(date.trim());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public Message copy(){
        Message copy = new Message();
        copy.title = title;
        copy.link = link;
        copy.description = description;
        copy.date = date;
        copy.body = body;
        return copy;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Title: ");
        sb.append(title);
        sb.append("Body: ");
        sb.append(body);
        sb.append('\n');
        sb.append("Date: ");
        sb.append(this.getDate());
        sb.append('\n');
        sb.append("Link: ");
        sb.append(link);
        sb.append('\n');
        sb.append("Description: ");
        sb.append(description);
        return sb.toString();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((date == null) ? 0 : date.hashCode());
        result = prime * result
                + ((description == null) ? 0 : description.hashCode());
        result = prime * result + ((link == null) ? 0 : link.hashCode());
        result = prime * result + ((title == null) ? 0 : title.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Message other = (Message) obj;
        if (date == null) {
            if (other.date != null)
                return false;
        } else if (!date.equals(other.date))
            return false;
        if (description == null) {
            if (other.description != null)
                return false;
        } else if (!description.equals(other.description))
            return false;
        if (link == null) {
            if (other.link != null)
                return false;
        } else if (!link.equals(other.link))
            return false;
        if (title == null) {
            if (other.title != null)
                return false;
        } else if (!title.equals(other.title)){
            return false;
        } else if (!body.equals(other.body))    
            return false;
        return true;
    }

    public int compareTo(Message another) {
        if (another == null) return 1;
        // sort descending, most recent first
        return another.date.compareTo(date);
    }
}

1 Ответ

1 голос
/ 14 июня 2011

Сообщение об ошибке здесь в значительной степени говорит вам, что происходит - вы пытаетесь получить доступ к сети в главном потоке.Вы действительно не должны делать это на любой версии Android, потому что это может (читай: будет) вызывать зависание вашего пользовательского интерфейса во время обработки соединения.

Есть способы отключить ошибку, но я выигралне вдавайтесь в них: вы не должны это делать.

Вместо этого вы хотите выполнить эту работу в фоновом потоке и опубликовать минимальный обработчик обратно в поток пользовательского интерфейса.У меня нет удобного примера (на моем планшете сейчас), но дайте мне знать, если вы не можете его найти.

.. edit .. OK, вот простой пример.Для этого требуется действие с текстовым представлением (идентификатор «текст») и, конечно, с правами доступа в Интернет.Дайте мне знать, если у вас есть какие-либо вопросы!

public class MainActivity extends Activity {
private TextView mTextView;

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

    mTextView = (TextView) findViewById(R.id.text);

    // start our call in a new thread
    (new Thread(new Runnable() {
        @Override
        public void run() {
            fetchPage();
        }
    })).start();
}

private void fetchPage() {
    try {
        URL url = new URL("http://stackoverflow.com/feeds");
        HttpURLConnection c = (HttpURLConnection) url.openConnection();
        c.setRequestMethod("GET");
        c.setDoOutput(true);
        c.connect();

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        InputStream is = c.getInputStream();

        byte[] buffer = new byte[1024];
        int len1 = 0;
        while ((len1 = is.read(buffer)) != -1) {
            bos.write(buffer, 0, len1);
        }
        bos.close();
        is.close();

        // Remember, all UI things must occur back on the UI thread!
        final String text = bos.toString();
        this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mTextView.setText(text);
            }
        });
    } catch (final IOException ioe) {
        this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, ioe.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }
}

спасибо, --randy

...