短视频开发,Android和JS互调实现图片传递

短视频开发,Android和JS互调实现图片传递

Android与Js互调的方式

Android与JS通过WebView互相调用方法,实际上是:

1.Android去调用JS的代码

2.JS去调用Android的代码

二者沟通的桥梁是WebView

对于Android调用JS代码的方法有2种:

通过WebView的loadUrl()

通过WebView的evaluateJavascript()

对于JS调用Android代码的方法有3种:

通过WebView的addJavascriptInterface()进行对象映射

通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url

通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话alert()、confirm()、prompt() 消息

需求

H5界面调用Android本地录制小视频的方法,H5界面获取首帧图像并展示

添加addJavascriptInterface注解方法

H5VerificationJavascriptInterface 对象映射

 

1
<br>public class H5VerificationJavascriptInterface extends BaseJavascriptInterface {<br>    private SoftReference<H5VerificationContact.View> contextReference;<br>    public H5VerificationJavascriptInterface(int titleHeight, int tabButtonHeight,<br>                                             ActionListener listener) {<br>        super(titleHeight,tabButtonHeight,listener);<br>    }<br>    public H5VerificationJavascriptInterface setView(H5VerificationContact.View view){<br>        contextReference = new SoftReference<>(view);<br>        return this;<br>    }<br>    @Nullable<br>    private H5VerificationContact.View getView(){<br>        if (contextReference.get()!=null){<br>            return contextReference.get();<br>        }<br>        return null;<br>    }<br>    /**<br>     * 启动视频录制界面<br>     * 选择成功后会调用js里面的方法<br>     * chooseLocalFilesCallback<br>     */<br>    @JavascriptInterface<br>    public void chooseLocalFiles(){<br>        if (getView()== null)return;<br>        getView().startTakeASmallVideo();<br>    }<br>}

​webView 对象映射

 

1
<br>mWebView.addJavascriptInterface(new H5VerificationJavascriptInterface(getStatusBarHeight(), 12<br>                , this::finish).setView(this), "android");

启动录制视频的具体代码

 

1
<br>    private final int CHOOSE_VIDEO = 0x102;<br>    @Override<br>    public void startTakeASmallVideo() {<br>        Intent intent = BaseApplication.getInstance().getIntentUtils().getActivityIntent(this,<br>                IntentUtils.INTENT_VIDEO_RECORDER);<br>        //获取外部存储文件夹--指定文件夹<br>        String videoPath = FilePathProvider.getPublicDir(this, DIR_VIDEO).getAbsolutePath();<br>        intent.putExtra(ConstantUtils.DIR_PATH, videoPath);<br>        startActivityForResult(intent, CHOOSE_VIDEO);<br>    }

录制成功后调用Js方法返回

 

1
onActivityResult<br>@Override<br>    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {<br>        super.onActivityResult(requestCode, resultCode, data);<br>        if (requestCode == CHOOSE_VIDEO && resultCode == RESULT_OK){<br>            mPresenter.convertVideoResources(data);<br>        }<br>    }

将图片转换成为Base64

 

1
<br>@Override<br>    public void convertVideoResources(Intent data) {<br>        final String videoFilePath = data.getStringExtra(ConstantUtils.VIDEO_FILE_PATH);<br>        final String firstFrameFilePath = data.getStringExtra(ConstantUtils.CAPTURE_FILE_PATH);<br>        if (TextUtils.isEmpty(firstFrameFilePath))return;<br>        if (TextUtils.isEmpty(videoFilePath))return;<br>        Flowable.just(firstFrameFilePath)<br>                .subscribeOn(Schedulers.io())<br>                .map(s -> {<br>                    String base64Img = "";<br>                    try {<br>                        byte[] buf = Base64RequestBody.readFile(firstFrameFilePath);<br>                        base64Img = Base64.encodeToString(buf, Base64.NO_WRAP);<br>                    } catch (Exception e) {<br>                        e.printStackTrace();<br>                    }<br>                    return base64Img;<br>                })<br>                .observeOn(AndroidSchedulers.mainThread())<br>                .subscribe(new BaseRequestSubscriber<String>(this,mView) {<br>                    @Override<br>                    protected void onDoRequestSuccess(String result) {<br>                        if (!TextUtils.isEmpty(result)){<br>                            mView.callJsChooseVideoCallback(videoFilePath,firstFrameFilePath,result);<br>                        }<br>                    }<br>                }.setIgnoreNetwork(true));<br>    }<br>    public static byte[] readFile(String file) throws IOException {<br>        return readFile(new File(file));<br>    }<br>    public static byte[] readFile(File file) throws IOException {<br>        // Open file<br>        RandomAccessFile f = new RandomAccessFile(file, "r");<br>        try {<br>            // Get and check length<br>            long longlength = f.length();<br>            int length = (int) longlength;<br>            if (length != longlength) {<br>                throw new IOException("File size >= 2 GB");<br>            }<br>            // Read file and return data<br>            byte[] data = new byte[length];<br>            f.readFully(data);<br>            return data;<br>        } finally {<br>            f.close();<br>        }<br>    }

回调Js中的方法并传递对应的参数

 

1
<br>@Override<br>    public void callJsChooseVideoCallback(String videoFilePath, String firstFrameFilePath, String imageBase64) {<br>        String sb = "javascript:chooseLocalFilesCallback(" +<br>                "\"" +<br>                videoFilePath +<br>                "\"" +<br>                "," +<br>                "\"" +<br>                firstFrameFilePath +<br>                "\"" +<br>                "," +<br>                "\"" +<br>                imageBase64 +<br>                "\"" +<br>                ")";<br>        mWebView.evaluateJavascript(sb, value -> { });<br>    }

H5界面

 

1
<!DOCTYPE html><br><html><br><head><br>    <script><br>function myFunction() {<br>    // document.getElementById("demo").innerHTML = "段落已被更改。";<br>    android.chooseLocalFiles();<br>}<br>function chooseLocalFilesCallback(videoFilePath,firstFrameFilePath,imageBase64) {<br>    // document.write('视频地址 = ');<br>    // document.write(videoFilePath);<br>    // document.write('首帧地址 = ');<br>    // document.write(firstFrameFilePath);<br>    // document.write('Base64 = ');<br>    // document.write(imageBase64);<br>    // document.getElementById("demo").innerHTML = imageBase64;<br>   document.getElementById("demo").innerHTML = imageBase64;<br>   var obj = document.getElementById("imgdemo");<br>   obj.src = "data:image/jpg;base64," + imageBase64;<br>}<br></script><br></head><br><body><br><button type="button" onclick="myFunction()">点击调用选择录屏</button><br></br><br><img id="imgdemo" height="200" width="200" src="data:image/jpg;base64,xxxxx"/><br></br><br><p id="demo">数据</p><br></body><br></html>

Activity加载html文件

 

1
<br>        mWebView.loadUrl("file:android_asset/text.html");

注意事项

Android调用JS方法的过程中,需要注意不能包含特殊字符,比如换行符。

所以在将图片转换成Base64的过程中,不能够使用默认Base64.encodeToString(buf, Base64.DEFAULT)的Flag,因为默认的生成String会包含换行符,使用Base64.NO_WRAP即可。

以上就是 短视频开发,Android和JS互调实现图片传递,更多内容欢迎关注之后的文章

 

posted @   云豹科技-苏凌霄  阅读(99)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示