android 离线下载

==========================离线下载

import java.io.BufferedInputStream;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;
import java.util.Timer;
import java.util.TimerTask;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;


import org.json.JSONException;
import org.json.JSONObject;


import com.rytong.tools.crypto.AESCipher;
import com.rytong.tools.crypto.Base64;
import com.rytong.tools.crypto.HMac;
import com.rytong.tools.httpconnect.HttpManager;
import com.rytong.tools.utils.Utils;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.os.Looper;
import android.util.DisplayMetrics;


public class OffStoreDownload {
private final String PLUGRESOURCES = "plug_in_resources.db";
private final String OFFLINERESOURCES = "offline_resources.db";
private Activity activity_;
// 是否必须更新(-1:不更新,0:不强制更新,1:强制更新)
private String mustupate_;
// 离线资源数据库
public static OffStoreDB offLineDB_;
// 插件数据库
public static OffStoreDB plugDB_;

static public String FILEROOT;

final static public String PLUGROOT = "plug-in-resources/";
final static public String OFFLINEROOT = "offline-resources/";
final static public String WRITEROOT = "write/";
// 需要更新资源列表
private HashMap<String, String> resourceMap_;
// 列表path和rev(SHA1的hash)
private HashMap<String, HashMap<String, String>> serverMap_;
private HashMap<String, Boolean> alreadyDownload_;
private String serverString_;
// 离线更新接口
public final String RESOURCE_UPDATE = "/ota/resource_update?";
private int downloadNum_;


public OffStoreDownload(Activity activity) {
activity_ = activity;
alreadyDownload_ = new HashMap<String, Boolean>();
downloadNum_ = 1;// 重复下载一次即可。
offLineDB_ = new OffStoreDB(activity, OFFLINERESOURCES);
plugDB_ = new OffStoreDB(activity, PLUGRESOURCES);
}


// 步骤1:发送请求:平台类型、屏幕分辨率、server.desc(不存在则为空)
public void downloadOfflineResource() {
// 手机平台
final String platform = Utils.getConfigStringFormAsset(activity_, "offstoreplatform");
// 分辨率
DisplayMetrics dm = new DisplayMetrics();
activity_.getWindowManager().getDefaultDisplay().getMetrics(dm);
final String screenResolution = String.valueOf(dm.widthPixels) + "*" + String.valueOf(dm.heightPixels);
// 本地离线文件client.desc(不为空则发送)
final String client_desc = (String) offLineDB_.find("client.desc");
Timer timer_ = new Timer();
timer_.schedule(new TimerTask() {
@Override
public void run() {
HttpManager hm = new HttpManager(activity_);
String uri = Utils.getConfigStringFormAsset(activity_, "SERVER_URI").concat(RESOURCE_UPDATE);// http://192.168.85.69:4002/ota/resource_update?
StringBuffer buf = new StringBuffer();
buf.append("desc=");
if (client_desc != null)
buf.append(client_desc).append("&");
else
buf.append("&");
buf.append("platform=").append(platform).append("&");
buf.append("resolution=").append(screenResolution);
String body = buf.toString();
Object server_update = hm.sendPostRequest(uri, body, HttpManager.MIME_JSON, null);
// 步骤2:读取返回的download.desc和server.desc。
parseResponse(server_update);
}
}, 0);
}


public void saveToDb(OffStoreDB db, String key, Object value) {
db.insert(key, value);
}


// 解析返回来的数据
protected void parseResponse(Object serverUpdate) {
if (null == serverUpdate)
return;
if (serverUpdate instanceof String)
parseJSON((String) serverUpdate);
}


// 先判断是否需要强制更新,如果不是强制更新,则提醒用户。
private void parseJSON(String serverResponse) {
try {
// {"mustupdate":0,"server":{"yybk.zip":{"rev":"0b08d0c498e0eb5e2d19abc6dda695cc7f462473","path":"android/480-320/zip","desc":{"html/showCard.html":"0afd92a6b7fa6070a3610ffad94d24c0137538d1","imgs/back_03.png":"91e81ea8d58fcca77f4e43699e3cc8186691cdb2","imgs/card1.png":"f4598e2ea5d5fee387cb906506a424e1e842aac7","imgs/card2.png":"c42659dd3ab85894685ea7b10bcd2755b6d7b2cc","imgs/card3.png":"debe586a42d9b3536574bcd1daaaafb67332e99a","imgs/photo1.png":"14fbab85d86ce08593b67153a86daa8085fec61f","imgs/title_02.png":"63f7b712014402807f35d37b34acfc557228e7d2","js/jquery-1.7.1.js":"62922be0191a2cc4d13ef3abe4a62d1ebc17492d"}}},"download":{"yybk.zip":"http://192.168.65.82:4004/ebank/resources/android/480-320/zip/yybk.zip"}};
// {"mustupdate":0,"server":{"colorful.png":{"rev":"7915a251510c265826a1ee14c5a7c1ac31459890","path":"android/320*480/png"},"background_cao.png":{"rev":"da39a3ee5e6b4b0d3255bfef95601890afd80709","path":"android/320*480/png"}},"download":{"background_cao.png":"http://192.168.63.68:4002/ebank/resources/android/320*480/png/background_cao.png","colorful.png":"http://192.168.63.68:4002/ebank/resources/android/320*480/png/colorful.png"}}
Utils.printOutToConsole("offstore data: " + serverResponse);
final JSONObject obj = new JSONObject(serverResponse);
// 是否必须更新
mustupate_ = obj.getString("mustupdate");
if (null == mustupate_)
return;
if (mustupate_.equalsIgnoreCase("0")) {
final Builder ad = new AlertDialog.Builder(activity_);
ad.setTitle("提示").setMessage("您有新的离线资源需要下载,是否更新?").setCancelable(false)
.setNegativeButton("确定", new DialogInterface.OnClickListener() {


public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
parseJSONIndeed(obj);
if (checkAllDownload()) {
// 下载10:下载完毕后存储server.desc文件。
saveToDb(offLineDB_, "client.desc", serverString_);
return;
}
downloadResourceByPath();// 根据路径下载每一个resource
}


}).setPositiveButton("取消", new DialogInterface.OnClickListener() {


public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}


});
if (!activity_.isFinishing()) {
activity_.runOnUiThread(new Runnable() {


@Override
public void run() {
// TODO Auto-generated method stub
ad.show();
}


});
}


} else {
parseJSONIndeed(obj);
if (checkAllDownload()) {
// 下载10:下载完毕后存储server.desc文件。
saveToDb(offLineDB_, "client.desc", serverString_);
return;
}
downloadResourceByPath();// 根据路径下载每一个resource
}


} catch (JSONException e) {
Utils.printException(e);
}
}


// 解析JSON---步骤3:解析download.desc。
private void parseJSONIndeed(JSONObject obj) {
// TODO Auto-generated method stub
// download.desc
try {
resourceMap_ = new HashMap<String, String>();
serverMap_ = new HashMap<String, HashMap<String, String>>();
JSONObject downObject;


downObject = obj.getJSONObject("download");


Iterator itDown = downObject.keys();
String key = "";
String value = "";
while (itDown.hasNext()) {
key = itDown.next().toString();
value = downObject.getString(key);
// 未下载时,更新标志为false;更新后修改标志位
alreadyDownload_.put(key, false);
resourceMap_.put(key, value);
}


// server.desc
JSONObject serverObject = obj.getJSONObject("server");
serverString_ = serverObject.toString();
Iterator itServer = serverObject.keys();
key = "";
JSONObject jsonValue;
String path;
String rev;
while (itServer.hasNext()) {
key = itServer.next().toString();
jsonValue = serverObject.getJSONObject(key);
HashMap<String, String> params = new HashMap<String, String>();
path = jsonValue.getString("path");
rev = jsonValue.getString("rev");
params.put("path", path);
params.put("rev", rev);
serverMap_.put(key, params);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
}


// 步骤5:根据download.desc下载列表建立任务队列task-list。
public void downloadResourceByPath() {
try {
String fileName = null, filePath = null, shaFile = null, serverFileName = null, serverPath = null, serverRev = null;
byte[] fileString = null;
if (resourceMap_ == null)
return;


Iterator it = resourceMap_.keySet().iterator();
HashMap<String, String> params;
while (it.hasNext()) {
fileName = it.next().toString();
filePath = resourceMap_.get(fileName);
if (checkDownload(fileName)) {
// 已经下载过,返回
return;
} else {
// 下载每个文件
fileString = downloadPerResource(filePath);
File file = Utils.getFileFromBytes(fileString, fileName);
if (Utils.getMIMEType(file).equalsIgnoreCase("zip")) {
// 如果数据是压缩的则应进行解压操作
unZip(new ByteArrayInputStream(fileString));
// fileString = Utils.gunzip(fileString);
}
file = null;
// 计算文件SHA1值
if (fileString != null) {
byte[] temp = HMac.SHA1(fileString);
shaFile = HMac.byteArrayToHexString(temp);
}
}
// 查找第二个Map中含有第一个Map的key
if (serverMap_.containsKey(fileName)) {
params = serverMap_.get(fileName);
serverPath = params.get("path");
serverRev = params.get("rev");
}
// 步骤6:每一个资源文件下载完毕后计算资源文件的SHA1值,并与server.desc记录的SHA1值进行比较。(递归)
comparedRedownload(fileName, shaFile, filePath, fileString, serverRev);
}
} catch (Exception e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
}


private void unZip(InputStream input) {
// TODO Auto-generated method stub
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(input));
try {
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int count;
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
String filename = ze.getName();
byte[] bytes = baos.toByteArray();
// do something with 'filename' and 'bytes'...
saveToDb(plugDB_, filename, bytes);
}
} catch (IOException e) {
// TODO Auto-generated catch block
Utils.printException(e);
} finally {
try {
if (null != zis)
zis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
}


}


/**
* @param fileName
* 客户端文件名
* @param shaFile
* 客户端计算出的SHA1
* @param filePath
* 客户端下载文件的路径
* @param fileString
* 客户端下载文件后的字节数组
* @param serverFileName
* 服务器端文件名
* @param serverRev
* 服务器端SHA1
*/
private void comparedRedownload(String fileName, String shaFile, String filePath, byte[] fileString,
String serverRev) {
try {
boolean noModify = comparedSHA1(fileName, shaFile, serverRev);
if (noModify) {
// 步骤7:验证资源文件的正确性后,以name为key存储资源文件。
// 下载完的文件保存到数据库


offLineDB_.deleteToDB(fileName);
if (fileName.contains(".png"))
saveToDb(offLineDB_, fileName, fileString);
else
saveToDb(offLineDB_, fileName, new String(fileString, "UTF-8"));


// 步骤8:更新download.desc的下载状态标记,标记为已下载。
// 保存到数据库后修改"已下载"的标志位
alreadyDownload_.put(fileName, true);
} else {
if (downloadNum_-- > 0) {
// 重新下载每个文件
fileString = downloadPerResource(filePath);
File file = Utils.getFileFromBytes(fileString, fileName);
if (Utils.getMIMEType(file).equalsIgnoreCase("zip")) {
// 如果数据是压缩的则应进行解压操作
fileString = Utils.gunzip(fileString);
}
file = null;
// 重新计算文件SHA1值
byte[] disg = HMac.SHA1(fileString);
if (disg != null) {
shaFile = disg.toString();
}
comparedRedownload(fileName, shaFile, filePath, fileString, serverRev);
}
}
} catch (UnsupportedEncodingException e) {
Utils.printException(e);
} catch (IOException e) {
// TODO Auto-generated catch block
Utils.printException(e);
} catch (Exception e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
}


// 判断文件名为fileName的文件是否下载过
private boolean checkDownload(String fileName) {
if (alreadyDownload_ != null) {
return alreadyDownload_.get(fileName);
}
return false;
}


// 判断所有的文件是否下载完
private boolean checkAllDownload() {
if (alreadyDownload_ != null) {
for (Map.Entry<String, Boolean> entry : alreadyDownload_.entrySet()) {
boolean entryDownload = entry.getValue();
// 如果有值为false,即为没有下载完,所有的都为true,才为全部下载完成
if (!entryDownload)
return false;
}
// 全部下载完成
return true;
}
return false;
}


// 比较下栽文件的SHA1和server.desc
private boolean comparedSHA1(String fileName, String shaFile, String serverSHA1) {
if (fileName != null && shaFile != null & serverSHA1 != null) {
if (shaFile.equalsIgnoreCase(serverSHA1)) {
return true;
}
}
return false;
}


// 下载文件列表中的每一个文件
private byte[] downloadPerResource(String filePath) {
ByteArrayOutputStream fileBuffer = new ByteArrayOutputStream(1024);
byte[] fileBytes = null;
try {
HttpManager hm = new HttpManager(activity_);
hm.read(filePath, fileBuffer, null);
fileBytes = fileBuffer.toByteArray();
} catch (Exception e) {
Utils.printException(e);
} catch (OutOfMemoryError oe) {
Utils.printOutToConsole(oe);
} finally {
if (null != fileBuffer)
try {
fileBuffer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
fileBuffer = null;
}
return fileBytes;
}


public boolean getFirstLogin() {
File file = new File(activity_.getFilesDir(), offLineDB_.DATABASE_NAME);
return file.exists();
}


/**
* 不联网情况下个别页面读取本地数据库XML
*
* @param itemValue
* @param currentView_
* @return
*/
public Object readOfflineResource(OffStoreDB db, String itemValue) {
return db.find(itemValue);
}


public static void setRootPath() {
FILEROOT = Utils.getActivity().getFilesDir().getPath().concat("/");
}


}


===============================================================================

//数据库操作


import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


public class OffStoreDB extends SQLiteOpenHelper {


public static String DATABASE_NAME = "emp.db";
private static int DATABASE_VERSION = 1;
private static String TABLE_NAME = "emp_table";
private static String COLUMN_ID = "_id";
private static String COLUMN_NAME = "name";
private static String COLUMN_VALUE = "value";


public OffStoreDB(Context context, String name) {
super(context, name, null, DATABASE_VERSION);
}


@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table ".concat(TABLE_NAME).concat("(").concat(COLUMN_ID)
.concat(" integer primary key autoincrement,").concat(COLUMN_NAME).concat(" varchar(20),")
.concat(COLUMN_VALUE).concat(" varchar(100))"));
}


@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS ".concat(TABLE_NAME));
onCreate(db);
}


public long insert(String column_name, Object column_value) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME, column_name);
if (column_value instanceof String)
cv.put(COLUMN_VALUE, (String) column_value);
else if (column_value instanceof byte[])
cv.put(COLUMN_VALUE, (byte[]) column_value);
long row = db.insert(TABLE_NAME, null, cv);
return row;
}


