Commit 93174cb0 by gao.chao

web升级为JS Bridge

parent 87ff79a3
...@@ -20,20 +20,21 @@ ...@@ -20,20 +20,21 @@
<application <application
android:name=".MyApplication" android:name=".MyApplication"
android:allowBackup="true" android:allowBackup="true"
android:appComponentFactory="androidx.core.app.CoreComponentFactory"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:theme="@style/Theme.AppCompat.Light.NoActionBar"
tools:replace="android:appComponentFactory" tools:replace="android:appComponentFactory">
android:appComponentFactory="androidx.core.app.CoreComponentFactory">
<meta-data <meta-data
android:name="com.amap.api.v2.apikey" android:name="com.amap.api.v2.apikey"
android:value="d78a6d571c700f3ad33f374d81fed6a2" /> android:value="d78a6d571c700f3ad33f374d81fed6a2" />
<activity android:name=".MainActivity" <activity
android:name=".MainActivity"
android:screenOrientation="portrait"> android:screenOrientation="portrait">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
...@@ -64,8 +65,13 @@ ...@@ -64,8 +65,13 @@
<activity android:name=".FragmentInteractiveActivity2" /> <activity android:name=".FragmentInteractiveActivity2" />
<activity android:name=".PageActivity" /> <activity android:name=".PageActivity" />
<activity android:name=".MyScanActivity" /> <activity android:name=".MyScanActivity" />
<activity android:name=".CutPicturesActivity" <activity android:name=".web.CallJavascriptActivity" />
android:screenOrientation="portrait"/> <activity android:name=".web.JavascriptCallNativeActivity" />
<activity android:name=".web.WrokWithFlyioTestActivity" />
<activity android:name=".web.MainActivity" />
<activity
android:name=".CutPicturesActivity"
android:screenOrientation="portrait" />
</application> </application>
<!-- 配置APP ID --> <!-- 配置APP ID -->
......
var bridge = {
default:this,// for typescript
call: function (method, args, cb) {
var ret = '';
if (typeof args == 'function') {
cb = args;
args = {};
}
var arg={data:args===undefined?null:args}
if (typeof cb == 'function') {
var cbName = 'dscb' + window.dscb++;
window[cbName] = cb;
arg['_dscbstub'] = cbName;
}
arg = JSON.stringify(arg)
//if in webview that dsBridge provided, call!
if(window._dsbridge){
ret= _dsbridge.call(method, arg)
}else if(window._dswk||navigator.userAgent.indexOf("_dsbridge")!=-1){
ret = prompt("_dsbridge=" + method, arg);
}
return JSON.parse(ret||'{}').data
},
register: function (name, fun, asyn) {
var q = asyn ? window._dsaf : window._dsf
if (!window._dsInit) {
window._dsInit = true;
//notify native that js apis register successfully on next event loop
setTimeout(function () {
bridge.call("_dsb.dsinit");
}, 0)
}
if (typeof fun == "object") {
q._obs[name] = fun;
} else {
q[name] = fun
}
},
registerAsyn: function (name, fun) {
this.register(name, fun, true);
},
hasNativeMethod: function (name, type) {
return this.call("_dsb.hasNativeMethod", {name: name, type:type||"all"});
},
disableJavascriptDialogBlock: function (disable) {
this.call("_dsb.disableJavascriptDialogBlock", {
disable: disable !== false
})
}
};
!function () {
if (window._dsf) return;
var ob = {
_dsf: {
_obs: {}
},
_dsaf: {
_obs: {}
},
dscb: 0,
dsBridge: bridge,
close: function () {
bridge.call("_dsb.closePage")
},
_handleMessageFromNative: function (info) {
var arg = JSON.parse(info.data);
var ret = {
id: info.callbackId,
complete: true
}
var f = this._dsf[info.method];
var af = this._dsaf[info.method]
var callSyn = function (f, ob) {
ret.data = f.apply(ob, arg)
bridge.call("_dsb.returnValue", ret)
}
var callAsyn = function (f, ob) {
arg.push(function (data, complete) {
ret.data = data;
ret.complete = complete!==false;
bridge.call("_dsb.returnValue", ret)
})
f.apply(ob, arg)
}
if (f) {
callSyn(f, this._dsf);
} else if (af) {
callAsyn(af, this._dsaf);
} else {
//with namespace
var name = info.method.split('.');
if (name.length<2) return;
var method=name.pop();
var namespace=name.join('.')
var obs = this._dsf._obs;
var ob = obs[namespace] || {};
var m = ob[method];
if (m && typeof m == "function") {
callSyn(m, ob);
return;
}
obs = this._dsaf._obs;
ob = obs[namespace] || {};
m = ob[method];
if (m && typeof m == "function") {
callAsyn(m, ob);
return;
}
}
}
}
for (var attr in ob) {
window[attr] = ob[attr]
}
bridge.register("_hasJavascriptMethod", function (method, tag) {
var name = method.split('.')
if(name.length<2) {
return !!(_dsf[name]||_dsaf[name])
}else{
// with namespace
var method=name.pop()
var namespace=name.join('.')
var ob=_dsf._obs[namespace]||_dsaf._obs[namespace]
return ob&&!!ob[method]
}
})
}();
module.exports = bridge;
\ No newline at end of file
<!DOCTYPE html>
<html>
<head lang="zh-cmn-Hans">
<meta charset="UTF-8">
<title></title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/>
<!--require dsbridge init js-->
<script src="https://cdn.jsdelivr.net/npm/dsbridge/dist/dsbridge.js"> </script>
<!--require flyio-->
<script src="https://cdn.jsdelivr.net/npm/flyio/dist/fly.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flyio/dist/engine-wrapper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dist/adapter/dsbridge.min.js"></script>
</head>
<style>
.btn {
text-align: center;
background: #eee;
color: #000;
padding: 10px;
margin: 20px;
font-size: 14px;
border-radius: 3px;
box-shadow: 4px 2px 10px #999;
}
.btn:active {
opacity: .7;
box-shadow: 4px 2px 10px #555;
}
#intro{
padding:16px;
}
</style>
<body>
<div id="intro">
<a href="https://github.com/wendux/fly">Fly.js </a> supports forwarding the http request (ajax) to Native through any Javascript bridge, And fly.js has already provide the dsBridge adapter. Because the Native side has no the same-origin policy restriction, fly.js can request any resource from any domain.
</div>
<div class="btn" id="fly-ajax">Get home page source code of baidu.com</div>
<div class="btn" id="git-cat">Show the logo of github </div>
<div style="text-align:center"><img id="img"></div>
<div class="btn" onclick="window.close()">Close window</div>
<script>
function addClick(id,onResult){
document.getElementById(id).addEventListener("click",onResult);
}
// fly will forward the ajax request to native by WebviewJavascriptBridge,
// the http request will be performed actually by native (onAjaxRequest).
//use by dsbridge adapter, reference on https://wendux.github.io/dist/#/doc/flyio-en/files
var engine = EngineWrapper(dsbAdapter)
fly.engine = engine;
addClick("fly-ajax",function(){
fly.get("https://www.baidu.com/").then(function(d){
alert(d.data)
})
})
addClick("git-cat",function(){
var img=document.getElementById("img")
var btn=document.getElementById("git-cat")
img.src="";
btn.innerText="loading..."
// request the image, reference on https://wendux.github.io/dist/#/doc/flyio-en/native
fly.get("https://assets-cdn.github.com/favicon.ico", null,{
responseType:"stream"
}).then(function (d) {
//data is encoded with base64
img.src=d.data;
btn.innerText="look!"
})
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="zh-cmn-Hans">
<meta charset="UTF-8">
<title>DSBridge Test</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no"/>
<!--require dsbridge init js-->
<script src="https://cdn.jsdelivr.net/npm/dsbridge/dist/dsbridge.js"></script>
</head>
<style>
.btn {
text-align: center;
background: #d8d8d8;
color: #222;
padding: 20px;
margin: 30px;
font-size: 24px;
border-radius: 4px;
box-shadow: 4px 2px 10px #999;
}
.btn:active {
opacity: .7;
box-shadow: 4px 2px 10px #555;
}
</style>
<body>
<div class="btn" onclick="callSyn()">Synchronous call</div>
<div class="btn" onclick="callAsyn()">Asynchronous call</div>
<div class="btn" onclick="callNoArgSyn()">Sync call without argument</div>
<div class="btn" onclick="callNoArgAsyn()">Async call without argument</div>
<div class="btn" onclick="echoSyn()">echo.syn</div>
<div class="btn" onclick="echoAsyn()">echo.asyn</div>
<div class="btn" onclick="callAsyn_()">Stress test,2K times consecutive asynchronous API calls</div>
<div class="btn" onclick="callNever()">Never call because without @JavascriptInterface
annotation<br/>( This test is
just for Android ,should be ignored in IOS )
</div>
<div class="btn" onclick="callProgress()">call progress <span id='progress'></span></div>
<div class="btn" onclick="hasNativeMethod('xx')">hasNativeMethod("xx")</div>
<div class="btn" onclick="hasNativeMethod('testSyn')">hasNativeMethod("testSyn")</div>
<script>
function callSyn() {
alert(dsBridge.call("testSyn","testSyn" ))
<!--dsBridge.call("goBrowser", "https://www.baidu.com")-->
<!--alert(dsBridge.call("getUserInfo",null ))-->
<!--alert(dsBridge.call("openDebug",null ))-->
<!--dsBridge.call("backPage",null )-->
<!--dsBridge.call("goCallPhone","{tel:18001874471}" )-->
<!--alert(dsBridge.call("clearCache",null ))-->
<!--dsBridge.call("sendSMS","{phone:18001874471,msg:短信内容}" )-->
<!--alert(dsBridge.call("goPage","{page:首页,parameter:{phone:18001874471,msg:短信内容}}" ))-->
}
function callAsyn() {
dsBridge.call("testAsyn","testAsyn", function (v) {
alert(v)
})
}
function callAsyn_() {
for (var i = 0; i < 2000; i++) {
dsBridge.call("testAsyn", "js+" + i, function (v) {
if (v == "js+1999 [ asyn call]") {
alert("All tasks completed!")
}
})
}
}
function callNoArgSyn() {
alert(dsBridge.call("testNoArgSyn"));
}
function callNoArgAsyn() {
dsBridge.call("testNoArgAsyn", function (v) {
alert(v)
});
}
function callNever() {
alert(dsBridge.call("testNever", {msg: "testSyn"}))
}
function echoSyn() {
// call function with namespace
var ret=dsBridge.call("echo.syn",{msg:" I am echoSyn call", tag:1});
alert(JSON.stringify(ret))
}
function echoAsyn() {
// call function with namespace
dsBridge.call("echo.asyn",{msg:" I am echoAsyn call",tag:2},function (ret) {
alert(JSON.stringify(ret));
})
}
function callProgress() {
dsBridge.call("callProgress", function (value) {
if(value==0) value="";
document.getElementById("progress").innerText = value
})
}
function hasNativeMethod(name) {
alert(dsBridge.hasNativeMethod(name))
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head lang="zh-cmn-Hans">
<meta charset="UTF-8">
<title>DSBridge Test</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=0.5,user-scalable=no"/>
<!--require dsbridge init js-->
<script src="https://cdn.jsdelivr.net/npm/dsbridge/dist/dsbridge.js"> </script>
</head>
<body>
<script>
dsBridge.register('addValue', function (r, l) {
return r + l;
})
dsBridge.registerAsyn('append', function (arg1, arg2, arg3, responseCallback) {
responseCallback(arg1 + " " + arg2 + " " + arg3);
})
dsBridge.registerAsyn('startTimer', function (responseCallback) {
var t = 0;
var timer = setInterval(function () {
if (t == 5) {
responseCallback(t)
clearInterval(timer)
} else {
// if the 2nd argument is false, the java callback handler will be not removed!
responseCallback(t++, false)
}
}, 1000)
})
// namespace test for syn functions
dsBridge.register("syn", {
tag: "syn",
addValue:function (r,l) {
return r+l;
},
getInfo: function () {
return {tag: this.tag, value:8}
}
})
// namespace test for asyn functions
dsBridge.registerAsyn("asyn", {
tag: "asyn",
addValue:function (r,l, responseCallback) {
responseCallback(r+l);
},
getInfo: function (responseCallback) {
responseCallback({tag: this.tag, value:8})
}
})
</script>
</body>
</html>
...@@ -10,6 +10,7 @@ import androidx.annotation.Nullable; ...@@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
import com.gc.call.CallConstant; import com.gc.call.CallConstant;
import com.gc.call.CallManage; import com.gc.call.CallManage;
import com.gc.call.CallParticipationBean; import com.gc.call.CallParticipationBean;
import com.mayi.demo.web.MainActivity;
import com.mayi.fastdevelop.base.BaseActivity; import com.mayi.fastdevelop.base.BaseActivity;
import com.mayi.fastdevelop.comnon.Key; import com.mayi.fastdevelop.comnon.Key;
import com.mayi.fastdevelop.comnon.RequestCode; import com.mayi.fastdevelop.comnon.RequestCode;
...@@ -22,12 +23,18 @@ public class PageActivity extends BaseActivity { ...@@ -22,12 +23,18 @@ public class PageActivity extends BaseActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page); setContentView(R.layout.activity_page);
findViewById(R.id.b0).setOnClickListener(new OnMultiClickListener() {
@Override
public void onMultiClick(View v) {
gotoActivity(MainActivity.class);
}
});
findViewById(R.id.b1).setOnClickListener(new OnMultiClickListener() { findViewById(R.id.b1).setOnClickListener(new OnMultiClickListener() {
@Override @Override
public void onMultiClick(View v) { public void onMultiClick(View v) {
CallParticipationBean bean = new CallParticipationBean("web_goWeb"); CallParticipationBean bean = new CallParticipationBean("web_goWeb");
bean.setContext(PageActivity.this); bean.setContext(PageActivity.this);
bean.addParameter("url", "https://customer.kujiatech.com/#/?token=8427db8972dd09105a00d62d8bc7cfd5&username=18001874470&v=" + System.currentTimeMillis()); bean.addParameter("url", "https://www.baidu.com");
CallManage.getInstance().handleTarget(bean); CallManage.getInstance().handleTarget(bean);
} }
}); });
...@@ -37,8 +44,7 @@ public class PageActivity extends BaseActivity { ...@@ -37,8 +44,7 @@ public class PageActivity extends BaseActivity {
CallParticipationBean bean = new CallParticipationBean("web_goWeb"); CallParticipationBean bean = new CallParticipationBean("web_goWeb");
bean.setContext(PageActivity.this); bean.setContext(PageActivity.this);
bean.setLooper(CallConstant.LOOPER_NO_MAIN_HANDLER_AND_MIAN_RETURN); bean.setLooper(CallConstant.LOOPER_NO_MAIN_HANDLER_AND_MIAN_RETURN);
bean.addParameter("url", "https://customer.kujiatech.com/#/?token=8427db8972dd09105a00d62d8bc7cfd5" + bean.addParameter("url", "https://www.baidu.com/?isNeedBackButton=true&userAppTitle=潜客");
"&username=18001874470&v=" + System.currentTimeMillis() + "&isNeedBackButton=true&userAppTitle=潜客");
CallManage.getInstance().handleTarget(bean); CallManage.getInstance().handleTarget(bean);
} }
}); });
......
package com.mayi.demo.web;
import android.util.Base64;
import com.mayi.fastdevelop.web.CompletionHandler;
import org.json.JSONObject;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Created by du on 2017/10/31.
*
* This class handles the Ajax requests forwarded by fly.js in DWebView
* More about fly.js see https://github.com/wendux/fly
*/
public class AjaxHandler {
public static void onAjaxRequest(final JSONObject requestData, final CompletionHandler handler){
// Define response structure
final Map<String, Object> responseData=new HashMap<>();
responseData.put("statusCode",0);
try {
int timeout =requestData.getInt("timeout");
// Create a okhttp instance and set timeout
final OkHttpClient okHttpClient = new OkHttpClient
.Builder()
.connectTimeout(timeout, TimeUnit.MILLISECONDS)
.build();
// Determine whether you need to encode the response result.
// And encode when responseType is stream.
String contentType="";
boolean encode=false;
String responseType=requestData.optString("responseType",null);
if(responseType!=null&&responseType.equals("stream")){
encode=true;
}
Request.Builder rb= new Request.Builder();
rb.url(requestData.getString("url"));
JSONObject headers=requestData.getJSONObject("headers");
// Set request headers
Iterator iterator = headers.keys();
while(iterator.hasNext()){
String key = (String) iterator.next();
String value = headers.getString(key);
String lKey=key.toLowerCase();
if(lKey.equals("cookie")){
// Here you can use CookieJar to manage cookie in a unified way with you native code.
continue;
}
if(lKey.toLowerCase().equals("content-type")){
contentType=value;
}
rb.header(key,value);
}
// Create request body
if(requestData.getString("method").equals("POST")){
RequestBody requestBody= RequestBody
.create(MediaType.parse(contentType),requestData.getString("data"));
rb.post(requestBody) ;
}
// Create and send HTTP requests
Call call=okHttpClient.newCall(rb.build());
final boolean finalEncode = encode;
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
responseData.put("responseText",e.getMessage());
handler.complete(new JSONObject(responseData).toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String data;
// If encoding is needed, the result is encoded by Base64 and returned
if(finalEncode){
data= Base64.encodeToString(response.body().bytes(), Base64.DEFAULT);
}else{
data=response.body().string();
}
responseData.put("responseText",data);
responseData.put("statusCode",response.code());
responseData.put("statusMessage",response.message());
Map<String, List<String>> responseHeaders= response.headers().toMultimap();
responseHeaders.remove(null);
responseData.put("headers",responseHeaders);
handler.complete(new JSONObject(responseData).toString());
}
});
}catch (Exception e){
responseData.put("responseText",e.getMessage());
handler.complete(new JSONObject(responseData).toString());
}
}
}
package com.mayi.demo.web;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.mayi.demo.R;
import com.mayi.fastdevelop.web.DWebView;
import com.mayi.fastdevelop.web.OnReturnValue;
import org.json.JSONObject;
public class CallJavascriptActivity extends AppCompatActivity implements View.OnClickListener {
DWebView dWebView;
public <T extends View> T getView(int viewId) {
View view = findViewById(viewId);
return (T) view;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call_javascript);
getView(R.id.addValue).setOnClickListener(this);
getView(R.id.append).setOnClickListener(this);
getView(R.id.startTimer).setOnClickListener(this);
getView(R.id.synAddValue).setOnClickListener(this);
getView(R.id.synGetInfo).setOnClickListener(this);
getView(R.id.asynAddValue).setOnClickListener(this);
getView(R.id.asynGetInfo).setOnClickListener(this);
getView(R.id.hasMethodAddValue).setOnClickListener(this);
getView(R.id.hasMethodXX).setOnClickListener(this);
getView(R.id.hasMethodAsynAddValue).setOnClickListener(this);
getView(R.id.hasMethodAsynXX).setOnClickListener(this);
DWebView.setWebContentsDebuggingEnabled(true);
dWebView= findViewById(R.id.wv);
dWebView.loadUrl("file:///android_asset/native-call-js.html");
}
void showToast(Object o) {
Toast.makeText(this, o.toString(), Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.addValue:
dWebView.callHandler("addValue", new Object[]{3, 4}, new OnReturnValue<Integer>() {
@Override
public void onValue(Integer retValue) {
showToast(retValue);
}
});
break;
case R.id.append:
dWebView.callHandler("append", new Object[]{"I", "love", "you"}, new OnReturnValue<String>() {
@Override
public void onValue(String retValue) {
showToast(retValue);
}
});
break;
case R.id.startTimer:
dWebView.callHandler("startTimer", new OnReturnValue<Integer>() {
@Override
public void onValue(Integer retValue) {
showToast(retValue);
}
});
break;
case R.id.synAddValue:
dWebView.callHandler("syn.addValue", new Object[]{5, 6}, new OnReturnValue<Integer>() {
@Override
public void onValue(Integer retValue) {
showToast(retValue);
}
});
break;
case R.id.synGetInfo:
dWebView.callHandler("syn.getInfo", new OnReturnValue<JSONObject>() {
@Override
public void onValue(JSONObject retValue) {
showToast(retValue);
}
});
break;
case R.id.asynAddValue:
dWebView.callHandler("asyn.addValue", new Object[]{5, 6}, new OnReturnValue<Integer>() {
@Override
public void onValue(Integer retValue) {
showToast(retValue);
}
});
break;
case R.id.asynGetInfo:
dWebView.callHandler("asyn.getInfo", new OnReturnValue<JSONObject>() {
@Override
public void onValue(JSONObject retValue) {
showToast(retValue);
}
});
break;
case R.id.hasMethodAddValue:
dWebView.hasJavascriptMethod("addValue", new OnReturnValue<Boolean>() {
@Override
public void onValue(Boolean retValue) {
showToast(retValue);
}
});
break;
case R.id.hasMethodXX:
dWebView.hasJavascriptMethod("XX", new OnReturnValue<Boolean>() {
@Override
public void onValue(Boolean retValue) {
showToast(retValue);
}
});
break;
case R.id.hasMethodAsynAddValue:
dWebView.hasJavascriptMethod("asyn.addValue", new OnReturnValue<Boolean>() {
@Override
public void onValue(Boolean retValue) {
showToast(retValue);
}
});
break;
case R.id.hasMethodAsynXX:
dWebView.hasJavascriptMethod("asyn.XX", new OnReturnValue<Boolean>() {
@Override
public void onValue(Boolean retValue) {
showToast(retValue);
}
});
break;
}
}
}
package com.mayi.demo.web;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.mayi.demo.R;
import com.mayi.fastdevelop.web.DWebView;
import com.mayi.fastdevelop.web.JsCallAppApi;
public class JavascriptCallNativeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_js_call_native);
final DWebView dwebView= findViewById(R.id.webview);
// set debug mode
DWebView.setWebContentsDebuggingEnabled(true);
dwebView.addJavascriptObject(new JsApi(), null);
dwebView.addJavascriptObject(new JsEchoApi(),"echo");
dwebView.loadUrl("file:///android_asset/js-call-native.html");
}
}
package com.mayi.demo.web;
import android.os.CountDownTimer;
import android.webkit.JavascriptInterface;
import com.mayi.fastdevelop.web.CompletionHandler;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by du on 16/12/31.
*/
public class JsApi{
@JavascriptInterface
public String testSyn(Object msg) {
return msg + "[syn call]";
}
@JavascriptInterface
public void testAsyn(Object msg, CompletionHandler<String> handler){
handler.complete(msg+" [ asyn call]");
}
@JavascriptInterface
public String testNoArgSyn(Object arg) throws JSONException {
return "testNoArgSyn called [ syn call]";
}
@JavascriptInterface
public void testNoArgAsyn(Object arg, CompletionHandler<String> handler) {
handler.complete( "testNoArgAsyn called [ asyn call]");
}
//@JavascriptInterface
//without @JavascriptInterface annotation can't be called
public String testNever(Object arg) throws JSONException {
JSONObject jsonObject= (JSONObject) arg;
return jsonObject.getString("msg") + "[ never call]";
}
@JavascriptInterface
public void callProgress(Object args, final CompletionHandler<Integer> handler) {
new CountDownTimer(11000, 1000) {
int i=10;
@Override
public void onTick(long millisUntilFinished) {
//setProgressData can be called many times util complete be called.
handler.setProgressData((i--));
}
@Override
public void onFinish() {
//complete the js invocation with data; handler will be invalid when complete is called
handler.complete(0);
}
}.start();
}
}
\ No newline at end of file
package com.mayi.demo.web;
import android.webkit.JavascriptInterface;
import com.mayi.fastdevelop.web.CompletionHandler;
import org.json.JSONException;
/**
* Created by du on 16/12/31.
*/
public class JsEchoApi {
@JavascriptInterface
public Object syn(Object args) throws JSONException {
return args;
}
@JavascriptInterface
public void asyn(Object args, CompletionHandler handler){
handler.complete(args);
}
}
\ No newline at end of file
package com.mayi.demo.web;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import com.mayi.demo.R;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_main);
findViewById(R.id.callJs).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,CallJavascriptActivity.class));
}
});
findViewById(R.id.callNative).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,JavascriptCallNativeActivity.class));
}
});
findViewById(R.id.fly).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,WrokWithFlyioTestActivity.class));
}
});
}
}
package com.mayi.demo.web;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.CookieManager;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
/**
* Created by du on 2017/9/16.
*/
public class NetUtils {
public static CookieManager cookieManager=new CookieManager();
public static Map<String, Object> request(String method, String url, String param, JSONObject headers) throws Exception {
URL uri = new URL(url);
method = method.toUpperCase();
HttpURLConnection urlCon = (HttpURLConnection) uri.openConnection();
urlCon.setRequestMethod(method);
urlCon.setConnectTimeout(10000);
handleRequestHeaders(urlCon,headers);
if (urlCon instanceof HttpsURLConnection) {
addCertVerifier((HttpsURLConnection) urlCon);
}
if (method.equals("POST")) {
urlCon.setDoOutput(true);
urlCon.setDoInput(true);
if (!param.trim().isEmpty()) {
PrintWriter pw = new PrintWriter(urlCon.getOutputStream());
pw.print(param);
pw.flush();
pw.close();
}
}
Map<String, Object> response=new HashMap<>();
response.put("responseText",inputStream2String(urlCon.getInputStream()));
response.put("statusCode",urlCon.getResponseCode());
Map<String, List<String>> responseHeaders= new HashMap<>(urlCon.getHeaderFields());
responseHeaders.remove(null);
responseHeaders=handleResponseHeaders(urlCon,responseHeaders);
response.put("headers",responseHeaders);
return response;
}
//对于https请求,进行证书校验
private static void addCertVerifier(HttpsURLConnection urlCon) throws Exception {
// 在此做证书校验
// urlCon.setSSLSocketFactory(getSSLSocketFactory());
urlCon.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
//return "api.dtworkroom.com".equals(hostname);
HostnameVerifier hv= HttpsURLConnection.getDefaultHostnameVerifier();
return hv.verify("*.dtworkroom.com",session);
}
});
}
//预处理请求头
private static void handleRequestHeaders(HttpURLConnection connection, JSONObject headers) throws Exception {
Iterator iterator = headers.keys();
while(iterator.hasNext()){
String key = (String) iterator.next();
String value = headers.getString(key);
if(!key.toLowerCase().equals("cookie")){
//请求cookie
connection.setRequestProperty(key, value);
}
}
List<HttpCookie> cookies= cookieManager.getCookieStore().get(connection.getURL().toURI());
cookies.toString();
}
private static Map<String, List<String>> handleResponseHeaders(HttpURLConnection connection, Map<String, List<String>> responseHeaders) throws Exception {
//获取响应头中的cookies,端上统一管理cookie
cookieManager.put(connection.getURL().toURI(),responseHeaders);
responseHeaders.remove("set-cookie");
return responseHeaders;
}
private static String inputStream2String(InputStream is) {
String result = "";
String line;
InputStreamReader inputReader = new InputStreamReader(is);
BufferedReader bufReader = new BufferedReader(inputReader);
try {
while ((line = bufReader.readLine()) != null)
result += line + "\r\n";
bufReader.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
package com.mayi.demo.web;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import androidx.appcompat.app.AppCompatActivity;
import com.mayi.demo.R;
import com.mayi.fastdevelop.web.CompletionHandler;
import com.mayi.fastdevelop.web.DWebView;
import org.json.JSONObject;
public class WrokWithFlyioTestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wrok_with_flyio_test);
DWebView dWebView = findViewById(R.id.webview);
dWebView.addJavascriptObject(new Object() {
/**
* Note: This method is for Fly.js
* In browser, Ajax requests are sent by browser, but Fly can
* redirect requests to native, more about Fly see https://github.com/wendux/fly
* @param requestData passed by fly.js, more detail reference https://wendux.github.io/dist/#/doc/flyio-en/native
* @param handler
*/
@JavascriptInterface
public void onAjaxRequest(Object requestData, CompletionHandler handler) {
// Handle ajax request redirected by Fly
AjaxHandler.onAjaxRequest((JSONObject) requestData, handler);
}
}, null);
dWebView.loadUrl("file:///android_asset/fly.html");
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.mayi.demo.web.JavascriptCallNativeActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<Button
android:id="@+id/addValue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="addValue(3,4)"
android:textAllCaps="false" />
<Button
android:id="@+id/append"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="append('I','love','you')"
android:textAllCaps="false" />
<Button
android:id="@+id/startTimer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="startTimer()"
android:textAllCaps="false" />
<Button
android:id="@+id/synAddValue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="syn.addValue(5,6)"
android:textAllCaps="false" />
<Button
android:id="@+id/synGetInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="syn.getInfo()"
android:textAllCaps="false" />
<Button
android:id="@+id/asynAddValue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="asyn.addValue(5,6)"
android:textAllCaps="false" />
<Button
android:id="@+id/asynGetInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="asyn.getInfo()"
android:textAllCaps="false" />
<Button
android:id="@+id/hasMethodAddValue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="hasJavascriptMethod('addValue')"
android:textAllCaps="false" />
<Button
android:id="@+id/hasMethodXX"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="hasJavascriptMethod('XX')"
android:textAllCaps="false" />
<Button
android:id="@+id/hasMethodAsynAddValue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="hasJavascriptMethod('asyn.addValue')"
android:textAllCaps="false" />
<Button
android:id="@+id/hasMethodAsynXX"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="hasJavascriptMethod('asyn.XX')"
android:textAllCaps="false" />
<com.mayi.fastdevelop.web.DWebView
android:id="@+id/wv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</LinearLayout>
</ScrollView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mayi.fastdevelop.web.DWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
...@@ -8,6 +8,13 @@ ...@@ -8,6 +8,13 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<Button
android:id="@+id/b0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="JS Bridge" />
<Button <Button
android:id="@+id/b1" android:id="@+id/b1"
android:layout_width="wrap_content" android:layout_width="wrap_content"
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="18dp"
android:text="Because unpkg.com's CDN has a slower access speed in China, it's normal to open the test page slowly sometimes, it's not a problem for DSBridge." />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="18dp"
android:paddingRight="18dp"
android:paddingBottom="18dp"
android:text="由于测试页面(h5)中是通过unpkg的CDN引入的dsbridge.js,但unpkg在中国地区访问速度会比较慢,所以当您发现有时打开测试页面比较慢时是正常的,这并不是DSBridge的问题,所以建议您在使用时将dsbridge.js下载并集成到您的工程。" />
<Button
android:id="@+id/callJs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Native call Javascript"
android:textAllCaps="false" />
<Button
android:id="@+id/callNative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Javascript call Native"
android:textAllCaps="false" />
<Button
android:id="@+id/fly"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Work with fly.js test"
android:textAllCaps="false" />
</LinearLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mayi.fastdevelop.web.DWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
\ No newline at end of file
...@@ -47,4 +47,6 @@ dependencies { ...@@ -47,4 +47,6 @@ dependencies {
// api project(':call') // api project(':call')
api 'com.gc:call:1.0.0' api 'com.gc:call:1.0.0'
api 'com.google.android.exoplayer:exoplayer:2.10.5' api 'com.google.android.exoplayer:exoplayer:2.10.5'
api 'com.tencent:mmkv:1.0.23'
} }
\ No newline at end of file
...@@ -28,6 +28,7 @@ import com.scwang.smartrefresh.layout.constant.SpinnerStyle; ...@@ -28,6 +28,7 @@ import com.scwang.smartrefresh.layout.constant.SpinnerStyle;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter; import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader; import com.scwang.smartrefresh.layout.header.ClassicsHeader;
import com.tencent.bugly.crashreport.CrashReport; import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.mmkv.MMKV;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
...@@ -47,6 +48,7 @@ public abstract class BaseApplication extends Application { ...@@ -47,6 +48,7 @@ public abstract class BaseApplication extends Application {
registerActivityListener(); registerActivityListener();
initLog(); initLog();
initSmartRefreshLayout(); initSmartRefreshLayout();
MMKV.initialize(this);
} }
private void initSmartRefreshLayout() { private void initSmartRefreshLayout() {
......
package com.mayi.fastdevelop.util; package com.mayi.fastdevelop.util;
import com.tencent.mmkv.MMKV;
import android.content.Context;
import android.content.SharedPreferences;
import com.mayi.fastdevelop.base.BaseApplication;
/** /**
...@@ -13,14 +9,13 @@ import com.mayi.fastdevelop.base.BaseApplication; ...@@ -13,14 +9,13 @@ import com.mayi.fastdevelop.base.BaseApplication;
public class SpUtil { public class SpUtil {
private static SharedPreferences sp; private static MMKV mmkv;
public static synchronized SharedPreferences getSp() { public static synchronized MMKV getSp() {
if (sp == null) { if (mmkv == null) {
Context context = BaseApplication.getInstance().getChildApplication(); mmkv = MMKV.defaultMMKV();
sp = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
} }
return sp; return mmkv;
} }
/** /**
......
...@@ -19,7 +19,7 @@ android { ...@@ -19,7 +19,7 @@ android {
} }
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) api fileTree(dir: 'libs', include: ['*.jar'])
api project(':fastDevelop') api project(':fastDevelop')
implementation files('libs/tbs_sdk_thirdapp_v3.6.0.1371_43624_sharewithdownload_withoutGame_obfs_20181106_121046.jar')//腾讯X5浏览器 api files('libs/tbs_sdk_thirdapp_v3.6.0.1371_43624_sharewithdownload_withoutGame_obfs_20181106_121046.jar')//腾讯X5浏览器
} }
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mayi.fastdevelop.web"> package="com.mayi.fastdevelop.web">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application> <application>
<activity android:name=".BaseWebActivity" /> <activity android:name=".BaseWebActivity" />
</application> </application>
......
...@@ -12,14 +12,12 @@ import android.os.AsyncTask; ...@@ -12,14 +12,12 @@ import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewParent; import android.view.ViewParent;
import android.webkit.JavascriptInterface;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
...@@ -31,16 +29,13 @@ import com.mayi.fastdevelop.comnon.RequestCode; ...@@ -31,16 +29,13 @@ import com.mayi.fastdevelop.comnon.RequestCode;
import com.mayi.fastdevelop.util.BitmapUtil; import com.mayi.fastdevelop.util.BitmapUtil;
import com.mayi.fastdevelop.util.DialogUtils; import com.mayi.fastdevelop.util.DialogUtils;
import com.mayi.fastdevelop.util.LogUtils; import com.mayi.fastdevelop.util.LogUtils;
import com.mayi.fastdevelop.util.SpUtil;
import com.mayi.fastdevelop.util.SystemUtil; import com.mayi.fastdevelop.util.SystemUtil;
import com.mayi.fastdevelop.view.CustomTitleBar; import com.mayi.fastdevelop.view.CustomTitleBar;
import com.mayi.fastdevelop.view.dialog.BaseDialog; import com.mayi.fastdevelop.view.dialog.BaseDialog;
import com.tencent.bugly.crashreport.CrashReport; import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.smtt.export.external.interfaces.GeolocationPermissionsCallback;
import com.tencent.smtt.export.external.interfaces.WebResourceError; import com.tencent.smtt.export.external.interfaces.WebResourceError;
import com.tencent.smtt.export.external.interfaces.WebResourceRequest; import com.tencent.smtt.export.external.interfaces.WebResourceRequest;
import com.tencent.smtt.sdk.ValueCallback; import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebSettings; import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView; import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient; import com.tencent.smtt.sdk.WebViewClient;
...@@ -56,22 +51,16 @@ import java.net.URLDecoder; ...@@ -56,22 +51,16 @@ import java.net.URLDecoder;
* web基本页面 * web基本页面
* 支持JS和Android相互调用 * 支持JS和Android相互调用
* 监听JS报错,上传bugly * 监听JS报错,上传bugly
* 支持清除缓存,拍照,相册,定位,打电话,返回上一页,跳转原生页面(待扩展), * 支持清除缓存,拍照,相册,定位,打电话,返回上一页,跳转原生页面(待扩展)(拍照,相册未放开)
* 开启Debug模式,给web传递用户信息,发送短信 * 开启Debug模式,给web传递用户信息,发送短信
*/ */
public class BaseWebActivity extends BaseActivity { public class BaseWebActivity extends BaseActivity {
private WebView webView; private DWebView webView;
private CustomTitleBar title; private CustomTitleBar title;
private Handler handler;
private ValueCallback<Uri> uploadMessage; private ValueCallback<Uri> uploadMessage;
private ValueCallback<Uri[]> uploadMessageAboveL; private ValueCallback<Uri[]> uploadMessageAboveL;
private String mCurrentPhotoPath; private String mCurrentPhotoPath;
private WebListener webListener;
public void setWebListener(WebListener webListener) {
this.webListener = webListener;
}
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
...@@ -85,35 +74,18 @@ public class BaseWebActivity extends BaseActivity { ...@@ -85,35 +74,18 @@ public class BaseWebActivity extends BaseActivity {
webPageBack(); webPageBack();
} }
}); });
handler = new Handler();
initWebView(); initWebView();
webView.setWebChromeClient(new WebChromeClient() { // webView.setWebChromeClient(new WebChromeClient() {
//
@Override // //For Android >= 5.0
public void onReceivedIcon(WebView view, Bitmap icon) { // @Override
super.onReceivedIcon(view, icon); // public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
} // uploadMessageAboveL = filePathCallback;
// uploadPicture();
@Override // return true;
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissionsCallback geolocationPermissionsCallback) { // }
geolocationPermissionsCallback.invoke(origin, true, false); //
super.onGeolocationPermissionsShowPrompt(origin, geolocationPermissionsCallback); // });
}
//For Android >= 5.0
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
uploadMessageAboveL = filePathCallback;
uploadPicture();
return true;
}
//For Android >= 4.1
public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
uploadMessage = valueCallback;
uploadPicture();
}
});
webView.setWebViewClient(new WebViewClient() { webView.setWebViewClient(new WebViewClient() {
@Override @Override
...@@ -132,6 +104,7 @@ public class BaseWebActivity extends BaseActivity { ...@@ -132,6 +104,7 @@ public class BaseWebActivity extends BaseActivity {
LogUtils.i(thr.getMessage()); LogUtils.i(thr.getMessage());
} }
}); });
webView.addJavascriptObject(new JsCallAppApi(webView), null);
initView(); initView();
} }
...@@ -252,95 +225,6 @@ public class BaseWebActivity extends BaseActivity { ...@@ -252,95 +225,6 @@ public class BaseWebActivity extends BaseActivity {
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
} }
//app调用web方法
public void appCallJs(final String method, final String data) {
handler.post(new Runnable() {
@Override
public void run() {
webView.loadUrl("javascript:appCallJs(" + method + "," + data + ")");
}
});
}
@JavascriptInterface
public void invoking(final String method, final String data) {
handler.post(new Runnable() {
@Override
public void run() {
if (TextUtils.equals("clearCache", method)) {//清除缓存
webView.clearCache(true);
webView.clearHistory();
webView.clearFormData();
} else if (TextUtils.equals("goCallPhone", method)) {//去打电话
try {
JSONObject jsonObject=new JSONObject(data);
SystemUtil.makePhoneCall(BaseWebActivity.this, jsonObject.optString("tel"));
} catch (JSONException e) {
e.printStackTrace();
}
} else if (TextUtils.equals("backPage", method)) {//返回上一页
webPageBack();
} else if (TextUtils.equals("goPage", method)) {//跳转原生页面
goPage(data);
} else if (TextUtils.equals("openDebug", method)) {//开启Debug模式
WebView.setWebContentsDebuggingEnabled(true);
} else if (TextUtils.equals("goBrowser", method)) {//跳转浏览器
SystemUtil.gotoWeb(BaseWebActivity.this, data);
} else if (TextUtils.equals("getUserInfo", method)) {//给web传递用户信息
appCallJs("setUserInfo", SpUtil.get(Key.USER_INFO, ""));
} else if (TextUtils.equals("sendSMS", method)) {//发送短信
sendSMS(data);
}
// else if (TextUtils.equals("location", method)) {//定位
// LocationUtils.startLocation(BaseWebActivity.this, new LocationUtils.LocationCallback() {
// @Override
// public void onFail(String msg) {
// appCallJs("LocationFail", msg);
// }
//
// @Override
// public void onSuccess(LocationBean bean) {
// appCallJs("LocationSuccess", JSON.toJSONString(bean));
// }
// });
// }
}
});
}
private void sendSMS(String data) {
try {
JSONObject jsonObject = new JSONObject(data);
SystemUtil.sendSMS(BaseWebActivity.this, jsonObject.optString("phone")
, jsonObject.optString("msg"));
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 跳转原生页面
* 待扩展
*/
public void goPage(String data) {
String pageName = null, parameter = null;
try {
JSONObject jsonObject = new JSONObject(data);
pageName = jsonObject.optString("page");
parameter = jsonObject.optString("parameter");
} catch (JSONException e) {
e.printStackTrace();
}
// if (TextUtils.equals(pageName, "MapLocation")) {//地图定位页面
// Intent intent = new Intent(this, MapLocationActivity.class);
// startActivityForResult(intent, RequestCode.MAP_LOCATION_ACTIVITY_RESULTCODE);
// } else {
if (webListener != null) {
webListener.goPageListener(pageName, parameter);
}
// }
}
private void initWebView() { private void initWebView() {
WebSettings settings = webView.getSettings(); WebSettings settings = webView.getSettings();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
...@@ -377,7 +261,6 @@ public class BaseWebActivity extends BaseActivity { ...@@ -377,7 +261,6 @@ public class BaseWebActivity extends BaseActivity {
settings.setGeolocationEnabled(true); //启用地理定位 settings.setGeolocationEnabled(true); //启用地理定位
settings.setGeolocationDatabasePath(dir); //设置定位的数据库路径 settings.setGeolocationDatabasePath(dir); //设置定位的数据库路径
settings.setDomStorageEnabled(true); //最重要的方法,一定要设置,这就是出不来的主要原因 settings.setDomStorageEnabled(true); //最重要的方法,一定要设置,这就是出不来的主要原因
webView.addJavascriptInterface(this, "jsCallApp");
} }
private void uploadImage(Uri imageUri) { private void uploadImage(Uri imageUri) {
......
package com.mayi.fastdevelop.web;
public interface CompletionHandler<T> {
void complete(T retValue);
void complete();
void setProgressData(T value);
}
package com.mayi.fastdevelop.web;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.webkit.JavascriptInterface;
import com.mayi.fastdevelop.comnon.Key;
import com.mayi.fastdevelop.util.SpUtil;
import com.mayi.fastdevelop.util.SystemUtil;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.ref.WeakReference;
public class JsCallAppApi {
private WeakReference<DWebView> weakReference;
private Handler handler = new Handler(Looper.getMainLooper());
public JsCallAppApi(DWebView dWebView) {
weakReference = new WeakReference<>(dWebView);
}
@JavascriptInterface
public String goBrowser(Object data) {//跳转浏览器
DWebView webView = weakReference.get();
if (webView != null) {
SystemUtil.gotoWeb(webView.getContext(), data.toString());
}
return "";
}
@JavascriptInterface
public String getUserInfo(Object data) {//给web传递用户信息
return SpUtil.get(Key.USER_INFO, "");
}
@JavascriptInterface
public String openDebug(Object data) {//开启Debug模式
DWebView.setWebContentsDebuggingEnabled(true);
return "开启Debug模式";
}
@JavascriptInterface
public String backPage(Object data) {//返回上一页
handler.post(new Runnable() {
@Override
public void run() {
DWebView webView = weakReference.get();
if (webView != null) {
if (webView.canGoBack()) {
webView.goBack();
} else {
if (webView.getContext() instanceof Activity) {
((Activity) webView.getContext()).finish();
}
}
}
}
});
return "返回上一页";
}
@JavascriptInterface
public String goCallPhone(Object data) {//去打电话
DWebView webView = weakReference.get();
if (webView != null) {
try {
JSONObject jsonObject = new JSONObject(data.toString());
SystemUtil.makePhoneCall(webView.getContext(), jsonObject.optString("tel"));
} catch (JSONException e) {
e.printStackTrace();
}
}
return "";
}
@JavascriptInterface
public String clearCache(Object data) {//清除缓存
handler.post(new Runnable() {
@Override
public void run() {
DWebView webView = weakReference.get();
if (webView != null) {
webView.clearCache(true);
webView.clearHistory();
webView.clearFormData();
}
}
});
return "清除缓存";
}
@JavascriptInterface
public String sendSMS(Object data) {//发送短信
DWebView webView = weakReference.get();
if (webView != null) {
try {
JSONObject jsonObject = new JSONObject(data.toString());
SystemUtil.sendSMS(webView.getContext(), jsonObject.optString("phone")
, jsonObject.optString("msg"));
} catch (JSONException e) {
e.printStackTrace();
}
}
return "";
}
/**
* 跳转原生页面
* 待扩展
*/
@JavascriptInterface
public String goPage(Object data) {
String pageName = null, parameter = null;
try {
JSONObject jsonObject = new JSONObject(data.toString());
pageName = jsonObject.optString("page");
parameter = jsonObject.optString("parameter");
} catch (JSONException e) {
e.printStackTrace();
}
// if (TextUtils.equals(pageName, "MapLocation")) {//地图定位页面
// Intent intent = new Intent(this, MapLocationActivity.class);
// startActivityForResult(intent, RequestCode.MAP_LOCATION_ACTIVITY_RESULTCODE);
// } else {
// if (webListener != null) {
// webListener.goPageListener(pageName, parameter);
// }
// }
return "跳转原生页面" + data.toString();
}
}
package com.mayi.fastdevelop.web; package com.mayi.fastdevelop.web;
public interface WebListener { public interface OnReturnValue<T> {
void onValue(T retValue);
public void goPageListener(String page,String parameter);//web跳转原生页面
} }
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/size_50" /> android:layout_height="@dimen/size_50" />
<com.tencent.smtt.sdk.WebView <com.mayi.fastdevelop.web.DWebView
android:id="@+id/webview" android:id="@+id/webview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment