Lấy dữ liệu trên 1 website dạng xml , bắt tay làm 1 ứng dụng dự báo thời tiêt


Từ: 10:32 14/06/2012
Bài: 112
Cảm ơn: 124
Thích: 18

Đây là hình ảnh sau khi hoàn thành ứng dụng :) . Chúng ta sẽ sử dụng ListActivity :p

CHúng ta sẽ lấy dữ liệu thời tiết từ 1 trang web , ví dụ ở đây là vnexpress

http://vnexpress.net/ListFile/Weather/hcm.xml

... blah blah ...

 

Source code :http://www.mediafire.com/?c866i2qjuq52zeb

File Activity_main.xml

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
 
    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" >
    </ListView>
 
</LinearLayout>
 
File listview_child.xml : sử dụng để tùy biến giao diện cho listactivity
 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
 
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent" >
 
        <ImageView
            android:id="@+id/imgStatusWeather"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher" />
    </LinearLayout>
 
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
 
        <TextView
            android:id="@+id/txtCity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Medium Text"
            android:textAppearance="?android:attr/textAppearanceMedium" />
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
 
            <TextView
                android:id="@+id/txtTemperature"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView" />
 
            <TextView
                android:id="@+id/txtStatusWeather"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Small Text"
                android:textAppearance="?android:attr/textAppearanceSmall" />
 
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" >
 
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical" >
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
 
</LinearLayout>
 
OK  :D . tiếp theo là tạo 1 đối tượng thời tiết mang các thuộc tính như : tên thành phố , nhiệt độ và thông tin :D
 
WeatherObject.java
 
package com.example.weatherforecast;
 
public class WeatherObject {
private String mCity;
private String mStatusWeather;
private int mTemperature;
private String mImageStatusWeather;
 
public String getCity() {
return this.mCity;
}
 
public void setCity(String city) {
this.mCity = city;
}
 
public String getStatusWeather() {
return this.mStatusWeather;
}
 
public void setStatusWeather(String statusWeather) {
this.mStatusWeather = statusWeather;
}
 
public int getTemperature() {
return this.mTemperature;
}
 
public void setTemperature(int temperature) {
this.mTemperature = temperature;
}
 
public String getImageStatusWeather() {
return this.mImageStatusWeather;
}
 
public void setImageStatusWeather(String imageStatusWeather) {
this.mImageStatusWeather = imageStatusWeather;
}
 
public WeatherObject(String city, String statusWeather, int temperature,
String imageStatusWeather) {
this.mCity = city;
this.mStatusWeather = statusWeather;
this.mTemperature = temperature;
this.mImageStatusWeather = imageStatusWeather;
}
}
 
Tiếp theo mình sẽ Tạo 1 class WeatherForecase.java để xử lí các tag html lấy trên internet
 
package com.example.weatherforecast;
 
import java.util.ArrayList;
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
 
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
import android.util.Log;
 
public class WeatherForecast {
public final static String SONLA = "Sonla.xml";
public final static String VIETTRI = "Viettri.xml";
public final static String HAIPHONG = "Haiphong.xml";
public final static String HANOI = "Hanoi.xml";
public final static String VINH = "Vinh.xml";
public final static String DANANG = "Danang.xml";
public final static String NHATRANG = "Nhatrang.xml";
public final static String PLEICU = "Pleicu.xml";
public final static String HOCHIMINH = "HCM.xml";
 
private final String URL = "http://vnexpress.net/ListFile/Weather/";
 
private final String LOG_EXCEPTION = "log exception";
 
public ArrayList<WeatherObject> getAllWeatherOfCity() {
ArrayList<WeatherObject> arrWeatherObject = new ArrayList<WeatherObject>();
arrWeatherObject.add(getWeatherForecase(WeatherForecast.SONLA));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.VIETTRI));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.HAIPHONG));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.HANOI));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.VINH));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.DANANG));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.NHATRANG));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.PLEICU));
arrWeatherObject.add(getWeatherForecase(WeatherForecast.HOCHIMINH));
return arrWeatherObject;
 
}
 
private String convertStatusWeather(String statusWeather) {
int index1 = statusWeather.indexOf('>');
int index2 = statusWeather.indexOf('<', index1);
if (index1 >= 0 && index2 >= 0) {
return statusWeather.substring(index1 + 1, index2);
}
return statusWeather;
}
 
private String convertCityToVNI(String cityXML) {
if (cityXML.equals(SONLA))
return "Sơn La";
else if (cityXML.equals(VIETTRI))
return "Việt Trì";
else if (cityXML.equals(HAIPHONG))
return "Hải Phòng";
else if (cityXML.equals(HANOI))
return "Hà Nội";
else if (cityXML.equals(VINH))
return "Vinh";
else if (cityXML.equals(DANANG))
return "Đà Nẵng";
else if (cityXML.equals(NHATRANG))
return "Nha Trang";
else if (cityXML.equals(PLEICU))
return "Pleicu";
else if (cityXML.equals(HOCHIMINH))
return "Hồ Chí Minh";
return null;
}
 