public Object find(String name) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("select value from emp_table where name = ?", new String[] { name });
// select value from emp_table where name = "fwzx.xml";
if (cursor.moveToNext()) {
Object value = null;
try {
// 如果是图片将会被保存为字节数组形式
if (name.contains(".png"))
value = cursor.getBlob(cursor.getColumnIndex(COLUMN_VALUE));
else
value = cursor.getString(cursor.getColumnIndex(COLUMN_VALUE));
cursor.close();
} catch (Exception e) {
Utils.printException(e);
}
return value;
} else {
cursor.close();
return null;
}
}


public int deleteToDB(String fileName) {
SQLiteDatabase db = this.getWritableDatabase();
// ContentValues cv = new ContentValues();
// cv.put(COLUMN_NAME, fileName);
return db.delete(TABLE_NAME, COLUMN_NAME + "=?", new String[] { fileName });
}
}


-----------------------------------------------utils

//#define Android2.2
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Vector;


import java.util.UUID;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONObject;


import com.rytong.tools.clienthello.ClientHello;
import com.rytong.tools.crypto.AESCipher;
import com.rytong.tools.crypto.HMac;
import com.rytong.tools.crypto.MD5;
import com.rytong.tools.crypto.RSACipher;
import com.rytong.tools.httpconnect.HttpManager;
import com.rytong.tools.offstore.OffStoreDownload;
import com.rytong.tools.ui.Component;
import com.rytong.tools.ui.LPLayout;


import android.R.color;
import android.R.integer;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.telephony.CellLocation;
import android.telephony.TelephonyManager;
// #ifdef Android2.2
import android.telephony.cdma.CdmaCellLocation;
// #endif
import android.telephony.gsm.GsmCellLocation;
import android.text.TextPaint;
import android.util.DisplayMetrics;
import android.view.View;


/**
* Utility class.
*/
public final class Utils {
private static int BRHEIGHT;
private static Activity activity_;
// 是否打印标志
private static boolean isPrintMessage_;
// 字体缩放参数,如果手机分辨率和密度同比增长,则该参数?,表示不需缩放,如果不匹配,则需校正该参数设?
public static float SCALEDFONT;
// 基准屏幕的宽,该值应和服务端定义xml的基准屏幕保持?????
public static int BenchmarkresolutionW_;
// 基准屏幕的高,该值应和服务端定义xml的基????幕保持一?
public static int BenchmarkresolutionH_;
/**
* Used for gzip. Re. rfc1951.
*/
static int gIndex = 0;
static int bitByte = 0;
static int bitIndex = 0;
private final static int MAX_BITS = 16;
private final static int[] EXTRA_L_BITS = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
5, 5, 5, 5, 0 };
private final static int[] EXTRA_L_VALUES = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
59, 67, 83, 99, 115, 131, 163, 195, 227, 258 };
private final static int[] EXTRA_D_BITS = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
10, 11, 11, 12, 12, 13, 13 };
private final static int[] EXTRA_D_VALUES = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 };
private final static int[] DYNAMIC_L_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };


// 界面X方向参考缩放参?此参数为控件宽或者字体大小的参考??
public static float SCALEDATEX;
// 界面Y方向参考缩放参?此参数为控件高的参考??
public static float SCALEDATEY;
/** Default alpha value used to draw menu panels and status bars. */
public final static int DEFAULT_TRANSPARENCY = 0xa0000000;
final static int OK_KEY = -5;
final static int LEFT_SOFTKEY = -6;
final static int RIGHT_SOFTKEY = -7;


// if it is sony ericsson, SONY_ERICSSON is true.
public final static boolean SONY_ERICSSON = false;
// 日志名称
public static final String LOGNAME = "LPC";
/**
* Used as indices in text parser's return result of a line break in a string.
*/
public final static int LBI_BREAK = 0; // Break position (this char is in current
// line)
public final static int LBI_NEXT = 1; // Next char position to resume scanning (to
// skip tags)
public final static int LBI_TYPE = 2; // Line break type: newline, paragraph, ...,
// defined below.
public final static int LBI_START = 3; // Starting position of this line.
public final static int LBI_SIZE = 4; // Number of linebreak indices.


/**
* Types of line breaks.
*/
final static int LB_NEWLINE = 0;
final static int LB_PARAGRAPH = 1;
final static int LB_SKIP = 2; // Skip characters within [LBI_BREAK,
// LBI_NEXT)
final static int LB_HYPHEN = 3;


/**
* The number of alpha transparency levels。will be reset by numAlphaLevels() in LPMid.java. The minimum
* numAlphaLevel_ is 2, which indicates only support for full transparency and full opacity.
*/
final static int numAlphaLevel_ = 256;


final static int BLUE = 0xFF0000FF;
final static int WHITE = 0xFFFFFFFF;
final static int BLACK = 0xFF000000;
final static int GREY = 0xFF808080;
final static int SELECTED_LINK_COLOR = 0xFF808080;
public final static int TABBARBACKGROUNDCOLOR = 0xFF294B78;


public final static char MATCH = '\"';


/** True if the user selects item Map */
public static boolean toMapView_;


final static String SPLIT_CHARACTERS = " ,.";


// 调用系统相机的请求码
public final static int CAMERA_REQUEST_CODE = 1001;


// 解读并存储assets文件夹下的Config.txt文件信息
private static HashMap<String, String> configHm_;


// 连点事件一时间间隔
public static int jat_lag = 0;


/**
* @return
*/
public final static byte[] getClientGMTUnixTime() {
// get local time.4 bytes.
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
int hours = date.getHours();
byte[] clientGmtUnixTime = new byte[4];
clientGmtUnixTime[0] = (byte) ((hours & 0x0000FF00) >> 8);
clientGmtUnixTime[1] = (byte) ((hours & 0x000000FF));
int minutes = date.getMinutes();
clientGmtUnixTime[2] = (byte) ((minutes & 0x0000FF00) >> 8);
clientGmtUnixTime[3] = (byte) ((minutes & 0x000000FF));
return clientGmtUnixTime;
}


// /**
// * 从资源图片里面获取指定文件名的图片,如果没有就返回空
// *
// * @param 指定的要查找的文件名
// * @param 界面对象
// * @return
// */
// public final final static Bitmap getBitmapFromDrawable(Activity bv, String bitmapName) {
// bitmapName = bitmapName.trim();
// if (bitmapName.endsWith(".png")) {
// // 服务端传送过来的图片名称有可能带?png后缀,先去掉后缀再进行相关操作比?
// bitmapName = bitmapName.substring(0, bitmapName.lastIndexOf(".png"));
// }
// // 利用反射机制获取对象域名
// Object obj = null;
// String varName = null;
// Field[] fields = R.drawable.class.getDeclaredFields();
// int size = fields.length;
// for (int i = 0, len = size; i < len; i++) {
// // 对于每个属性,获取属性名
// varName = fields[i].getName();
// if (varName.equalsIgnoreCase(bitmapName)) {
// try {
// // 获取原来的访问控制权?
// boolean accessFlag = fields[i].isAccessible();
// // 修改访问控制权限
// fields[i].setAccessible(true);
// // 获取在对象f中属性fields[i]对应的对象中的变?
// obj = fields[i].get(varName);
// // ????访问控制权限
// fields[i].setAccessible(accessFlag);
// int id = Integer.parseInt(obj.toString());
// Bitmap bm = getBitmap(id, bv);
// return bm;
// } catch (IllegalArgumentException ex) {
// printException(ex);
// } catch (IllegalAccessException ex) {
// printException(ex);
// }
// }
// }
// return null;
// }
/**
* 发送端?
*
* @param phoneNum
* @param content
*/
public final static void sendSms(int phoneNum, String content) {
Intent intent = new Intent();
// 系统默认的action,用来打开默认的短信界?
intent.setAction(Intent.ACTION_SENDTO);
// 需要发短息的号?
intent.setData(Uri.parse("smsto:" + phoneNum));
intent.putExtra("sms_body", content);
activity_.startActivity(intent);
}


/**
* 获取资源图片
*
* @param context
* @param resourcesName
* @return
*/
public final static Bitmap getBitmapFromResources(Context context, String resourcesName) {
Bitmap bitmap = null;
if (resourcesName == null)
return bitmap;


Object img = null;
// 先补?png后缀名从sql中取出对应的图片
resourcesName = getPNGName(resourcesName);
img = OffStoreDownload.plugDB_.find(resourcesName);
if (null != img && img instanceof byte[]) {
byte[] temp = (byte[]) img;
bitmap = BitmapFactory.decodeByteArray(temp, 0, temp.length);
return bitmap;
}


img = OffStoreDownload.offLineDB_.find(resourcesName);
if (null != img && img instanceof byte[]) {
byte[] temp = (byte[]) img;
bitmap = BitmapFactory.decodeByteArray(temp, 0, temp.length);
return bitmap;
}
// 如果sql中没有存储对应的图片,则将后缀去掉,在资源文件里面搜索
if (resourcesName.endsWith(".png")) {
resourcesName = resourcesName.substring(0, resourcesName.lastIndexOf(".png"));
}
resourcesName = resourcesName.toLowerCase();
int resourcesId = getResourcesId(context, resourcesName, "drawable");
if (resourcesId != 0) {
bitmap = getBitmap(resourcesId, (Activity) context);
}


return bitmap;
}


/**
* 获取资源id
*
* @param context
* @param resourcesName
* @param resourcesType
* @param packageName
* @return
*/
public final static int getResourcesId(Context context, String resourcesName, String resourcesType) {
int resourcesId = 0;
resourcesId = context.getResources().getIdentifier(resourcesName, resourcesType, context.getPackageName());
return resourcesId;
}


/**
* 获取项目Config中的app名称,用于联网后台区别报?
*
* @param activity
*/
public final static void getAppName(Activity activity) {
HttpManager.APPNAME = getConfigStringFormAsset(activity, "app");
}


public final static void getPlatform(Activity activity) {
HttpManager.OPLATFORM = getConfigStringFormAsset(activity, "oPlatform");
}


public final static String getClientType(Activity activity) {
return getConfigStringFormAsset(activity, "clientType");
}


/**
* 判断字符串是否以.png结尾,如果不是则加上该后缀
*/
public final static String getPNGName(String name) {
name = name.trim();
if (!name.endsWith(".png")) {
if (name.indexOf(".") != -1)
name = name.substring(0, name.indexOf("."));
name = name.concat(".png");
}
return name;
}


public final static Bitmap getBitmap(int rdoing, Activity bv) {
// TODO Auto-generated method stub
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
InputStream is = bv.getResources().openRawResource(rdoing);


Bitmap img = BitmapFactory.decodeStream(is, null, opt);
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
return img;
}


public final static int getColorValue(String value) {
String colorstr = "";
try {
colorstr = getValidColorString(value);


if (colorstr.length() > 6) {
int color = Integer.parseInt(colorstr, 16);
color |= 0x00000000;
return color;
} else {
int color = Integer.parseInt(colorstr, 16);
color |= 0xFF000000;
return color;
}
} catch (Exception e) {
// TODO Auto-generated catch block
Utils.printException(e);
return 0xFFFFFFFF;
}


}


/**
* The valid color string is a 6 bit hex number. e.g., FFFFFF.
*
* @param srcColorstr
* @return
*/
public final static String getValidColorString(final String srcColorstr) throws Exception {
String colorstr = srcColorstr;
if (colorstr.startsWith("#")) {
colorstr = colorstr.substring(1);
}
return colorstr;
}


