ANDROIND CHO ỨNG DỤNG LẤY TIN TỰ ĐỘNG TRÊN MỘT SỐ TRANG BÁO CÓ CHUẨN RSS
3.5. Trình đọc tin Android (Ứng dụng lấy trang tin VNExpress)
Như chúng ta đã biết việc lấy tin RSS thực chất là ta làm việc với XML. Như đã giới thiệu ở trên có nhiều cách để làm việc với XML như: Simple API của Java cho XML (SAX) và Document Object Model (DOM) hiện đều có sẵn trên Android. Nhưng ở đây chúng tôi sử dụng trình kéo theo trong Android để phân tích XML.
3.5.1. Áp dụng trình phân tích kéo
Vì Android không cung cấp hỗ trợ cho StAX API của Java. Tuy nhiên Android lại đi kèm với một trình phân tích kéo làm việc tương tự như StAX. Nó cho phép mã ứng dụng
của bạn kéo hoặc tìm kiếm các sự kiện từ trình phân tích, trái ngược với trình phân tích SAX tự động đẩy các sự kiện cho trình xử lý. Phần này miêu tả một thực thi trình phân tích kéo của một giao diện trình phân tích điểm tin.
StAX là API cho việc thao tác với tài liệu XML dựa trên sự kiện. Tuy nhiên nó khác với cách xử lý của SAX (Simple API for XML). StAX dùng pull-parsing còn SAX dùng push-parsing.
void XuLiTinLayVe(InputStream dauvao, RSSListAdapter dstin) throws IOException, XmlPullParserException { XmlPullParser xpp = Xml.newPullParser(); xpp.setInput(dauvao, null); int sukien; String title = ""; String link = ""; String description = ""; sukien = xpp.getEventType();
while (sukien != XmlPullParser.END_DOCUMENT) { if (sukien == XmlPullParser.START_TAG) {
String tag = xpp.getName(); if (tag.equals("item")) {
title = link = description = ""; } else if (tag.equals("title")) { xpp.next(); title = xpp.getText(); } else if (tag.equals("link")) { xpp.next(); link = xpp.getText(); } else if (tag.equals("description")) { xpp.next(); description = xpp.getText(); }
} else if (sukien == XmlPullParser.END_TAG) { String tag = xpp.getName();
if (tag.equals("item")) {
RSSItems item = new RSSItems(title, link, description); Handler.post(new ThemTin(item)); } } sukien = xpp.next(); } }
Trình phân tích kéo làm việc tương tự như trình phân tích SAX. Nó có các sự kiện tương tự (phần tử bắt đầu, phần tử kết thúc) nhưng bạn phải kéo từ chúng (xpp.next()). Các sự kiện được gửi đi dưới dạng các mã số, vì thế bạn có thể sử dụng một case-switch đơn giản. Chú ý, thay vì nghe cho đến khi kết thúc các phần tử như trong phân tích SAX, với trình phân tích kéo, thật dễ dàng tiến hành hầu hết các xử lý ngay từ đầu và còn cho phép bạn sớm tạm dừng việc đọc tài liệu XML, vì bạn biết rằng mã trình sẽ không quan tâm đến phần còn lại của tài liệu. Điều này có thể rất hữu ích, đặc biệt nếu bạn chỉ cần một phần nhỏ tài liệu đang được truy cập. Bạn có thể giảm đáng kể thời gian phân tích bằng cách dừng việc phân tích càng sớm càng tốt. Hơn nữa, kiểu tối ưu hóa này đặc biệt quan trọng trên thiết bị di động nơi tốc độ kết nối có thể chậm. Trình phân tích kéo có một vài ưu điểm về hiệu năng cũng như ưu điểm sử dụng dễ dàng. Cũng có thể sử dụng nó để viết XML.
3.5.2. Tạo menu
public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu);
menu.add(0, 0, 0, "VNExpress-Van hoa") .setOnMenuItemClickListener(new TaoMenu("http://vnexpress.net/rss/gl/van-hoa.rss"));
menu.add(0, 0, 0, "VNExpress-Kinh te") .setOnMenuItemClickListener(new
TaoMenu("http://vnexpress.net/rss/gl/kinh-doanh.rss")); menu.add(0, 0, 0, "VNExpress-Xa hoi")
.setOnMenuItemClickListener(new TaoMenu("http://vnexpress.net/rss/gl/xa-hoi.rss"));
menu.add(0, 0, 0, "VNExpress-The thao") .setOnMenuItemClickListener(new TaoMenu("http://vnexpress.net/rss/gl/the-thao.rss"));
menu.add(0, 0, 0, "Reset")
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) { resetUI(); return true; } }); return true; }
private class TaoMenu implements MenuItem.OnMenuItemClickListener {
private CharSequence Url; TaoMenu(CharSequence url) { Url = url;
}
public boolean onMenuItemClick(MenuItem item) { UrlText.setText(Url);
UrlText.requestFocus(); return true;
} }
Ở trên là code tạo menu để có thể giúp cho người sử dụng chuyển sang chuyên mục khác bằng cách chọn vào chuyên mục có trên menu. Khi người dùng Click vào 1 chuyên mục tương ứng thì tất cả các tiêu đề tin và đoạn tóm tắt tin(khoảng 100 kí tự) của chuyên mục đó sẽ được hiển thị lên. Giúp người sử dụng thuận tiện hơn trong việc lựa chọn chuyên mục tin mới(sẽ không phải gõ lại địa chỉ cần truy cập).
3.5.3. Kết nối để lấy tin về
private class KETNOI extends Thread { private CharSequence Url;
public KETNOI(CharSequence url) { Url = url;
}
@Override
public void run() { String trangthai = ""; try {
URL url = new URL(Url.toString());
URLConnection connection = url.openConnection(); connection.setConnectTimeout(10000);
connection.connect();
InputStream in = connection.getInputStream(); XuLiTinLayVe(in, DSTin);
trangthai="Ket noi thanh cong: Tin da duoc load ve!"; } catch (Exception e) {
trangthai = "Khong tai duoc:" + e.getMessage(); }
final String temp = trangthai; if (isCurrentWorker(this)) { Handler.post(new Runnable() { public void run() {
TrangThai.setText(temp); } }); } } }
Đoạn code này dùng để kết nối đến URL tương ứng để lấy tin về. Nếu kết nối thành công thì tin sẽ được load về và đưa ra thong báo là “Kết nối thành công: Tin đã được load về!”. Ngược lại, thì sẽ thong báo “Không tải được”.
3.5.4. Sử dụng lớpRSSListAdapter
private class RSSListAdapter extends ArrayAdapter<RSSItems> { private LayoutInflater Inflater;
public RSSListAdapter(Context context, List<RSSItems> objects) { super(context, 0, objects); Inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_S ERVICE); } @Override
public View getView(int position, View convertView, ViewGroup parent) { TwoLineListItem view; if (convertView == null) { view = (TwoLineListItem)Inflater.inflate(android.R.layout.simple_list_item_2, null); } else {
view = (TwoLineListItem) convertView; }
RSSItems item = this.getItem(position); view.getText1().setText(item.getTitle());
String description = item.getDescription().toString(); description = removeTags(description);
view.getText2().setText(description.substring(0,Math.min(description.lengt h(), DODAI)));
return view; }
Đây là lớp mở rộng của lớp import android.widget.ArrayAdapter. Lớp này đóng vai trò như là cầu nối giữa dữ liệu cơ bản để hiển thị thong tin cho người sử dụng. Ngoài ra, nó còn cung cấp quyền truy cập vào các mục dữ liệu. Nó đảm nhiệm việc hiển thị một cách đầy đủ thong tin của một tin tức cho người sử dụng có thể đọc được.
3.5.5. Giao diện chính
<?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:padding="10dip" android:orientation="vertical"> <EditText android:id="@+id/text"
android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="12sp" android:autoText="false" android:capitalize="none" android:text="@string/rss_text" /> <Button android:id="@+id/taitrang"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/rss_taitrang" /> <TextView android:id="@+id/trangthai" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/rss_trangthai" android:autoText="false"/>
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:drawSelectorOnTop="false"/> </LinearLayout>