赞
踩
近日项目集成了个带聊天功能的Webview,一开始只是文字聊天后来增加需求要可以发文字/图片/语音等,一开始使用Webview自带的授权来实现录音功能的,只要授权即可,后面由于IOS的不支持,导致要跟IOS一致,本地写几个方法.
1.开始录音
2.暂停录音
3.取消录音
4.发送转换后的数据到后台,后台在处理.
先来看下webview的本地录音实现方法,
老规矩,界面就一个进度条和webview,webview采用的是BridgeWebView方便交互,BridgeWebView库
- <?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:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
-
- <ProgressBar
- android:id="@+id/progressBar"
- style="@android:style/Widget.ProgressBar.Horizontal"
- android:layout_width="match_parent"
- android:layout_height="3dp"
- android:max="100"
- android:progressDrawable="@drawable/progress_bar_bg" />
-
- <com.github.lzyzsd.jsbridge.BridgeWebView
- android:id="@+id/webview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingLeft="5dp"
- android:paddingRight="5dp" />
-
-
-
- </LinearLayout>
代码方面:
-
-
- /**
- * create by
- * on 2020/5/27
- * explain${聊天}
- */
- public class ChatFragment extends BaseFragment {
- private String mFrom;
- private ProgressBar progressbar;
- private BridgeWebView webView;
-
- private String baseurl = BaseHttpsUrl.NEW_BASE_LIVE_CHAT_WEBVIEW;
-
- /**
- * 被用户拒绝的权限列表
- */
- private List<String> mPermissionList = new ArrayList<>();
- private boolean isRecording;
- private AudioRecord audioRecord;
- public String encodedString;
-
- public final static int FILECHOOSER_RESULTCODE = 1;
- public final static int FILECHOOSER_RESULTCODE_FOR_ANDROID_5 = 2;
- private static final int MY_PERMISSIONS_REQUEST = 1001;
-
- /**
- * 需要申请的运行时权限
- */
- private String[] permissions = new String[]{
- Manifest.permission.RECORD_AUDIO,
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- };
-
-
-
- static ChatFragment newInstance(String from) {
- ChatFragment fragment = new ChatFragment();
- Bundle bundle = new Bundle();
- bundle.putString("from", from);
- fragment.setArguments(bundle);
- return fragment;
- }
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments() != null) {
- mFrom = getArguments().getString("from");
- }
-
- //录音授权
- Authorization();
- }
-
- @Override
- protected int setLayoutId() {
- return R.layout.chat_layout;
- }
-
- @Override
- protected void initView() {
- webView = (BridgeWebView) mRootView.findViewById(R.id.webview);
- progressbar = (ProgressBar) mRootView.findViewById(R.id.progressBar);
- String request_url = BaseCacheUtil.getString(getActivity(), "webview_url");
-
- baseurl = BaseHttpsUrl.NEW_BASE_LIVE_CHAT_WEBVIEW;
- initWebView();
- }
-
- private void initWebView() {
- WebSettings settings = webView.getSettings();
- settings.setJavaScriptEnabled(true);// 让WebView能够执行javaScript
- settings.setDomStorageEnabled(true);
- settings.setJavaScriptCanOpenWindowsAutomatically(true);// 让JavaScript可以自动打开windows
- settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); // 设置缓存模式,一共有四种模式
- // 开启 DOM storage API 功能
- //开启 database storage API 功能
- settings.setDatabaseEnabled(true);
- //开启 Application Caches 功能
- settings.setAppCacheEnabled(true);
- settings.setSupportZoom(true);// 支持缩放(适配到当前屏幕)
- settings.setUseWideViewPort(true); // 将图片调整到合适的大小
- settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); // 支持内容重新布局,一共有四种方式 默认的是NARROW_COLUMNS
- settings.setDisplayZoomControls(true); // 设置可以被显示的屏幕控制
- settings.setDefaultFontSize(12); // 设置默认字体大小
-
- settings.setAllowFileAccessFromFileURLs(true);
- settings.setAllowUniversalAccessFromFileURLs(true);
- settings.setMediaPlaybackRequiresUserGesture(false);
- webView.loadUrl(baseurl);
-
-
- //实现:按手机回退键,如果浏览器有上一个网页,则返回上一个网页
- webView.setOnKeyListener((v, keyCode, event) -> {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- if (keyCode == KEYCODE_BACK && webView.canGoBack()) {
- webView.goBack();
- return true;
- }
- }
- return false;
- });
-
- webView.setWebChromeClient(new WebChromeClient() {
- @Override
- public void onProgressChanged(WebView view, int newProgress) {
- progressbar.setProgress(newProgress);
- if (newProgress == 100) {
- progressbar.setVisibility(View.GONE);
- } else {
- progressbar.setVisibility(View.VISIBLE);
- }
- super.onProgressChanged(view, newProgress);
- }
-
- @Override
- public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
- result.confirm();
- return true;
- }
-
- @Override
- public void onPermissionRequest(PermissionRequest request) { //webview自带录音授权(重点!!!)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- request.grant(request.getResources());
- request.getOrigin();
- }
- }
-
- //扩展浏览器上传文件
- //3.0++版本
- public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
- openFileChooserImpl(uploadMsg);
- }
-
- //3.0--版本
- public void openFileChooser(ValueCallback<Uri> uploadMsg) {
- openFileChooserImpl(uploadMsg);
- mUploadMessage = uploadMsg;
- }
-
- public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
- openFileChooserImpl(uploadMsg);
- }
-
- @Override
- public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
- onenFileChooseImpleForAndroid(filePathCallback);
- return true;
- }
-
-
- });
-
- //下载文件
- webView.setDownloadListener((url, userAgent, contentDisposition, mimeType, contentLength) -> {
- // TODO: 2017-5-6 处理下载事件
- Uri uri = Uri.parse(url);
- Intent intent = new Intent(Intent.ACTION_VIEW, uri); //跳转浏览器下载
- startActivity(intent);
- });
-
- //开始录音
- webView.registerHandler("startRecord", (data, function) -> {
- checkPermissions();
- startRecordVoice();
- String str = "这是html返回给java的数据:" + data;
- //回调返回给Js
- // function.onCallBack();
- });
-
- //暂停录音
- webView.registerHandler("stopRecord", (data, function) -> {
- stopRecordVoice();
- });
-
- //删除录音
- webView.registerHandler("cancelRecord", (data, function) -> {
- delete();
- });
- //发送录音
- webView.registerHandler("sendRecord", (data, function) -> {
- sendRecord1();
- });
- }
-
-
- /**
- * 录音授权
- */
- private void Authorization() {
- Objects.requireNonNull(getActivity()).runOnUiThread(this::checkPermissions);
- }
-
- private void checkPermissions() {
- // Marshmallow开始才用申请运行时权限
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- for (int i = 0; i < permissions.length; i++) {
- if (ContextCompat.checkSelfPermission(getActivity(), permissions[i]) !=
- PackageManager.PERMISSION_GRANTED) {
- mPermissionList.add(permissions[i]);
- }
- }
- if (!mPermissionList.isEmpty()) {
- String[] permissions = mPermissionList.toArray(new String[mPermissionList.size()]);
- ActivityCompat.requestPermissions(getActivity(), permissions, MY_PERMISSIONS_REQUEST);
- }
- }
- }
-
-
- @Override
- protected void setListener() {
- webView.setWebViewClient(new MyWebViewClient(webView) {
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- super.onPageStarted(view, url, favicon);
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- super.onPageFinished(view, url);
- }
- });
- webView.setDefaultHandler(new myHadlerCallBack());
- }
-
- /**
- * 自定义的WebViewClient
- */
- class MyWebViewClient extends BridgeWebViewClient {
- public MyWebViewClient(BridgeWebView webView) {
- super(webView);
- }
- }
-
- /**
- * 自定义回调
- */
- class myHadlerCallBack extends DefaultHandler {
- @Override
- public void handler(String data, CallBackFunction function) {
- if (function != null) {
- // Toast.makeText(WebViewTest.this, data, Toast.LENGTH_SHORT).show();
- }
- }
- }
-
- public ValueCallback<Uri> mUploadMessage;
-
- private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) {
- mUploadMessage = uploadMsg;
- Intent i = new Intent(Intent.ACTION_GET_CONTENT);
- i.addCategory(Intent.CATEGORY_OPENABLE);
- i.setType("image/*");
- startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
- }
-
- public ValueCallback<Uri[]> mUploadMessageForAndroid5;
-
- private void onenFileChooseImpleForAndroid(ValueCallback<Uri[]> filePathCallback) {
- mUploadMessageForAndroid5 = filePathCallback;
- Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
- contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
- contentSelectionIntent.setType("image/*");
-
- Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
- chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
- chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
-
- startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5);
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- super.onActivityResult(requestCode, resultCode, intent);
- if (requestCode == FILECHOOSER_RESULTCODE) {
- if (null == mUploadMessage)
- return;
- Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
- mUploadMessage.onReceiveValue(result);
- mUploadMessage = null;
-
- } else if (requestCode == FILECHOOSER_RESULTCODE_FOR_ANDROID_5) {
- if (null == mUploadMessageForAndroid5)
- return;
- Uri result = (intent == null || resultCode != RESULT_OK) ? null : intent.getData();
- if (result != null) {
- mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result});
- } else {
- mUploadMessageForAndroid5.onReceiveValue(new Uri[]{});
- }
- mUploadMessageForAndroid5 = null;
- }
- }
-
-
-
-
-
-
- /**
- * 申请权限
- *
- * @param permission
- */
- private void requestPermission(String permission) {
- if (ContextCompat.checkSelfPermission(getActivity(), permission) != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(getActivity(), new String[]{permission}, 0);
- }
- }
-
-
- /**
- * 删除录音
- */
- private void delete() {
- File mp3File = new File(getActivity().getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.mp3");
- if (mp3File.exists()) {
- mp3File.delete();
- }
- }
-
-
- /**
- * 当前录音文件
- */
- private File audioFile;
- /**
- * 文件存储目录
- */
- private File mVoiceDir;
-
- public ChatFragment() {
- mVoiceDir = FileUtil.getChatVoiceDir();
- }
-
- /**
- * 按下录音
- */
- public void startRecordVoice() {
- try {
- recorder = new MediaRecorder();
- recorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置音频采集原
- recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);// 内容输出格式
- recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 音频编码方式
-
- audioFile = new File(mVoiceDir, DateUtil.formatDatetime(new Date(), "yyyyMMddHHmmss") + ".mp3");
- if (!audioFile.exists()) {
- boolean flag = audioFile.createNewFile();
- Log.i("speak", String.valueOf(flag));
- }
- ABLELogUtils.e("m_tag_", "文件路劲为:" + audioFile.getAbsolutePath() + "=====" + audioFile.getPath());
- recorder.setOutputFile(audioFile.getAbsolutePath());
-
- recorder.prepare(); // 预期准备
- recorder.start();//开始录音
-
- } catch (IllegalStateException e) {
- recorder = null;
- } catch (IOException e) {
- recorder = null;
- }
- }
-
- /**
- * 停止录音
- */
- public void stopRecordVoice() {
- try {
- recorder.stop();// 停止刻录
- recorder.reset();// 重设
- recorder.release();// 刻录完成一定要释放资源
- recorder = null;
- } catch (Exception e) {
- ABLELogUtils.e("RecordVoice", e.getMessage());
- }
- }
-
- /**
- * sendRecord()
- * 發送錄音
- */
- private void sendRecord1() {
- try {
- FileInputStream inputFile = new FileInputStream(audioFile);
- byte[] buffer = new byte[(int) audioFile.length()];
- inputFile.read(buffer);
- inputFile.close();
- encodedString = Base64.encodeToString(buffer, Base64.DEFAULT);
- Log.e("m_tag_Base64", "Base64--后的MP3文件-->" + encodedString);
-
- if (!TextUtils.isEmpty(encodedString)) {
- String file_type = "audio/mp3";
- String sender = "operator";
- RecordData(getActivity(), xxxx, encodedString, file_type, xxxx);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
两种实现方式都实现了,由于本地实现的录音在本地正常播放传到后台后播放不了,后面就空置了,还是采取了第一种自带的录音方式...
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。