现在的位置: 首页 > 综合 > 正文

创建一个地震Viewer

2012年11月06日 ⁄ 综合 ⁄ 共 9922字 ⁄ 字号 评论关闭
   

    接下来的例子,你将要创建一个使用USGS地震种子来显示最近地震列表的工具。

     

    你将数次回到这个地震应用程序,第一次是在第6章中的用一个Content Provider保存和共享地震数据,再一次是在第7章和第8章中,添加映射支持和在后台服务中更新地震数据。

     

    在这个例子中,你将要创建一个基于ListActivity,它连向一个地震种子,并显示位置、等级以及地震的时间。另外,你还将使用一个AlertDialog来提供一个细节的窗口,包含一个链向USGS站点的可链接TextView

     

    1. 创建一个地震工程,包含一个Earthquake Activity。修改main.xml layout资源包含一个ListView控件——确保要命名它,因为在Activity的代码中你要引用它。

     

    <?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”>

    <ListView

    android:id=”@+id/earthquakeListView”

    android:layout_width=”fill_parent”

    android:layout_height=”wrap_content”

    />

    </LinearLayout>

     

    2. 创建一个新的Quake公共类。这个类用于储存每个地震的细节(时间,细节,位置,等级和链接等)。重写toString方法来提供在ListView中使用的每个Quake的字符串。

     

    package com.paad.earthquake;

    import java.util.Date;

    import java.text.SimpleDateFormat;

    import android.location.Location;

     

    public class Quake {

    private Date date;

    private String details;

    private Location location;

    private double magnitude;

    private String link;

     

    public Date getDate() { return date; }

     

    public String getDetails() { return details; }

     

    public Location getLocation() { return location; }

     

    public double getMagnitude() { return magnitude; }

     

    public String getLink() { return link; }

     

    public Quake(Date _d, String _det, Location _loc, double _mag,String _link) {

    date = _d;

    details = _det;

    location = _loc;

    magnitude = _mag;

    link = _link;

    }

     

    @Override

    public String toString()

    {

    SimpleDateFormat sdf = new SimpleDateFormat(“HH.mm”);

    String dateString = sdf.format(date);

    return dateString + “: “ + magnitude + “ “ + details;

    }

    }

     

    3. 在Earthquake Activity里,重写onCreate方法来储存一个Quake对象的ArrayList,并使用一个ArrayAdapter绑定其到ListView上。

     

    package com.paad.earthquake;

    import java.io.IOException;

    import java.io.InputStream;

    import java.net.HttpURLConnection;

    import java.net.MalformedURLException;

    import java.net.URL;

    import java.net.URLConnection;

    import java.text.ParseException;

    import java.text.SimpleDateFormat;

    import java.util.ArrayList;

    import java.util.Date;

    import java.util.GregorianCalendar;

    import javax.xml.parsers.DocumentBuilder;

    import javax.xml.parsers.DocumentBuilderFactory;

    import javax.xml.parsers.ParserConfigurationException;

    import org.w3c.dom.Document;

    import org.w3c.dom.Element;

    import org.w3c.dom.NodeList;

    import org.xml.sax.SAXException;

    import android.app.Activity;

    import android.app.Dialog;

    import android.location.Location;

    import android.os.Bundle;

    import android.view.Menu;

    import android.view.View;

    import android.view.WindowManager;

    import android.view.MenuItem;

    import android.widget.AdapterView;

    import android.widget.ArrayAdapter;

    import android.widget.ListView;

    import android.widget.TextView;

    import android.widget.AdapterView.OnItemClickListener;

     

    public class Earthquake extends Activity {

    ListView earthquakeListView;

    ArrayAdapter<Quake> aa;

    ArrayList<Quake> earthquakes = new ArrayList<Quake>();

     

    @Override

    public void onCreate(Bundle icicle) {

    super.onCreate(icicle);

    setContentView(R.layout.main);

    earthquakeListView =(ListView)this.findViewById(R.id.earthquakeListView);

    int layoutID = android.R.layout.simple_list_item_1;

    aa = new ArrayAdapter<Quake>(this, layoutID , earthquakes);

    earthquakeListView.setAdapter(aa);

    }

    }

     

    4. 接下来,处理地震种子。在这个例子中,使用的种子是1天的USGS种子,并且等级大于2.5级。

     

    以外部字符串资源的方式添加种子的位置。这种方式的优点是对于不同的用户位置来说可以指定不同的种子。

     

    <?xml version=”1.0” encoding=”utf-8”?>

    <resources>

    <string name=”app_name”>Earthquake</string>

    <string name=”quake_feed”>

    http://earthquake.usgs.gov/eqcenter/catalogs/1day-M2.5.xml

    </string>

    </resources>

     

    5. 在你的程序能访问Internet之前,需要授予Internet的权限。在manifest中添加uses-permission节点。

     

    <uses-permission xmlns:android=”http://schemas.android.com/apk/res/android”

    android:name=”android.permission.INTERNET”>

    </uses-permission>

     

    6. 回到Earthquake Activity中,创建一个新的refreshEarthquakes方法来连接,解析地震种子。提取每个earthquake,并解析细节来获得时间、等级、链接和位置。当你完成每个earthquake的解析,传递它到新的addNewQuake方法中。

     

    XML的解析如下所示,没有太多的解释。

     

    private void refreshEarthquakes()

    {

    // Get the XML

    URL url;

    try

    {

    String quakeFeed = getString(R.string.quake_feed);

    url = new URL(quakeFeed);

    URLConnection connection;

    connection = url.openConnection();

    HttpURLConnection httpConnection = (HttpURLConnection)connection;

    int responseCode = httpConnection.getResponseCode();

    if (responseCode == HttpURLConnection.HTTP_OK)

    {

    InputStream in = httpConnection.getInputStream();

    DocumentBuilderFactory dbf;

    dbf = DocumentBuilderFactory.newInstance();

    DocumentBuilder db = dbf.newDocumentBuilder();

    // Parse the earthquake feed.

    Document dom = db.parse(in);

    Element docEle = dom.getDocumentElement();

    // Clear the old earthquakes

    earthquakes.clear();

    // Get a list of each earthquake entry.

    NodeList nl = docEle.getElementsByTagName(“entry”);

     

    if (nl != null && nl.getLength() > 0)

    {

    for (int i = 0 ; i < nl.getLength(); i++)

    {

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

    Element title =

    (Element)entry.getElementsByTagName(“title”).item(0);

    Element g =

    (Element)entry.getElementsByTagName(“georss:point”).item(0);

    Element when =

    (Element)entry.getElementsByTagName(“updated”).item(0);

    Element link =

    (Element)entry.getElementsByTagName(“link”).item(0);

    String details = title.getFirstChild().getNodeValue();

    String hostname = “http://earthquake.usgs.gov/”;

    String linkString = hostname + link.getAttribute(“href”);

    String point = g.getFirstChild().getNodeValue();

    String dt = when.getFirstChild().getNodeValue();

     

    SimpleDateFormat sdf;

    sdf = new SimpleDateFormat(“yyyy-MM-dd’T’hh:mm:ss’Z’”);

    Date qdate = new GregorianCalendar(0,0,0).getTime();

     

    try

    {

    qdate = sdf.parse(dt);

    }

    catch (ParseException e)

    {

    e.printStackTrace();

    }

    String[] location = point.split(“ “);

    Location l = new Location(“dummyGPS”);

    l.setLatitude(Double.parseDouble(location[0]));

    l.setLongitude(Double.parseDouble(location[1]));

    String magnitudeString = details.split(“ “)[1];

    int end = magnitudeString.length()-1;

    double magnitude;

    magnitude = Double.parseDouble(magnitudeString.substring(0, end));

    details = details.split(“,”)[1].trim();

    Quake quake = new Quake(qdate, details, l,

    magnitude, linkString);

    // Process a newly found earthquake

    addNewQuake(quake);

    }

    }

    }

    }

    catch (MalformedURLException e)

    {

    e.printStackTrace();

    }

    catch (IOException e)

    {

    e.printStackTrace();

    }

    catch (ParserConfigurationException e)

    {

    e.printStackTrace();

    }

    catch (SAXException e)

    {

    e.printStackTrace();

    }

    finally

    {

    }

    }

     

    private void addNewQuake(Quake _quake) {

    // TODO: Add the earthquakes to the array list.

    }

     

    7. 更新addNewQuake方法,让它可以带一个刚处理过的Quake参数并将其添加EarthquakeArrayList中。它还应该通知ArrayAdapter底层数据发生了变化。

     

    private void addNewQuake(Quake _quake) {

    // Add the new quake to our list of earthquakes.

    earthquakes.add(_quake);

    // Notify the array adapter of a change.

    aa.notifyDataSetChanged();

    }

     

    8. 修改onCreate方法在启动时调用refreshEarthquakes

     

    @Override

    public void onCreate(Bundle icicle) {

    super.onCreate(icicle);

    setContentView(R.layout.main);

    earthquakeListView =

    (ListView)this.findViewById(R.id.earthquakeListView);

    int layoutID = android.R.layout.simple_list_item_1;

    aa = new ArrayAdapter<Quake>(this, layoutID , earthquakes);

    earthquakeListView.setAdapter(aa);

    refreshEarthquakes();

    }

     

    Internet查询目前发生在UI主线程。这是一种糟糕的方式,当查询需要花费超过几秒的时间时应用程序会变得无响应。在第8章,你将学习如何将这样的耗时的操作移到后台线程中。

     

    9. 如果你运行你的工程,你应该看到一个ListView中显示了过去24小时里等级大于2.5的地震,如图5-6所示。

     

    5-6

     

    10. 还剩下两步来能你的程序变得更加有用。第一,创建一个菜单项来让用户在需要的时候更新一下地址种子。

     

    10.1 为菜单选择添加外部字符串。

     

    <string name=”menu_update”>Refresh Earthquakes</string>

     

    10.2  然后重写ActivityonCreateOptionsMenuonOptionsItemSelected方法,来显示和处理菜单项的更新操作。

     

    static final private int MENU_UPDATE = Menu.FIRST;

     

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

    super.onCreateOptionsMenu(menu);

    menu.add(0, MENU_UPDATE, Menu.NONE, R.string.menu_update);

    return true;

    }

     

    @Override

    public boolean onOptionsItemSelected(MenuItem item) {

    super.onOptionsItemSelected(item);

    switch (item.getItemId())

    {

    case (MENU_UPDATE):

    {

    refreshEarthquakes();

    return true;

    }

    }

    return false;

    }

     

    11. 现在,添加一些用户交互。当用户从地震列表中选择一项时,打开一个对话框,显示更多的地震细节。

     

    11.1 创建新的quake_details.xml layout资源,作为用户点击项目时显示的对话框的布局。

     

    <?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”

    android:padding=”10sp”>

    <TextView

    android:id=”@+id/quakeDetailsTextView”

    android:layout_width=”fill_parent”

    android:layout_height=”fill_parent”

    android:textSize=”14sp”

    />

    </LinearLayout>

     

    11.2 然后,修改onCreate方法,为ListView添加一个onItemClickListener,当一个地震项目选择时显示一个对话框。

     

    static final private int QUAKE_DIALOG = 1;

    Quake selectedQuake;

    @Override

    public void onCreate(Bundle icicle) {

    super.onCreate(icicle);

    setContentView(R.layout.main);

    earthquakeListView =

    (ListView)this.findViewById(R.id.earthquakeListView);

    earthquakeListView.setOnItemClickListener(new OnItemClickListener() {

    public void onItemClick(AdapterView _av, View _v, int _index, long arg3) {

    selectedQuake = earthquakes.get(_index);

    showDialog(QUAKE_DIALOG);

    }

    });

    int layoutID = android.R.layout.simple_list_item_1;

    aa = new ArrayAdapter<Quake>(this, layoutID , earthquakes);

    earthquakeListView.setAdapter(aa);

    refreshEarthquakes();

    }

     

    11.3 现在,重写onCreateDialogonPrepareDialog方法来创建对话框和填入地震细节。

     

    @Override

    public Dialog onCreateDialog(int id) {

    switch(id) {

    case (QUAKE_DIALOG) :

    LayoutInflater li = LayoutInflater.from(this);

    View quakeDetailsView = li.inflate(R.layout.quake_details, null);

    AlertDialog.Builder quakeDialog = new AlertDialog.Builder(this);

    quakeDialog.setTitle(“Quake Time”);

    quakeDialog.setView(quakeDetailsView);

    return quakeDialog.create();

    }

    return null;

    }

     

    @Override

    public void onPrepareDialog(int id, Dialog dialog) {

    switch(id) {

    case (QUAKE_DIALOG) :

    SimpleDateFormat sdf;

    sdf = new SimpleDateFormat(“dd/MM/yyyy HH:mm:ss”);

    String dateString = sdf.format(selectedQuake.getDate());

    String quakeText = “Mangitude “ + selectedQuake.getMagnitude() +

    “\n” + selectedQuake.getDetails() + “\n” + selectedQuake.getLink();

    AlertDialog quakeDialog = (AlertDialog)dialog;

    quakeDialog.setTitle(dateString);

    TextView tv =

    (TextView)quakeDialog.findViewById(R.id.quakeDetailsTextView);

    tv.setText(quakeText);

    break;

    }

    }

     

    11.4 最后一步,为对话框制作超链接指向USGS。调整对话框的XML layout资源定义,包含一个autolink特性。

     

    <?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”

    android:padding=”10sp”>

    <TextView

    android:id=”@+id/quakeDetailsTextView”

    android:layout_width=”fill_parent”

    android:layout_height=”fill_parent”

    android:textSize=”14sp”

    android:autoLink=”all”

    />

    </LinearLayout>

     

    再次运行你的Activity。当你点击某个地震项目时,一个对话框会显示出来,并使列表部分模糊,如图5-7所示。

     

    5-7

     

    Sample Code

    http://files.cnblogs.com/xirihanlin/DL090804@cc-Earthquake.zip

     

    Sample图示:

     

     

抱歉!评论已关闭.