// 将字符串数组中的内???转换成????????方便字符数组检?
public final static String getArrayString(String[] sa) {
if (null == sa)
return "";
return Arrays.toString(sa);
}


final static boolean isLeftSoftKey(int key) {
return (key == LEFT_SOFTKEY);
}


final static boolean isRightSoftKey(int key) {
// Motorola some phones's right key is -22, and other is 22.
// return (key == RIGHT_SOFTKEY || key == -RIGHT_SOFTKEY);
return (key == RIGHT_SOFTKEY);
}


final static int getLeftSoftKey() {
return LEFT_SOFTKEY;
}


final static int getRightSoftKey() {
return RIGHT_SOFTKEY;
}


/**
*
* 把字节数组保存为一个文?
*
*/
public final static File getFileFromBytes(byte[] b, String outputFile) {


String pathString = activity_.getFilesDir().getPath().concat("/");
BufferedOutputStream stream = null;


File file = null;


try {


file = new File(pathString.concat(outputFile));
file.createNewFile();
FileOutputStream fstream = new FileOutputStream(file);


stream = new BufferedOutputStream(fstream);


stream.write(b);


} catch (Exception e) {


printException(e);


} finally {


if (stream != null) {


try {


stream.close();


} catch (IOException e1) {


printException(e1);


}


}


}


return file;


}


/**
* 根据文件后缀名返回文件类?
*
* @param fileTemp
* @return
*/
public final static String getMIMEType(File fileTemp) {
// TODO Auto-generated method stub
String type = "";
String fName = fileTemp.getName();
String end = fName.substring(fName.lastIndexOf(".") + 1, fName.length()).toLowerCase();
if (end.equals("m4a") || end.equals("mp3") || end.equals("mid") || end.equals("xmf") || end.equals("ogg")
|| end.equals("wav")) {
type = "audio";
} else if (end.equals("3gp") || end.equals("mp4")) {
type = "video";
} else if (end.equals("jpg") || end.equals("gif") || end.equals("png") || end.equals("jpeg")
|| end.equals("bmp")) {
type = "image";
} else if (end.equals("apk")) {
type = "application/vnd.android.package-archive";
} else if (end.equals("zip")) {
type = "zip";
} else if (end.equals("apk")) {


} else {
type += "/*";
}
return type;
}


/**
* Graphics.drawRegion() has a bug in 4.2.1 and we have to use a replacement function.
*/
public final static void drawRegion(Canvas g, Bitmap img, int srcX, int srcY, int width, int height, int dstX,
int dstY) {
g.drawBitmap(img, new Rect(srcX, srcY, srcX + width, srcY + height), new Rect(dstX, dstY, dstX + width, dstY
+ height), new Paint());
}


public final static int fixTransparentPixel(int pixel) {
// We don't use semitransparent pixel if the phone only support for full
// transparency and full opacity.
if (numAlphaLevel_ > 2 && (pixel & 0xff000000) != 0)
return (pixel & 0x00ffffff) + DEFAULT_TRANSPARENCY;
else
return pixel;
}


/**
* Given an image, assign transparency value to its non-background pixels (background pixels are pixels that are
* completely transparent).
*
* @param transparency
* 255 == totally opaque.
*/
public final static Bitmap fixTransparentImage(Bitmap img) throws Exception {
if (null == img)
return null;
int width = img.getWidth();
int height = img.getHeight();
int sz = width * height;
int[] rgb = new int[sz];
// Params: (rgb, offset, scanlength, x, y, width, height)
// rgbData[offset + (a - x) + (b - y) * scanlength] = P(a, b);
img.getPixels(rgb, 0, width, 0, 0, width, height);
for (int i = 0; i < sz; ++i) {
rgb[i] = fixTransparentPixel(rgb[i]);
}
img = Bitmap.createBitmap(rgb, width, height, Bitmap.Config.RGB_565);
return img;
}


/*
* Check if the image is over 4kB or not.
*
* @param name the full name with a path of an image file.
*
* @return
*/
// private final final static final boolean isImgBelow4KB(String name) {
// boolean isNotOver = ConfigManager.IMAGE_TRANSPARENCY;
// try {
// int imgSize = 0;
// InputStream is = null;
// is = new Object().getClass().getResourceAsStream(name);
// imgSize = is.available();
// if (imgSize < 1024 * 4){
// isNotOver = true;
// }
// } catch (Exception e) {
// printOutToConsole("LPUtils.isImgOver4KB(): " + e.toString());
// }
// return isNotOver;
// }


public final static String abbrevString(String title, Paint font, int maxWidth) {
if (title == null)
return "";
if (font.measureText(title) > maxWidth) {
int pos = nextLinePosition(title.toCharArray(), 0, font, maxWidth,
font.getTextWidths(ELLIPSIS, 0, ELLIPSIS.length, new float[ELLIPSIS.length]));
if (pos == -1)
return title;
else
return title.substring(0, pos) + "...";
} else
return title;
}


final static String appendDots(String src, Paint font, int maxWidth) {
if (src == null || font == null || maxWidth < 0) {
return null;
}
String dest = null;
dest = src + "...";
while (font.measureText(dest) > maxWidth) {
dest = src.substring(0, src.length() - 2) + "...";
}
return dest;
}


private final static char ELLIPSIS[] = { '.', '.', '.' };


public final static int getEllipsisWidth(Paint f) {
return f.getTextWidths(ELLIPSIS, 0, ELLIPSIS.length, new float[ELLIPSIS.length]);
}


/**
* Is this character whitespace?
*/
public final static boolean isWhitespace(char ch) {
return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
}


/**
* Case insensitive string match
*
* @param ignoreCase
* if true, ignore case
* @param s1
* @param s2
*/
public final static boolean stringMatch(boolean ignoreCase, String s1, String s2) {
int cmplen = Math.max(s1.length(), s2.length());
if ((s1 == null) || (s2 == null)) {
return false;
}
return s1.regionMatches(true, 0, s2, 0, cmplen);
}


/**
* Given a starting position in a string, return the next position that this string should be split if it cannot fit
* within the given width. If it does not fit, we will include an ellipsis at the end to indicate broken line. If it
* does fit, we return -1.
*/
public final static int nextLinePosition(char[] str, int pos, Paint f, int maxWidth, int ellWidth) {
int strWidth = 0;
while (pos < str.length) {
if (str[pos] == '\n') {
return pos;
}
strWidth += f.measureText(String.valueOf(str[pos]));
if (strWidth + ellWidth > maxWidth) {
// If the rest of string can fit instead of the ellipsis, put it
// there.
// int tmp = f.getTextWidths(str, pos + 1, str.length - pos - 1,
// new float[str.length - pos - 1]);
int tmp = (int) f.measureText(str, pos + 1, str.length - pos - 1);
if (strWidth + tmp <= maxWidth) {
return -1;
} else {
return pos;
}
}
++pos;
}
return -1;
}


/**
* Starting from pos in str, find the longest string that fits in maxLineWidth. If doesn't fit, break the line by
* hyphenation or at a line break point.
*
* If newLine is true, we are starting from a new line and should get rid of initial white spaces.
*
* Returns the position of the next character to be scanned in str after this line break.
*/
public final static int nextLineLayout(char[] str, int pos, Paint f, int maxLineWidth, int hyphenWidth,
int[] linebreak, boolean newLine) {
int strWidth = 0;
int startPos = pos;
int lastBreakPoint = pos;


// Filter out initial white spaces at start of a line.
if (newLine) {
while (pos < str.length && (str[pos] == ' ' || str[pos] == '\t'))
++pos;
}


linebreak[LBI_START] = pos;
while (pos < str.length) {
boolean punct = false;
switch (str[pos]) {
// NOTE: don't recognize CR because in XML, only <br> or <p> should
// matter.
case '\n':
// Insert a newline.
linebreak[LBI_BREAK] = pos - 1;
linebreak[LBI_NEXT] = pos + 1;
linebreak[LBI_TYPE] = LB_SKIP;
return pos + 1;
case '<': {
// Look ahead to see if we have a <p>, <br>, <p/>, <br/>, </p>,
// </br>, <b> <tr> <td>
// XXX We ignore complex cases, such as newlines are inserted
// into tags.
// NOTE: the 32 limit is an arbitrary one
int endPos = pos;
while (endPos < (str.length - 1) && endPos - pos < 8) {
++endPos;
if (str[endPos] == '>') {
int pp1 = pos + 1;
int pp2 = pos + 2;
int pp3 = pos + 3;
char ch_pp1 = Character.toLowerCase(str[pp1]);
if (ch_pp1 == 'p' && (pp2 == endPos || str[pp2] == '/' || str[pp2] == ' ')) {
linebreak[LBI_BREAK] = pos - 1;
linebreak[LBI_NEXT] = endPos + 1;
linebreak[LBI_TYPE] = LB_PARAGRAPH; // Paragraph
return endPos + 1;
} else if (ch_pp1 == 'b'
&& (pp2 == endPos || (Character.toLowerCase(str[pp2]) == 'r' && (pp3 == endPos
|| str[pp3] == '/' || str[pp3] == ' ')))) {
linebreak[LBI_BREAK] = pos - 1;
linebreak[LBI_NEXT] = endPos + 1;
// Only add newline if this is a br.
linebreak[LBI_TYPE] = (pp2 == endPos) ? LB_SKIP : LB_NEWLINE;
return endPos + 1;
} else if (ch_pp1 == '/' || ch_pp1 == 'i' || ch_pp1 == 'e' || ch_pp1 == 's' || ch_pp1 == 'c'
|| ch_pp1 == 't' || ch_pp1 == 'h') {


// Ignore <em>, <strong>, <center>
// Ignore all kinds of end tags.
linebreak[LBI_BREAK] = pos - 1;
linebreak[LBI_NEXT] = endPos + 1;
linebreak[LBI_TYPE] = LB_SKIP;
return endPos + 1;
}
}
}
// XXX FIXME: Ignore <a href=...> and <font ...>, <a target...>,
// <a title...>, <a rel...> here. We will capture the hyper link
// and tie it to the link body later.
char ch_pp1 = Character.toLowerCase(str[pos + 1]);
if (str.length - pos >= 5 && (ch_pp1 == 'a' || ch_pp1 == 'f')) {
if (ch_pp1 == 'a') {
// Skip spaces between a and href
endPos = pos + 2;
while (endPos < str.length && str[endPos] == ' ')
++endPos;
} else {
endPos = pos + 1;
}
if (str.length - endPos > 3) {
ch_pp1 = Character.toLowerCase(str[endPos]);
char ch_pp2 = Character.toLowerCase(str[endPos + 1]);
char ch_pp3 = Character.toLowerCase(str[endPos + 2]);
char ch_pp4 = Character.toLowerCase(str[endPos + 3]);
if ((ch_pp1 == 'h' && ch_pp2 == 'r' && ch_pp3 == 'e' && ch_pp4 == 'f')
|| (ch_pp1 == 'f' && ch_pp2 == 'o' && ch_pp3 == 'n' && ch_pp4 == 't')
|| (ch_pp1 == 't' && ch_pp2 == 'a' && ch_pp3 == 'r' && ch_pp4 == 'g')
|| (ch_pp1 == 't' && ch_pp2 == 'i' && ch_pp3 == 't' && ch_pp4 == 'l')
|| (ch_pp1 == 'r' && ch_pp2 == 'e' && ch_pp3 == 'l')) {
// Ignore everything, including newline, till next
// '>'
while (endPos < str.length && str[endPos] != '>')
++endPos;
}
}
linebreak[LBI_BREAK] = pos - 1;
if (endPos + 1 < str.length)
linebreak[LBI_NEXT] = endPos + 1;
else
linebreak[LBI_NEXT] = str.length - 1;
linebreak[LBI_TYPE] = LB_SKIP;
return endPos + 1;
}
// XXX FIXME: Ignore <p class=...> & <img src=...>,<span ...>
// <lp...> , </lp:...>, <table > <div>here. We will capture the
// hyper link
// and tie it to the link body later.
if (str.length - pos >= 8
&& (ch_pp1 == 'p' || ch_pp1 == 'i' || ch_pp1 == 'l' || ch_pp1 == 's' || ch_pp1 == 't' || ch_pp1 == 'd')
|| ch_pp1 == '/') {
endPos = pos + 2;
// Ignore everything, including newline, till next '>'
while (endPos < str.length && str[endPos] != '>')
++endPos;


linebreak[LBI_BREAK] = pos - 1;
linebreak[LBI_NEXT] = endPos + 1;
linebreak[LBI_TYPE] = LB_SKIP;
return endPos + 1;
}


// For tags that we do not recognize, fall through.
}
case ' ':
case '\t':
lastBreakPoint = pos;
// fall through
default:
// Check one more character to see if it fits current string. If
// not,
// try to break at the last line break point. If that is too far
// away,
// add a hyphen at this place.
strWidth += f.measureText(String.valueOf(str[pos]));
if (strWidth >= maxLineWidth) {
// This was meant for hyphenation. When we insert a newline,
// can do that right at the starting point.
if (lastBreakPoint == startPos) {
lastBreakPoint = (pos == startPos) ? pos : (pos - 1);
}
linebreak[LBI_BREAK] = lastBreakPoint - 1;
linebreak[LBI_NEXT] = lastBreakPoint;
linebreak[LBI_TYPE] = LB_NEWLINE;
return lastBreakPoint;
}
}
++pos;
}
return -1;
}


