Android开发 - 使用Internet资源

连接Internet资源

首先需要在应用程序清单中添加一个INTERNET uses-permission节点。

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

打开Internet数据流

String myFeed = getString(R.String.myFeed);

URL url = new URL(quakeFeed);

URLConnection connection = url.openConnection();

HttpURLConnection httpConnection = (HttpURLConnection) connection;
int responsed = httpConnection.getResponseCode();

if (responsed == HttpURLConnection.HTTP_OK) {
      //DoSomthing...
}

尝试在主UI线程上执行网路操作会引发NetWorkOnMainThreadException异常。所以,一定要在后台线程中执行。

分析XML

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

//装载内容流
Document dom = db.parse(in);
//获取根节点
Element docEle = dom.getDocumentElement();

//遍历子节点
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("georess:point").item(0);
        Element when = (Element) entry.getElementsByTagName("updated").item(0);
        Element link = (Element) entry.getElementsByTagName("link").item(0);

        String point = g.getFirstChild().getNodeValue();
        String dt = when.getFirstChild().getNodeValue();
    }
}

使用DocumentBuilder来装载内容流至Document对象。

使用getDocumentElement方法获取Document对象上的文档根节点。

通过getElementsByTagName获取指定名称的节点集合。

遍历节点时通过.item(index)、getElementsByTagName.item(index)、getFirstChild()等方法获取子节点。

Example:从http://earthquake.usgs.gov/读取当天全球地震数据

创建一个地震数据对象,用于封装地震数据

package com.example.guqiang.earthquake.Models;

import android.location.Location;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by GuQiang on 2016/9/29.
 * 地震数据对象
 */
public class Quake {
    private Date date;

    public String getLink() {
        return link;
    }

    public Quake(String link, Date date, String details, Location location, double magnitude) {
        this.link = link;
        this.date = date;
        this.details = details;
        this.location = location;
        this.magnitude = magnitude;
    }

    @Override
    public String toString() {
        SimpleDateFormat sdf=new SimpleDateFormat("HH:MM");
        String dateString=sdf.format(this.date);
        return dateString+": "+magnitude+" "+details;
    }

    public Date getDate() {
        return date;
    }

    public String getDetails() {
        return details;
    }

    public Location getLocation() {
        return location;
    }

    public double getMagnitude() {
        return magnitude;
    }

    private String details;
    private Location location;
    private double magnitude;
    private String link;
}

创建一个派生自ListFragment的Fragment,用来在View显示时开启后台线程读取数据、解析XML、填充数据源、显示数据。

package com.example.guqiang.earthquake.Layouts;

import android.app.ListFragment;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;

import com.example.guqiang.earthquake.Models.Quake;
import com.example.guqiang.earthquake.R;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

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;

/**
 * Created by GuQiang on 2016/9/29.
 * 用于显示地震列表
 */
public class EarthquakeListFragment extends ListFragment {

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

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        int layoutId = android.R.layout.simple_list_item_1;
        //数据源
        quakesAdapter = new ArrayAdapter<Quake>(getActivity(), layoutId, earthquakes);

        //设定列表于数据源的绑定
        this.setListAdapter(quakesAdapter);

