Po dłuższym utęsknieniu i znalezieniu czasu pomiędzy pracą inżynierską, graniem a przeklinaniem na notebook, znalazłem czas oraz chęci na kontynuowanie kursu programowania na platformę Android. Tym razem obiektem mojego kursu zostały listy oraz wg sondaży czytnik rss (przykro mi, bazy będą w innej części).
Jako, że lotto nie ma oficjalnego czytnika rss , użyję rss z mojego serwisu. (https://szymonmotyka.pl/feed/)
Zacznijmy więc od stworzenia layoutu dla naszego czytnika ( oczywiście, layout będzie fragmentem poprzednio stworzonego layoutu:
< ?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <textview android:id="@+id/TextView08" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#0C5687" android:text="@string/rss" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="#FFD11C" android:textStyle="bold"></textview> <listview android:id="@id/android:list" android:layout_width="match_parent" android:layout_height="match_parent" > </listview> </linearlayout>
Jest to prosty layout z listview z nagłówkiem znanym z innych fragmentów. Urodziwe to nie jest, ale działa. Reszta zależy od was czytelnicy
Kolejnym krokiem jest też dodanie layoutu dla wierszy naszej linii, by adapter wiedział, co gdzie umieścić.
< ?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/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge"></textview> <textview android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Medium Text" android:textAppearance="?android:attr/textAppearanceMedium"></textview> <textview android:id="@+id/date" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Small Text" android:textAppearance="?android:attr/textAppearanceSmall"></textview> </linearlayout>
Kolejnym krokiem jest utworzenie nowego fragmentu, tym razem dziedziczącego po listfragment
public class RSS extends ListFragment { ArrayList<rssmodel> rsslist=new ArrayList</rssmodel><rssmodel>(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View mainView = inflater.inflate(R.layout.rsslayout, container, false); //Tworzenie przykładowej arraylisty, którą potem uzupełnimy wpisami z rss rsslist.add(new RSSModel("Test", "testskontent", "http://developer.android.com/reference/android/app/ListFragment.html","10-10-2012")); <pre> //Tworzenie obiektu rssAdapter RSSAdapter rssAdapter=new RSSAdapter(getActivity(), rsslist); //PRzypisanie jej do listy setListAdapter(rssAdapter); return mainView; } @Override public void onListItemClick (ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(rsslist.get(position).getLink())); startActivity(intent); } }
Jest to prosty fragment dziedziczący po listFragment. Dodatkowo dzięki metodzie onListItemClick można zaimplementować zdarzenie po kliknięciu w element listy.
Dodatkowo do naszej metody trzeba zaimplementować klasy RSSModel
class RSSModel { private String Title; private String Link; private String Date; public String getTitle() { return Title; } public void setLink(String string) { Link=string; } public void setDate(String string) { Date=string; } public void setTitle(String string) { Title=string; } public String getLink() { return Link; } public String getDate() { return Date; } public RSSModel() { } }
oraz najważniejsze w przypadku listy. czyli adapter:
class RSSAdapter extends ArrayAdapter<rssmodel>{ private final Activity context; private ArrayList</rssmodel><rssmodel> rssy; /* * Konstruktor pobierający listę RSS, ustawiający layout dla linijek naszego rss */ public RSSAdapter(Activity context, ArrayList</rssmodel><rssmodel> lista) { super(context, R.layout.rssrow, lista); this.context = context; this.rssy=lista; } static class ViewHolder { public TextView tytul; public TextView date; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; View rowView = convertView; if (rowView == null) { LayoutInflater inflater = context.getLayoutInflater(); rowView = inflater.inflate(R.layout.rssrow, null, true); holder = new ViewHolder(); holder.tytul= (TextView) rowView.findViewById(R.id.title); holder.date=(TextView) rowView.findViewById(R.id.date); rowView.setTag(holder); } else { holder = (ViewHolder) rowView.getTag(); } //Przypisanie elementów z arraylist do wierszy naszej listy holder.tytul.setText(rssy.get(position).getTitle()); holder.date.setText(rssy.get(position).getDate()); return rowView; } }
Takim oto sposobem, nasz fragment powinien wyglądać tak:
Teraz zabierzmy się za nasz prosty czytnik RSS. Ze względów estetycznych. Utworzę do niego osobną metodę, która zwracać będzie ArrayList<RSSModel>. Uwierzcie. Dawanie wszystkich instrukcji do głównej metody utrudnia nam potem wrócenie do tego kodu 😉
I teraz zaczyna się zabawa:
RSS:
private ArrayList</rssmodel><rssmodel> getRSS() { String url="https://szymonmotyka.pl/feed/"; SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser; RssParseHandler handler = new RssParseHandler(); try { saxParser = factory.newSAXParser(); saxParser.parse(url, handler); } catch (ParserConfigurationException e1) { e1.printStackTrace(); } catch (SAXException e1) { e1.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return handler.getItems(); }
Wywołujemy metodę,
rsslist=getRSS();
w onCreateView.
a na końcu dodajemy klasę :
class RssParseHandler extends DefaultHandler { private ArrayList</rssmodel><rssmodel> rssItems; private RSSModel currentItem; private boolean parsingTitle; private boolean parsingLink; private boolean parsingDate; public RssParseHandler() { rssItems = new ArrayList</rssmodel><rssmodel>(); } public ArrayList</rssmodel><rssmodel> getItems() { return rssItems; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("item".equals(qName)) { currentItem = new RSSModel(); } else if ("title".equals(qName)) { parsingTitle = true; } else if ("link".equals(qName)) { parsingLink = true; } else if ("pubDate".equals(qName)) parsingDate=true; } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("item".equals(qName)) { rssItems.add(currentItem); currentItem = null; } else if ("title".equals(qName)) { parsingTitle = false; } else if ("link".equals(qName)) { parsingLink = false; } else if ("pubDate".equals(qName)) { parsingDate = false; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (parsingTitle) { if (currentItem != null) currentItem.setTitle(new String(ch, start, length)); } else if (parsingLink) { if (currentItem != null) { currentItem.setLink(new String(ch, start, length)); parsingLink = false; } } else if (parsingDate) { if (currentItem != null) { currentItem.setDate(new String(ch, start, length)); parsingDate = false; } } } }
za pomocą tej klasy parsujemy nasz xml z RSS, dzięki czemu otrzymujemy ArrayListę z obiektami typu RSSModel potrzebnymi do naszego adaptera. Oczywiście nic nie stoi na przeszkodzie, by pobrać jeszcze obrazki. Ale to juz zależy od was.
Zostało już tylko dodanie fragmentu RSS w MainActivity:
fragments.add(Fragment.instantiate(this, RSS.class.getName()));
Na końcu:
Jeżeli nie dodaliście reklam, pominęliście itp to prawdopodobnie nie dodaliście jeszcze pozwolenia na używanie internetu.
W tym celu wchodzimy do manifestu. Osobiście preferuję edycję xml, więc przechodzimy do zakładki AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="pl.szymonmotyka.tutorialrandomizer" android:versionCode="2" android:versionName="1.1"> <uses -sdk android:minSdkVersion="8"></uses> <uses -permission android:name="android.permission.INTERNET"></uses> <uses -permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="portrait"> <intent -filter> <action android:name="android.intent.action.MAIN"></action> <category android:name="android.intent.category.LAUNCHER"></category> </intent> </activity> </application> </manifest>
Poza pozwoleniami <uses-permission> dodałem jeszcze atrybut do activitity android:screenOrientation=”portrait”
Źródło: https://dl.dropbox.com/u/14815030/prog6zip.zip
Aplikacja również w markecie: https://play.google.com/store/apps/details?id=pl.szymonmotyka.tutorialrandomizer
Czynik RSS oparty o : http://www.itcuties.com/android/how-to-write-android-rss-parser/ . Lista pokazana na własnym przykładzie
Jeżeli jeszcze was nie zanudziłem, zapraszam do oczekiwania na kolejne części. W planach : SQLite, zewnętrzne biblioteki. Zapraszam również do polubienia i częstego odwiedzania: https://www.facebook.com/SzymonMotykapl