在前一篇文章《优酷SDK学习》中使用优酷API根据视频种类进行搜索,可是优酷设置的视频种类中只有游戏,没有我想要搜索的DOTA2视频。于是为了弄懂怎么去搜索DOTA2视频,专门在优酷网页上打开了一个DOTA2视频,把他的网址记下来,然后解析出该视频的id,再运用id将该视频所用的具体信息打印出来。我发现在该视频的信息中有一个tag属性,记录了该视频是一个DOTA2视频。于是我就在想能不能根据这个tag去进行搜索。查看优酷API之后,果真发现有根据tag搜索视频的。多个tag之间用逗号分开。
public static final String TAG_URL = "https://openapi.youku.com/v2/searches/video/by_tag.json";
在解决了这个问题之后,然后就是listview显示的问题了。对于ListView的上下拉刷新加载问题,我直接引用了开源框架XListView。下面直接上主界面显示DOTA2视频列表的代码。
package com.jgh.watchdota;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.jgh.cache.FileService;
import com.jgh.util.DotaItemAdapter;
import com.jgh.util.ItemDate;
import com.jgh.util.StaticsUtil;
import me.maxwin.view.XListView;
import me.maxwin.view.XListView.IXListViewListener;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;
public class HomeFragment extends Fragment implements IXListViewListener,
OnItemClickListener {
public static final String TAG_URL = "https://openapi.youku.com/v2/searches/video/by_tag.json";// 优酷API搜索url
public Activity mActivity;
private XListView mListView;// ListView
private DotaItemAdapter mAdapter;// 自定义适配器
private static List<Map<String, Object>> items = new ArrayList<Map<String, Object>>();// ListView中的Item集合
private Map<String, String> params;// 搜索的参数
private Handler mHandler;
private Handler handler;
private int page = 1;// 搜索的当前页数
private static int pageCount = 20;// 每页搜索的item条数
private boolean isOnRefresh = false;// 标记是否正处于下拉刷新状态
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.layout_home, container, false);
params = new HashMap<String, String>();// 初始化搜索参数
params.put("client_id", StaticsUtil.CLIENT_ID);// APK申请的client_id
params.put("category", "游戏");
params.put("tag", "DOTA2");
params.put("orderby", "published");
params.put("page", page+"");
params.put("count", pageCount+"");
mActivity = getActivity();
initList(view);// 初始化ListView
return view;
}
private void initList(View view) {
// TODO Auto-generated method stub
getItems();// 开启异步线程获取item
mListView = (XListView) view.findViewById(R.id.xListView);
mListView.setPullLoadEnable(true);// 上拉加载更多
mListView.setPullRefreshEnable(false);// 下拉刷新,这里暂时关闭该功能
mListView.setXListViewListener(this);
mListView.setOnItemClickListener(this);
handler = new Handler();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case 0:// 加载失败
page --;
onLoad();
Toast.makeText(mActivity, "网络异常,加载失败!", Toast.LENGTH_SHORT).show();
break;
case 1:
mAdapter = new DotaItemAdapter(mActivity, items);
mListView.setAdapter(mAdapter);
break;
case 2:
Log.i("jiangguohu","handler case 2");
mAdapter.notifyDataSetChanged();
onLoad();
break;
default:
break;
}
}
};
}
private void getItems() {
// TODO Auto-generated method stub
thread.start();
}
@Override
public void onRefresh() {// 下拉刷新时会调用的方法
// TODO Auto-generated method stub
handler.postDelayed(new Runnable() {
@Override
public void run() {
mListView.setAdapter(mAdapter);
onLoad();
}
}, 2000);
}
@Override
public void onLoadMore() {// 上拉加载更多的方法
// TODO Auto-generated method stub
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.i("jiangguohu","isOnRefresh = "+isOnRefresh);
if (checkNetWork(mActivity)) {// 检查网络,没有联网时停止加载
if (!isOnRefresh) {
isOnRefresh = true;
page ++;// 加载下一页数据
final Map<String, String> params2 = new HashMap<String, String>();
params2.put("client_id", StaticsUtil.CLIENT_ID);
params2.put("category", "游戏");
params2.put("tag", "DOTA2");
params2.put("orderby", "published");
params2.put("page", page+"");
params2.put("count", pageCount+"");
new Thread(new Runnable() {
public void run() {
boolean b = false;
try {
b = sendGETRequest(TAG_URL, params2, mActivity);
Log.i("jiangguohu", "b2 = " + b);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (b) {// 运用handler返回处理结果,刷新界面
mHandler.sendEmptyMessage(2);
} else {
mHandler.sendEmptyMessage(0);
}
}
}).start();
}
} else {
Toast.makeText(mActivity, "请检查网络设置!", Toast.LENGTH_SHORT).show();
onLoad();
}
}
}, 2000);
}
private void onLoad() {// 下拉刷新或者上拉加载结束时候手动调用该方法,结束刷新
mListView.stopRefresh();
mListView.stopLoadMore();
mListView.setRefreshTime("刚刚");
isOnRefresh = false;
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {// ListView的点击事件,在这里我直接跳转到优酷Demo中的播放界面
// TODO Auto-generated method stub
if (!checkNetWork(mActivity)) {
Toast.makeText(mActivity, "请检查网络设置!", Toast.LENGTH_SHORT).show();
return;
}
Intent i = new Intent(
mActivity, PlayerActivity.class);
String id = (String) items.get(arg2-1).get("id");
i.putExtra("vid", id.trim());
startActivity(i);
}
Thread thread = new Thread(new Runnable() {
public void run() {
boolean b = false;
try {
b = sendGETRequest(TAG_URL, params, mActivity);
Log.i("jiangguohu", "b = " + b);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (b) {
mHandler.sendEmptyMessage(1);
} else {
mHandler.sendEmptyMessage(0);
}
}
});
private static boolean sendGETRequest(String path,
Map<String, String> params, Context context) throws Exception {// GET方式访问网络获取数据
StringBuilder sb = new StringBuilder();
sb.append(path).append("?");
if (params != null && params.size() != 0) {
for (Map.Entry<String, String> entry : params.entrySet()) {
sb.append(entry.getKey()).append("=")
.append(URLEncoder.encode(entry.getValue(), "utf-8"));
sb.append("&");
}
sb.deleteCharAt(sb.length() - 1);
}
if (checkNetWork(context)) {
URL url = new URL(sb.toString());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
Log.i("jiangguohu","sendGETRequest conn.getResponseCode() = "+conn.getResponseCode());
if (conn.getResponseCode() == 200) {
InputStream is = conn.getInputStream();
byte[] data = readStream(is);
String json = new String(data);
loadDate(json);
FileService fileService = new FileService(context);// 文件缓存,保存当前页面从网络获取的json数据
fileService.clear();
fileService.save(json);
return true;
}
return false;
} else {// 没有网络时,加载本地缓存数据
items.clear();
loadDate(new FileService(context).read());
if (items.size() != 0) {
return true;
} else {
return false;
}
}
}
public static byte[] readStream(InputStream inputStream) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
bout.write(buffer, 0, len);
}
bout.close();
inputStream.close();
return bout.toByteArray();
}
/**
* 将json数据存入list
* @param string
*/
public static void loadDate(String string) {
JSONObject jsonObject;
try {
jsonObject = new JSONObject(string);
JSONArray jsonArray = (JSONArray) jsonObject.opt("videos");
Map<String, Object> map = null;
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject item = jsonArray.getJSONObject(i);
ItemDate itemDate = new ItemDate();// 自己写的ItemDate类,用于封装item信息
map = itemDate.getHashMap(item);
if (map != null) {
items.add(map);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 检查网络连接
* @param mContext
* @return
*/
public static boolean checkNetWork(Context mContext) {
ConnectivityManager connectivityManager = (ConnectivityManager) mContext
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
if (info == null || !info.isAvailable()) {
return false;
} else {
return true;
}
}
}
下面再让我们来看看ItemDate这个类吧:
package com.jgh.util;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
/**
* 查询网页,返回结果进行处理的包装类
*
* @author jiangguohu
*
*/
public class ItemDate {
private String id;// 视频的id
private String title;// 视频的标题
private String link;// 视频的链接地址
private String duration;// 视频的总shichang
private String thumbnail;// 视频截图
private String published;// 视频发布的时间
public ItemDate() {
super();
}
public ItemDate(String id, String title, String link, String duration,
String thumbnail, String published) {
super();
this.id = id;
this.title = title;
this.link = link;
this.duration = duration;
this.thumbnail = thumbnail;
this.published = published;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getThumbnail() {
return thumbnail;
}
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
public String getPublished() {
return published;
}
public void setPublished(String published) {
this.published = published;
}
public Map<String, Object> getHashMap(JSONObject item) {// 将从网络中获取的json信息处理为Map对象,然后存放在List中
// TODO Auto-generated method stub
Map<String, Object> map = new HashMap<String, Object>();
try {
if (10*60 > item.getInt("duration")) {// 排除十分钟一下的视频
Log.i("jiangguohu","时间太短,排除!");
return null;
}
title = item.getString("title");
id = item.getString("id");
link = item.getString("link");
duration = String.valueOf(item.getInt("duration"));
thumbnail = item.getString("thumbnail");
published = item.getString("published");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
map.put("id", id);
map.put("title", title);
map.put("link", link);
map.put("thumbnail", thumbnail);
map.put("published", published);
map.put("duration", changeTimeFormat(duration + ""));// 更改视频总时长显示的格式
return map;
}
/**
* 将从网络中获取的时间进行转化
* @param time
* @return
*/
public static String changeTimeFormat(String time) {
if (time != null) {
int timeInt = Integer.parseInt(time);
int second = timeInt % 60;
int minute = (timeInt / 60) % 60;
int hour = (timeInt / 60) / 60;
return "" + (hour < 10 ? ("0" + hour) : hour + "") + ":"
+ (minute < 10 ? ("0" + minute) : minute + "") + ":"
+ (second < 10 ? ("0" + second) : second);
}
return time;
}
public static ItemDate getItemDate(Map<String, Object> map) {// 将一个Map对象处理为一个ItemDate类对象
return new ItemDate((String) map.get("id"), (String) map.get("title"),
(String) map.get("link"), (String) map.get("duration"),
(String) map.get("thumbnail"), (String) map.get("published"));
}
}
再来看看我们自定义的Adapter吧:
package com.jgh.util;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import com.jgh.cache.ImageLoader;
import com.jgh.watchdota.R;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class DotaItemAdapter extends BaseAdapter {
private Activity mActivity;
private List<Map<String, Object>> items;
ImageLoader imageLoader;
public DotaItemAdapter(Activity mActivity, List<Map<String, Object>> items) {
// TODO Auto-generated constructor stub
this.mActivity = mActivity;
this.items = items;
imageLoader = new ImageLoader(mActivity);// 图片缓存处理类
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return items.get(arg0);
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
ItemDate itemMap = ItemDate.getItemDate(items.get(arg0));// 将List中获取Map然后转化为ItemDate
LayoutInflater inflater = mActivity.getLayoutInflater();
View itemView = inflater.inflate(R.layout.list_item, null);
TextView title = (TextView) itemView.findViewById(R.id.title);
TextView published = (TextView) itemView.findViewById(R.id.published);
TextView duration = (TextView) itemView.findViewById(R.id.duration);
ImageView imageView = (ImageView) itemView.findViewById(R.id.image);
title.setText(itemMap.getTitle());
published.setText(itemMap.getPublished());
duration.setText(itemMap.getDuration()+"");
//Log.i("jiangguohu","itemMap.get(thumbnail) = "+itemMap.get("thumbnail"));
//imageView.setImageURI(Uri.parse(itemMap.get("thumbnail")));
//imageView.setImageBitmap((Bitmap) itemMap.get("thumbnail"));
imageLoader.displayImage(itemMap.getThumbnail(), imageView);// 加载缓存图片,如若没有缓存,从网络获取
return itemView;
}
}
好啦,以上就是现阶段的分享啦。下一章将会讲解缓存部分。等到做的差不多的时候再发布源码。欢迎大家留言讨论,共同进步。