接入智齿客服网页端流程:

主要问题就是Android webview 屏蔽了上传文件功能,本文附带解决了WebView 不支持<input type=file>文件上传,WebView 点击没有反应的问题;

  智齿客服网页端接入有两种部署方式。1、网页组件;2、聊天链接。本文档不涉及业务流程,只讲述开发接入过程;

今天主要说一下Android 、ios 对 聊天链接 这种方式的接入,第一种接入方式后期再做描述。

1、 先注册智齿客服,然后用超级管理员账号登陆后到“设置-支持渠道”获取部署代码;

例:获取聊天链接如下:

https://www.sobot.com/chat/pc/index.html?sysNum=a047ca3c8fec47cca963d4a6e27b8706

2、这是智齿客服官方提供的链接开发文档:智齿客服官方文档,文档最后列出了聊天链接可以拼接的参数,可根据需要自行配置,值得注意的是customerFields 字段,是智齿客服提供的允许自定义的字段,登入智齿客服官网 到“设置-自定义字段” 中设置你所需要的字段。

例如新建字段名称为“游戏”,点击“显示ID”,查看自定义字段所对应的参数。最后将自定义字段拼接成json字符串,拼接到链接后面。如下:

拼接链接如下:https://www.sobot.com/chat/pc/index.html?sysNum=a047ca3c8fec47cca963d4a6e27b8706&customerFileds={"customField1":"麻将","customField2":"北京"}

3通过Android或IOS , webview 加载此链接。说明:ios 不需要做任何更改,直接加载链接就可以使用智齿客服网页版的聊天链接了。Android直接加载无法上传图片和拍照。


4、Android 上传图片和拍照问题解决

由于安全因素android webview屏蔽了文件上传控件,但是他并没有完全封掉。

解决方法步骤如下:

(1)、Activity 定义:

   private static final int REQUEST_CODE_PERMISSION_CAMERA = 0x03;private static final int REQUEST_CODE_CAMERA = 0x02;private static final int REQUEST_CODE_ALBUM = 0x01;private ValueCallback<Uri[]> uploadMessageAboveL;private ValueCallback<Uri> uploadMessage;

