Android JS交互-记录我所遇到的

  • android 和javascript相互
    • android 调取JS方法
    • JS调取Android方法
    • JS image标签上传图片
    • WebView本地加载复文本标签配置
    • JS视频同时播放问题
    • JS视频全屏播放问题
    • 获取复文本img标签url

android 和javascript相互

android 和javascript交互很多,尤其是新闻类app,有的新闻是由复文本编辑的,需要直接加载复文本,会遇到很多问题,记录一下

android 调取JS方法

有两种调取方法:
1、loadUrl()
2、evaluateJavascript()方法
推荐使用2方法,加载JS方法,因为1方法会刷新页面

先给webview加入设置

  WebSettings settings = webView.getSettings();// 设置WebView支持JavaScriptsettings.setJavaScriptEnabled(true);webView.addJavascriptInterface(new JSInterface(), "APPJS");

js代码

<script>window.onload=function(){videoMore()}</script>

1、loadUrl()

    @Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);webView.loadUrl("window.onload.videoMore()");}

2、evaluateJavascript()方法

     //在网页加载完成后,调取JS方法webView.setWebViewClient(new WebViewClient() {@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);//网页加载完之后,java调用js方法if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//当Android SDK>=4.4时callEvaluateJavascript(webView, false);}}});private void callEvaluateJavascript(WebView webView, boolean b) {// 调取JS方法,js看前端怎么定义,移动端就怎么加webView.evaluateJavascript("window.onload.videoMore()", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {//此处为 js 返回的结果}});}

JS调取Android方法

