Pull to refresh

Простой RSS-клиент на Android

Reading time 14 min
Views 109K
Пошаговое руководство по созданию RSS-клиента на Android. Статья для начинающих разработчиков.
Android – операционная система для мобильных устройств от Google.
Система очень перспективная и динамично развивается. Базовые навыки разработки будут совсем не лишними.
Осторожно много скриншотов!

1. Начало

Вначале нужно зайти на официальный сайт и ознакомиться с возможностями последней версии Android 2.2. На сайте есть специальный раздел для разработчиков. Тут можно скачать все необходимые инструменты, найти инструкцию по установке, инструкцию по созданию первого приложения и справку по пакетам и классам библиотеки.

2. Установка SDK

На компьютере должен быть установлен JDK версии 5 или 6. Для разработки под Android нужно скачать и установить Android SDK, в котором есть эмулятор Android. Далее нужно установить Eclipse версии 3.4 или 3.5. И последнее, нужно установить плагин ADT для Eclipse.

3. Создание RSS-клиента

За основу я взял статью Creating Rss Reader in Android. Но в статье есть ошибки, и получить рабочей приложение сразу не получится. По моей просьбе, автор выложил полный рабочий проект. Но пока шла переписка, я сам исправил ошибки и написал свою версию программы.

3.1. Создание проекта
Запускаем Eclipse, выбираем меню File->New->Project. Запускается диалог New Project, выбираем папку Android и проект Android Project, жмем Next.

image

Открывается окно New Android Project. Заполняем поле Project name: uRSS, Выбираем в таблице Build Target строку Android 2.2. Дальше нужно заполнить свойства проекта в разделе Properties.

Application name: uRSS.
Package name: rembo.network.urss.
RSSactivity.
Min SDK Version: 8.

Жмем Next и в следующем окне ничего не меняем и жмем Finish.

image

image

Все проект создан.

3.2. Написание кода
Eclipse создаст много папок и файлов проекта (в них легко запутаться).
Главные файлы такие:
src/rembo.network.rss/RSSactivity.java – файл с классом RSSactivity, который задает логику главного окна (тут напишем обработчики событий);
res/layout/main.xml – XML описание главного окна (тут создадим элементы управления);
AndroidManifest.xml – файл описания свойств приложения (тут свяжем XML описание с кодом и зададим разрешение на работу в сети).

Для начала зададим содержимое главного окна в файле res/layout/main.xml. Главное окно будет построено на основе контейнера LinearLayout. Оно содержит надпись TextView, поле для ввода текста EditText, кнопку Button и список ListView. Обратите внимание, что у каждого элемента есть android:id. Это идентификатор по которому с элементом интерфейса можно связаться из кода.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
  
  <TextView
  android:id="@+id/label"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Enter RSS URL:"
  />
  
  <EditText
  android:id="@+id/rssURL"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@android:drawable/editbox_background"
  android:text="http://feeds.feedburner.com/MicrosoftUserGroupVinnitsya"
  />
  
  <Button
  android:id="@+id/fetchRss"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginRight="10dip"
  android:text="Fetch Rss" />

  <ListView
  android:id="@+id/rssListView"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content" />
</LinearLayout>

* This source code was highlighted with Source Code Highlighter.


Для элемента списка нужно задать содержимое. Для этого создайте файл res/layout/list_item.xml.

<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="13sp"
android:autoLink="all" >
</TextView>

* This source code was highlighted with Source Code Highlighter.


При нажатии на элемент списка, новость должна открыться в новом окне. Создадим файл res/layout/rss_item_displayer.xml для этого окна.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
 >
 
 <TextView
  android:id="@+id/titleTextView"
   android:text="Title:"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:padding="10dp"
  android:textSize="13sp"
  android:autoLink="all"
  />
 
 <TextView
  android:id="@+id/contentTextView"
  android:text="Content:"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:textSize="13sp"
  android:autoLink="all"
  />
  
</LinearLayout>

* This source code was highlighted with Source Code Highlighter.


Итак, интерфейс создан. Теперь нужно писать код. Создаем новый класс RssItem в файле src/rembo.network.rss/RssItem.java. Класс получает RSS содержимое из Интернета.

package rembo.network.urss;
import java.util.*;
import java.text.*;
import java.net.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;

public class RssItem {

  private String title;
  private String description;
  private Date pubDate;
  private String link;