        //在后台线程中执行网络操作,如果在主UI线程中执行会引发NetworkOnMainThreadException
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                refreshEarthquakes();
            }
        });

        t.start();
    }

    private static final String TAG = "EARTHQUAKE";
    private android.os.Handler handler = new android.os.Handler();

    public void refreshEarthquakes() {
        URL url;
        try {
            //创建获取当天数据的URI
            String quakeFeed = getString(R.string.quake_feed);
            SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String today = sDateFormat.format(new Date());
            quakeFeed = quakeFeed + "&starttime=" + today;
            url = new URL(quakeFeed);

            //获取数据
            URLConnection connection = url.openConnection();
            HttpURLConnection httpConnection = (HttpURLConnection) connection;
            int responsed = httpConnection.getResponseCode();

            if (responsed == HttpURLConnection.HTTP_OK) {
                //获取返回数据流
                InputStream in = httpConnection.getInputStream();

                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();

                //分析地震源
                Document dom = db.parse(in);
                Element docEle = dom.getDocumentElement();

                //清除旧的地震数据
                earthquakes.clear();

                //获得每个地震项的列表
                NodeList nl = docEle.getElementsByTagName("event");
                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("description").item(0);
                        Element when = (Element) entry.getElementsByTagName("origin").item(0);

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

                        String dt = when.getFirstChild().getFirstChild().getFirstChild().getNodeValue();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd‘T‘hh:mm:ss.SSS‘Z‘");
                        Date qdate = new GregorianCalendar(0, 0, 0).getTime();

                        try {
                            qdate = sdf.parse(dt);
                        } catch (ParseException e) {
                            Log.d(TAG, "Date parsing exception." + e);
                        }

                        Location l = new Location("dumpGPS");

                        final Quake quake = new Quake("", qdate, details, l, 0d);

                        //处理一个新发现的地震
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                addNewQuake(quake);
                            }
                        });
                    }
                }
            }
        } catch (MalformedURLException e) {
            Log.d(TAG, "MalformedURLException");
        } catch (IOException e) {
            Log.d(TAG, "IOException");
        } catch (ParserConfigurationException e) {
            Log.d(TAG, "Parser Configuration Exception");
        } catch (SAXException e) {
            Log.d(TAG, "SAXException");
        } finally {

        }
    }

    private void addNewQuake(Quake quake) {
        //将新地震源添加到地震列表中
        earthquakes.add(quake);

        //向Array Adapter通知改变
        quakesAdapter.notifyDataSetChanged();
    }
}

主界面中包含刚刚创建的 EarthquakeListFragment

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

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.example.guqiang.earthquake.Layouts.EarthquakeListFragment"
        android:id="@+id/EarthquakeListFragment"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />
</LinearLayout>

Manifest文件中设定程序需要网络权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.guqiang.earthquake">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

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

运行效果如下:

下载文件

使用Download Manager服务。Download Manager通过处理HTTP连接、监控连接的变化和系统重新启动来确保每一次下载都能成功完成。

使用getSystemService方法请求DOWNLOAD_SERVICE。

String serviceString= Context.DOWNLOAD_SERVICE;
DownloadManager dm=(DownloadManager)getSystemService(serviceString);

getSystemService方法基于context

使用Download Manager下载文件

Uri uri= Uri.parse("XXXX.zip");
DownloadManager.Request request=new DownloadManager.Request(uri);
long reference=dm.enqueue(request);

在Request对象中,可以通过调用方法addRequestHeader()和setMimeType()给请求添加HTTP报头或者重写服务器返回的MIME类型。

也可以给某个下载指定连接条件。setAllowedNetworkTypes方法限制下载类型为Wi-Fi或者移动网络。在手机漫游时,setAllowOverRoaming方法可以有预见性的阻止下载。

下面的代码片段展示了如何确保只有连接到Wi-Fi时才进行大文件的下载。

request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);

在Android API Level 11中引入了一个便利的方法getRecommendedMaxBytesOverMobile,它会通过返回一个在移动数据连接上传输时推荐的最大字节数来确认是否应该限制下载为Wi-Fi。

想要在下载完成后接收通知,就需要注册一个Receiver来接收ACTION_DOWNLOAD_COMPLETE广播。

监控下载的完成

BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        if(myDownRef==reference){
            //对指定的下载文件进行操作
        }
    }
};

通过调用Download Manager的openDownloadedFile方法,可以获得文件的Parcel File Descriptor,查询Download Manager来获得文件的位置。

指定下载位置

默认情况下,Download Manager会把下载的文件保存到共享下载缓存中,而且使用系统生成的文件名。

可以在Request对象中调用setDestinationUri方法,指定存储路径。

DownloadManager.Request request = new DownloadManager.Request(uri);
request.setDestinationUri(uri);

也可以使用 setDestinationInExternalFilesDir 指定使用外部存储文件夹中存储

request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS,"AAA");

取消和删除下载

downloadManager.remove(REFERENCE_ID_1,REFERENCE_ID_2);

如果下载被取消,它所关联的文件-未完全下载的和完全下载的-都会被删除。

时间: 2024-10-08 11:04:48

Android开发 - 使用Internet资源的相关文章