/**
* Starting from pos in str, find the longest string that fits in maxLineWidth.
*
* Don't need to check
* <p>
* , <br>
* ,
* <p/>
* , <br/>
* ,
* </p>
* , </br>, <b>
* <tr>
* <td>again. They should be parsed by HTML.
*/
public final static int getLineEndIndex(char[] chars, int pos, Paint f, int LineWidth, int[] linebreak,
boolean newLine, boolean isTrimHeadBlank, boolean isBreakWord) {
if (chars == null || f == null)
return -1;
int strWidth = 0;
int startPos = pos;
int lastBreakPoint = pos;
// Filter out initial white spaces at start of a line.
if (newLine) {
if (isTrimHeadBlank) {
while (pos < chars.length && (chars[pos] == ' ' || chars[pos] == '\t'))
++pos;
} else {
while (pos < chars.length && chars[pos] == '\t')
++pos;
}
}
linebreak[LBI_START] = pos;
while (pos < chars.length) {
switch (chars[pos]) {
// NOTE: don't recognize CR because in XML, only <br> or <p> should
// matter.
case '\n':
chars[pos] = ' ';
return pos;
case ' ':
case '.':
case '/':
case '\t':
lastBreakPoint = pos + 1;
default:
// Check one more character to see if it fits current string. If
// not,
// try to break at the last line break point.
strWidth += f.measureText(String.valueOf(chars[pos]));
if (strWidth > LineWidth) {
if (isBreakWord) {
return pos - 1;
} else {
// It is possible that a word's width bigger than line
// width.
if (lastBreakPoint == startPos && pos > startPos && newLine) {
return pos - 1;
} else {
return lastBreakPoint;
}
}
}
}
++pos;
}
return chars.length;
}


public final static boolean isPunct(char ch) {
switch (ch) {
case '.':
case ',':
case '?':
case '!':
case '\'':
case '"':
case ':':
case ';':
case '-':
return true;
}
return false;
}


public final static String escapeHTML(String str) {
if (str == null)
return null;
StringBuffer sb = new StringBuffer();
int num = str.length();
for (int i = 0; i < num; i++) {
char ch = str.charAt(i);
switch (ch) {
case '<':
sb.append("&lt;");
break;
case '>':
sb.append("&gt;");
break;
case '&':
sb.append("&amp;");
break;
case '"':
sb.append("&quot;");
break;
case ' ':
sb.append("&nbsp;");
break;
default:
sb.append(ch);
break;
}
}
return sb.toString();
}


/**
* Unescape a HTML string by filtering out &...; sequences, including &#<numbers>;. We do not consider the case
* where one sequence is broken into multiple lines.
*/
public final static String unescapeHTML(String str) {
char[] src = str.toCharArray();
char[] dest = new char[src.length];
boolean foundAmber = false;
int escapeIdx = -1;
int dstIdx = 0;
int j;
int ch;


for (int i = 0; i < src.length; i++) {
switch (src[i]) {
case '&':
// we should not miss the case &aaa&.
while (escapeIdx > 0 && escapeIdx < i) {
dest[dstIdx++] = src[escapeIdx++];
}
escapeIdx = i;
break;
case ';':
if (escapeIdx >= 0) {
if (src[escapeIdx + 1] == '#') {
ch = 0;
for (j = escapeIdx + 2; j < i; ++j) {
if (src[j] < '0' || src[j] > '9') {
ch = -1;
break;
} else {
ch *= 10;
ch += src[j] - '0';
}
}
} else {
int pp1 = escapeIdx + 1;
int pp2 = escapeIdx + 2;
int pp3 = escapeIdx + 3;
int pp4 = escapeIdx + 4;
int pp5 = escapeIdx + 5;
if (src[pp1] == 'q' && src[pp2] == 'u' && src[pp3] == 'o' && src[pp4] == 't' && pp5 == i)
ch = '"';
else if (src[pp1] == 'a' && src[pp2] == 'm' && src[pp3] == 'p' && pp4 == i)
ch = '&';
else if (src[pp1] == 'l' && src[pp2] == 't' && pp3 == i)
ch = '<';
else if (src[pp1] == 'g' && src[pp2] == 't' && pp3 == i)
ch = '>';
else if (src[pp1] == 'n' && src[pp2] == 'b' && src[pp3] == 's' && src[pp4] == 'p' && pp5 == i)
ch = ' ';
else
ch = -1;
if (ch != -1) {
dest[dstIdx++] = (char) ch;
escapeIdx = -1;
break;
}
}
} else
ch = -1;


// Replace the Html Special Characters likes &#<numbers>.
if (ch >= 0) {
switch (ch) {
case 123:
ch = '{';
break;
case 125:
ch = '}';
break;
case 133:
for (int k = 0; k < 3; k++)
dest[dstIdx++] = '.';
ch = -1;
break;
case 146:
ch = '\'';
break;
case 147:
case 148:
ch = '"';
break;
case 151:
ch = '-';
break;
default:
ch = ' ';
break;
}
if (ch != -1)
dest[dstIdx++] = (char) ch;
} else {
// If current charactor is only a characters ";" ,
// not a Html Special Characters, we copy it in dest.
if (escapeIdx < 0)
dest[dstIdx++] = src[i];
else {
for (j = escapeIdx; j <= i; ++j)
dest[dstIdx++] = src[j];
}
}
escapeIdx = -1;
break;
default:
if (escapeIdx < 0)
dest[dstIdx++] = src[i];
else if (escapeIdx > 0 && ((i - escapeIdx) > 5)) {
for (int k = escapeIdx; k <= i; k++) {
dest[dstIdx++] = src[k];
}
escapeIdx = -1;
}
break;
}
}


return String.valueOf(dest, 0, dstIdx);
}


/**
* non-ASCII characters are encoded as: first using the UTF-8 algorithm to encode to a sequence of 2 or 3 bytes,
* then each of these bytes is encoded as "%xx".
*/
public final static String escapeURIComponent(String str) {
printOutToConsole("escapeURIComponent " + str);
if (str == null)
return null;
StringBuffer sbuf = new StringBuffer();
int ch;
int len = str.length();
for (int i = 0; i < len; i++) {
ch = str.charAt(i);
if ('A' <= ch && ch <= 'Z') {
sbuf.append((char) ch);
} else if ('a' <= ch && ch <= 'z') {
sbuf.append((char) ch);
} else if ('0' <= ch && ch <= '9') {
sbuf.append((char) ch);
} else if (ch == '-' || ch == '_' || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\''
|| ch == '(' || ch == ')') {
sbuf.append((char) ch);
} else if (ch < 0x0F) {
sbuf.append('%');
sbuf.append('0');
sbuf.append(Integer.toHexString(ch));
} else if (ch < 0x7F) {
sbuf.append('%');
sbuf.append(Integer.toHexString(ch));
} else if (ch <= 0x07FF) { // non-ASCII characters and value <=
// 0x7FF
sbuf.append('%');
sbuf.append(Integer.toHexString(0xc0 | (ch >> 6)));
sbuf.append('%');
sbuf.append(Integer.toHexString(0x80 | (ch & 0x3F)));
} else { // non-ASCII characters and value <= 0xFFFF
sbuf.append('%');
sbuf.append(Integer.toHexString(0xe0 | (ch >> 12)));
sbuf.append('%');
sbuf.append(Integer.toHexString(0x80 | ((ch >> 6) & 0x3F)));
sbuf.append('%');
sbuf.append(Integer.toHexString(0x80 | (ch & 0x3F)));
}
}
return sbuf.toString();
}


public final static String unescapeURIComponent(String url) {
if (url == null)
return null;
StringBuffer sbuf = new StringBuffer();
int len = url.length();
int ch;
int b;
int total = 0;
int more = -1;
int hb;
int lb;
for (int i = 0; i < len; i++) {
switch (ch = url.charAt(i)) {
case '%':
ch = url.charAt(++i);
hb = (Character.isDigit((char) ch) ? ch - '0' : 10 + Character.toLowerCase((char) ch) - 'a') & 0xF;
ch = url.charAt(++i);
lb = (Character.isDigit((char) ch) ? ch - '0' : 10 + Character.toLowerCase((char) ch) - 'a') & 0xF;
b = (hb << 4) | lb;
break;
default:
b = ch;
}
// Decode byte b as UTF-8, sumb collects incomplete chars
if ((b & 0xc0) == 0x80) {
total = (total << 6) | (b & 0x3f);
if (--more == 0)
sbuf.append((char) total);
} else if ((b & 0x80) == 0x00) {
sbuf.append((char) b);
} else if ((b & 0xe0) == 0xc0) {
total = b & 0x1f;
more = 1;
} else if ((b & 0xf0) == 0xe0) {
total = b & 0x0f;
more = 2;
} else if ((b & 0xf8) == 0xf0) {
total = b & 0x07;
more = 3;
} else if ((b & 0xfc) == 0xf8) {
total = b & 0x03;
more = 4;
} else {
total = b & 0x01;
more = 5;
}
}
return sbuf.toString();
}


/**
* Convert a string of double number to an integer, assuming the number is a coordinate.
*/
public final static int strCoordToInt(String strDouble) {
char[] src = strDouble.toCharArray();
StringBuffer dst = new StringBuffer();
int digitsAfterDot = 0;
boolean dotFound = false;
for (int i = 0; i < src.length && digitsAfterDot < 6; i++) {
if (src[i] != '.') {
dst.append(src[i]);
if (dotFound) {
++digitsAfterDot;
}
} else {
dotFound = true;
}
}
// multiply by 1000000
for (int i = digitsAfterDot; i < 6; i++) {
dst.append('0');
}
return Integer.parseInt(dst.toString());
}


/**
* Convert an integer coordinate into a float string.
*/
public final static String intToFloatCoord(int coord) {
StringBuffer buf = new StringBuffer();
buf.append(coord);
buf.insert(buf.length() - 6, '.');
return buf.toString();
}


/**
* Parse a ISO8601 date string and return it in a calendar object. Return UTC time.
*/
public final static long parseISO8601(String text) throws Exception {
printOutToConsole(text);


// Example date string: 2006-11-29T15:30:00.000-08:00
int idx = text.indexOf('T');
if (idx == -1) {
// Invalid date
throw new IOException("错误的数据格?");
}
String date = text.substring(0, idx);
int idx2 = text.indexOf('-', ++idx);
String time;
if (idx2 == -1) {
time = text.substring(idx);
} else {
time = text.substring(idx, idx2);
}


idx = date.indexOf('-');
int year = Integer.parseInt(date.substring(0, idx));
idx2 = date.indexOf('-', ++idx);
int month = Integer.parseInt(date.substring(idx, idx2));
int day = Integer.parseInt(date.substring(++idx2));


idx = time.indexOf(':');
int hour = Integer.parseInt(time.substring(0, idx));
idx2 = time.indexOf(':', ++idx);
int min = Integer.parseInt(time.substring(idx, idx2));
// The separater between seconds and time offset field can be 'Z' for
// standard time,
// or +/- for time zone offset.
int idx3 = time.indexOf('+', ++idx2);
String zoneString = null;
int zoneOffset = 0; // time zone offset, in seconds
if (idx3 == -1) {
idx3 = time.indexOf('-', idx2);
} else {
zoneString = time.substring(idx3 + 1);
zoneOffset = 1;
}
if (idx3 == -1) {
idx3 = time.indexOf('Z', idx2);
} else {
zoneString = time.substring(idx3 + 1);
zoneOffset = -1;
}
if (idx3 == -1) {
idx3 = time.length();
} else if (zoneString != null) {
int idx4 = zoneString.indexOf(':', 0);
if (idx4 != -1) {
int zoneHour;
int zoneMin;
try {
zoneHour = Integer.parseInt(zoneString.substring(0, idx4));
zoneMin = Integer.parseInt(zoneString.substring(idx4 + 1));
zoneOffset *= zoneHour * 3600 + zoneMin * 60;
} catch (Exception ignored) {
zoneOffset = 0;
}
}
}
int sec = 0;
if (idx3 > idx2) {
// Filter out sub-second component
int idx4 = time.indexOf('.', idx2);
if (idx4 != -1)
idx3 = idx4;
sec = Integer.parseInt(time.substring(idx2, idx3));
}


// Make a calendar time assuming that is UTC, then we'll make time zone
// adjustment from UTC seconds.
Calendar updatedDate = Calendar.getInstance();
updatedDate.set(Calendar.YEAR, year);
updatedDate.set(Calendar.MONTH, month - 1); // NOTE: month starts from
// 0??
updatedDate.set(Calendar.DAY_OF_MONTH, day); // Day start from 1??
updatedDate.set(Calendar.HOUR_OF_DAY, hour);
updatedDate.set(Calendar.MINUTE, min);
updatedDate.set(Calendar.SECOND, sec);
updatedDate.set(Calendar.MILLISECOND, 0);
printOutToConsole("date: " + year + "-" + month + "-" + day + " " + hour + ":" + min + ":" + sec + " time "
+ updatedDate.getTime());
printOutToConsole("timezone offset " + zoneOffset);
return updatedDate.getTime().getTime() + zoneOffset * 1000;
}


