/*
* Copyright 2011-2012 Renren Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.renren.api.connect.android;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Iterator;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.net.ConnectivityManager;
import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import com.renren.api.connect.android.exception.RenrenError;
import com.renren.api.connect.android.exception.RenrenException;
/**
*工具支持类
*
* @author yong.li@opi-corp.com
*
*/
public final class Util {
public static final String LOG_TAG = "Renren-SDK";
public static final String USER_AGENT_SDK = System.getProperties().getProperty("http.agent")
+ " Renren_Android_SDK_v3.0_beta";
public static void logger(String message) {
Log.i(LOG_TAG, message);
}
/**
* 将Key-value转换成用&号链接的URL查询参数形式。
*
* @param parameters
* @return
*/
public static String encodeUrl(Bundle parameters) {
if (parameters == null) {
return "";
}
StringBuilder sb = new StringBuilder();
boolean first = true;
for (String key : parameters.keySet()) {
if (first) {
first = false;
} else {
sb.append("&");
}
sb.append(key + "=" + URLEncoder.encode(parameters.getString(key)));
//sb.append(key + "=" + parameters.getString(key));
}
return sb.toString();
}
/**
* 将用&号链接的URL参数转换成key-value形式。
*
* @param s
* @return
*/
public static Bundle decodeUrl(String s) {
Bundle params = new Bundle();
if (s != null) {
params.putString("url", s);
String array[] = s.split("&");
for (String parameter : array) {
String v[] = parameter.split("=");
if (v.length > 1) {
params.putString(v[0], URLDecoder.decode(v[1]));
}
}
}
return params;
}
/**
* 解析URL中的查询串转换成key-value
*
* @param url
* @return
*/
public static Bundle parseUrl(String url) {
url = url.replace("rrconnect", "http");
url = url.replace("#", "?");
try {
URL u = new URL(url);
Bundle b = decodeUrl(u.getQuery());
b.putAll(decodeUrl(u.getRef()));
return b;
} catch (MalformedURLException e) {
return new Bundle();
}
}
/**
* 发送http请求
*
* @param url
* @param method GET 或 POST
* @param params
* @return
*/
public static String openUrl(String url, String method, Bundle params) {
if (method.equals("GET")) {
url = url + "?" + encodeUrl(params);
}
String response = "";
try {
Log.d(LOG_TAG, method + " URL: " + url);
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestProperty("User-Agent",USER_AGENT_SDK);
if (!method.equals("GET")) {
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.getOutputStream().write(encodeUrl(params).getBytes("UTF-8"));
}
InputStream is = null;
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
is = conn.getInputStream();
} else {
is = conn.getErrorStream();
}
response = read(is);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return response;
}
private static HttpURLConnection openConn(String url, String method, Bundle params) {
if (method.equals("GET")) {
url = url + "?" + encodeUrl(params);
}
try {
Log.d(LOG_TAG, method + " URL: " + url);
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestProperty("User-Agent",USER_AGENT_SDK);
if (!method.equals("GET")) {
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.getOutputStream().write(encodeUrl(params).getBytes("UTF-8"));
}
return conn;
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
throw new RuntimeException(e.getMessage(), e);
}
}
private static String read(InputStream in) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader r = new BufferedReader(new InputStreamReader(in), 1000);
for (String line = r.readLine(); line != null; line = r.readLine()) {
sb.append(line);
}
in.close();
return sb.toString();
}
public static byte[] getBytes(String url, Bundle params) {
try {
HttpURLConnection conn = openConn(url, "post", params);
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
InputStream is = conn.getInputStream();
for (int i = 0; (i = is.read(buf)) > 0;) {
os.write(buf, 0, i);
}
is.close();
os.close();
return os.toByteArray();
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
throw new RuntimeException(e.getMessage(), e);
}
}
public static String uploadFile(String reqUrl, Bundle parameters, String fileParamName,
String filename, String contentType, byte[] data) {
HttpURLConnection urlConn = null;
try {
urlConn = sendFormdata(reqUrl, parameters, fileParamName, filename, contentType, data);
String responseContent = read(urlConn.getInputStream());
return responseContent.trim();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (urlConn != null) {
urlConn.disconnect();
}
}
}
private static HttpURLConnection sendFormdata(String reqUrl, Bundle parameters,
String fileParamName, String filename, String contentType, byte[] data) {
HttpURLConnection urlConn = null;
try {
URL url = new URL(reqUrl);
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setRequestMethod("POST");
urlConn.setConnectTimeout(5000);// (单位:毫秒)jdk
urlConn.setReadTimeout(5000);// (单位:毫秒)jdk 1.5换成这个,读操作超时
urlConn.setDoOutput(true);
urlConn.setRequestProperty("connection", "keep-alive");
String boundary = "-----------------------------114975832116442893661388290519"; // 分隔符
urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
boundary = "--" + boundary;
StringBuffer params = new StringBuffer();
if (parameters != null) {
for (Iterator<String> iter = parameters.keySet().iterator(); iter.hasNext();) {
String name = iter.next();
String value = parameters.getString(name);
params.append(boundary + "\r\n");
params.append("Content-Disposition: form-data; name=\"" + name + "\"\r\n\r\n");
// params.append(URLEncoder.encode(value, "UTF-8"));
params.append(value);
params.append("\r\n");
}
}
StringBuilder sb = new StringBuilder();
sb.append(boundary);
sb.append("\r\n");
sb.append("Content-Disposition: form-data; name=\"" + fileParamName + "\"; filename=\""
+ filename + "\"\r\n");
sb.append("Content-Type: " + contentType + "\r\n\r\n");
byte[] fileDiv = sb.toString().getBytes();
byte[] endData = ("\r\n" + boundary + "--\r\n").getBytes();
byte[] ps = params.toString().getBytes();
OutputStream os = urlConn.getOutputStream();
os.write(ps);
os.write(fileDiv);
os.write(data);
os.write(endData);
os.flush();
os.close();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return urlConn;
}
public static void clearCookies(Context context) {
@SuppressWarnings("unused")
CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
}
/**
* 将服务器返回的错误JSON串,转化成RenrenError.
*
* @param JSON串
* @return
*/
private static RenrenError parseJson(String jsonResponse) {
try {
JSONObject json = new JSONObject(jsonResponse);
int errorCode = json.getInt("error_code");
String errorMessage = json.getString("error_msg");
errorMessage = RenrenError.interpretErrorMessage(errorCode, errorMessage);
return new RenrenError(errorCode, errorMessage, jsonResponse);
} catch (JSONException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* 将服务器返回的错误XML串,转化成RenrenError.
*
* @param JSON串
* @return
*/
private static RenrenError parseXml(String xmlResponse) {
XmlPullParser parser = Xml.newPullParser();
RenrenError error = null;
try {
parser.setInput(new StringReader(xmlResponse));
int evtCode = parser.getEventType();
int errorCode = -1;
String errorMsg = null;
while (evtCode != XmlPullParser.END_DOCUMENT) {
switch (evtCode) {
case XmlPullParser.START_TAG:
if ("error_code".equals(parser.getName())) {
errorCode = Integer.parseInt(parser.nextText());
}
if ("error_msg".equals(parser.getName())) {
errorMsg = parser.nextText();
}
break;
}
if (errorCode > -1 && errorMsg != null) {
error = new RenrenError(errorCode, errorMsg, xmlResponse);
break;
}
evtCode = parser.next();
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return error;
}
/**
* 响应的内容是错误信息时,被转化成RenrenError,否则返回NULL
*
* @param response
* @param responseFormat
* @return
*/
public static RenrenError parseRenrenError(String response, String responseFormat) {
if (response.indexOf("error_code") < 0) return null;
if (Renren.RESPONSE_FORMAT_JSON.equalsIgnoreCase(responseFormat)) return parseJson(response);
return parseXml(response);
}
/**
*
* 检查接口返回的内容,是否包含错误信息,如包含,则抛出{@link RenrenException}
*
* @param response
* @param responseFormat
* @throws RenrenException
*/
public static void checkResponse (String response, String responseFormat) throws RenrenException {
if (response != null) {
if (response.indexOf("error_code") < 0) {
return;
}
RenrenError error = null;
if (Renren.RESPONSE_FORMAT_JSON.equalsIgnoreCase(responseFormat)) {
error = parseJson(response);
} else {
error = parseXml(response);
}
if (error != null) {
throw new RenrenException(error);
}
}
}
/**
* 显示一个简单的对话框;只能在UI线程中调用。
*
* @param context
* @param title
* @param text
*/
public static void showAlert(Context context, String title, String text, boolean showOk) {
AlertDialog alertDialog = new Builder(context).create();
alertDialog.setTitle(title);
alertDialog.setMessage(text);
if (showOk) {
OnClickListener listener = null;
alertDialog.setButton2("确定", listener);
}
alertDialog.show();
}
/**
* 显示一个简单的对话框;只能在UI线程中调用。
*
* @param context
* @param title
* @param text
*/
public static void showAlert(Context context, String title, String text) {
showAlert(context, title, text, true);
}
public static String md5(String string) {
if (string == null || string.trim().length() < 1) {
return null;
}
try {
return getMD5(string.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static String getMD5(byte[] source) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
StringBuffer result = new StringBuffer();
for (byte b : md5.digest(source)) {
result.append(Integer.toHexString((b & 0xf0) >>> 4));
result.append(Integer.toHexString(b & 0x0f));
}
return result.toString();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* 检查当前网络连接状态
* @param
* 调用此方法的Context
* @return
* true - 有可用的网络连接(3G/GSM、wifi等)
* false - 没有可用的网络连接,或传入的context为null
*/
public static boolean isNetworkConnected(Context context) {
if(context == null){
return false;
}
ConnectivityManager connManager =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
State mobileState = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
State wifiState = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
if(mobileState == State.DISCONNECTED && wifiState == State.DISCONNECTED) {
return false;
}
return true;
}
/**
* 显示征询“确认”以及“取消”的对话框
*
* @param activity 显示此对话框的Activity对象
* @param title 对话框的标题
* @param text 对话框显示的内容
* @param listener 用户选择的监听器
*/
public static void showOptionWindow(Activity activity, String title,
String text, OnOptionListener listener) {
AlertDialog dialog = new AlertDialog.Builder(activity).create();
if(title != null) {
dialog.setTitle(title);
}
if(text != null) {
dialog.setMessage(text);
}
final OnOptionListener oListener = listener;
dialog.setButton(AlertDialog.BUTTON_POSITIVE,
activity.getString(R.string.renren_sdk_submit),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
oListener.onOK();
}
});
dialog.setButton(AlertDialog.BUTTON_NEGATIVE,
activity.getString(R.string.renren_sdk_cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
oListener.onCancel();
}
});
dialog.show();
}
/**
* 二元选择的监听器
*
* @author Shaofeng Wang (shaofeng.wang@renren-inc.com)
*
*/
public static interface OnOptionListener {
/**
* 对确认选择的响应
*/
public void onOK();
/**
* 对取消选择的响应
*/
public void onCancel();
}
/**
* 工具类,读取文件二进制数据
*
* @param file
* @return
* @throws IOException
*/
public static byte[] fileToByteArray(File file) {
try {
return streamToByteArray(new FileInputStream(file));
} catch (FileNotFoundException e) {
logger(e.getMessage());
return null;
}
}
/**
* 工具,将输入流转换成字节数组
*
* @param inputStream
* @return
* @throws IOException
*/
public static byte[] streamToByteArray(InputStream inputStream) {
byte[] content = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedInputStream bis = new BufferedInputStream(inputStream);
try {
byte[] buffer = new byte[1024];
int length = 0;
while ((length = bis.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
content = baos.toByteArray();
if (content.length == 0) {
content = null;
}
baos.close();
bis.close();
} catch (IOException e) {
logger(e.getMessage());
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
logger(e.getMessage());
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
logger(e.getMessage());
}
}
}
return content;
}
}