public WeatherObject getWeatherForecase(String city) {
try {
HttpGet uri = new HttpGet(URL + city);
 
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse resp = client.execute(uri);
 
StatusLine status = resp.getStatusLine();
if (status.getStatusCode() != 200) {
Log.d(LOG_EXCEPTION, "HTTP error, invalid server status code: "
+ resp.getStatusLine());
}
 
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(resp.getEntity().getContent());
 
NodeList weatherTag = doc.getElementsByTagName("Weather");
Node weatherNode = weatherTag.item(0);
String statusWeather = weatherNode.getTextContent();
 
String temperatureStr = "";
for (int i = 1; i <= 5; i++) {
NodeList adImgTag = doc.getElementsByTagName("AdImg" + i);
Node temperatureNode = adImgTag.item(0);
String temperatureContent = temperatureNode.getTextContent();
if (!temperatureContent.equals("")) {
String str = temperatureContent.substring(0,
temperatureContent.indexOf('.'));
if (checkDigit(str))
temperatureStr += str;
}
}
 
String imageStatusWeather = "";
NodeList adImgTag = doc.getElementsByTagName("AdImg");
Node imgStatusWeather = adImgTag.item(0);
imageStatusWeather = imgStatusWeather.getTextContent();
 
WeatherObject weatherObject = new WeatherObject(
convertCityToVNI(city),
convertStatusWeather(statusWeather),
Integer.parseInt(temperatureStr), imageStatusWeather);
return weatherObject;
} catch (Exception e) {
Log.d(LOG_EXCEPTION, e.getMessage());
return null;
}
}
 
private boolean checkDigit(String digit) {
char[] arr = digit.toCharArray();
for (char c : arr) {
if (!Character.isDigit(c))
return false;
}
return true;
}
}
 
1 class tên WeatherApdater.java để tùy biến adapter khi bind vào listactivity
 
package com.example.weatherforecast;
 
import java.util.ArrayList;
 
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
public class WeatherAdapter extends ArrayAdapter<WeatherObject> {
 
private final String URL = "http://vnexpress.net/Images/Weather/";
private Context mContext;
private ArrayList<WeatherObject> mArrayWeatherObject;
 
public WeatherAdapter(Context context, int textViewResourceId,
ArrayList<WeatherObject> arrayWeatherObject) {
super(context, textViewResourceId, arrayWeatherObject);
this.mContext = context;
this.mArrayWeatherObject = arrayWeatherObject;
 
}
 
@Override
public View getView(int position, View convertView, ViewGroup parent) {
WeatherObject weatherObject = (WeatherObject) getItem(position);
if (weatherObject != null) {
if (convertView == null) {
LayoutInflater inf = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inf.inflate(R.layout.listview_child, null);
}
ImageView imgStatusWeather = (ImageView) convertView
.findViewById(R.id.imgStatusWeather);
TextView txtCity = (TextView) convertView
.findViewById(R.id.txtCity);
TextView txtTemperature = (TextView) convertView
.findViewById(R.id.txtTemperature);
TextView txtStatusWeather = (TextView) convertView
.findViewById(R.id.txtStatusWeather);
 
txtCity.setText(weatherObject.getCity());
 
txtTemperature.setText(String.valueOf(weatherObject
.getTemperature()) + " *C");
 
txtStatusWeather.setText(weatherObject.getStatusWeather());
 
new DownloadImageTask(imgStatusWeather).execute(URL
+ weatherObject.getImageStatusWeather());
}
return convertView;
}
 
@Override
public WeatherObject getItem(int position) {
return mArrayWeatherObject.get(position);
}
 
}
 
 
Cuối cùng là MainActivity.java
 
package com.example.weatherforecast;
 
import java.util.ArrayList;
 
import android.app.ListActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
 
public class MainActivity extends ListActivity {
 
private WeatherAdapter mWeatherAdapter;
private ArrayList<WeatherObject> mArrWeather;
 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mArrWeather = new WeatherForecast().getAllWeatherOfCity();
mWeatherAdapter = new WeatherAdapter(this,
android.R.layout.simple_list_item_1, mArrWeather);
setListAdapter(mWeatherAdapter);
Thread thread = new Thread(new ThreadLoop());
thread.start();
}
 
public Handler updateHandler = new Handler() {
public void handleMessage(Message msg) {
mArrWeather = new WeatherForecast().getAllWeatherOfCity();
mWeatherAdapter.notifyDataSetChanged();
super.handleMessage(msg);
}
};
 
public class ThreadLoop implements Runnable {
 
@Override
public void run() {
while (true) {
try {
Thread.sleep(10000);
MainActivity.this.updateHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
}
}
}
}
}
 