/**
* Displays a UTC time (in milliseconds) as MM/DD-HH:MM
*/
public final static void formatTimeString(long utc, StringBuffer str) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date(utc));
str.append(cal.get(Calendar.MONTH) + 1); // NOTE: month starts from 0
str.append("/");
str.append(cal.get(Calendar.DAY_OF_MONTH));
str.append("-");
str.append(cal.get(Calendar.HOUR_OF_DAY));
str.append(":");
str.append(cal.get(Calendar.MINUTE));
}


/**
* Displays a UTC time in milliseconds as YYYY/MM/DD
*/
public final static void formatDateString(long utc, StringBuffer str) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date(utc));
str.append(cal.get(Calendar.YEAR));
str.append("/");
str.append(cal.get(Calendar.MONTH) + 1); // NOTE: month starts from 0
str.append("/");
str.append(cal.get(Calendar.DAY_OF_MONTH));
}


/**
* Display a UTC time as format hh:mm am/pm
*/
public final static void fromatTimeAmPm(long utc, StringBuffer str) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date(utc));
int hour = cal.get(Calendar.HOUR);
int minu = cal.get(Calendar.MINUTE);
if (hour < 10)
str.append("0");
str.append(hour);
str.append(":");
if (minu < 10)
str.append("0");
str.append(minu);
if (cal.get(Calendar.AM_PM) == 0)
str.append(" AM");
else
str.append(" PM");
}


/**
* Parse simple state response XMLs from server and retrieve attributes from it. Used by UserManager, PoiRepository
* (add/remove POI), etc.
*/
public final static String getXMLResponseAttribute(String reply, String attr, int startIndex, char matchCh) {
int start = reply.indexOf(attr, startIndex);
if (start < 0)
return null;
start += attr.length();
int end = reply.indexOf(matchCh, start);
if (end > start) {
String s = reply.substring(start, end);
return s;
}
return null;
}


/**
* Check the email address whether is valid.
*/
public final static boolean checkEmail(String emailAdd) {
int length = emailAdd.length();
int temp1 = emailAdd.indexOf("@");
int temp2 = emailAdd.indexOf(".");


// temp1 > 1 means in this email address contains an “@?and there is a
// user’s name before it.
// temp2 != -1 means in this email address contains an "."
// (length - temp1 > 3) means after “@?contains at least one letter
// except ??
// (length - temp2 > 1) means "." is not the last letter
if (temp1 > 1 && temp2 != -1 && (length - temp1 > 3) && (length - temp2 > 1)) {
return true;
} else
return false;
}


/*
* A Java implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS PUB 180-1 Copyright (C) Sam Ruby
* 2004 All rights reserved
*
* Based on code Copyright (C) Paul Johnston 2000 - 2002. See http://pajhome.org.uk/site/legal.html for details.
*
* Converted to Java by Russell Beattie 2004 Base64 logic and inlining by Sam Ruby 2004 Bug fix correcting single
* bit error in base64 code by John Wilson
*
* BSD License
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


// /*
// * Bitwise rotate a 32-bit number to the left
// */
// private final final static int rol(int num, int cnt) {
// return (num << cnt) | (num >>> (32 - cnt));
// }
/*
* Take a string and return the base64 representation of its SHA-1.
*/
public final static String sha1(String str) throws Exception {


// Convert a string to a sequence of 16-word blocks, stored as an array.
// Append padding bits and the length, as described in the SHA1 standard


byte[] x = str.getBytes("UTF-8");
int[] blks = new int[(((x.length + 8) >> 6) + 1) * 16];
int i;


for (i = 0; i < x.length; i++) {
blks[i >> 2] |= x[i] << (24 - (i % 4) * 8);
}


blks[i >> 2] |= 0x80 << (24 - (i % 4) * 8);
blks[blks.length - 1] = x.length * 8;


// calculate 160 bit SHA1 hash of the sequence of blocks


int[] w = new int[80];


int a = 1732584193;
int b = -271733879;
int c = -1732584194;
int d = 271733878;
int e = -1009589776;
int num;


for (i = 0; i < blks.length; i += 16) {
int olda = a;
int oldb = b;
int oldc = c;
int oldd = d;
int olde = e;


for (int j = 0; j < 80; j++) {
if (j < 16) {
w[j] = blks[i + j];
} else {
num = w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16];
w[j] = ((num << 1) | (num >>> (32 - 1)));
}
int t = ((a << 5) | (a >>> (32 - 5)))
+ e
+ w[j]
+ ((j < 20) ? 1518500249 + ((b & c) | ((~b) & d)) : (j < 40) ? 1859775393 + (b ^ c ^ d)
: (j < 60) ? -1894007588 + ((b & c) | (b & d) | (c & d)) : -899497514 + (b ^ c ^ d));
e = d;
d = c;
c = ((b << 30) | (b >>> (32 - 30))); // rol(b, 30);
b = a;
a = t;
}


a = a + olda;
b = b + oldb;
c = c + oldc;
d = d + oldd;
e = e + olde;
}


// Convert 160 bit hash to base64
int[] words = { a, b, c, d, e, 0 };
byte[] base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes();
byte[] result = new byte[28];
for (i = 0; i < 27; i++) {
int start = i * 6;
int word = start >> 5;
int offset = start & 0x1f;


if (offset <= 26) {
result[i] = base64[(words[word] >> (26 - offset)) & 0x3F];
} else if (offset == 28) {
result[i] = base64[(((words[word] & 0x0F) << 2) | ((words[word + 1] >> 30) & 0x03)) & 0x3F];
} else {
result[i] = base64[(((words[word] & 0x03) << 4) | ((words[word + 1] >> 28) & 0x0F)) & 0x3F];
}
}
result[27] = '=';


return new String(result);
}


public final static Bitmap bilinearResample(Bitmap oriImg, int newWidth, int newHeight) {
return bilinearResample(oriImg, newWidth, newHeight, WHITE);
}


/**
* Function for scale an image from a large to a smaller size, then return a new image with new size predefined.
*/
public final static Bitmap bilinearResample(Bitmap oriImg, int newWidth, int newHeight, int bgColor) {
int oldW = oriImg.getWidth();
int oldH = oriImg.getHeight();


int[] ori_rgb = new int[oldW * oldH];
int[] des_rgb = new int[newWidth * newHeight];


oriImg.getPixels(ori_rgb, 0, oldW, 0, 0, oldW, oldH);


int newIndex = 0;
// draw each pixel in the new image
for (int i = 1; i <= newHeight; i++) {
// generate the y calculation variables
int interplY = (i - 1) * oldH / newHeight;
int calcY = (i - 1) * oldH % newHeight;


for (int j = 1; j <= newWidth; j++) {
// generate the x calculation variables
int interplX = (j - 1) * oldW / newWidth;
int calcX = (j - 1) * oldW % newWidth;


int theColour1 = ori_rgb[(interplX) + (interplY) * oldW];
int theColour2 = ori_rgb[(interplX + 1) + (interplY) * oldW];
int theColour3 = ori_rgb[(interplX) + (interplY + 1) * oldW];
int theColour4 = ori_rgb[(interplX + 1) + (interplY + 1) * oldW];


// calculate the new colour
int alpha1 = (theColour1 >> 24 & 0xFF) * (newHeight - calcY) / newHeight + (theColour3 >> 24 & 0xFF)
* calcY / newHeight;
int alpha2 = (theColour2 >> 24 & 0xFF) * (newHeight - calcY) / newHeight + (theColour4 >> 24 & 0xFF)
* calcY / newHeight;
int newAlpha = isOutofColor(alpha1 * (newWidth - calcX) / newWidth + alpha2 * calcX / newWidth);
int newColor1r = (theColour1 >> 16 & 0xFF) * (newHeight - calcY) / newHeight
+ (theColour3 >> 16 & 0xFF) * calcY / newHeight;
int newColor2r = (theColour2 >> 16 & 0xFF) * (newHeight - calcY) / newHeight
+ (theColour4 >> 16 & 0xFF) * calcY / newHeight;
int newColorr = isOutofColor(newColor1r * (newWidth - calcX) / newWidth + newColor2r * calcX / newWidth);
int newColor1g = (theColour1 >> 8 & 0xFF) * (newHeight - calcY) / newHeight + (theColour3 >> 8 & 0xFF)
* calcY / newHeight;
int newColor2g = (theColour2 >> 8 & 0xFF) * (newHeight - calcY) / newHeight + (theColour4 >> 8 & 0xFF)
* calcY / newHeight;
int newColorg = isOutofColor(newColor1g * (newWidth - calcX) / newWidth + newColor2g * calcX / newWidth);
int newColor1b = (theColour1 & 0xFF) * (newHeight - calcY) / newHeight + (theColour3 & 0xFF) * calcY
/ newHeight;
int newColor2b = (theColour2 & 0xFF) * (newHeight - calcY) / newHeight + (theColour4 & 0xFF) * calcY
/ newHeight;
int newColorb = isOutofColor(newColor1b * (newWidth - calcX) / newWidth + newColor2b * calcX / newWidth);
int newColor = ((newAlpha & 0xFF) << 24) | ((newColorr & 0xFF) << 16) | ((newColorg & 0xFF) << 8)
| (newColorb & 0xFF);


// Set this pixel into the new image
des_rgb[newIndex++] = newColor;
}
}


Bitmap desImage = null;
desImage = Bitmap.createBitmap(des_rgb, newWidth, newHeight, Bitmap.Config.RGB_565);
// 缩放图片
desImage = Bitmap.createScaledBitmap(desImage, newWidth, newHeight, true);
if (desImage == null)
desImage = oriImg;
return desImage;
}


// it's used by the function bilinearResample().
final static int isOutofColor(int color) {
if (color < 0)
color = 0;
if (color > 255)
color = 255;
return color;
}


/**
* If we are on low memory or the photo can not be loaded, we will show a red cross in the photo frame.
*/
final static void createImageLoadFail(Canvas canvas) {
Paint paint = new Paint();
paint.setTypeface(Typeface.DEFAULT);
int wh = (int) (4 * paint.getTextSize());
canvas.drawRGB(0, 0, 0);
canvas.drawRect(new Rect(0, 0, wh - 1, wh - 1), new Paint());
canvas.drawRGB(255, 0, 0);
int xStart = wh / 2 - 3;
int yStart = wh / 2 - 3;


canvas.drawLine(xStart, yStart, xStart + 6, yStart + 6, paint);
canvas.drawLine(xStart, yStart + 1, xStart + 6, yStart + 7, paint);
canvas.drawLine(xStart + 6, yStart, xStart, yStart + 6, paint);
canvas.drawLine(xStart + 6, yStart + 1, xStart, yStart + 7, paint);
}


final static boolean isInComponent(int x, int y, View c) {
if (c == null)
return false;
if (x < c.getLeft() || x > c.getLeft() + c.getWidth() || y < c.getTop() || y > c.getTop() + c.getHeight())
return false;
else
return true;
}


/**
* Divide the given string to paragraphs with the given font and width.
*
* @param strSource
* the source string
* @param font
* the font
* @param width
* the width of each line.
* @return the String array
*/
public final static String[] getParagraph(final String strSource, final Paint font, final int width) {
String[] strs = null;
if (strSource == null || font == null || width <= 0) {
return strs;
} else if (strSource.equals("")) {
strs = new String[] { "" };
return strs;
}
Vector<String> vector = new Vector<String>();
try {
String temp = strSource;
int i, j;
boolean isOver;
while (!temp.equals("")) {
isOver = false;
i = temp.indexOf("\n");
if (i == -1) {
i = temp.length();
isOver = font.measureText(temp) > width;
}
if (i > 0 && font.measureText(temp.substring(0, i)) > width) {
isOver = true;
}
if (isOver) {
// gets the critical point
while (font.measureText(temp.substring(0, i)) > width) {
i = i - 1;
}
}
vector.addElement(temp.substring(0, i));
if (i == temp.length()) {
temp = "";
} else {
if (temp.charAt(i) == '\n') {
temp = temp.substring(i + 1);
} else {
temp = temp.substring(i);
}
}
}
if (vector.size() > 0) {
strs = new String[vector.size()];
vector.copyInto(strs);
}
} catch (Exception e) {


printOutToConsole("getSubsection:" + e);
}
return strs;
}