  public RssItem(String title, String description, Date pubDate, String link) {
    this.title = title;
    this.description = description;
    this.pubDate = pubDate;
    this.link = link;
  }
  
  public String getTitle()
  {
    return this.title;
  }
  
  public String getLink()
  {
    return this.link;
  }
  
  public String getDescription()
  {
    return this.description;
  }
  
  public Date getPubDate()
  {
    return this.pubDate;
  }
  
  @Override
  public String toString() {

    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd - hh:mm:ss");

    String result = getTitle() + "  ( " + sdf.format(this.getPubDate()) + " )";
    return result;
  }

  public static ArrayList<RssItem> getRssItems(String feedUrl) {

    ArrayList<RssItem> rssItems = new ArrayList<RssItem>();
    
    RssItem rssItemT = new RssItem("MSUG news", "Best IT news.",
        new Date(), "http://msug.vn.ua/");

    rssItems.add(rssItemT);

    try {
      //open an URL connection make GET to the server and
      //take xml RSS data
      URL url = new URL(feedUrl);
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();

      if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
        InputStream is = conn.getInputStream();

        //DocumentBuilderFactory, DocumentBuilder are used for
        //xml parsing
        DocumentBuilderFactory dbf = DocumentBuilderFactory
            .newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();

        //using db (Document Builder) parse xml data and assign
        //it to Element
        Document document = db.parse(is);
        Element element = document.getDocumentElement();

        //take rss nodes to NodeList
        NodeList nodeList = element.getElementsByTagName("item");

        if (nodeList.getLength() > 0) {
          for (int i = 0; i < nodeList.getLength(); i++) {

            //take each entry (corresponds to <item></item> tags in
            //xml data

            Element entry = (Element) nodeList.item(i);

            Element _titleE = (Element) entry.getElementsByTagName(
                "title").item(0);
            Element _descriptionE = (Element) entry
                .getElementsByTagName("description").item(0);
            Element _pubDateE = (Element) entry
                .getElementsByTagName("pubDate").item(0);
            Element _linkE = (Element) entry.getElementsByTagName(
                "link").item(0);

            String _title = _titleE.getFirstChild().getNodeValue();
            String _description = _descriptionE.getFirstChild().getNodeValue();
            Date _pubDate = new Date(_pubDateE.getFirstChild().getNodeValue());
            String _link = _linkE.getFirstChild().getNodeValue();

            //create RssItemObject and add it to the ArrayList
            RssItem rssItem = new RssItem(_title, _description,
                _pubDate, _link);

            rssItems.add(rssItem);
          }
        }

      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    return rssItems;
  }

}

* This source code was highlighted with Source Code Highlighter.


Теперь создадим класс RssItemDisplayer в файле src/rembo.network.rss/RssItemDisplayer.java. Он отвечает за логику окна, которое показывает полный текст новости. Обратите внимание как по id элемента управления его получают в коде TextView titleTv = (TextView)findViewById(R.id.titleTextView);

package rembo.network.urss;
import android.app.Activity;
import android.os.Bundle;
import android.widget.*;
import java.util.*;
import java.text.*;
import java.net.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import android.view.*;
public class RssItemDisplayer extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.rss_item_displayer);

    RssItem selectedRssItem = RSSactivity.selectedRssItem;
    //Bundle extras = getIntent().getExtras();
    TextView titleTv = (TextView)findViewById(R.id.titleTextView);
    TextView contentTv = (TextView)findViewById(R.id.contentTextView);

    String title = "";
    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd - hh:mm:ss");
    title = "\n" + selectedRssItem.getTitle() + "  ( "
        + sdf.format(selectedRssItem.getPubDate()) + " )\n\n";

    String content = "";
    content += selectedRssItem.getDescription() + "\n"
        + selectedRssItem.getLink();

    titleTv.setText(title);
    contentTv.setText(content);
  }
}

* This source code was highlighted with Source Code Highlighter.


