package com.qmusic.webdoengine;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import org.apache.http.Header;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.FileAsyncHttpResponseHandler;
import com.qmusic.MyApplication;
import com.qmusic.common.BConstants;
import com.qmusic.uitls.BIOUtilities;
import com.qmusic.uitls.BLog;
import com.qmusic.uitls.BUtilities;
public final class BWebdoEngine {
static final String TAG = "BWebdoEngine";
private static boolean USE_ASSET = true;
private static volatile boolean resourceReady;
private static HashMap<String, BWebView> cachedWebView;
// done
public static final String URL_HTML_SPA = "html/index_spa.html";
public static final String URL_HTML = "html/index.html";
@SuppressLint("NewApi")
public static final void init(final Context ctx) {
cachedWebView = new HashMap<String, BWebView>();
// ==========================================
AsyncTask<Void, Void, Boolean> asyncTask = new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
resourceReady = false;
boolean result = updateResource(ctx);
return result;
}
@Override
protected void onPostExecute(Boolean result) {
// Add check in case that getWebview is called before update
// resource finished
if (!cachedWebView.containsKey(URL_HTML_SPA)) {
cachedWebView.put(URL_HTML_SPA, getWebview(URL_HTML_SPA));
}
if (!cachedWebView.containsKey(URL_HTML)) {
cachedWebView.put(URL_HTML, getWebview(URL_HTML));
}
resourceReady = true;
}
};
asyncTask.execute();
}
/**
*
* @param type
* : in which webView the statement should be executed, if it is
* empty then all.
* @param statement
*/
public static final void sendJavascript(final String type, final String statement) {
if (TextUtils.isEmpty(type)) {
for (BWebView webView : cachedWebView.values()) {
webView.sendJavascript(statement);
}
} else {
BWebView webView = cachedWebView.get(type);
if (webView != null) {
webView.sendJavascript(statement);
}
}
}
/**
* return a cached Webview, if there is no such Webview, then create a new
* one
*
* @param relativeUrl
* : the relative url root path is asset/www/
* @return
*/
public static final BWebView getWebview(String relativeUrl) {
BWebView webView = cachedWebView.get(relativeUrl);
if (webView == null) {
final Context context = MyApplication.getContext();
webView = new BWebView(context);
String url;
final File htmlCache = BUtilities.getHTMLFolder();
if (USE_ASSET || htmlCache == null || !new File(htmlCache, relativeUrl).exists()) {
url = "file:///android_asset/www/" + relativeUrl;
} else {
url = String.format("file://%s/%s", htmlCache.getAbsolutePath(), relativeUrl);
}
webView.loadUrl(url);
cachedWebView.put(relativeUrl, webView);
}
return webView;
}
public static final boolean isWebdoEngineReady() {
return resourceReady;
}
/**
* This could take some time to finish, please don't call this function in
* UI thread
*
* @param ctx
*/
private static final boolean updateResource(final Context ctx) {
// Step 1: check if there are html in sdcard
// Step 2: check if there are download htmls.zip
// Step 3: check if there are updates from server
final File htmlFolder = BUtilities.getHTMLFolder();
if (htmlFolder == null || !htmlFolder.isDirectory()) {
return false;
}
if (htmlFolder.list().length == 0) {
// then copy assert to sdcard
try {
final String root = "www";
final String[] files = ctx.getAssets().list(root);
for (String file : files) {
BIOUtilities.copyAssertToSDCard(ctx, String.format("%s%s%s", root, File.separator, file), htmlFolder);
}
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
final File zipFile = new File(ctx.getExternalCacheDir(), "htmls.zip");
if (zipFile.exists()) {
// Note: rename to another filename is to prevent the zip file
// unziping failed. One zip file has only one chance to unzip.
File zippingFile = new File(ctx.getExternalCacheDir(), "htmls.unzipping");
boolean result = zipFile.renameTo(zippingFile);
if (result) {
InputStream is = null;
try {
is = new FileInputStream(zippingFile);
BLog.i(TAG, "start to unzip htmls.zip");
BIOUtilities.unZipFolder(is, htmlFolder.getAbsolutePath());
BLog.i(TAG, "htmls.zip unziped sucessfully");
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
zippingFile.delete();
} else {
zipFile.delete();
}
} else {
// get zip from server async
final String url = "http://192.168.1.105/htmls.zip";
BLog.i(TAG, "downloading htmls.zip from " + url);
// AjaxCallback<File> callback = new AjaxCallback<File>() {
// @Override
// public void callback(String url, File object, AjaxStatus
// status) {
// if (object != null) {
// object.renameTo(zipFile);
// BLog.i(TAG, "htmls.zip download sucessfully");
// String lastModified = status.getHeader("Last-Modified");
// BUtilities.setPref(BConstants.PRE_KEY_LAST_MODIFIED_HTML,
// lastModified);
// } else if (status.getCode() == 304) {
// BLog.i(TAG, "htmls.zip is already up to date");
// } else {
// BLog.e(TAG, "htmls.zip download failed");
// }
// }
// };
// callback.url(url).type(File.class).uiCallback(false);//
// .targetFile(zipFile);
// String lastModifiedStr =
// BUtilities.getPref(BConstants.PRE_KEY_LAST_MODIFIED_HTML);
// if (!TextUtils.isEmpty(lastModifiedStr)) {
// callback.header("If-Modified-Since", lastModifiedStr);
// }
// callback.async(ctx);
}
}
return true;
}
}