1.使用addJavascriptInterface

    public class JSInterface {//js定义的事件,安卓对应操作,获取JS传的值,做对应操作@JavascriptInterfacepublic void Gotohelp(int num) {Intent intent = new Intent(HelpDetailActivity.this, HelpDetailActivity.class);intent.putExtra(Constants.ID, num + "");intent.putExtra(Constants.TITLE_NAME, "签署电子合同");HelpDetailActivity.this.startActivity(intent);}@JavascriptInterfacepublic void setVideoMore() {}}

2、使用shouldOverrideUrlLoading,不需要JS传值的情况下,可以使用该方法,直接拦截对应url.做相应操作,和前端约定好,也可以做一些操作,例如下面

        webView.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {Logger.e("---->  " + url);WebView.HitTestResult hit = view.getHitTestResult();if (hit != null) {int hitType = hit.getType();if (hitType == WebView.HitTestResult.SRC_ANCHOR_TYPE) {// 点击超链接if (TextUtils.equals(url, "http://0.0.0.138/")) {Intent intent = new Intent(HelpDetailActivity.this, HelpDetailActivity.class);intent.putExtra(Constants.ID, 138 + "");intent.putExtra(Constants.TITLE_NAME, "签署电子合同");HelpDetailActivity.this.startActivity(intent);} else {if (url.startsWith("http")) {openBrowser(HelpDetailActivity.this, url);}}}}return true;}});//跳转外部浏览器public static void openBrowser(Context context, String url) {final Intent intent = new Intent();intent.setAction(Intent.ACTION_VIEW);intent.setData(Uri.parse(url));// 注意此处的判断intent.resolveActivity()可以返回显示该Intent的Activity对应的组件名// 官方解释 : Name of the component implementing an activity that can display the intentif (intent.resolveActivity(context.getPackageManager()) != null) {final ComponentName componentName = intent.resolveActivity(context.getPackageManager());context.startActivity(Intent.createChooser(intent, "请选择浏览器"));} else {ToastUtils.show("链接错误或无浏览器");}}

3、onJsPrompt,onJsAlert,onJsConfirm处理JS弹窗的
没使用过这种方式,具体可以查看这篇文章添加链接描述

  // 设置允许JS弹窗webSettings.setJavaScriptCanOpenWindowsAutomatically(true);webView.setWebChromeClient(new WebChromeClient() {@Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {return handleJsPrompt(view, url, message, defaultValue, result);}@Overridepublic boolean onJsAlert(WebView view, String url, String message, JsResult result) {return handleJsAlert(view, url, message, result);}@Overridepublic boolean onJsConfirm(WebView view, String url, String message, JsResult result) {return handleJsConfirm(view, url, message, result);}});

JS image标签上传图片

JS代码

//实现android手机打开相机选择相册功能:
<input class="js_upFile cover1" type="file" name="cover" accept="image/*" capture="camera" multiple/>

JS这么配置完,发现个很恶心的问题,就是IOS 直接就能调取手机相册,但是安卓不行,那没办法,只能我们自力更生了,自己找办法了,具体方法就是通过WebChromeClient的onShowFileChooser,openFileChooser方法,自己处理调取本地相册,给JS传图片,但是经过检测发现,原生webView和腾讯TBS X5Webview都失效,没有效果,最终查找,使用AgentWeb成功解决此问题,接下来贴代码
AgentWeb链接 (AgentWeb Github)

引入AgentWeb

    api 'com.just.agentweb:agentweb-androidx:4.1.4'api 'com.just.agentweb:filechooser-androidx:4.1.4'// (可选)

实现逻辑

private ValueCallback<Uri[]> uploadMessageAboveL;webView = AgentWeb.with(this).setAgentWebParent(linWeb, new LinearLayout.LayoutParams(-1, -1)).useDefaultIndicator(0).setWebChromeClient(webChromeClient).setWebViewClient(webViewClient).interceptUnkownUrl().createAgentWeb().ready().go(url);WebChromeClient webChromeClient = new WebChromeClient() {@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);}uploadMessageAboveL = filePathCallback;//运行是权限判断if (PermissionUtil.lacksPermission(WebH5ViewActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)) {WebH5ViewActivityPermissionsDispatcher.takeWithPermissionCheck(WebH5ViewActivity.this);} else {take();}return true;}//>4.1.1public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {uploadMessage = uploadMsg;take();}};//选取本地相册逻辑@NeedsPermission({Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA})public void take() {Intent i = new Intent(Intent.ACTION_GET_CONTENT);i.addCategory(Intent.CATEGORY_OPENABLE);i.setType("image/*");startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILECHOOSER_RESULTCODE);}//选择照片成功回调,给JS传图片@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == FILECHOOSER_RESULTCODE) {if (uploadMessage == null && uploadMessageAboveL == null) {return;}//取消拍照或者图片选择时,返回null,否则<input file> 就是没有反应if (resultCode != RESULT_OK) {if (uploadMessage != null) {uploadMessage.onReceiveValue(null);uploadMessage = null;}if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);uploadMessageAboveL = null;}}//拍照成功和选取照片时if (resultCode == RESULT_OK) {if (data != null) {imageUri = data.getData();}}//上传文件if (uploadMessage != null) {uploadMessage.onReceiveValue(imageUri);uploadMessage = null;}if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(new Uri[]{imageUri});uploadMessageAboveL = null;}}if (requestCode == FILECHOOSER_RESULTCODE){//用户跳到Setting界面也有可能没有去开启权限for (String PERMISSION : PERMISSIONS) {if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(this, PERMISSION)) {finishActivity();return;}}}}@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {if (requestCode != FILECHOOSER_RESULTCODE || uploadMessageAboveL == null) {return;}Uri[] results = null;if (resultCode == Activity.RESULT_OK) {if (data == null) {results = new Uri[]{imageUri};} else {String dataString = data.getDataString();ClipData clipData = data.getClipData();if (clipData != null) {results = new Uri[clipData.getItemCount()];for (int i = 0; i < clipData.getItemCount(); i++) {ClipData.Item item = clipData.getItemAt(i);results[i] = item.getUri();}}if (dataString != null)results = new Uri[]{Uri.parse(dataString)};}}if (results != null) {uploadMessageAboveL.onReceiveValue(results);uploadMessageAboveL = null;} else {results = new Uri[]{imageUri};uploadMessageAboveL.onReceiveValue(results);uploadMessageAboveL = null;}return;}

WebView本地加载复文本标签配置

每个项目可能设置都不一样,具体配置和前端协调。这个配置里面包含副本本加载本地JS方法,复文本样式配置,副文本视频同时播放问题

    public static String getHtmlData(String bodyHTML) {String head = "<head>"+ "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\"> "+  "<script src=\"file:///android_asset/tinymceVideoControl.js\">"+ "</script>\n"+ "<style>" +
//                "areatext{ font-size: 28px!important; }" +
//                ".box { font-size:28px!important;}" +
//                ".box p{ font-size:28px!important;}" +"img{max-width: 100%; width:auto; height:auto;}" +"body{padding:5px 10px 10px 10px}" +"video { width:100%!important }" +"p{margin: 0;line-height: 1.6em;font-size:18px;}" +"strong{margin: 0;line-height: 1.5em;}" +"table{text-align: left;width:100% !important;font-size:12px;}" +
//                "*{font-size:28px;}" +"</style>" +"</head>";String changeContent = "<html>" + head + "<body>" + bodyHTML +  "<script>"+"window.οnlοad=function(){\n"+ " videoMore()\n"+ "}</script>"+"</body></html>";return changeContent;}//webview加载复文本String tv_html = data.getContent();StringBuilder sb = new StringBuilder();sb.append(StringUtils.getHtmlData(tv_html));webView.loadDataWithBaseURL(null, sb.toString(), "text/html", "utf-8", null);

JS视频同时播放问题

下面这个JS代码和上面复文本的配置逻辑,是加载复文本解决JS一个页面视频同时播放问题,如果是H5页面,有多个视频,只需要把这些配置让前端配置就好了,我们只需要调取下面的执行JS方法代码就行

JS代码

// 接收调用传来的索引 循环所有video 索引与传来的索引不相同的 暂停 重载
var videos = document.getElementsByTagName('video')// 获取所有video
function pauseAll(index) {window.addEventListener('scroll', () => {const offset = videos[index].getBoundingClientRect()const offsetTop = offset.topconst offsetBottom = offset.bottomconst offsetHeight = offset.height// 进入可视区域if (offsetTop <= -offsetHeight / 2 || offsetBottom >= document.body.clientHeight + offsetHeight / 2) {// console.log('移出可视区域')videos[index].pause()} else {// console.log('进入可视区域')}}, true) // 监听 监听元素是否进入/移出可视区域for (var j = videos.length - 1; j >= 0; j--) {if (j !== index) {videos[j].pause()// videos[j].load();}}
}
function videoMore() {if (videos && videos.length > 0) {// 循环给所有video添加监听事件 当前的video开始播时  调用pauseAll 将当前播放的video的索引传值过去for (var i = videos.length - 1; i >= 0; i--) {(function(n) {videos[n].addEventListener('play', () => {pauseAll(n)})})(i)}}
}

Android调用

```java//在网页加载完成后,调取JS方法webView.setWebViewClient(new WebViewClient() {@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);//网页加载完之后,java调用js方法if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//当Android SDK>=4.4时callEvaluateJavascript(webView, false);}}});private void callEvaluateJavascript(WebView webView, boolean b) {// 调取JS方法,js看前端怎么定义,移动端就怎么加webView.evaluateJavascript("window.onload.videoMore()", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {//此处为 js 返回的结果}});}

JS视频全屏播放问题

一般复文本或者H5页面都有视频,需要去全屏播放,这个视频标签一般都是全屏按钮,前端处理不能适配移动端全屏播放,需要移动端单独处理,移动端处理有两种方法,一种是点击适配播放的时候,拿到视频,跳转一个页面,跳到咱们APP自己的视频播放器播放,另外一种就是在webView页面上直接播放,点击全屏按钮,做横竖屏处理,这里处理的主要是后一种方案,在页面上播放

配置activity清单文件属性

        <activity android:name=".activity.HelpDetailActivity"android:configChanges="keyboardHidden|orientation|screenSize"android:hardwareAccelerated="true"android:screenOrientation="portrait"/>
        <com.xxx.xxx.widget.MyScrollViewandroid:id="@+id/scrollview"android:layout_width="match_parent"android:layout_height="match_parent"><WebViewandroid:id="@+id/webView"android:layout_width="match_parent"android:layout_height="wrap_content" /></com.xxx.xxx.widget.MyScrollView><FrameLayoutandroid:id="@+id/flVideoContainer"android:layout_width="match_parent"android:layout_height="match_parent"></FrameLayout>

//使用ScrollView 是为了解决全屏播放数据自动弹到顶部的问题

public class MyScrollView extends ScrollView {private OnScrollListener onScrollListener;public MyScrollView(Context context) {super(context);}public MyScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected int computeVerticalScrollRange() {return super.computeVerticalScrollRange();}@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);if (onScrollListener != null) {onScrollListener.onScroll(t);}}/*** 接口对外公开* @param onScrollListener*/public void setOnScrollListener(OnScrollListener onScrollListener) {this.onScrollListener = onScrollListener;}/**** 滚动的回调接口** @author xiaanming**/public interface OnScrollListener{/*** 回调方法, 返回MyScrollView滑动的Y方向距离* @param scrollY*              、*/void onScroll(int scrollY);}
}

WebView代码处理全屏逻辑

 private int scrollY = 0 ;@BindView(R.id.empty_view)public LinearLayout empty_view;@BindView(R.id.scrollview)public MyScrollView myScrollView ;@BindView(R.id.flVideoContainer)public FrameLayout flVideoContainer;myScrollView.setOnScrollListener(this);webView.setWebChromeClient(new WebChromeClient() {@Overridepublic void onReceivedTitle(WebView view, String title) {}CustomViewCallback mCallback;@Overridepublic void onShowCustomView(View view, CustomViewCallback callback) {Log.i("ToVmp", "onShowCustomView");fullScreen();webView.setVisibility(View.INVISIBLE);flVideoContainer.setVisibility(View.VISIBLE);flVideoContainer.addView(view);mCallback = callback;super.onShowCustomView(view, callback);}@Overridepublic void onHideCustomView() {Log.i("ToVmp", "onHideCustomView");fullScreen();webView.setVisibility(View.VISIBLE);flVideoContainer.setVisibility(View.GONE);flVideoContainer.removeAllViews();super.onHideCustomView();}});private void fullScreen() {if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);Log.i("ToVmp", "横屏");} else {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);Log.i("ToVmp", "竖屏");myScrollView.post(new Runnable() {@Overridepublic void run() {myScrollView.scrollTo(0, scrollY);}});}}@Overridepublic void onScroll(int scrolly) {if (scrolly > 0){scrollY = scrolly ;}}

获取复文本img标签url

先添加javaScript接口

webView.addJavascriptInterface(new javaScriptInterface(), "imagelistner");

获取setWebViewClient的onPageFinished 和 onPageStarted方法

        webView.setWebViewClient(new WebViewClient() {@Overridepublic void onPageFinished(WebView webView, String s) {super.onPageFinished(webView, s);setsetWebImageClick(webView,"imagelistner");}@Overridepublic void onPageStarted(WebView webView, String s, Bitmap bitmap) {webView.getSettings().setJavaScriptEnabled(true);super.onPageStarted(webView, s, bitmap);}});private void setsetWebImageClick(WebView webView, String method) {String jsCode = "javascript:(function(){" +"var imgs=document.getElementsByTagName(\"img\");" +"for(var i=0;i<imgs.length;i++){" +"imgs[i].pos = i;"+"imgs[i].οnclick=function(){" +"window."+method+".openImage(this.src,this.pos);" +"}}})()";webView.loadUrl(jsCode);}public class javaScriptInterface{@JavascriptInterfacepublic void openImage(String img,int pos ){Logger.e("----> "+img +"   " + pos);//            List v_list = new ArrayList();
//            PhotoView imageView = new PhotoView(getActivity());
//            GlideLoadUtil.displayDetailImage(img, imageView);
//            v_list.add(imageView);
//            DialogUtil.showPicDialog(getActivity().getSupportFragmentManager(), 0, v_list,true);}}

拿到了图片url

Android JS交互-记录我所遇到的相关推荐

  1. android html 启动app,Android js交互 与 Html启动App

    最近项目刚好有做到内部HTML页面跳转原生页面和html代码启动App页面的功能,做完之后觉得相关知识可以整理一下 先说下项目所用到的js交互 android调取JS的方法 WebView直接加载js ...

  2. Android js交互 UI不能更新 切会炸包

    草!!!!是一种植物 这脑残问题一局话就能解决 我有两个js交互 一个是展示dialog加载 一个是关掉dialog加载 然后这货一直报错 @JavascriptInterfacepublic voi ...

  3. android js交互 数组,Android WebView —— Java 与 JavaScript 交互总结

    相比于 Native App 和 Web App,Hybrid App 凭借其迭代灵活.控制自如.多端同步的优势在应用市场上越发显得优胜,主要得力于,其将变更频繁的部分产品功能使用 H5 开发并在客户 ...

  4. android点击弹框,Android——js交互实现点击弹框

    1.在main文件夹下创建assets文件夹导入html文件 Carson_Ho // JS代码 // Android需要调用的方法 function callJS(){ alert("An ...

  5. Android 与 JS 的交互 以及 JS与Android 的交互

    Android与JS交互以及JS与Android 的交互 是通过WebView互相调用方法 对于Android调用JS代码的方法有2种: 通过WebView的loadUrl() 通过WebView的e ...

  6. android webview js交互,响应webview图片的响应事件

    2019独角兽企业重金招聘Python工程师标准>>> 方案思路, 1.在点击图片的时候调用本地的java方法并给出响应的图片地址 2.本地获得图片地址后,开启一个遮罩activit ...

  7. android ios web兼容,js与android iOS 交互兼容

    js与android iOS 交互兼容 在Android与js交互方面还是要比iOS方便很多,而UIWebView只暴漏出- (BOOL)webView:(UIWebView *)webView sh ...

  8. android和ios HybridApp的js交互

    android的webview和js交互 https://github.com/chenhaifeng2016/AndroidWebview ios的uiwebview和js交互 https://gi ...

  9. Android—WebView与JS交互

    Html文件: WebView与JS交互方式: 1. 前提: WebSettings webSettings = webView.getSettings(); // 设置与Js交互的权限 webSet ...

  10. Android之webview与js交互

    对于android初学者应该都了解webView这个组件.之前我也是对其进行了一些简单的了解,但是在一个项目中不得不用webview的时候,发现了webview的强大之处,今天就分享一下使用webvi ...

最新文章

  1. 不要抱怨,勇敢向前走,你就能拥有更好的自己
  2. 从无到有算法养成篇-利⽤栈思想解决问题
  3. python源码提取_Python|第一个python程序(获取音乐下载地址,附源码)
  4. node --- koa、Mongoose、vue联系知识梳理
  5. 安装Ubuntu RISC V toolchain失败(网速、git配置原因)
  6. 全国高速恢复收费!阿里云:自由流“3大特色能力”使能智慧之路
  7. ssm read time out的原因_为什么得肝病的男人越来越多?爱喝酒不是原因,或跟老婆有关系!...
  8. 中国移动云能力中心 高薪诚聘各路运维技术专家
  9. 20191112每日一句
  10. linux 串口终端源码,LINUX 串口通讯源码
  11. ie属性中程序中的internet程序中的html编辑器为空,修改Internet Explorer(IE)查看源文件中的编辑器的方法...
  12. MCU】可怕,别人把我MCU固件给反汇编了!(逆向)J-FLASH通过下面的选项路径,即可读取所选Flash区域或者所有Flash区域(Entire Chip)安装IDA Pro逆向工具
  13. VMware虚拟机中安装的系统共享主机无线网络的方法
  14. authorization BASIC
  15. VS Code下载Beautify扩展插件 | CSDN创作打卡
  16. 直接使用Jlink仿真器下载程序至Freescale K60系列 MCU
  17. QPainter 画扇形
  18. 计算机网络实验一:验证性实验
  19. 响铃:抖音微视撕逼,但音乐短视频只有“神曲”逻辑吗?
  20. 12~18k的前端面试会问什么?

热门文章

  1. java poi word转html 报错
  2. python xlsxwriter dict_使用python库xlsxwriter库来输出各种xlsx文件的示例
  3. [编程开发工具-7]:四款功能强大的代码比较工具:Araxis Merge、Beyond compare、DiffMerge、WinMerge
  4. Python学习2——DBSCAN聚类算法
  5. 早鸟票开售 | 世界级大师Sanjiv和他的敏捷领导力(CAL)认证课程
  6. wordcloud库详解
  7. python中的对数_python中计算log对数的方法
  8. Python—WebSocket爬虫实战
  9. JVM 学习笔记(二)垃圾回收
  10. nc交换平台翻译器翻译仓库问题以及解决方法