/**
* Divide the given string to paragraphs with the given font and width.
*
* @param strSource
* the source string
* @param font
* the font
* @param width
* the width of each line.
* @return the String array
*/
public final static String[] getParagraph(final String strSource, final Paint font, final int width,
final String splitChars) {
String[] strs = null;
if (strSource == null || font == null || width <= 0) {
return strs;
} else if (strSource.equals("")) {
strs = new String[] { "" };
return strs;
}
Vector vector = new Vector(2);
try {
String temp = strSource;
int i, j;
boolean isOver;
while (!temp.equals("")) {
isOver = false;
i = temp.indexOf("\n");
if (i == -1) {
i = temp.length();
isOver = font.measureText(temp) > width;
}
if (i > 0 && font.measureText(temp.substring(0, i)) > width) {
isOver = true;
}
if (isOver) {
// gets the critical point
while (font.measureText(temp.substring(0, i)) > width) {
i = i - 1;
}
if (!splitChars.equals("")) {
j = i; // restore the last index of this line for maybe
// there is a long word over a line.
while (splitChars.indexOf(temp.charAt(i - 1)) == -1) {
i--;
if (i == 0) {
i = j; // crash a word, if it is needed.
break;
}
}
}
}
vector.addElement(temp.substring(0, i));
if (i == temp.length()) {
temp = "";
} else {
if (temp.charAt(i) == '\n') {
temp = temp.substring(i + 1);
} else {
temp = temp.substring(i);
}
}
}
if (vector.size() > 0) {
strs = new String[vector.size()];
vector.copyInto(strs);
}
} catch (Exception e) {


printOutToConsole("getSubsection:" + e);
}
return strs;
}


/**
* @param src
* source image.
* @param desW
* expected width
* @param desH
* expected height
* @param isBackgroundTrans
* makes the background transparent
* @param isTrans
* makes the image transparent
* @return Image
*/
// public final final static final Image scaleImage(Image src, int desW, int desH,
// boolean isBackgroundTrans, boolean isTrans) {
// Image desImg = null;
// try {
// int srcW = src.getWidth(); // source image width
// int srcH = src.getHeight(); // source image height
// int[] srcBuf = new int[srcW * srcH]; // source image pixel
// src.getRGB(srcBuf, 0, srcW, 0, 0, srcW, srcH);
// // compute interpolation table
// int[] tabY = new int[desH];
// int[] tabX = new int[desW];
// int sb = 0;
// int db = 0;
// int tems = 0;
// int temd = 0;
// int distance = srcH > desH ? srcH : desH;
// for (int i = 0; i <= distance; i++) { /* vertical direction */
// tabY[db] = sb;
// tems += srcH;
// temd += desH;
// if (tems > distance) {
// tems -= distance;
// sb++;
// }
// if (temd > distance) {
// temd -= distance;
// db++;
// }
// }
// sb = 0;
// db = 0;
// tems = 0;
// temd = 0;
// distance = srcW > desW ? srcW : desW;
// for (int i = 0; i <= distance; i++) { /* horizontal direction */
// tabX[db] = (short) sb;
// tems += srcW;
// temd += desW;
// if (tems > distance) {
// tems -= distance;
// sb++;
// }
// if (temd > distance) {
// temd -= distance;
// db++;
// }
// }
// // formation enlarge and shorten buffer pixel
// int[] desBuf = new int[desW * desH];
// int dx = 0;
// int dy = 0;
// int sy = 0;
// int oldy = -1;
// for (int i = 0; i < desH; i++) {
// if (oldy == tabY[i]) {
// System.arraycopy(desBuf, dy - desW, desBuf, dy, desW);
// } else {
// dx = 0;
// for (int j = 0; j < desW; j++) {
// desBuf[dy + dx] = srcBuf[sy + tabX[j]];
// dx++;
// }
// sy += (tabY[i] - oldy) * srcW;
// }
// oldy = tabY[i];
// dy += desW;
// }
// if (isTrans) {
// // int a= 100;//set the transparence of pixel 100
// for (int i = 0; i < desBuf.length; i++) {
// if (desBuf[i] == 0x00FFFFFF)
// continue;
// int alpha = ((desBuf[i] & 0xff000000) >>> 24) == 0 ? 0 : 100;
// desBuf[i] = ((alpha + 1) << 24) | (desBuf[i] & 0x00FFFFFF);
// }
// }
// if (isBackgroundTrans) {
// desImg = Image.createRGBImage(desBuf, desW, desH, true);
// } else {
// desImg = Image.createRGBImage(desBuf, desW, desH, false);
// }
// } catch (Exception ex) {
// LPUtils.printException(ex);
// desImg = null;
// }
// return desImg;
// }


/**
* @param strSrc
* @param strSepr
* @return
*/
public final static String[] string2Array(String strSrc, String strSepr) {
String[] astr = null;
try {
Vector vec = new Vector(5, 1);
str2Arr(strSrc, strSepr, vec);
vec.trimToSize();
astr = new String[vec.size()];
vec.copyInto(astr);
vec.removeAllElements();
} catch (Exception ex) {
}
return astr;
}


public final static void setPrint(Activity activity) {
if (getConfigStringFormAsset(activity, "isprintMessage").equalsIgnoreCase("true")) {
isPrintMessage_ = true;
}
setActivity(activity);
}


public final static void setActivity(Activity activity) {
// TODO Auto-generated method stub
activity_ = activity;
}


public final static Activity getActivity() {
return activity_;
}


private final static void str2Arr(String strSrc, String strSepr, Vector vec) throws Exception {
if (strSrc.indexOf(strSepr) == -1) {
vec.addElement(strSrc);
} else {
vec.addElement(strSrc.substring(0, strSrc.indexOf(strSepr)));
strSrc = strSrc.substring(strSrc.indexOf(strSepr) + strSepr.length());
str2Arr(strSrc, strSepr, vec);
}
}


// 将传入的字符串中的特殊字符予以替换,保证解析顺利进行或使已替换的字符串还?
public final static String insteadOfSpecillCharacter(String str, boolean isReplace) {
if ((null == str) || (str.equalsIgnoreCase("")))
return str;
String strTemp = str;
// 特殊字符?
String[] A = { "&" };
// 需要替换的字符
String[] substitute;
// 替换后的字符?
String[] B = { "***###" };
// 替换后的字符
String[] beReplaced;


if (isReplace) {
// 替换特殊字符串,方便解析
substitute = A;
beReplaced = B;
} else {
// 将特殊字符还?
substitute = B;
beReplaced = A;
}
int length = substitute.length;
for (int i = 0; i < length; i++) {
strTemp = strTemp.replace(substitute[i], beReplaced[i]);
}
return strTemp;
}


// 设置与是否获得焦?
// final final static public void setFocus(boolean isFocus, int keyCode, View view) {
// if (view instanceof LPTable) {
// LPTable temp = (LPTable) view;
// // temp.setFocus(isFocus, keyCode);
// } else {
// if (isFocus) {
// view.requestFocus();
// } else {
// view.clearFocus();
// }
// }
//
// }


/**
* @param obj
*/
public final static void printOutToConsole(Object obj) {
if (isPrintMessage_) {
if (obj instanceof String) {
printOutToConsole((String) obj);
} else if (obj instanceof byte[]) {
printOutToConsole((byte[]) obj);
} else {
System.out.println(obj);
}
}
}


/**
* @param s
*/
public final static void printOutToConsole(String s) {
if (isPrintMessage_) {
int length = s.length();
int offset = 3000;
if (length > offset) {// 解决报文过长,打印不全的问题?
int n = 0;
for (int i = 0; i < length; i += offset) {
n += offset;
if (n > length)
n = length;
System.err.println("Debug = " + s.substring(i, n));
}
} else {
System.err.println("Debug = " + s);
}
}
}


/**
* @param byts
*/
public final static void printOutToConsole(byte[] byts) {
if (isPrintMessage_) {
if (byts == null) {
return;
}
for (int i = 0; i < byts.length; i++) {
System.out.print("[" + i + "]" + " : \t");
System.out.println(byts[i]);
}
}
}


public final static void LogD(String tag, String msg) {
if (isPrintMessage_) {
android.util.Log.d(tag, msg);
}
}


public final static void printException(Exception e) {
if (isPrintMessage_) {
e.printStackTrace();
}
}


/**
* 检测服务端发过来的接口前面是否带有/,如果没有则自动加?提高程序健壮?
*
* @param url
* @return
*/
public final static String checkUrl(Object url) {
// TODO Auto-generated method stub
String tempString = url.toString().trim();
if (!tempString.startsWith("/"))
tempString = "/".concat(tempString);
return tempString;
}


/**
* Network Byte Order
*
* @param byts
* @param offset
* @return
*/
public final static int byteArrayToIntInNBO(byte[] byts, int offset) {
int intValue = 0;
for (int i = 0; i < 4; i++) {
int shift = (4 - 1 - i) * 8;
intValue += (byts[i + offset] & 0x000000FF) << shift;
}
return intValue;
}


/**
* Network Byte Order
*
* @param intValue
* @return
*/
public final static byte[] intToByteArrayInNBO(int intValue) {
byte[] byt = new byte[4];
for (int i = 0; i < 4; i++) {
byt[i] = (byte) (intValue >>> (24 - i * 8));
}
return byt;
}


/**
* @param firstBytes
* @param lastBytes
* @return
*/
public final static byte[] jogBytes(byte[]... byts) throws Exception {
if (byts.length == 0) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (byte[] byt : byts) {
if (byt == null) {
continue;
}
out.write(byt);
}
try {
out.flush();
} catch (Exception e) {
printException(e);
}
byte[] result = out.toByteArray();
try {
out.close();
} catch (Exception e) {
printException(e);
}
out = null;
return result;
}


public final static String getStringFormAsset(Activity activity, String str) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(activity.getAssets().open(str)), 8 * 1024);
String line;
StringBuilder buffer = new StringBuilder();
while ((line = in.readLine()) != null)
buffer.append(line).append('\n');
return buffer.toString();
} catch (IOException e) {
Utils.printException(e);
return "";
} finally {
if (in != null) {
try {
in.close();
in = null;
} catch (IOException e) {
// TODO Auto-generated catch block
printException(e);
}
}
}
}


/**
* 修正日期值的传输,将?”予以去除,月份日期小于10,则前面予以?
*
* @param value
* @return
*/
public final static String adjustDate(String value) {
// TODO Auto-generated method stub
if (value.contains("-")) {
String valueTemp = value;
String year = valueTemp.substring(0, valueTemp.indexOf("-"));
String month = valueTemp.substring(valueTemp.indexOf("-") + 1, valueTemp.lastIndexOf("-"));
String day = valueTemp.substring(valueTemp.lastIndexOf("-") + 1);
if (Integer.parseInt(month) < 10 && month.length() < 2)
month = "0".concat(month);
if (Integer.parseInt(day) < 10 && day.length() < 2)
day = "0".concat(day);
return year.concat(month).concat(day).replace("-", "");
}
return value;
}


/**
* 解读assets文件夹下的Config.txt文件信息
*
* @param activity
* @param tag
* 需要在该文件里面查找的key
* @return 文件中key对应的value
*/
public final static String getConfigStringFormAsset(Activity activity, String tag) {
if (configHm_ == null) {
initConfigStringFormAsset(activity);
}
String value = configHm_.get(tag);
return value == null ? "" : value;
}


/**
* 解读assets文件夹下的Config.txt文件信息
*
* @param activity
* @param tag
* 需要在该文件里面查找的key
* @return 文件中key对应的value
*/
private final static void initConfigStringFormAsset(Activity activity) {
//  只读取一次Config文件
if (null == activity)
return;
configHm_ = new HashMap<String, String>();
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(activity.getAssets().open("Config.txt")), 1024);
String line;
String key;
String value;
while ((line = in.readLine()) != null) {
int index = line.indexOf(" ");
if (index != -1) {
key = line.substring(0, index);
value = line.substring(index).trim();// 去掉前面的空?
configHm_.put(key, value);
}
}


String str_lag = configHm_.get("jat_lag");
jat_lag = Integer.parseInt(str_lag);
} catch (Exception e) {
} finally {
if (in != null) {
try {
in.close();
in = null;
} catch (Exception e) {
// TODO Auto-generated catch block
printException(e);
}
}
}
}


public final static int getScaledValueX(float num) {
// TODO Auto-generated method stub
float numtemp = SCALEDATEX * num;
return (int) numtemp;
}


public final static int getFontSize(int size) {
size = (int) (size * SCALEDFONT);
return size;
}


public final static int getScaledValueY(float num) {
// TODO Auto-generated method stub
float numtemp = SCALEDATEY * num;
return (int) numtemp;
}


/**
*
* @param wRate
* 参照宽度
* @param hRate
*/
private final static void setScaledParams(float wRate, float hRate) {
// TODO Auto-generated method stub
SCALEDATEX = wRate;
SCALEDATEY = hRate;
}