Android开发/源码资源汇总

Android 应用源码大收藏http://neast.cn/forum.php?mod=viewthread&tid=9483&fromuid=5 全网最全的Android游戏源码汇总http://neast.cn/forum.php?mod=viewthread&tid=5080&fromuid=5 AndroidUI设计之高仿系列http://neast.cn/forum.php?mod=viewthread&tid=5293&fromuid=5 全网

Delphi XE8中Android开发有用的资源!

一,FireMonkey Component Library在XE8帮助(topics.chm)中的位置:FireMonkey Component Library,展示了FireMonkey控件在VCL类库中的各种关系,对于我们理解FireMonkey类库有非常大的帮助. 二,Delphi XE8中Android类库源代码位置:C:\Program Files (x86)\Embarcadero\Studio\16.0\source\rtl\android ,C:\Program Files (

Android开发之一些资源索引

1.android标题栏(titlebar)显示进度条 1 protected void onCreate(Bundle savedInstanceState) { 2 super.onCreate(savedInstanceState); 3 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);//先给Activity注册界面进度条功能 4 setContentView(R.layout.main); 5 setProgres

Android开发之资源文件存储

本文介绍在Android开发中关于资源文件的存储操作.对于Android资源也是非常重要的,主要包括文本字符串(strings).颜色(colors).数组(arrays).动画(anim).布局(layout).图像和图标(drawable).音频视频(media)和其他应用程序使用的组件. 在Android开发中,资源文件是我们使用频率最高的,无论是string,drawable,还是layout,这些资源都是我们经常使用到的,而且为我们的开发提供了很多方便,不过我们平时接触的资源目录一般都

开发常用镜像资源替换为国内开源镜像(yum,compose,maven,docker,android sdk,npm,国内开源镜像汇总)

一.国内开源镜像站点汇总 阿里云开源镜像站 (http://mirrors.aliyun.com/)网易开源镜像站 (http://mirrors.163.com/)中国科学技术大学开源镜像站 (http://mirrors.ustc.edu.cn/)清华大学开源软件镜像站 (https://mirrors.tuna.tsinghua.edu.cn/)中国电信天翼云 (http://mirrors.ctyun.cn/) 二.软件版 (一).操作系统类 1.Ubuntu阿里云:http://mir

整理的Android开发资源

Android网址或Blog Android官网 身为Android开发者不知道这个网站就太说不过去了,上面有你任何你需要的东西 Android Developers Blog Android官网博客, 在上面可以关注Android最新的进展与最权威的博客(须翻墙) Android开源项目汇总 我的好朋友Trinea整理的非常全面的GitHub开源项目汇总,不需要重复发明轮子,尽情遨游在开源世界里吧 Android的开源库 国外整理的Android开源库汇总,和上面的比起来分类更明确,你总能很方

Android应用程序如何使用Internet资源?

思路:连接Internet资源-->分析XML资源-->使用Download Manager下载文件 Android的Internet连接模型和用于分析Internet数据源的Java技术. Android的Internet连接模型和用于分析Internet数据源的Java技术. 胖客户端和瘦客户端(完全依靠基于Web的解决方案)的本地应用程序的区别和优点: 1. 上述胖客户端指非原生的Android应用程序(或基于Web的应用程序):瘦客户端指原生Android应用程序(或本地应用程序,或者

Android开发资源推荐第2季

Android CPU监控想法,思路,核心技术和代码 http://www.csdn123.com/html/blogs/20131026/89017.htm Android App /Task/Stack 总体分析 http://www.eoeandroid.com/thread-161703-1-1.html Android Widget设计指南 http://mobile.51cto.com/widget-248860_all.htm 系统深入学习android http://www.cn

Android开发人员必知的开发资源

developer.android.com 官方开发人员网站推荐资源 在动手编写第一个 Android 应用之前,用心读一读 Android Design 章节.尤其是以下的这些文章: Devices and Displays  (设备和显示) Touch Feedback(触摸反馈) Metrics and Grids (度量和网格) Iconography (图像研究) 同一时候也请下载 Downloads 部分的代码,这些代码囊括了 Android 图标和控件的设计模板,源文件.样式以及无