(2)、 扩展WebChromeClient

 webView.setWebChromeClient(mWebChromeClient);protected WebChromeClient mWebChromeClient = new WebChromeClient() {@Overridepublic void onReceivedTitle(WebView view, String title) {super.onReceivedTitle(view, title);if (basetitle != null && !TextUtils.isEmpty(title)) {basetitle.setText(title);} else {basetitle.setText(" ");}}// For Android 4.1 - 5.0@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, FileChooserParams fileChooserParams) {uploadMessageAboveL = valueCallback;uploadPicture();return true;}// For Android >= 5.1@Overridepublic void openFileChooser(ValueCallback<Uri> valueCallback, String s, String s1) {//super.openFileChooser(valueCallback, s, s1);uploadMessage = valueCallback;uploadPicture();}};

(3)、解决选择文件后按钮失效问题,需要覆写onActivityResult方法

    @Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_CODE_ALBUM || requestCode == REQUEST_CODE_CAMERA) {if (uploadMessage == null && uploadMessageAboveL == null) {return;}//取消拍照或者取消选择相册if (resultCode != RESULT_OK) {if (uploadMessage != null) {uploadMessage.onReceiveValue(null);uploadMessage = null;}if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);uploadMessageAboveL = null;}}//拍照成功或选择照片if (resultCode == RESULT_OK) {Uri imageUri = null;switch (requestCode) {case REQUEST_CODE_ALBUM:if (data != null) {imageUri = data.getData();}break;case REQUEST_CODE_CAMERA:if (!TextUtils.isEmpty(mCurrentPhotoPath)) {File file = new File(mCurrentPhotoPath);Uri loadUri = Uri.fromFile(file);Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, loadUri);sendBroadcast(localIntent);imageUri = Uri.fromFile(file);mLastPhotoPath = mCurrentPhotoPath;}break;}//上传文件if (uploadMessage != null) {uploadMessage.onReceiveValue(imageUri);uploadMessage = null;}if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(new Uri[]{imageUri});uploadMessageAboveL = null;}}}}

(4)、以上是主要功能点,下面是我自己用到的一个完整文件,可以参考,里面内容部分多余的请自动忽略。

public class BannerWebActivity extends BaseActivity implements View.OnClickListener {private static final int REQUEST_CODE_PERMISSION_CAMERA = 0x03;private static final int REQUEST_CODE_CAMERA = 0x02;private static final int REQUEST_CODE_ALBUM = 0x01;private int type;private WebView webView;private ProgressBar pbProcess;private String weburl;private ImageView basetitleleftim;private TextView basetitle;private ValueCallback<Uri[]> uploadMessageAboveL;private ValueCallback<Uri> uploadMessage;private String mLastPhotoPath;private Thread mThread;Context mContext;private String mCurrentPhotoPath;@Overridepublic void initView() {mContext = getApplicationContext();basetitleleftim = getViewID(R.id.basetitle_leftim);webView = getViewID(R.id.webview);pbProcess = getViewID(R.id.pb_process);basetitle = getViewID(R.id.basetitle_title);Intent intent = getIntent();weburl = intent.getStringExtra("weburl");type = intent.getIntExtra("type", 0);basetitleleftim.setOnClickListener(this);if (type == 1000) {OkHttpUtils.getInstance().getToken(this, AgencyUrl.ReadStrategyUrl, 1, BaseDiabean.class);}}@Overridepublic void initData() throws Exception {WebSettings settings = webView.getSettings();/* 大部分网页需要自己保存一些数据,这个时候就的设置下面这个属性 */settings.setDomStorageEnabled(true);settings.setDatabaseEnabled(true);/* 设置缓存模式,我这里使用的默认,不做多讲解 */settings.setCacheMode(WebSettings.LOAD_DEFAULT);/* 设置支持Js,必须设置的,不然网页基本上不能看 */settings.setJavaScriptEnabled(true);settings.setAppCacheEnabled(true);settings.setAppCachePath(context.getCacheDir().getAbsolutePath());/* 设置为使用webview推荐的窗口 */settings.setUseWideViewPort(true);settings.setLoadWithOverviewMode(true);/* 设置是否允许webview使用缩放的功能,我这里设为false,不允许 */settings.setBuiltInZoomControls(false);/* webview 不显示图片兼容 */if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {settings.setMixedContentMode(android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}webView.setWebChromeClient(mWebChromeClient);webView.setWebViewClient(mWebViewClient);webView.setDownloadListener(new DownloadListener() {@Overridepublic void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addCategory(Intent.CATEGORY_BROWSABLE);intent.setData(Uri.parse(url));startActivity(intent);}});webView.setHorizontalScrollBarEnabled(false);webView.loadUrl(weburl);}protected WebViewClient mWebViewClient = new WebViewClient() {public boolean shouldOverrideUrlLoading(WebView view, String url) { // 重写此方法表明点击网页里面的链接不调用系统浏览器,而是在本WebView中显示view.loadUrl(url);//加载需要显示的网页return true;// return super.shouldOverrideUrlLoading(view, url);}};protected WebChromeClient mWebChromeClient = new WebChromeClient() {@Overridepublic void onProgressChanged(WebView view, int newProgress) {//  super.onProgressChanged(view, newProgress);pbProcess.setProgress(newProgress);if (newProgress >= 100) {pbProcess.setVisibility(View.GONE);} else {pbProcess.setVisibility(View.VISIBLE);}}@Overridepublic void onReceivedTitle(WebView view, String title) {super.onReceivedTitle(view, title);if (basetitle != null && !TextUtils.isEmpty(title)) {basetitle.setText(title);} else {basetitle.setText(" ");}}@Overridepublic boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, FileChooserParams fileChooserParams) {uploadMessageAboveL = valueCallback;uploadPicture();return true;}@Overridepublic void openFileChooser(ValueCallback<Uri> valueCallback, String s, String s1) {uploadMessage = valueCallback;uploadPicture();}};Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);takePhoto();}};@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (grantResults == null && grantResults.length == 0) {return;}if (requestCode == REQUEST_CODE_PERMISSION_CAMERA) {if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {takePhoto();} else {new AlertDialog.Builder(mContext).setTitle("无法拍照").setMessage("您未授予拍照权限").setNegativeButton("取消", null).setPositiveButton("去设置", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Intent localIntent = new Intent();localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");localIntent.setData(Uri.fromParts("package", getPackageName(), null));startActivity(localIntent);}}).create().show();}}}/*** 选择相机或者相册*/public void uploadPicture() {AlertDialog.Builder builder = new AlertDialog.Builder(BannerWebActivity.this);builder.setTitle("请选择图片上传方式");builder.setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {if (uploadMessage != null) {uploadMessage.onReceiveValue(null);uploadMessage = null;}if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);uploadMessageAboveL = null;}}});//相机builder.setPositiveButton("相机", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (!TextUtils.isEmpty(mLastPhotoPath)) {mThread = new Thread(new Runnable() {@Overridepublic void run() {File file = new File(mLastPhotoPath);if (file != null) {file.delete();}mHandler.sendEmptyMessage(1);}});mThread.start();} else {if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {takePhoto();} else {ActivityCompat.requestPermissions(BannerWebActivity.this, new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_PERMISSION_CAMERA);}}}});builder.setNegativeButton("相册", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {chooseAlbumPic();}});builder.create().show();}/*** 拍照*/private void takePhoto() {StringBuilder fileName = new StringBuilder();Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);fileName.append(UUID.randomUUID()).append("_upload.png");File tempFile = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName.toString());if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);Uri uri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileProvider", tempFile);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);} else {Uri uri = Uri.fromFile(tempFile);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);}mCurrentPhotoPath = tempFile.getAbsolutePath();startActivityForResult(intent, REQUEST_CODE_CAMERA);}/*** 选择相册照片*/private void chooseAlbumPic() {Intent i = new Intent(Intent.ACTION_GET_CONTENT);i.addCategory(Intent.CATEGORY_OPENABLE);i.setType("image/*");startActivityForResult(Intent.createChooser(i, "Image Chooser"), REQUEST_CODE_ALBUM);}/** 回调** */@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_CODE_ALBUM || requestCode == REQUEST_CODE_CAMERA) {if (uploadMessage == null && uploadMessageAboveL == null) {return;}//取消拍照或者取消选择相册if (resultCode != RESULT_OK) {if (uploadMessage != null) {uploadMessage.onReceiveValue(null);uploadMessage = null;}if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(null);uploadMessageAboveL = null;}}//拍照成功或选择照片if (resultCode == RESULT_OK) {Uri imageUri = null;switch (requestCode) {case REQUEST_CODE_ALBUM:if (data != null) {imageUri = data.getData();}break;case REQUEST_CODE_CAMERA:if (!TextUtils.isEmpty(mCurrentPhotoPath)) {File file = new File(mCurrentPhotoPath);Uri loadUri = Uri.fromFile(file);Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, loadUri);sendBroadcast(localIntent);imageUri = Uri.fromFile(file);mLastPhotoPath = mCurrentPhotoPath;}break;}//上传文件if (uploadMessage != null) {uploadMessage.onReceiveValue(imageUri);uploadMessage = null;}if (uploadMessageAboveL != null) {uploadMessageAboveL.onReceiveValue(new Uri[]{imageUri});uploadMessageAboveL = null;}}}}@Overridepublic int setViewLayout() {return R.layout.activity_banner_web;}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.basetitle_leftim:if (webView != null && webView.canGoBack()) {webView.goBack();} else {fishActivity(this);}break;default:break;}}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (webView != null && webView.canGoBack()) {webView.goBack();return true;}return super.onKeyDown(keyCode, event);}@Overridepublic void onSuccessResponse(Call call, RBResponse resultBean, int requestCode) throws IOException {if (requestCode == 1) {BaseDiabean baseDiabean = (BaseDiabean) resultBean;if (baseDiabean != null) {if (baseDiabean.getCode() != 200) {ToastUtils.showShort(this, baseDiabean.getMessage(), 1);}} else {ToastUtils.showShort(this, "出错了", 1);}}}@Overridepublic void onFailResponse(Call call, IOException e, int requestCode) {}@Overrideprotected void onDestroy() {if (webView != null) {webView.setWebChromeClient(null);webView.setWebViewClient(null);webView.destroy();webView = null;}super.onDestroy();}
}

5、智齿客服聊天链接接入完毕。总结一下,主要要处理的一个问题就是Android webview 屏蔽了文件上传。解决了这个问题也就完全解决了,说明一下,选择拍照或者相册的弹窗,可以自己根据需要自己重新写一下UI样式。

智齿客服H5聊天链接接入及WebView不支持input file文件上传解决相关推荐

  1. type=file文件上传H5新特性

    1.语法 <input name="myFile" type="file"> 2.属性(以下三个仅 HTML5支持,因此存在兼容性问题 ) (1)m ...

  2. 保姆级别SpringBoot接入又拍云实现表单文件上传手册

    一.背景 本来打算使用七牛云进行文件上传的,由于自己一直没有实名认证(需要上传手持身份证就很烦),导致现在想用的时候用不了.另外自己所在的公司用的是又拍云,就试着看看又拍云能不能用,结果就有了这篇文章 ...

  3. Android webview支持H5页面通过js实现文件上传、图片上传

    一.问题场景: 项目中遇到通过网页上传文件的需求,IOS直接是支持的,安卓端却没反应,有些机型甚至闪退.其实是Android的webview默认是不支持<input type="fil ...

  4. 智齿客服Android集成流程,一种基于编程语言接入智齿客服的方法以及电子设备与流程...

    技术特征: 1.一种基于编程语言接入智齿客服的方法,其特征在于,包括: A.获取智齿客服的编号信息,通过脚本文件导入所述编号信息,以及配置所述智齿客服的属性信息: B.通过编程语言的内框架承载所述智齿 ...

  5. 如何在自己APP中接入在线客服系统,App接入第三方在线客服系统方法

    很多App都有能直接在App内找到客服咨询入口,方便及时解决客户问题. 如果你的app也想要配置客服系统,怎么才能实现? App内需要添加好一个客户咨询按钮,然后在客服咨询按钮点击后跳转到H5客服聊天 ...

  6. Android 集成阿里百川实现在线客服、聊天功能

    首先要感谢Android 技术 @淘子磊 最近开发中要实现在线客服和客服热线功能,实现在线客服有很多种方式,我觉得阿里百川做的事很好好的,无论是集成Step方面还是UI适配方面,关键还是免费的-- 附 ...

  7. 全渠道客服系统 php开发,在线客服系统全渠道接入有什么作用?

    在线客服系统渠道接入的发展历程 在线客服系统渠道接入的方式是跟互联网.移动互联网的发展紧密相关的. 过去,在移动互联网未能普及的时候,人们多是使用电脑,通过电脑网页.邮件.客服电话这样的传统的方式来跟 ...

  8. 在线客服系统源码 自适应手机移动端 支持多商家 带搭建教程

     下载链接: 在线客服系统源码自适应手机移动端支持多商家支持微信公众号/微信小程序带搭建教程-PHP文档类资源-CSDN下载 PHP轻量级人工在线客服系统源码 自适应手机移动端 支持多商家 带搭建教程 ...

  9. Markdown入门和解决MD文件上传博客后图片无法显示问题

    文章目录 Markdown基础和解决MD文件上传博客后图片无法显示问题 一.常见文本操作 1.标题 一级标题 二级标题 三级标题 四级标题 2.代码块 3.字体 4.引用 5.分割线 6.超链接 7. ...

  10. Node.js 博客实例(三)添加文件上传功能

    原教程 https://github.com/nswbmw/N-blog/wiki/_pages的第三章 上传文件眼下有三种方法: 使用 Express 自带的文件上传功能,不涉及数据库 使用 For ...

最新文章

  1. python3操作mysql教程_python3操作mysql教程
  2. 关于v$process与v$session中process的理解
  3. 华为鸿蒙概念机990,华为5G概念新机:鸿蒙OS系统+麒麟990+石墨烯 安卓机皇来势汹汹...
  4. Silverlight专题(WatermarkedTextBox使用)--摘录 很受用
  5. 在长文本中当中使用正则表达式匹配限定长度范围的数字串的方法
  6. Creating a Java VM from Android Native Code
  7. 热门搜索怎么实现_三个步骤教你学会,搜索引擎霸屏技术!
  8. mysql安装注意步骤,mysql安装步骤
  9. 详解nginx 代理多个服务器(多个server方式)
  10. python零基础能学吗-Python真的零基础可以学会吗?
  11. python urlopen错误_urlopen()出错
  12. php+log+iis,利用nxlog以syslog方式发送iis日志
  13. 二维码生成软件如何生成汉信码
  14. 4、杂项:Hyper-v/远程桌面使用USB设备(串口、加密狗等)
  15. [生存志] 第104节 吕览一字千金
  16. git修改已提交commit的Author信息
  17. js 七大继承--史上最全最易懂
  18. 机器学习之Apriori算法
  19. HTML5开发环境搭建
  20. python基于pingouin包进行统计分析:使用tost函数执行单样本的双单侧检验(TOST)、以dataframe的形式输出分析结果(包含p值、自由度、bound等)

热门文章

  1. 定义网络营销,到底和网店有什么区别
  2. category theory 简介
  3. XFtp - 显示隐藏的文件和文件夹
  4. 徐磊8,9,10 名词性从句
  5. m苹果放n篮子_m个苹果放入n个篮子
  6. ubuntu upgrade problem
  7. 兼容 IE、 FireFox 的 javascript 日历控件 原创作者:寒羽枫(cityhunter172)
  8. 阿里云OSS使用详解(java版本)
  9. 【转载】测试报告模板
  10. JAVA怎么开发一个胖客户端_胖客户端瘦客户端哑终端