// 计算界面宽高
public final static void calculateScreenSize(Activity activity) {
// 从Config配置文档中读取服务端xml的基准分辨率,该分辨率应时刻与服务端定义的模板标准分辨率一?
BenchmarkresolutionW_ = Integer.parseInt(getConfigStringFormAsset(activity, "BenchmarkresolutionW"));
BenchmarkresolutionH_ = Integer.parseInt(getConfigStringFormAsset(activity, "BenchmarkresolutionH"));


DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
Component.SCREENWIDTH = dm.widthPixels;
// 该值为暂定值无实际意义,该值会在BaseView的onWindowFocusChanged方法中从新计算得?
// Component.SCREENHEIGHT = dm.heightPixels;
final float w = BenchmarkresolutionW_;
final float h = BenchmarkresolutionH_;
float wRate = dm.widthPixels / w;
float hRate = dm.heightPixels / h;
setScaledParams(wRate, hRate);
setBrHeight();
setMarginAndGap();
SCALEDFONT = 1;
int dw = dm.widthPixels;
int dh = dm.heightPixels;
float ds = dm.scaledDensity;


if (dw <= 240 && dh <= 320) {
if (ds != 0.75f) {
SCALEDFONT = 0.75f / ds;
}
} else if (dw <= 320 && dh <= 500) {
if (ds != 1f) {
SCALEDFONT = 1f / ds;
}
} else if (dw <= 480 && dh <= 900) {
if (ds != 1.5f) {
SCALEDFONT = 1.5f / ds;
}
} else if (dw <= 600) {
if (ds != 2f) {
SCALEDFONT = 2f / ds;
}
}
}


private static void setMarginAndGap() {
// TODO Auto-generated method stub
String tempString = getConfigStringFormAsset(getActivity(), "verticalMarginOfB");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VMB = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的body框架纵向边距经过缩放后为:" + LPLayout.VMB);


tempString = getConfigStringFormAsset(getActivity(), "horizontalMarginOfB");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HMB = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置body框架水平边距经过缩放后为:" + LPLayout.HMB);


tempString = getConfigStringFormAsset(getActivity(), "verticalGapOfB");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VGB = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的body框架子元素纵向间距经过缩放后为:" + LPLayout.VGB);


tempString = getConfigStringFormAsset(getActivity(), "horizontalGapOfB");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HGB = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置的body框架子元素横向间距经过缩放后为:" + LPLayout.HGB);


tempString = getConfigStringFormAsset(getActivity(), "verticalMarginOfF");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VMF = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的form框架纵向边距经过缩放后为:" + LPLayout.VMF);


tempString = getConfigStringFormAsset(getActivity(), "horizontalMarginOfF");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HMF = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置的form框架水平边距经过缩放后为:" + LPLayout.HMF);


tempString = getConfigStringFormAsset(getActivity(), "verticalGapOfF");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VGF = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的form框架子元素纵向间距经过缩放后为:" + LPLayout.VGF);


tempString = getConfigStringFormAsset(getActivity(), "horizontalGapOfF");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HGF = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置的form框架子元素横向间距经过缩放后为:" + LPLayout.HGF);


tempString = getConfigStringFormAsset(getActivity(), "verticalMarginOfD");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VMD = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的div框架纵向边距经过缩放后为:" + LPLayout.VMD);


tempString = getConfigStringFormAsset(getActivity(), "horizontalMarginOfD");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HMD = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置的div框架水平边距经过缩放后为:" + LPLayout.HMD);


tempString = getConfigStringFormAsset(getActivity(), "verticalGapOfD");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VGD = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的div框架子元素纵向间距经过缩放后为:" + LPLayout.VGD);


tempString = getConfigStringFormAsset(getActivity(), "horizontalGapOfD");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HGD = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置的div框架子元素横向间距经过缩放后为:" + LPLayout.HGD);


tempString = getConfigStringFormAsset(getActivity(), "verticalMarginOfT");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VMT = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的td框架纵向边距经过缩放后为:" + LPLayout.VMT);


tempString = getConfigStringFormAsset(getActivity(), "horizontalMarginOfT");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HMT = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置的td框架水平边距经过缩放后为:" + LPLayout.HMT);


tempString = getConfigStringFormAsset(getActivity(), "verticalGapOfT");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.VGT = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的td框架子元素纵向间距经过缩放后为:" + LPLayout.VGT);


tempString = getConfigStringFormAsset(getActivity(), "horizontalGapOfT");
if (null == tempString || tempString.equals(""))
tempString = "0";
LPLayout.HGT = getScaledValueX(Integer.parseInt(tempString));
printOutToConsole("Config设置的td框架子元素横向间距经过缩放后为:" + LPLayout.HGT);
}


public static void setBrHeight() {
// TODO Auto-generated method stub
String tempString = getConfigStringFormAsset(getActivity(), "brHeight");
if (null == tempString || tempString.equals(""))
tempString = "0";
BRHEIGHT = getScaledValueY(Integer.parseInt(tempString));
printOutToConsole("Config设置的br节点高度经过缩放后为:" + BRHEIGHT);
}


public static int getBrHeight() {
return BRHEIGHT;
}


/**
* 获取手机的model型号
*
* @return
*/
public final static String getPhoneModel() {
String temp = android.os.Build.MODEL;
temp = temp.replace(" ", "").replace("-", "_").trim();
return temp;
}


public final static String getPhoneTarget() {
String temp = android.os.Build.DEVICE;
temp = temp.replace(" ", "").replace("-", "_").trim();
return temp;


}


public final static String getClientID() {
String temp = android.os.Build.ID;
temp = temp.replace(" ", "").replace("-", "_").trim();
return temp;
}


/**
* 获取界面分辨率并且组合成?
*
* @param activity
* @return
*/
public final static String getResolution(Activity activity) {
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
String w = String.valueOf(dm.widthPixels);
String h = String.valueOf(dm.heightPixels);
return w.concat("*").concat(h);
}


public final static Typeface getTypeFace(String string) {
Typeface tface = null;
try {
if (string.equalsIgnoreCase("bold")) {
tface = Typeface.defaultFromStyle(Typeface.BOLD);
} else if (string.equalsIgnoreCase("normal")) {
tface = Typeface.defaultFromStyle(Typeface.NORMAL);
} else {
tface = null;
}
} catch (Exception e) {
tface = null;
}
return tface;
}


/**
* 设置字体是否粗体
* */
private final static boolean getFontType(String string) {
if (string.equalsIgnoreCase("bold")) {
return true;
} else {
return false;
}
}


/** * 图片去色,返回灰度图片 * @param bmpOriginal 传入的图?* @return 去色后的图片 */
public final static Bitmap getGrayBitmap(Bitmap bmpOriginal) {
if (null == bmpOriginal)
return null;
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}


/**
* @param activity
* @param fileName
* @param data
*/
public final static void updateFile(Activity activity, String fileName, byte[] data) {
try {
FileOutputStream fos = activity.openFileOutput(fileName, Activity.MODE_PRIVATE);
fos.write(new byte[] {}); // clear file.
fos.write(data);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Utils.printException(e);
} catch (IOException e) {
Utils.printException(e);
} catch (Exception e) {
Utils.printException(e);
}


}


