Android 网络连接(PhotoGallery应用)

基本网络连接

GitHub 地址:关于联网显示图片的应用

前期准备

fragment + recyclerView 实现基本框架,这就不说了,前面有介绍过,没总结过 http 与后台的知识

设置网络类

  1. 创建一个类,并实现两个方法分别用来获取数据的字节流并把字节流转化为字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class FlickerFerchr {
public byte[] getUrlBytes(String urlSpec) throws IOException {
// 创建 URL 对象将 url 字符串转换为URL
URL url = new URL(urlSpec);
// 创建连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try{
// 实例化字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
// getInputStream() 连接
InputStream in = connection.getInputStream();
// 判断是否连接成功
if (connection.getResponseCode()!=HttpURLConnection.HTTP_OK){
throw new IOException(connection.getResponseMessage()+"with:"+urlSpec);
}
int bytesRead=0;
byte[] buffer=new byte[1024];
// 循环读取,读取一定数量字节放入缓存区数组buffer,并以整数形式返回实际读取的字节数
while ((bytesRead=in.read(buffer))>0){
out.write(buffer,0,bytesRead);
}
// 关闭输出流
out.close();
return out.toByteArray();
}finally {
connection.disconnect();
}
}
public String getUrlString(String urlSpec) throws IOException {
return new String(getUrlBytes(urlSpec));
}
}

获取网络使用权限

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

使用 AsyncTask 在后台线程上运行代码

我们前面都是使用的 UI 线程,当进行网络访问的等操作,如果还在 UI 线程上,会出现程序不响应,是否结束任务的提示,所以使用 AsyncTask 工具类创建一个后台线程处理网络请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*创建一个 AsyncTask 的内部类,后台处理网络*/
private class FetchItemsTask extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... voids) {
// 获取网络中的String 数据
try {
String result = new FlickerFerchr()
.getUrlString("http://www.bignerdranch.com");
// log 显示 String
Log.i("TAG","Fetched contents of URL:+"+result);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

启动后台线程

1
2
// 执行AsyncTask
new FetchItemsTask().execute();

线程与主线程

网络连接需要时间。Web 服务器也需要时间响应请求,文件下载则需要更长的时间。Android 禁止任何主线程网络连接行为。如果 Android 也会抛出 NetworkOnMainThreadException 异常
线程:单一执行序列,单个线程代码会逐步执行。
Android 应用运行从主线程开始,但它并不是线程那样的预定执行序列。相反,它是一个无限循环的运行状态,等待用户或者系统触发的事件的发生。事件触发后,主线程便负责执行代码.

从 Flickr 获取 JSON 数据

前面的网站虽然通过 web 可以进行访问,但是并没有返回我们可以使用时信息,我们通过 Flickr 提供的 JSON API 获取我们想要的信息,并显示到我们的应用上

下面是我自己建立的,这个过程耗费我两天,因为flickr 创建的 key 一直不生效,最后发现是权限为私有,打开为公有还要上传照片、添加标签、添加 url 最后才能修改

https://api.flickr.com/services/rest/?method=flickr.photos.getRecent&api_key=461a0d44890535444f94fd9d9643b6b6&format=json&nojsoncallback=1

构建 url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*创建一个构造url的方法*/
public void fetchItems(){
try {
// 构建url 字符串供 getUrlString 方法使用
String url =Uri.parse("https://api.flickr.com/services/rest/")
.buildUpon()
.appendQueryParameter("method","flickr.photos.getRecent")
.appendQueryParameter("api_key","461a0d44890535444f94fd9d9643b6b6")
.appendQueryParameter("format","json")
.appendQueryParameter("nojsoncallback","1")
.appendQueryParameter("extras","url_s")
.build().toString();
String jsonString=getUrlString(url);
Log.e("TAG","JSON: "+jsonString);
} catch (IOException e) {
e.printStackTrace();
}
}

重新修改后台访问网络连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*创建一个 AsyncTask 的内部类,后台处理网络*/
private class FetchItemsTask extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... voids) {
// 获取网络中的String 数据
/* String result = new FlickerFerchr()
.getUrlString("http://www.bignerdranch.com");
// log 显示 String
Log.i("TAG","Fetched contents of URL:+"+result);*/
new FlickerFerchr().fetchItems();
return null;
}
}

Console 台显示 json 字符串

(*^▽^*)