我的Android 4 学习系列之使用 Internet 资源
目录
- 连接Internet资源
- 分析XML资源
- 使用Download Manager下载文件
- 查询Download manager
- 使用Account Manager 对 Google App Engine 进行身份认证
连接Internet资源
在访问internet之前,需要在应用程序清单中添加一个INTERNET uses-permission节点:
<uses-permission android:name=”android.permission.INTERNET” />
String myFeed = getString(R.id.action_settings);
try{
URL url = new URL(myFeed);
// 创建新的HTTP URL链接
URLConnection urlConnection = url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
int responseCode = httpURLConnection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
InputStream stream = httpURLConnection.getInputStream();
processStream(stream);
}
}
catch(MalformedURLException e){
Log.d(TAG, "Malformed URL Exception.");
}
catch(IOException e){
Log.d(TAG, "IO Exception.");
}
分析XML资源
与DOM分析器不同,Pull Parser 用一个顺序的事件和标记序列呈现文档的元素。
你在文档中的位置是由当前的事件表示的。通过调用 getEventType,可以确定当前的事件。每个文档都从START_DOCMENT事件开始,到END_DOCMENT事件结束。
要遍历标记,只需要调用next,这会遍历一系列匹配的(并且通常是嵌套)START_TAG 和 END_TAG 事件。通过调用getName可以提取每个标记的名称,通过调用getNextText可以提取每组标记之间的文本。
private void processStream(InputStream stream) {
// 创建XML Pull 分析器
XmlPullParserFactory factory;
try{
factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
//分配新的输入流
xpp.setInput(stream, null);
int eventType = xpp.getEventType();
//继续直至文档末尾
while (eventType != XmlPullParser.END_DOCUMENT) {
//检查结果标记的开始标记
if(eventType == XmlPullParser.START_TAG && xpp.getName().equals("result")){
eventType = xpp.next();
String name = "";
//处理结果标记中的每个结果
while (!(eventType == XmlPullParser.END_TAG && xpp.getName().equals("result"))) {
//检查结果标记中名称标记
if (eventType == XmlPullParser.START_TAG && xpp.getName().equals("name")) {
//提取POI名称
name = xpp.nextText();
//移动到下一个标记
eventType = xpp.next();
}
//... 对每个POI名称执行某些操作
}
//移动到下一个标记
eventType = xpp.next();
}
}
}
catch(XmlPullParserException e){
Log.d("PULPARSER", "XML Pull Parser Exception", e);
} catch (IOException e) {
Log.d("PULLPARSER", "IO Exception." ,e);
e.printStackTrace();
}
}
创建一个地震查看器
1. 首先,创建Earthquake项目,并创建EarthquakeActivity。
2. 创建一个ListFragment的扩展EarthquakeListFragment。该Fragment用于显示地震列表。
public class EarthquakeListFragment extends ListFragment {
}
3. 修改main.xml布局资源来包含第2步创建的Fragment。一定要保证对它的进行的命名,这样就可以对它在Activity中引用。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.earthquake.EarthquakeActivity" >
<fragment android:name="com.example.earthquake.EarthquakeListFragment"
android:id="@+id/EarthquakeListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
4. 创建一个新的公有Quake类。这个类用来存储每一次地震的详细的数据(日期、细节、位置、震级、链接)。重写toString包装数据的输出格式。
package com.example.earthquake;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.annotation.SuppressLint;
import android.location.Location;
@SuppressLint("SimpleDateFormat") public class Quake {
private Date date;
private String details;
private Location location;
private double magnitue;
private String link;
public Date getDate(){ return date; }
public String getDetails(){ return details; }
public Location getLocation(){ return location; }
public String getLink(){ return link; }
public Quake(Date _date, String _details, Location _location, double _magnitue, String _link){
this.date = _date;
this.details = _details;
this.location = _location;
this.magnitue = _magnitue;
this.link = _link;
}
@Override
public String toString() {
return new SimpleDateFormat("HH.mm").format(date) + ": " + this.magnitue + " " + this.details;
}
}
5. 在EarthquakeListFragment中,重写onActivityCreated事件存储Quake对象列表ArrayList,并使用一个ArraryAdapter将这个数组绑定到底层的ListView。
ArrayAdapter<Quake> aa;
ArrayList<Quake> earthquakes = new ArrayList<Quake>();
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
aa = new ArrayAdapter<Quake>(getActivity(), android.R.layout.simple_list_item_1, earthquakes);
}
6. 接下来处理地震源。Demo中使用的数据源是1天内USGS提供的震级大于2.5的地震数据。这里使用资源的方式将源的位置加进来:
<string name="quake_feed">http://earthquake.usgs.gov/eqcenter/catalogs/1day-M2.5.xml</string>
7. 访问Internet需要加入相应的访问权限。
<uses-permission android:name="android.permission.INTERNET" />
8. 返回到EarthquakeListFragment,创建refreshEarthquake方法。该方法链接到地震源并对其数据进行分析。
private static final String TAG = "EARTHQUAKE";
private Handler handler = new Handler();
public void refreshEarthquake(){
//获得xml
URL url;
try {
String quakeFeed = getString(R.string.quake_feed);
url = new URL(quakeFeed);
HttpURLConnection cn = (HttpURLConnection)url.openConnection();
int responseCode = cn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream stream = cn.getInputStream();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
//分析地震源
org.w3c.dom.Document doc = db.parse(stream);
Element element = doc.getDocumentElement();
//清除旧的地震数据源
earthquakes.clear();
//获得每个地震项的列表
NodeList nodeList = element.getElementsByTagName("entry");
if (nodeList != null && nodeList.getLength() > 0) {
for (int i = 0; i < nodeList.getLength(); i++) {
Element entry = (Element)nodeList.item(i);
Element title = (Element)entry.getElementsByTagName("title").item(0);
Element g = (Element)entry.getElementsByTagName("georss:point").item(0);
if(g == null) continue;
Element when = (Element)entry.getElementsByTagName("updated").item(0);
Element link = (Element)entry.getElementsByTagName("link").item(0);
String details = title.getFirstChild().getNodeValue();
String hostname = "http://earthquak.usgs.gov";
String linkString = hostname + link.getAttribute("href");
String point = g.getFirstChild().getNodeValue();
String dt = when.getFirstChild().getNodeValue();
SimpleDateFormat 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) {
Log.d(TAG, "Date Parse Exception.", e);
}
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 = Double.parseDouble(magnitudeString.substring(0, end));
details = details.split(",")[1].trim();
final Quake quake = new Quake(qDate, details, l, magnitude, linkString);
//处理一个发现的地震
handler.post(new Runnable() {
@Override
public void run() {
addNewQuake(quake);
}
});
}
}
}
} catch(MalformedURLException e){
Log.d(TAG, "MalformedURLException");
}
catch(IOException e){
Log.d(TAG, "IO Exception.");
}
catch(ParserConfigurationException e){
Log.d(TAG, "ParserConfigurationException");
}
catch (SAXException e) {
Log.d(TAG, "SAXException");
}
finally{
}
}
9. 更新AddNewEarthquake()
private void addNewQuake(Quake quake) {
//将新地震添加到地震列表中
earthquakes.add(quake);
//向Array Adapter通知改变
aa.notifyDataSetChanged();
}
10. 修改 onActivityCreated 方法,在启动时调用 refreshEarthquakes。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
aa = new ArrayAdapter<Quake>(getActivity(), android.R.layout.simple_list_item_1, earthquakes);
setListAdapter(aa);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
refreshEarthquake();
}
});
t.start();
}
运行效果图:
使用Download Manager下载文件
1. 下载文件
DownloadManager 是文件下载的管理类。
String seviceString = Context.DOWNLOAD_SERVICE;
DownloadManager dm = (DownloadManager)getSystemService(seviceString);
Uri uri = Uri.parse("http://deveoper.android.com/shareables/icon_templates-v4.0.zip");
DownloadManager.Request request = new Request(uri);
long reference = dm.enqueue(request);
根据返回的引用值,可以对某个下载进行进一步的操作或者查询,包括查看状态,取消下载。
也可以给下载指定限定条件,setAllowedNetworkType方法可以限制下载类型为Wi-Fi或者移动网络,而手机漫游,setAllowedOverRomaing方法可以有预见性的阻止下载。
request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
监控下载的完成:
IntentFilter filter = new IntentFilter(DownloadManager.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(myDownloadReferenc == reference){
// 对下载的文件进行的操作
}
}
};
registerReceiver(receiver, filter);
2. 自定义 Download Manager Notification
默认情况,会为Download Manager 显示一个持续的Notification。每个Notification都会显示一个下载文件名和下载进度。
Download Manager 可以为每个下载请求自定义Notification,包括把它完全隐藏。
request.setTitle(“Earthquake”);
request.setDescription(“Earthquake XML”);
通过setNotificationVisibility方法并使用下面的标识之一来控制何时以及是否应该为请求显示一个Notification:
Request.VISIBILITY_VISIBLE 默认选项。持续显示Notification,下载完成移除Notification。
Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED 下载时持续显示,完成后继续显示Notification。
Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETED 只有下载完显示Notification。
Request.VISIBILITY_HIDDEN 不为此下载显示Notification。为了使用这个标识,必须在manifest中指定uses-permission为DOWNLOAD_WITHOUT_NOTIFICATION
3. 指定下载位置
默认情况下,Download Manager会把下载的文件保存到共享下载缓存中,而且使用系统生成的文件名。每一个请求对象都可以指定一个下载路径位置,想让下载文件存储到外部存储器必须在manifest中注册uses-permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
指定下载路径:
request.setDestinationUri(uri);
4. 取消下载,删除下载
dm.remove(reference, reference1);
查询Download manager
query 一个下载的请求的状态、进度、和详细信息。该方法会返回下载的Cursor对象。
query 方法接收DownloadManager.Query 对象作为参数。使用setFieldById 方法给 Query 对象指定一个下载引用 ID 的序列,或者使用 setFilterByStatus 方法过滤下载的状态,该方法使用某个DownloadManager.STATUS_* 常量来指定下载的运行、暂停、失败、或者成功。
DownloadManager包含了很多COLUMN_*静态常量,可以用他们来查询结果Cursor。可以得到每个下载的详细信息,包括状态、文件大小、目前下载的字节数、标题、描述、URI、本地文件名和URI、媒体类型以及Media Provider下载URI。
@Override
public void onReceive(Context context, Intent intent) {
long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if(myDownloadReferenc == reference){
// 对下载的文件进行的操作
Query q = new Query();
q.setFilterById(reference);
Cursor download = dm.query(q);
if (download.moveToFirst()) {
int fileNameIdx = download.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
int fileUriIdx = download.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String fileName = download.getString(fileNameIdx);
String fileUri = download.getString(fileUriIdx);
}
download.close();
}
}
使用Account Manager 对 Google App Engine 进行身份认证
使用 Google Play Store。
如果应用程序连接到 Goolge App Engine 的后端来存储和检索一个特定用户的相关数据,那么可以使用Account Manager来处理身份验证。
要想使用这一功能,需要添加uses-permission标签:android.permission.GET_ACCOUNTS
1. 连接到 Google App Engine
请求一个token:
String acctSvc = Context.ACCOUNT_SERVICE;
AccountManager am = (AccountManager)getSystemService(acctSvc);
Account[] accounts = am.getAccountsByType("com.google");
if (accounts.length > 0) {
am.getAuthToken(accounts[0], "ah", false, callback, null);
}
2. 下载数据而不会耗尽电量的最佳实践
移动设备的无线电的激活状态时会消耗大量的电量,因此,考虑应用程序的连接模式如何影响它所应用的无线电硬件的操作是很重要的工作。
- 主动预取
- 将连接和下载绑定
- 重用现有连接而不是创建新连接
- 尽可能少调用重复下载
我的Android 4 学习系列之使用 Internet 资源的更多相关文章
- 我的Android 4 学习系列
Android 简介 开始入手 创建应用程序和Activity 创建用户界面 Intent 和 Broadcast Revicever 使用 Internet 资源 文件,保存状态和首选项 数据库和C ...
- 我的Android 4 学习系列之创建应用程序和Activity:Manifest、Application、Activity
目录 介绍Android应用程序组件,以及使用这些组件构建的各种Android应用程序 Android应用程序的生命周期 如何创建应用程序Manifest 如何使用外部资源提供对位置.语言和硬件配置的 ...
- 我的Android 4 学习系列之文件、保存状态和首选项
目录 使用Shared Preference 保留简单的应用程序数据 保存回话间的Activity实例数据 管理应用程序首选项和创建Preference Screen 保存并加载文件以及管理本地文件系 ...
- 我的Android 4 学习系列之创建用户基本界面
目录 使用视图和布局 理解Fragment 优化布局 创建分辨率无关的用户界面 扩展.分组.创建和使用视图 使用适配器将数据绑定到视图 使用视图和布局 1. Android UI 几个基本概念 视图: ...
- 我的Android 4 学习系列之数据库和Content Provider
目录 创建数据库和使用SQLite 使用Content Provider.Cusor和Content Value来存储.共享和使用应用程序数据 使用Cursor Loader异步查询Content P ...
- 我的Android 4 学习系列之Intent 和 Broadcast Reciever
目录 Intent 简介 使用隐式和显式Intent启动Activity.子Acitivity和Service 使用Linkify 使用Broadcast Intent 广播事件 使用 Pending ...
- 我的Android 4 学习系列之开始入手:配置开发环境与理解Hello World!
目录 如何安装Android SDK.创建开发环境和调试项目 移动设计中一些注意事项 使用Android虚拟设备.模拟器和其他开发工具 如何安装Android SDK.创建开发环境和调试项目 下载和安 ...
- android 动画学习系列(一)
老师今天开始讲android的游戏,讲到了view和surfaceview 下面是view的演示部分 private Paint paint; //游戏里很少用double,都是用long priva ...
- Android Studio学习NO.1 了解项目资源
2018.3.1 12:40:51 阅读书籍:第一行代码 1. res目录 drawable 图片 mipmap 图标 values 字符串.样式.颜色 layout 布局 2. 引用(可在Andro ...
随机推荐
- atitit.提升稳定性---hibernate 添加重试retry 机制解决数据库连接关闭
atitit.提升稳定性---hibernate 添加重试retry 机制解决数据库连接关闭 1. 流程总结 retry(5times).invoke(xxx).test().rest().$() t ...
- python抓取网络内容
最近想做研究互联网来获取数据,只是有一点python,让我们来看一个比较简单的实现. 例如,我想抓住奥巴马的每周演讲http://www.putclub.com/html/radio/VOA/pres ...
- iOS6和iOS7适应代码(6) —— NSLocalizedString
我们的应用程序都需要国际化,字符串的重要组成部分.一般来说.我们是通过一个string资源文件来达到这个目的,我们需要支持多国语言,有多少次把这个文档本地化.需要使用的代码NSLocalizedStr ...
- hdu 1542 Atlantis 段树区,并寻求,,,尼玛真坑人数据,不要打开一小阵!
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- Android监视返回键
android在发展中,监视键返回到后事件经常被用来,在下面的例子来说明什么android返回键事件监听器. public class BackKeyTest extends Activity { / ...
- table中的边框合并实例
<html><head><style type="text/css">table,th,td{border:1px solid blue;bor ...
- Android网络通信android-async-http入门
android-async-http入门 门免费链接分享前:http://pan.baidu.com/s/1mg9SvgO 密码:cgg7 API原文:http://loopj.com/android ...
- HDU 3376 && 2686 方格取数 最大和 费用流裸题
题意: 1.一个人从[1,1] ->[n,n] ->[1,1] 2.仅仅能走最短路 3.走过的点不能再走 问最大和. 对每一个点拆点限流为1就可以满足3. 费用流流量为2满足1 最大费用流 ...
- hdu 3874
求一个序列中全部数字的和,当中数值同样的仅仅能计算一次. 先储存全部的请求,然后依照它们的右边界排序,在查询的同一时候更新区间.这里事实上有一点点DP的味道,在它进行某个查询之前,保证全部的反复数字( ...
- Python编写网页爬虫爬取oj上的代码信息
OJ升级,代码可能会丢失. 所以要事先备份. 一開始傻傻的复制粘贴, 后来实在不能忍, 得益于大潇的启示和聪神的原始代码, 网页爬虫走起! 已经有段时间没看Python, 这次网页爬虫的原始代码是 p ...