Android 使用Javascript作為腳本計算器
來自: http://my.oschina.net/ososchina/blog/610964
原則上Java 本身不支持腳本計算,早期通過ScriptManager或者J2V8支持腳本計算,但在Android中閹割了此部分功能,因此,為了能進行腳本計算,我們需要特別封裝
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.webkit.ConsoleMessage;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by Noah on 2016/1/23.
*/
public class JavaScriptManager implements Handler.Callback{
//計算引擎
private WebView jsEngine;
//計算結果回調
private Handler.Callback mCallback;
//判斷頁面是否加載完成
private boolean isLoadFinished;
//表示加載完成
public final static int STATE_FINISHED = 200;
//返回正確結果
public final static int STATE_RESULT_OK = 100;
//計算出錯
public final static int STATE_RESULT_FAILED = -100;
//加載開始
public final static int STATE_STARTING = 300;
private JavaScriptManager(Context context,Handler.Callback callback) {
jsEngine = new WebView(context);
initJsEngine();
this.mCallback = callback;
}
public static JavaScriptManager newInstance(Context context,Handler.Callback callback)
{
return new JavaScriptManager(context,callback);
}
private void initJsEngine()
{
if(jsEngine!=null)
{
WebSettings settings = jsEngine.getSettings();
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setAppCacheEnabled(false);
settings.setJavaScriptCanOpenWindowsAutomatically(false);
settings.setSupportMultipleWindows(false);
settings.setSaveFormData(false);
settings.setGeolocationEnabled(false);
settings.setJavaScriptEnabled(true);
settings.setSupportZoom(false);
settings.setDefaultTextEncodingName("utf-8");
jsEngine.setWebChromeClient(new JsEngineChromeClient(this));
jsEngine.setWebViewClient(new JsEngineWebClient(this));
}
}
@Override
public boolean handleMessage(Message msg) {
if(msg!=null)
{
if(msg.what==STATE_RESULT_OK)
{
return mCallback.handleMessage(msg);
}
else if(msg.what==STATE_FINISHED)
{
isLoadFinished = true;
}else if(msg.what==STATE_STARTING){
isLoadFinished = false;
}else{
Log.e("JavaScriptManager","ErrorCode="+msg.what+"description="+(String)msg.obj);
//防止腳本出錯之后影響程序運行,有必要重新刷新
if(msg.what==STATE_RESULT_FAILED)
{
jsEngine.reload();
}
return mCallback.handleMessage(msg);
}
}
return false;
}
public void loadWebData(String html)
{
if(isLoadFinished && jsEngine!=null)
{
jsEngine.loadData(html,"text/html;charset=utf-8","utf-8");
}
}
public void executeScript(String script)
{
if(jsEngine!=null)
{
if(Build.VERSION.SDK_INT>=19)
{
jsEngine.evaluateJavascript(script, new ValueCallback<String>() {
@Override
public void onReceiveValue(String message) {
Message msg = new Message();
try {
JSONObject json = new JSONObject(message);
msg.what = json.optInt("code",STATE_RESULT_OK);
msg.obj = json.optString("result","");
} catch (JSONException e) {
e.printStackTrace();
msg.what = -STATE_RESULT_FAILED;
}
JavaScriptManager.this.handleMessage(msg);
}
});
}else{
jsEngine.loadUrl("javascript:"+script);
}
}
}
private static class JsEngineWebClient extends WebViewClient{
public Handler.Callback callback;
public JsEngineWebClient(Handler.Callback callback){
this.callback = callback;
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
Message msg = new Message();
msg.what = errorCode;
msg.obj = description;
callback.handleMessage(msg);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Message msg = new Message();
msg.what = STATE_FINISHED;
msg.obj = "finished";
callback.handleMessage(msg);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Message msg = new Message();
msg.what = STATE_STARTING;
msg.obj = "finished";
callback.handleMessage(msg);
}
}
private static class JsEngineChromeClient extends WebChromeClient{
public Handler.Callback callback;
public JsEngineChromeClient(Handler.Callback callback){
this.callback = callback;
}
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
if (consoleMessage.messageLevel()==ConsoleMessage.MessageLevel.ERROR)
{
Log.e("JavaScriptManager" + consoleMessage.lineNumber(), consoleMessage.message());
}else if(consoleMessage.messageLevel()==ConsoleMessage.MessageLevel.WARNING){
Log.w("JavaScriptManager"+consoleMessage.lineNumber(),consoleMessage.message());
}else{
Log.i("JavaScriptManager"+consoleMessage.lineNumber(),consoleMessage.message());
}
return super.onConsoleMessage(consoleMessage);
}
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
result.confirm();
Message msg = new Message();
try {
JSONObject json = new JSONObject(message);
msg.what = json.optInt("code",STATE_RESULT_OK);
msg.obj = json.optString("result","");
} catch (JSONException e) {
e.printStackTrace();
msg.what = STATE_RESULT_FAILED;
}
callback.handleMessage(msg);
return true;
}
}
} 當然,我們還需要初始化,以保證我們的腳本可以更加健壯
public class ScriptFactory {
public String createScript()
{
StringBuilder sb = new StringBuilder();
sb.append("<!DOCTYPE HTML>");
sb.append("\r\n");
sb.append("<html>");
sb.append("\r\n");
sb.append("<head>");
sb.append("\r\n");
sb.append("<meta charset='utf-8'>");
sb.append("\r\n");
sb.append("<meta http-equiv='cache-control' content='no-cache,private'>");
sb.append("\r\n");
sb.append("<title>Javascript Engine</title>");
sb.append("\r\n");
sb.append("</head>");
sb.append("\r\n");
sb.append("<body>");
sb.append("\r\n");
sb.append("<script type='text/javascript'>");
sb.append("\r\n");
sb.append("window.handleEval = function( s)");
sb.append("\r\n");
sb.append("{");
sb.append("\r\n");
sb.append(" try{");
sb.append("\r\n");
sb.append(" var result = window.eval(s); ");
sb.append("\r\n");
sb.append(" var ret = {code:100,result:result}; ");
sb.append("\r\n");
sb.append(" alert(JSON.stringify(ret)); ");
sb.append("\r\n");
sb.append(" }");
sb.append("\r\n");
sb.append(" catch(e)");
sb.append("\r\n");
sb.append(" {");
sb.append("\r\n");
sb.append(" var ret = {code:-100,result:'Express Error['+s+']==>'+e.message}; ");
sb.append("\r\n");
sb.append(" alert(JSON.stringify(ret)); ");
sb.append("\r\n");
sb.append(" }");
sb.append("\r\n");
sb.append("}");
sb.append("\r\n");
sb.append("</script>");
sb.append("\r\n");
sb.append("</body>");
sb.append("\r\n");
sb.append("</html>");
return sb.toString();
}
}
本文由用戶 KalArispe 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!