logo.png
PrimWeb 是一个代理的WebView基于的 Android WebView 和 腾讯 x5 WebView,容易、灵活使用以及功能非常强大的库,提供了 WebView 一系列的问题解决方案 ,并且轻量和灵活, 更方便 webview 的切换.
Activity调用PrimWeb | Fragment调用PrimWeb | 识别电话短信邮箱 |
---|---|---|
activity.gif | fragment.gif | sms.gif |
JS通信 | 文件上传 | 自定义错误页面 |
---|---|---|
js.gif | input.gif | error.gif |
PrimWeb.with(getActivity())
.setWebParent(webParent, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
.useDefaultUI()
.useDefaultTopIndicator()
.setWebViewType(PrimWeb.WebViewType.X5)
.setListenerCheckJsFunction(this)
.buildWeb()
.lastGo()
.launch(mParam1);
.setWebParent(frameLayout, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
内存泄漏不用担心,已经在内部处理了
@Override
public void destroy() {
removeAllViewsInLayout();
ViewParent parent = getParent();
if (parent instanceof ViewGroup) {//从父容器中移除webview
((ViewGroup) parent).removeAllViewsInLayout();
}
releaseConfigCallback();
super.destroy();
}
如果要是用x5的webview需要在application中调用此方法 PrimWeb.init(this); 初始化x5
//使用库中X5的webview
.setWebViewType(PrimWeb.WebViewType.X5)
//使用库中Android的webview
.setWebViewType(PrimWeb.WebViewType.Android)
public enum WebViewType {
Android, X5
}
primWeb.getJsInterface().addJavaObject(new MyJavaObject(),"jsAgent")
/** 注入js脚本 */
public class MyJavaObject {
@JavascriptInterface
public void login(String data) {
}
}
primWeb.getCallJsLoader().callJS("jsMethod");
primWeb.getCallJsLoader().callJS("callByAndroidParam", 1234);
primWeb.getCallJsLoader().callJs("callByAndroidMoreParams", agentValueCallback, getJson(), "prim", true);
//可传多个参数,可使用高级的API
@RequiresApi(Build.VERSION_CODES.KITKAT)
void callJs(String method, AgentValueCallback<String> callback, String... params);
@RequiresApi(Build.VERSION_CODES.KITKAT)
void callJs(String method, AgentValueCallback<String> callback);
void callJS(String method, String... params);
void callJS(String method);
.setAgentWebSetting(new X5DefaultWebSetting(this))
public class X5DefaultWebSetting extends BaseAgentWebSetting<WebSettings> {
private Context context;
private static final String APP_CACAHE_DIRNAME = "/webcache";
public X5DefaultWebSetting(Context context) {
this.context = context;
}
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void toSetting(WebSettings webSetting) {
webSetting.setJavaScriptEnabled(true);
webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// 通过 file url 加载的 Javascript 读取其他的本地文件 .建议关闭
webSetting.setAllowFileAccessFromFileURLs(false);
// 允许通过 file url 加载的 Javascript 可以访问其他的源,包括其他的文件和 http,https 等其他的源
webSetting.setAllowUniversalAccessFromFileURLs(false);
}
}
......
}
.setAgentWebViewClient(agentWebViewClient)
AgentWebViewClient agentWebViewClient = new AgentWebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(IAgentWebView view, String url) {
Log.e(TAG, "shouldOverrideUrlLoading: " + url);
return super.shouldOverrideUrlLoading(view, url);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean shouldOverrideUrlLoading(IAgentWebView view, WebResourceRequest request) {
Log.e(TAG, "shouldOverrideUrlLoading: WebResourceRequest --> " + request.getUrl());
return super.shouldOverrideUrlLoading(view, request);
}
};
.setAgentWebChromeClient(agentChromeClient)
AgentChromeClient agentChromeClient = new AgentChromeClient() {
@Override
public void onReceivedTitle(View webView, String s) {
super.onReceivedTitle(webView, s);
if (actionBar != null) {
actionBar.setTitle(s);
}
}
};
.alwaysOpenOtherPage(true)
关闭进度指示器:
.colseTopIndicator()
设置默认的进度指示器:
.useDefaultTopIndicator()
如果想改变指示器的颜色可以调用如下:
.useDefaultTopIndicator(@ColorInt int color)
.useDefaultTopIndicator(@NonNull String color)
如果想改变指示器的高可以调用如下:
.useDefaultTopIndicator(@ColorInt int color, int height)
如果想自定义指示器可以调用如下:主要需要继承BaseIndicatorView
.useCustomTopIndicator(@NonNull BaseIndicatorView indicatorView)
设置默认的UI
.useDefaultUI()
可以设置布局的layout和点击的id
.useCustomUI(@LayoutRes int errorLayout, @IdRes int errorClickId)
可以设置为一个view
.useCustomUI(@NonNull View errorView)
primWeb.getUrlLoader().loadUrl();
primWeb.getUrlLoader().reload();
primWeb.getUrlLoader().stopLoading();
@Override
protected void onResume() {
super.onResume();
primWeb.webLifeCycle().onResume();
}
@Override
protected void onPause() {
super.onPause();
primWeb.webLifeCycle().onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
primWeb.webLifeCycle().onDestory();
}
//设置监听
.setListenerCheckJsFunction(this)
//要检查的js方法
primWeb.getCallJsLoader().checkJsMethod("returnBackHandles");
@Override
public void jsFunExit(Object data) {
Toast.makeText(getActivity(), data.toString() + "方法存在", Toast.LENGTH_SHORT).show();
}
@Override
public void jsFunNoExit(Object data) {
Toast.makeText(getActivity(), data.toString() + "方法不存在", Toast.LENGTH_SHORT).show();
}
内部是这样处理的,我自己写了一个js方法,来专门判断, 具体请看BaseCallJsLoader
@Override
public void checkJsMethod(String method) {
StringBuilder sb = new StringBuilder();
sb.append("function checkJsFunction(){ if(typeof ")
.append(method)
.append(" != \"undefined\" && typeof ")
.append(method)
.append(" == \"function\")")
.append("{console.log(\"")
.append(method)
.append("\");")
.append("checkJsBridge['jsFunctionExit']();")
.append("}else{")
.append("if(typeof checkJsBridge == \"undefined\") return false;")
.append("checkJsBridge['jsFunctionNo']();}}");
call("javascript:" + sb.toString() + ";checkJsFunction()", null);
}
PrimWeb库已经默认实现了文件上传
如果想禁止文件上传可以设置:
.setAllowUploadFile(false)
如果想使用第三方文件选择库上传文件设置:
.setUpdateInvokThrid(true)
同时具体的上传逻辑需要自己完成,具体的可以看Demo
@Override
public void jsOpenVideos() {
Log.e(TAG, "jsOpenVideos: ");
PrimPicker.with(WebFragment.this)
.choose(MimeType.ofVideo())
.setMaxSelected(1)
.setImageLoader(new MyImageLoad())
.setShowSingleMediaType(true)
.setCapture(false)
.setSpanCount(3)
.lastGo(1001);
}
@Override
public void jsOpenPick() {
PrimPicker.with(WebFragment.this)
.choose(MimeType.ofImage())
.setMaxSelected(1)
.setImageLoader(new MyImageLoad())
.setShowSingleMediaType(true)
.setCapture(false)
.setSpanCount(3)
.lastGo(1001);
}
private ValueCallback<Uri[]> agentValueCallbacks;
private ValueCallback<Uri> agentValueCallback;
AgentChromeClient agentChromeClient = new AgentChromeClient() {
@Override
public boolean onShowFileChooser(View webView, ValueCallback<Uri[]> valueCallback, com.tencent.smtt.sdk.WebChromeClient.FileChooserParams fileChooserParams) {
agentValueCallbacks = valueCallback;
//注意监听需要写在这里 否则监听有时候会收不到
primWeb.setThriedChooserListener(WebFragment.this);
return super.onShowFileChooser(webView, valueCallback, fileChooserParams);
}
@Override
public void openFileChooser(ValueCallback<Uri> valueCallback) {
agentValueCallback = valueCallback;
primWeb.setThriedChooserListener(WebFragment.this);
super.openFileChooser(valueCallback);
}
@Override
public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType) {
agentValueCallback = valueCallback;
primWeb.setThriedChooserListener(WebFragment.this);
super.openFileChooser(valueCallback, acceptType);
}
@Override
public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
agentValueCallback = valueCallback;
primWeb.setThriedChooserListener(WebFragment.this);
super.openFileChooser(valueCallback, acceptType, capture);
}
};
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e(TAG, "onActivityResult: requestCode --> " + requestCode + " | resultCode --> " + resultCode);
if (resultCode == RESULT_CANCELED && requestCode == 1001) {
cancelFilePathCallback();
} else if (resultCode == RESULT_OK && requestCode == 1001) {
uploadImgVideo(PrimPicker.obtainUriResult(data).get(0));
}
}
private void uploadImgVideo(Uri uri) {
Uri result = uri;
Uri[] results = new Uri[]{uri};
if (agentValueCallbacks != null) {
agentValueCallbacks.onReceiveValue(results);
agentValueCallbacks = null;
} else if (agentValueCallback != null) {
if (result == null) {
return;
}
agentValueCallback.onReceiveValue(result);
agentValueCallback = null;
}
}
private void cancelFilePathCallback() {
if (agentValueCallback != null) {
agentValueCallback.onReceiveValue(null);
agentValueCallback = null;
} else if (agentValueCallbacks != null) {
agentValueCallbacks.onReceiveValue(null);
agentValueCallbacks = null;
}
}
返回键的回退简化:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (primWeb.handlerKeyEvent(keyCode, event)) {
return true;
}
return super.onKeyDown(keyCode, event);
}
返回按钮的回退简化:
if (!primWeb.handlerBack()) {
this.finish();
}