Теперь пишем код класса RSSactivity в файле src/rembo.network.rss/ RSSactivity.java.java. Он отвечает за логику главного окна. Обратите внимание как создаются обработчики событий для клика по кнопке и по элементу списка fetchRss.setOnClickListener(new View.OnClickListener()…

package rembo.network.urss;

import android.app.Activity;
import android.os.Bundle;
import android.widget.*;
import java.util.*;
import java.text.*;
import java.net.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import android.view.*;
import android.view.View;
import android.widget.*;
import android.content.*;

public class RSSactivity extends Activity {
  
  public static RssItem selectedRssItem = null;
  String feedUrl = "";
  ListView rssListView = null;
  ArrayList<RssItem> rssItems = new ArrayList<RssItem>();
  ArrayAdapter<RssItem> aa = null;

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

    // get textview from our layout.xml
    final TextView rssURLTV = (TextView) findViewById(R.id.rssURL);

    // get button from layout.xml
    Button fetchRss = (Button) findViewById(R.id.fetchRss);

    // define the action that will be executed when the button is clicked.
    fetchRss.setOnClickListener(new View.OnClickListener() {

      //@Override
      public void onClick(View v) {
        feedUrl = rssURLTV.getText().toString();
        //TextView TVtitle=(TextView)findViewById(R.id.label);
        //CharSequence cs="fetching";
        //TVtitle.setText(cs);
        aa.notifyDataSetChanged();
        refressRssList();
        //cs="Feed:";
        //TVtitle.setText(cs);
      }
    });

    // get the listview from layout.xml
    rssListView = (ListView) findViewById(R.id.rssListView);
    // here we specify what to execute when individual list items clicked
    rssListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

      //@Override
      public void onItemClick(AdapterView<?> av, View view, int index,
          long arg3) {
        selectedRssItem = rssItems.get(index);

        // we call the other activity that shows a single rss item in
        // one page
        Intent intent = new Intent(
            "rembo.network.urss.displayRssItem");
        startActivity(intent);
      }
    });

        //adapters are used to populate list. they take a collection,
        //a view (in our example R.layout.list_item
    aa = new ArrayAdapter<RssItem>(this, R.layout.list_item, rssItems);
        //here we bind array adapter to the list
    rssListView.setAdapter(aa);
    feedUrl = rssURLTV.getText().toString();
    refressRssList();
  }

  private void refressRssList() {

    ArrayList<RssItem> newItems = RssItem.getRssItems(feedUrl);

    rssItems.clear();
    rssItems.addAll(newItems);

    //TextView TVtitle=(TextView)findViewById(R.id.label);
    //CharSequence cs="0";
    //if(newItems.size()>0) cs="is 1";
    //if(newItems.size()>5) cs="is 5";
    ///TVtitle.setText(cs);
    
    aa.notifyDataSetChanged();
  }

}

* This source code was highlighted with Source Code Highlighter.


Остался последний штрих. Нужно связать интерфейс и код в файле AndroidManifest.xml и разрешить приложению выход в Интернет.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="rembo.network.urss"
   android:versionCode="1"
   android:versionName="1.0">
  <application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".RSSactivity"
         android:label="@string/app_name">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity android:name=".RssItemDisplayer" android:label="Display Rss Item">
      <intent-filter>
        <action android:name="rembo.network.urss.displayRssItem" />
        <category android:name="android.intent.category.DEFAULT"></category>
      </intent-filter>
    </activity>
    

  </application>
  <uses-permission android:name="android.permission.INTERNET" />

</manifest>

* This source code was highlighted with Source Code Highlighter.


3.3. Запуск
Пора запускать наше приложение. Но вначале нужно создать виртуальную машину. Для этого в Eclipse переходим в меню Window->Android SDK and AVD Manager.

image

Жмем New и выбираем свойства виртуальной машины. В разделе Hardware обязательно нужно добавить GSM modem, поддержку Touchscreeen, Device ram size и Max VM application heap size (при такой конфигурации устройство удачно подключается к Интернету). Жмем Create AVD (тут придется немного подождать).

image

Жмем кнопку старт и запускаем виртуальную машину. Тут нужно запастись терпением. Ждать придется минут 10-20, пока машина не загрузится. Убедитесь, что виртуальное устройство подключено к Интернету. Если нет, то попробуйте перегрузиться или создать новую машину.

image

image

image

image

После запуска виртуальной машины переходим в Eclipse и запускаем приложение (жмем Run). Снова придется подождать минут 5, пока приложение установится на виртуальную машину и запустится. Если приложение не запускается, то попробуйте выключить виртуальную машину и запустить приложение (тут уже придется долго ждать, пока виртуальная машина стартует снова).

image

image
Tags:
Hubs:
+61
Comments 46
Comments Comments 46

Articles