/**
* @param activity
* @param fullPathName
* @return
*/
public final static byte[] readFile(Activity activity, String fullPathName) {
byte[] buffer = null;
FileInputStream fis = null;
try {
File file = new File(fullPathName);
if (file.exists()) {
fis = activity.openFileInput(fullPathName);
int len = fis.available();
buffer = new byte[len];
fis.read(buffer);
fis.close();
}
} catch (FileNotFoundException e) {
printException(e);
} catch (IOException e) {
printException(e);
} catch (Exception e) {
printException(e);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
return buffer;
}


public final static String getVersionName(Activity activity) {
try {
PackageManager pm = activity.getPackageManager();


PackageInfo pi;


pi = pm.getPackageInfo(activity.getPackageName(), PackageManager.GET_ACTIVITIES);
return pi.versionName;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
Utils.printException(e);
return "1.0";
}


}


/**
* User-Agent string we use in all of our HTTP transactions. XXX DO NOTE CHANGE THIS!!
*/
public final static String makeUserAgent(String version) {
StringBuffer buf = new StringBuffer("LightPole/");
buf.append(version);
buf.append("/");
buf.append("android1.5");
return buf.toString();
}


// Get a code from data.
private final static int getCode(byte data[], int tree[]) {
int node = tree[0];
while (node >= 0) {
if (bitIndex == 0)
bitByte = (data[gIndex++] & 0xFF);
node = (((bitByte & (1 << bitIndex)) == 0) ? tree[node >> 16] : tree[node & 0xFFFF]);
bitIndex = (bitIndex + 1) & 0x7;
}
return (node & 0xFFFF);
}


/**
* 判断报文是否存在xml?如果没有则手动加?
*
* @param xml
* @return
*/
public final static String addXmlHead(String xml) {
if (xml.indexOf("<?xml") == -1) {
xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>".concat(xml);
}
return xml;
}


// get num bits from data. the num should not bigger than 32.
private final static int getBits(byte[] data, int num) {
int result = 0;
int i = 0;
if (bitIndex != 0) {
i = 8 - bitIndex;
result = bitByte >> bitIndex;
}
while (i < num) {
bitByte = data[gIndex++] & 0xFF;
result |= (bitByte << i);
i += 8;
}
bitIndex = (bitIndex + num) & 0x7;// calculate (bitIndex + num)%8
result &= (0xffffffff >>> (32 - num));
return result;
}


// It's used to decompress gzip data. Re. rfc1951 and rfc 1952.
public final static byte[] gunzip(byte[] gzipData) throws IOException {
// Check if the data is gzip format and if it is used "deflate"
// compression method.
if (gzipData[0] != 31 || gzipData[1] != -117)
throw new IOException("压缩数据格式错误!");
if (gzipData[2] != 8)
throw new IOException("压缩数据方法错误!");


// Skip the gzip data header.
byte flg = gzipData[3];
gIndex = 10;
bitIndex = 0;
bitByte = 0;
if ((flg & 4) != 0)
gIndex += getBits(gzipData, 16);
if ((flg & 8) != 0)
while (gzipData[gIndex++] != 0)
;
if ((flg & 16) != 0)
while (gzipData[gIndex++] != 0)
;
if ((flg & 2) != 0)
gIndex += 2;


int temp = gIndex;
gIndex = gzipData.length - 4;
// The size of the original input data
int size = getBits(gzipData, 16) | (getBits(gzipData, 16) << 16);
byte[] unzipData = new byte[size];
gIndex = temp;


int unzipIndex = 0;
bitIndex = 0;
bitByte = 0;
int lastBlock = 0; // 0 indicates have more block when 1 indicates it is
// the last block.
int type = 0;// 0 indicates uncompress data, 1 indicates use final final static
// Huffman, 2 indicates use dynamic Huffman.
while (lastBlock == 0) {
lastBlock = getBits(gzipData, 1);
type = getBits(gzipData, 2);
if (type == 0) {
// uncompress data
bitIndex = 0;
int length = getBits(gzipData, 16);
gIndex += 2;
System.arraycopy(gzipData, gIndex, unzipData, unzipIndex, length);
gIndex += length;
unzipIndex += length;
} else {
byte[] lBits;
byte[] dBits;
if (type == 1) {
// use final final static huffman.
lBits = new byte[288];// The lTree node numbers 286, the
// last two nodes is use for full
// tree.
for (int i = 0; i < 288; i++) {
if (i < 144 || i > 279) {
lBits[i] = 8;
} else if (i < 256) {
lBits[i] = 9;
} else {
lBits[i] = 7;
}
}
dBits = new byte[32];// The dTree node numbers 30, the last
// two nodes is use for full tree.
for (int i = 0; i < dBits.length; i++) {
dBits[i] = 5;
}
} else if (type == 2) {
// use dynamic huffman.
int hlit = getBits(gzipData, 5) + 257;
int hdist = getBits(gzipData, 5) + 1;
int hclen = getBits(gzipData, 4) + 4;
byte[] bltreeBits = new byte[19];// The blTree node numbers
// 19.
for (int i = 0; i < hclen; i++)
bltreeBits[DYNAMIC_L_ORDER[i]] = (byte) getBits(gzipData, 3);
int[] blTree = huffmanTree(bltreeBits);
lBits = decompressCode(gzipData, blTree, hlit);
dBits = decompressCode(gzipData, blTree, hdist);
} else {
throw new IOException("不能正确解压数据.");
}


int[] lTree = huffmanTree(lBits);// The literal/length tree.
int[] dTree = huffmanTree(dBits);// The distance tree.
int code = 0;
while ((code = getCode(gzipData, lTree)) != 256) {// code=256
// indicates
// the end
// of this
// block.
if (code < 256) {// literal byte
unzipData[unzipIndex++] = (byte) code;
} else {// length/distance pairs
code -= 257;
int length = EXTRA_L_VALUES[code];
if (EXTRA_L_BITS[code] > 0)
length += getBits(gzipData, EXTRA_L_BITS[code]);
code = getCode(gzipData, dTree);
int distance = EXTRA_D_VALUES[code];
if (EXTRA_D_BITS[code] > 0)
distance += getBits(gzipData, EXTRA_D_BITS[code]);
while (distance < length) {
System.arraycopy(unzipData, unzipIndex - distance, unzipData, unzipIndex, distance);
unzipIndex += distance;
length -= distance;
}
System.arraycopy(unzipData, unzipIndex - distance, unzipData, unzipIndex, length);
unzipIndex += length;
}
}
}
}
return unzipData;
}


// Get a huffman tree.
private final static int[] huffmanTree(byte bits[]) {
int bl_count[] = new int[MAX_BITS + 1];
for (int i = 0; i < bits.length; i++) {
bl_count[bits[i]]++;
}
int code = 0;
bl_count[0] = 0;
int next_code[] = new int[MAX_BITS + 1];
// Count the number of codes for each code length.
for (int i = 1; i <= MAX_BITS; i++) {
code = (code + bl_count[i - 1]) << 1;
next_code[i] = code;
}
int tree[] = new int[((bits.length - 1) << 1) + MAX_BITS];
int treeInsert = 1;
for (int i = 0; i < bits.length; i++) {
int len = bits[i];
if (len != 0) {
code = next_code[len]++;
int node = 0;
for (int bit = len - 1; bit >= 0; bit--) {
int value = code & (1 << bit);
if (value == 0) {
int left = tree[node] >> 16;
if (left == 0) {
tree[node] |= (treeInsert << 16);
node = treeInsert++;
} else
node = left;
} else {
int right = tree[node] & 0xFFFF;
if (right == 0) {
tree[node] |= treeInsert;
node = treeInsert++;
} else
node = right;
}
}
tree[node] = 0x80000000 | i;
}
}
return tree;
}


// Decompress the literal/length code and the distance code.
private final static byte[] decompressCode(byte data[], int blTree[], int count) {
int code = 0;
byte previousCode = 0;
int times = 0; // The number of the previous code's length need to
// repeat.
byte treeBits[] = new byte[count];
int index = 0;
while (index < count) {
code = getCode(data, blTree);
if (code == 16) {
times = getBits(data, 2) + 3;
} else if (code == 17) {
times = getBits(data, 3) + 3;
previousCode = 0;
} else if (code == 18) {
times = getBits(data, 7) + 11;
previousCode = 0;
} else {
times = 0;
previousCode = (byte) code;
treeBits[index++] = (byte) code;
}
for (int i = 0; i < times; i++) {
treeBits[index++] = previousCode;
}
}
return treeBits;
}


public final static String getVersion() {
// 获取手机操作系统版本?
return android.os.Build.VERSION.RELEASE;
}


public final static String getModel() {
// 获取手机型号
return android.os.Build.MODEL;
}


public final static String getName() {
// 获取用户姓???
return android.os.Build.USER;
}


public final static String getDeviceName() {
return android.os.Build.DEVICE;
}


public final static String getPlayform() {
// 当前系统平台
return "Android";
}


public final static String getUUID() {
final TelephonyManager tm = (TelephonyManager) activity_.getBaseContext().getSystemService(
Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, tmPhone, androidId;
tmDevice = "" + tm.getDeviceId();
tmSerial = "" + tm.getSimSerialNumber();
androidId = ""
+ android.provider.Settings.Secure.getString(activity_.getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
UUID deviceUuid = new UUID(androidId.hashCode(), ((long) tmDevice.hashCode() << 32) | tmSerial.hashCode());
return deviceUuid.toString();
}


public final static String connectType(Activity bv) {
// TODO Auto-generated method stub
try {
Context context = bv.getApplicationContext();
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);


NetworkInfo ni = connectivity.getActiveNetworkInfo();


if ((null != ni) && ni.isAvailable()) {
return ni.getTypeName();
}
} catch (Exception e) {
Utils.printException(e);
return getConfigStringFormAsset(getActivity(), "httpError");
}
return getConfigStringFormAsset(getActivity(), "httpError");


}


private final static String getLocationByNet(Activity bv) {
// TODO Auto-generated method stub
double LATITUDE = 0;
double LONGITUDE = 0;
int timeoutConnection = 3000;
int timeoutSocket = 5000;
TelephonyManager mTelNet = (TelephonyManager) bv.getSystemService(Context.TELEPHONY_SERVICE);
String operator = mTelNet.getNetworkOperator();
CellLocation cl = mTelNet.getCellLocation();
// #ifdef Android2.2
if (cl instanceof CdmaCellLocation) {
CdmaCellLocation location = (CdmaCellLocation) cl;
LATITUDE = (double) location.getBaseStationLatitude() / 14400;// 14400?*90/1296000
LONGITUDE = (double) location.getBaseStationLongitude() / 14400;


} else if (null != operator && !operator.equals("")) {
// #else
// @ if (null != operator && !operator.equals("")) {
// #endif
String mcc = operator.substring(0, 3);
String mnc = operator.substring(3);


if (cl instanceof GsmCellLocation) {
GsmCellLocation location = (GsmCellLocation) cl;
if (null != location) {
int cid = location.getCid();
int lac = location.getLac();
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient httpclient = new DefaultHttpClient(httpParameters);
HttpPost post = new HttpPost("http://www.google.com/loc/json");
try {
JSONObject holder = new JSONObject();
holder.put("version", "1.1.0");
holder.put("host", "maps.google.com");
holder.put("address_language", "zh_CN");
holder.put("request_address", true);
JSONObject tower = new JSONObject();
tower.put("mobile_country_code", mcc);
tower.put("mobile_network_code", mnc);
tower.put("cell_id", cid);
tower.put("location_area_code", lac);
JSONArray towerarray = new JSONArray();
towerarray.put(tower);
holder.put("cell_towers", towerarray);
StringEntity query = new StringEntity(holder.toString());
post.setEntity(query);
HttpResponse response = httpclient.execute(post);
HttpEntity entity = response.getEntity();
BufferedReader buffReader = new BufferedReader(new InputStreamReader(entity.getContent()));
StringBuffer strBuff = new StringBuffer();
String result = null;
while ((result = buffReader.readLine()) != null) {
strBuff.append(result);
}
JSONObject json = new JSONObject(strBuff.toString());
JSONObject subjosn = new JSONObject(json.getString("location"));
LATITUDE = Double.parseDouble(subjosn.getString("latitude"));
LONGITUDE = Double.parseDouble(subjosn.getString("longitude"));
} catch (Exception e) {
// LPUtils.printException(e);
Utils.printException(e);
}
}
}
}


return (String.valueOf(LATITUDE)).concat(",").concat(String.valueOf(LONGITUDE));
}


/**
* 查看android手机是否被刷过机.linux系统下root权限可以使用su命令,android本身也是小型的linux系统
*
* @param command
* "id" 或其他的 su命令
*/
public final static boolean runRootCommand(String command) {


Process process = null;
DataOutputStream os = null;
try {
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(command + "\n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (Exception e) {
printException(e);
return false;
} finally {
try {
if (os != null) {
os.close();
}
process.destroy();
} catch (Exception e) {
// nothing
}
}
return true;
}


/**
* * 保存对象到文?* * @param obj * @param fileName * @throws Exception
*
* @param publicKey
*/
public static void saveFile(Activity activity, Object obj, String fileName) {
ObjectOutputStream output;
try {
output = new ObjectOutputStream(activity.openFileOutput(fileName, Context.MODE_PRIVATE));


output.writeObject(obj);
output.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
printException(e);
} catch (IOException e) {
// TODO Auto-generated catch block
printException(e);
}
}


/**
* 读取Config的文本默认颜色设置,如果没有,默认为黑色
*
* @param activity
*/
public static void readTextClolr(Activity activity) {
String colortemp = getConfigStringFormAsset(activity, "textColor");
Component.TEXTCOLOR = Color.BLACK;
if (null != colortemp && !colortemp.equals("")) {
if (colortemp.equalsIgnoreCase("black"))
Component.TEXTCOLOR = Color.BLACK;
else if (colortemp.equalsIgnoreCase("BLUE"))
Component.TEXTCOLOR = Color.BLUE;
else if (colortemp.equalsIgnoreCase("CYAN"))
Component.TEXTCOLOR = Color.CYAN;
else if (colortemp.equalsIgnoreCase("dkgray"))
Component.TEXTCOLOR = Color.DKGRAY;
else if (colortemp.equalsIgnoreCase("white"))
Component.TEXTCOLOR = Color.WHITE;
else if (colortemp.equalsIgnoreCase("gray"))
Component.TEXTCOLOR = Color.GRAY;
else if (colortemp.equalsIgnoreCase("green"))
Component.TEXTCOLOR = Color.GREEN;
else if (colortemp.equalsIgnoreCase("ltgray"))
Component.TEXTCOLOR = Color.LTGRAY;
else if (colortemp.equalsIgnoreCase("magenta"))
Component.TEXTCOLOR = Color.MAGENTA;
else if (colortemp.equalsIgnoreCase("red"))
Component.TEXTCOLOR = Color.RED;
else if (colortemp.equalsIgnoreCase("transparent"))
Component.TEXTCOLOR = Color.TRANSPARENT;
else if (colortemp.equalsIgnoreCase("yellow"))
Component.TEXTCOLOR = Color.YELLOW;
}
}


/** * 从文件读取object * * @param fileName * @return * @throws Exception */
public static Object readFromFile(Activity activity, String fileName) {
ObjectInputStream input;
try {
input = new ObjectInputStream(activity.openFileInput(fileName));
Object obj = input.readObject();
input.close();
return obj;
} catch (StreamCorruptedException e) {
// TODO Auto-generated catch block
printException(e);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
printException(e);
} catch (IOException e) {
// TODO Auto-generated catch block
printException(e);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
printException(e);
}
return null;
}


public static void saveFile(String name, byte[] buffer) {
if (null == name || name.equals(""))
return;
name = OffStoreDownload.FILEROOT.concat(name);


if (name.endsWith("/")) {
createPath(name);
} else {
createFile(name, buffer);
}
}


/**
* @param activity
* @param fullPathName
* @return
*/
public final static byte[] readFile(String fullPathName) {
byte[] buffer = null;
try {
File file = new File(fullPathName);
FileInputStream fis = new FileInputStream(file);
int len = fis.available();
buffer = new byte[len];
fis.read(buffer);
fis.close();
buffer = AESCipher.decrypt(buffer, AESCipher.customerKey_, AESCipher.customerIv_);
} catch (FileNotFoundException e) {
printException(e);
} catch (IOException e) {
printException(e);
} catch (Exception e) {
printException(e);
}
return buffer;
}


private static void createFile(String path, byte[] buffer) {
// TODO Auto-generated method stub
File file = null;
FileOutputStream fstream = null;
try {
file = new File(path);
if (!file.exists()) {
file.createNewFile();
fstream = new FileOutputStream(file);
buffer = AESCipher.encrypt(buffer, AESCipher.customerKey_, AESCipher.customerIv_);
fstream.write(buffer);
}
} catch (Exception e) {


printException(e);


} finally {


if (fstream != null) {


try {
fstream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
printException(e);
}


}


}
}


public static void createPath(String path) {
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
}


/**
* 初始化本地存储的 key,iv
*
* @param activity
*/
public static void initCustomerSecretKey(Activity activity) {
try {
TelephonyManager tm = (TelephonyManager) activity.getSystemService(Activity.TELEPHONY_SERVICE);
String deviceId = tm.getDeviceId();
String deviceName = Build.DEVICE;
String packageName = activity.getPackageName();
if (deviceId == null) {
deviceId = "";
}
if (deviceName == null) {
deviceName = "";
}
if (packageName == null) {
packageName = "com.rytong.tools";
}
String message = deviceId.concat(deviceName).concat(packageName)
.concat(RSACipher.PUBLIC_CER_MODULUS_FILENAME).concat(HMac.KEY_MAC_MD5);
byte[] sha1 = HMac.SHA1(message.getBytes());
byte[] md5 = MD5.getMD5(message.getBytes());
byte[] secretKey = new byte[sha1.length + md5.length];
System.arraycopy(sha1, 0, secretKey, 0, sha1.length);
System.arraycopy(md5, 0, secretKey, sha1.length, md5.length);
AESCipher.customerKey_ = ClientHello.getAESKey(secretKey);
AESCipher.customerIv_ = new byte[16];
for (int i = 0; i < 16; i++) {
AESCipher.customerIv_[i] = secretKey[secretKey.length - 1 - i];
}
} catch (Exception e) {
printOutToConsole(e);
}
}


/**
* 清空界面所有控件
*/
public static void clearWidget() {
// TODO Auto-generated method stub
if (null != Component.VWIDGETARRAY && !Component.VWIDGETARRAY.isEmpty()) {
int size = Component.VWIDGETARRAY.size();
Component comp;
int index = Integer.MIN_VALUE;
for (int i = 0; i < size; i++) {
comp = (Component) Component.VWIDGETARRAY.get(i);
if (null != comp.getTag() && comp.getTag().equalsIgnoreCase("body"))
index = i;
}
if (index != Integer.MIN_VALUE) {
comp = (Component) Component.VWIDGETARRAY.get(index);
comp.releaseResource(comp);
}
}
}


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值