android编程权威指南 的PhotoGallery项目Flickr 不能访问的替代解决方法
参考:
<<android编程权威指南(第2版)>>的PhotoGallery项目的练习 http://blog.csdn.net/u013163117/article/details/74356828
方法:
A json-server + xampp服务器 (本地的或远端的)
B 第三方云存储,如七牛云存储。
A.
json-server 用于传输json文件
https://www.npmjs.com/package/json-server
安装json-server需要npm,npm又需要Node.js,所以:
1 下载Node.js
http://nodejs.cn/download/
Node.js 是一个基于 Chrome V8 引擎的JavaScript 运行环境。
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
Node.js 的包管理器 npm,是全球最大的开源库生态系统。
F:\json_server\node-v8.9.0-win-x64>node-v
v8.9.0
F:\json_server\node-v8.9.0-win-x64>npm-v
5.5.1
2 通过npm安装json-server
F:\json_server\node-v8.9.0-win-x64>npminstall -g json-server
F:\json_server\node-v8.9.0-win-x64\json-server-> F:\json_server\node-v8.9.0-win
-x64\node_modules\json-server\bin\index.js
+ json-server@0.12.1
added 228 packages in 48.842s
F:\json_server\node-v8.9.0-win-x64>json-server-v
0.12.1
3 启动json-server
F:\json_server\node-v8.9.0-win-x64>json-server--watch photos.json --port 9090
\{^_^}/ hi!
Loading photos.json
Done
Resources
http://localhost:9090/photos
Home
http://localhost:9090
Type s + enter at any time to create a snapshot of the database
Watching...
GET /photos 200 2.580 ms - 947
GET /photos 200 1.738 ms - 947
浏览器访问:
http://localhost:9090 这个地址很慢
http://localhost:9090/photos 这个地址足够快;PhotoGallery 软件中用这个地址(“localhost”替换为实际IP地址)
photos.json 是自行建立的一个文件,如下:
{
"photos": {
"photo": [
{
"id": "123487091",
"title": "pic_1",
"url_s": "http://192.168.0.100:81/photos/1.jpg"
},
{
"id": "123487092",
"title": "pic_2",
"url_s": "http://192.168.0.100:81/photos/2.jpg"
},
{
"id": "123487098",
"title": "pic_8",
"url_s": "http://192.168.0.100:81/photos/8.jpg"
},
{
"id": "123487099",
"title": "pic_9",
"url_s": "http://192.168.0.100:81/photos/9.jpg"
}
]
}
}
以上内容是根据PhotoGallery 的需求构建的,url_s是图片文件存放的网络地址。根据实际情况填写相关信息。
xampp
https://www.apachefriends.org/zh_cn/index.html
测试图片存放位置
浏览器访问
PhotoGallery 的代码需修改部分:
public class FlickrFetchr{
…
private static final String myPhotosURL = "http://192.168.0.100:9090/photos";// json-server -w -p 9090 photos.json
…..
private List<GalleryItem> downloadGalleryItems(String url){ List<GalleryItem> items = new ArrayList<>(); try{ Log.i(TAG,"url:" + url); String urlx = Uri.parse(myPhotosURL) .buildUpon().toString(); String jsonString = getUrlString(urlx); Log.i(TAG,"Received JSON: " + jsonString); JSONObject jsonBody = new JSONObject(jsonString); parseItems(items,jsonBody); }catch (IOException ioe){ Log.e(TAG,"Failed to fetch items",ioe); }catch (JSONException je){ Log.e(TAG,"Failed to parse JSON",je); } return items; }
private void parseItems(List<GalleryItem> items, JSONObject jsonBody) throws JSONException { //JSONObject photosJsonObject = jsonBody.getJSONObject("photos"); //JSONArray photoJsonArray = photosJsonObject.getJSONArray("photo"); JSONArray photoJsonArray = jsonBody.getJSONArray("photo"); for(int i = 0; i < photoJsonArray.length();i++){ JSONObject photoJsonObject = photoJsonArray.getJSONObject(i); GalleryItem item = new GalleryItem(); item.setId(photoJsonObject.getString("id")); item.setCaption(photoJsonObject.getString("title")); if(!photoJsonObject.has("url_s")){ continue; } item.setUrl(photoJsonObject.getString("url_s")); items.add(item); } }
注:代码中,GridLayoutManager的列数被更改为:1。(测试的图片较少的缘故)
mPhotoRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(),1 /* 3 */));
B 第三方云存储方法
七牛云注册有免费试用,所以…
java sdk https://developer.qiniu.com/kodo/sdk/1239/java
android sdk https://developer.qiniu.com/kodo/sdk/1236/android
1 注册;2 实名认证(个人或企业);3创建对象存储空间;4 上传测试图片
确认以下信息:
① 测试域名,②存储空间名,③两对密钥(Access/SecretKey),④机房位置
项目中使用 java-sdk:
compile 'com.qiniu:qiniu-java-sdk:7.2.8'
获取空间文件列表
//构造一个带指定Zone对象的配置类
Configuration cfg = newConfiguration(Zone.zone0());
//...其他参数参考类注释
String accessKey = "your accesskey";
String secretKey = "your secretkey";
String bucket = "your bucketname";
Auth auth = Auth.create(accessKey,secretKey);
BucketManager bucketManager = newBucketManager(auth, cfg);
//文件名前缀
String prefix = "";
//每次迭代的长度限制,最大1000,推荐值 1000
int limit = 1000;
//指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串
String delimiter = "";
//列举空间文件列表
BucketManager.FileListIteratorfileListIterator = bucketManager.createFileListIterator(bucket, prefix, limit,delimiter);
while (fileListIterator.hasNext()) {
//处理获取的file list结果
FileInfo[] items = fileListIterator.next();
for (FileInfo item : items) {
System.out.println(item.key);
System.out.println(item.hash);
System.out.println(item.fsize);
System.out.println(item.mimeType);
System.out.println(item.putTime);
System.out.println(item.endUser);
}
}
通过以上方法,获取文件名列表,就可以自行构建List<GalleryItem>。
PhotoGallery 的代码需修改部分:
新建类QiniuPhotos.java
package com.example.andyli.photogallery; import android.net.Uri; import android.util.Log; import com.qiniu.common.Zone; import com.qiniu.storage.BucketManager; import com.qiniu.storage.Configuration; import com.qiniu.storage.model.FileInfo; import com.qiniu.util.Auth; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * Created by andyli on 2017/12/28. */ public class QiniuPhotos { /* 七牛云存储 AccessKey: SecretKey: 机房位置: 华南 Zone.zone2() ;
存储空间名: 测试域名: http://xxxxx 样式分隔符设置Style separator set: - 图片样式(缩略图模式,自建) : imageFop http://xxxxx/1.jpg http://xxxx/1.jpg-imageFop 关于Zone对象和机房的关系如下: 机房 Zone对象 华东 Zone.zone0() 华北 Zone.zone1() 华南 Zone.zone2() 北美 Zone.zoneNa0() android-sdk: compile 'com.qiniu:qiniu-android-sdk:7.3.10' java-sdk: compile 'com.qiniu:qiniu-java-sdk:7.2.8' */ private static final String qiniuPhotosURL = "http:// "; private static final String TAG = "QiniuPhotos"; private static final String accessKey = ""; private static final String secretKey = ""; private static final String bucket = ""; private static final String StyleSeparator = "-"; private static final String ImageMode = "imageFop"; public List<GalleryItem> fetchRecentPhotos(){ return downloadGalleryItems(null); } public List<GalleryItem> searchPhotos(String query){ return downloadGalleryItems(query); } private List<GalleryItem> downloadGalleryItems(String query){ List<GalleryItem> items = new ArrayList<>(); Log.i(TAG,"query:" + query); getFileList(items,query); return items; } private void getFileList(List<GalleryItem> items,String query) { //构造一个带指定Zone对象的配置类 Configuration cfg = new Configuration(Zone.zone2()); //...其他参数参考类注释 Auth auth = Auth.create(accessKey, secretKey); BucketManager bucketManager = new BucketManager(auth, cfg); //文件名前缀 String prefix = ""; //每次迭代的长度限制,最大1000,推荐值 1000 int limit = 1000; //指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串 String delimiter = ""; //列举空间文件列表 BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucket, prefix, limit, delimiter); while (fileListIterator.hasNext()) { //处理获取的file list结果 FileInfo[] FileItems = fileListIterator.next(); //UnknownHostException if(FileItems == null)//NullPointerException continue; for (FileInfo item : FileItems) { /*System.out.println(item.key); file name System.out.println(item.hash); System.out.println(item.fsize); file size System.out.println(item.mimeType); System.out.println(item.putTime); System.out.println(item.endUser);*/ Log.i(TAG,"key:"+item.key+",hash:"+item.hash+",fsize:"+item.fsize+",mimeType:"+item.mimeType); if(query != null && !item.key.contains(query)) continue; GalleryItem galleryItem = new GalleryItem(); galleryItem.setId(item.hash); galleryItem.setCaption(item.key); //galleryItem.setUrl(qiniuPhotosURL + "/"+ item.key + StyleSeparator + ImageMode);
galleryItem.setUrl(qiniuPhotosURL + "/"+ item.key); Log.i(TAG,"url:"+galleryItem.getUrl()); items.add(galleryItem); } } } }
PhotoGalleryFragment.java
public class PhotoGalleryFragment extends Fragment{
….
private class FetchItemsTask extends AsyncTask<Void,Void,List<GalleryItem>>{ private String mQuery; public FetchItemsTask(String query){ mQuery = query; } @Override protected List<GalleryItem> doInBackground(Void... params) { if(mQuery == null){ //return new FlickrFetchr().fetchRecentPhotos(); return new QiniuPhotos().fetchRecentPhotos(); }else{ //return new FlickrFetchr().searchPhotos(mQuery); return new QiniuPhotos().searchPhotos(mQuery); } }