Trong file Manifest.xml nhớ thêm 
<uses-permission android:name="android.permission.INTERNET" />
để cho kết nối internet nhé
 
 
 

 

Source code :http://www.mediafire.com/?c866i2qjuq52zeb

Label
Từ: 10:32 14/06/2012
Bài: 112
Cảm ơn: 124
Thích: 18

Mình sẽ hướng dẫn lấy dữ liệu từ 1 trang web với mã html trong bài sau :d

Label
Từ: 21:54 09/09/2012
Bài: 4
Cảm ơn: 6
Thích: 2

:D. Cũng đang tìm hiểu Android. Bài viết rất hay. đợi bài lấy dữ liệu từ html của bạn.

Mình chưa xem kỹ nhưng thấy đoạn getView bạn nên dùng setTag với getTag thì sẽ nhanh hơn. Mỗi lần scroll nó lại getView lại nên lần nào cũng khởi tạo lại như kia => chậm. Hi.

Label
Từ: 10:32 14/06/2012
Bài: 112
Cảm ơn: 124
Thích: 18

cám ơn buithanhminh.hou

Bạn có thể nói rõ áp dụng setTag và getTag như thế nào ko smiley

Label
Từ: 16:10 29/06/2012
Bài: 6
Cảm ơn: 10
Thích: 3

Bạn có thể dùng 1 class ViewHolder để quản lý các item của listview được dễ hơn hoặc có thể tách ra 1 view (sử dụng mô hình mvc)

Ý bạn buithanhminh.hou là như thế này không biết có đúng ko, bạn nguyentungduong.9x1 tham khảo thêm nhé :D

 

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inf = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inf.inflate(R.layout.listview_child, null);
holder = new ViewHolder();
holder.imgStatusWeather = (ImageView) convertView.findViewById(R.id.imgStatusWeather); 
holder.txtCity = (TextView) convertView.findViewById(R.id.txtCity);
holder.txtTemperature = (TextView) convertView.findViewById(R.id.txtTemperature);
holder.txtStatusWeather = (TextView) convertView.findViewById(R.id.txtStatusWeather);
 
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
 
WeatherObject weatherObject = (WeatherObject) getItem(position);
if (weatherObject  != null)
{
holder.txtCity.setText(weatherObject.getCity());
holder.txtTemperature.setText(String.valueOf(weatherObject.getTemperature()) + " *C");
holder.txtStatusWeather.setText(weatherObject.getStatusWeather());
new DownloadImageTask(imgStatusWeather).execute(URL+ weatherObject.getImageStatusWeather());
}
return convertView;
}
 
static class ViewHolder {
ImageView imgStatusWeather;
TextView txtCity;
TextView txtTemperature;
TextView txtStatusWeather;
}
----------------------------------
Nếu có chỗ nào sai, các bạn góp ý cho mình nhé :D
Label
Từ: 10:32 14/06/2012
Bài: 112
Cảm ơn: 124
Thích: 18

thanks a đức . cái này tuyệt :D

Label
Từ: 10:48 29/11/2014
Bài: 1
Cảm ơn: 0
Thích: 0

Bạn ơi cho mình hỏi DownloadImageTask trong class WeatherApdater là mình tự định nghĩa hay có sẵn, mình bị lỗi chỗ đó  sad

Label
Từ: 09:00 20/09/2014
Bài: 10
Cảm ơn: 2
Thích: 3

@huyensoc DownloadImageTask  theo mình thấy trong code và chức năng của nó thì, nó là 1 class kế thừa từ lại từ lớp AsyncTask, chức năng của nó là tạo tiến trình ngầm để load ảnh lên View. Code của nó có thể như thế này, bạn nên cho nó vào một file java riêng rồi import vào chỗ cần dùng:

public class DownloadImageTask extends AsyncTask<URL, Void, Bitmap> {
 
private static final String LOG_E_TAG = "DownloadImageTask";
private final WeakReference<ImageView> containerImageView;
 
public DownloadImageTask(ImageView imageView) {
this.containerImageView = new WeakReference<ImageView>(imageView);
}
 
@Override
protected Bitmap doInBackground(URL... params) {
URL imageURL = params[0];
Bitmap downloadedBitmap = null;
try {
InputStream inputStream = imageURL.openStream();
downloadedBitmap = BitmapFactory.decodeStream(inputStream);
} catch (Exception e) {
Log.e(LOG_E_TAG, e.getMessage());
e.printStackTrace();
}
return downloadedBitmap;
}
 
@Override
protected void onPostExecute(Bitmap result) {
ImageView imageView = this.containerImageView.get();
if (imageView != null) {
imageView.setImageBitmap(result);
}
}
}
 
hãy lưu ý khi có quá nhiều task được tạo ra, nó sẽ làm tràn bộ nhớ của thiết bị