Android使用WebView實(shí)現(xiàn)截圖分享功能
在APP項(xiàng)目的開發(fā)過(guò)程中,經(jīng)常會(huì)用到分享圖片的功能,有時(shí)候還需要根據(jù)當(dāng)前用戶信息獲取指定的分享圖片,比如要求在用戶分享圖中顯示用戶名、Uid、用戶頭像等信息。想到的實(shí)現(xiàn)方法主要有兩點(diǎn):
1.通過(guò)android SDK自帶的Canvas方法進(jìn)行繪制。
2.通過(guò)webView實(shí)現(xiàn)客戶端與H5交互,然后將H5界面做截圖處理。
本文主要介紹第二種方式的實(shí)現(xiàn)過(guò)程,第一種方式的實(shí)現(xiàn)方法,后續(xù)有時(shí)間會(huì)在博客中做說(shuō)明,下面開始本文內(nèi)容。
首先確定我們要實(shí)現(xiàn)的邏輯:
1.客戶端與H5的交互,客戶端將用戶信息(用戶名、Uid、用戶頭像等)發(fā)送給H5;
2.客戶端截取WebView功能的實(shí)現(xiàn);
3.分享功能的添加。
1.客戶端與H5交互
在界面布局中添加webView布局,對(duì)WebView布局進(jìn)行初始化操作(此處需要網(wǎng)絡(luò)權(quán)限,不做單獨(dú)處理)
wv_imgweb = (WebView) findViewById(R.id.h5_wv_imgweb);
WebSettings webSettings = wv_imgweb.getSettings(); //此處可更加具體的H5界面功能進(jìn)行相應(yīng)的WebSettings設(shè)置,本文只是演示基本效果 webSettings.setJavaScriptEnabled(true); webSettings.setSupportZoom(false); wv_imgweb.requestFocusFromTouch(); wv_imgweb.setDrawingCacheEnabled(true); wv_imgweb.setVerticalScrollBarEnabled(false); wv_imgweb.setHorizontalScrollBarEnabled(false); wv_imgweb.setVerticalScrollbarOverlay(false); wv_imgweb.setHorizontalScrollbarOverlay(false); wv_imgweb.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); //加載邏輯的處理 } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); //加載邏輯的處理 } }); //添加用戶信息參數(shù),加載H5分享地址 wv_imgweb.loadUrl(h5_url);
2.截圖功能的實(shí)現(xiàn)
上文中的WebView頁(yè)面加載完成后,即可調(diào)用截圖功能,并將圖片保存在本地指定文件夾(此處需要存儲(chǔ)權(quán)限,不做單獨(dú)處理)
android中WebView可以通過(guò)多種方式實(shí)現(xiàn)截圖,下面分別做不同介紹:
2.1截取屏幕內(nèi)內(nèi)容
第一種方式是通過(guò)Bitmap bitmap = webView.getDrawingCache()截取屏幕內(nèi)顯示內(nèi)容,注意調(diào)用此方法setDrawingCacheEnabled(true)必須設(shè)置為true;
2.2截取整個(gè)WebView內(nèi)容
第二種方式是通過(guò)Picture snapShot = wv_imgweb.capturePicture()來(lái)截取整個(gè)WebView的內(nèi)容
Picture snapShot = wv_imgweb.capturePicture(); if (snapShot != null && snapShot.getWidth() > 0 && snapShot.getHeight() > 0) { Bitmap bitmap = Bitmap.createBitmap(snapShot.getWidth(), snapShot.getHeight(), Bitmap.Config.ARGB_8888);//設(shè)置相應(yīng)的圖片質(zhì)量 Canvas canvas = new Canvas(bitmap); snapShot.draw(canvas); //將截取的圖片保存到本地 try { File appFile = new File(Environment.getExternalStorageDirectory() + "/testpic/app"); if (!appFile.exists() && !appFile.isDirectory()) { appFile.mkdirs(); } String fileName = Environment.getExternalStorageDirectory().getPath() + "/testpic/app/share.jpg"; FileOutputStream fos = new FileOutputStream(fileName); //設(shè)置保存本地圖片質(zhì)量 bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos); fos.close(); } catch (Exception e) { UIUtils.setLogInfo("eee", e.getMessage()); } }
2.3截取整個(gè)WebView內(nèi)容
Android 為了提高各方面的繪制速度(如滾動(dòng)操作),為每一個(gè) View 建立一個(gè)緩存,使用 View.buildDrawingCache 為自己的 View 建立相應(yīng)的緩存, 這個(gè) cache 就是一個(gè) bitmap 對(duì)象。利用這個(gè)功能可以對(duì)整個(gè)屏幕視圖進(jìn)行截屏并生成 Bitmap ,也可以獲得指定的 View 的 Bitmap 對(duì)象。
wv_imgweb.measure(View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); wv_imgweb.layout(0, 0, wv_imgweb.getMeasuredWidth(), wv_imgweb.getMeasuredHeight()); wv_imgweb.setDrawingCacheEnabled(true); wv_imgweb.buildDrawingCache(); Bitmap longImage = Bitmap.createBitmap(wv_imgweb.getMeasuredWidth(), wv_imgweb.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(longImage); // 畫布的寬高和 WebView 保持一致 Paint paint = new Paint(); canvas.drawBitmap(longImage, 0, wv_imgweb.getMeasuredHeight(), paint); wv_imgweb.draw(canvas); //將截取的圖片保存到本地 try { File appFile = new File(Environment.getExternalStorageDirectory() + "/testpic/app"); if (!appFile.exists() && !appFile.isDirectory()) { appFile.mkdirs(); } String fileName = Environment.getExternalStorageDirectory().getPath() + "/testpic/app/share.jpg"; FileOutputStream fos = new FileOutputStream(fileName); longImage.compress(Bitmap.CompressFormat.JPEG, 70, fos); fos.close(); } catch (Exception e) { UIUtils.setLogInfo("eee", e.getMessage()); }
問題:在5.0+上會(huì)發(fā)現(xiàn),截取的快照只顯示了webview中顯示出來(lái)的那部分,沒有顯示出來(lái)的部分是空白的。通過(guò)google找到了原因,在5.0+版本上,Android對(duì)webview做了優(yōu)化,旨在減少內(nèi)存占用以提高性能。因此在默認(rèn)情況下會(huì)智能的繪制html中需要繪制的部分,其實(shí)就是當(dāng)前屏幕展示的html內(nèi)容,因此會(huì)出現(xiàn)未顯示的圖像是空白的。解決辦法是調(diào)用enableSlowWholeDocumentDraw()方法。這個(gè)方法需要在webview創(chuàng)建之前調(diào)用,在Activity里就是在setContentView前去調(diào)用,此方法會(huì)有顯著的性能開銷。
3.分享圖片
通過(guò)原生或第三方分享功能,將上述生成的圖片添加到代碼中,完成分享。
如果有不同的見解,歡迎留言指正。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android開發(fā)筆記之如何正確獲取WebView的網(wǎng)頁(yè)Title
- 快速解決android webview https圖片不顯示的問題
- Android使用WebView實(shí)現(xiàn)文件下載功能
- Android WebView實(shí)現(xiàn)截長(zhǎng)圖功能
- Android混合開發(fā)教程之WebView的使用方法總結(jié)
- 關(guān)于Android中WebView遠(yuǎn)程代碼執(zhí)行漏洞淺析
- WebView的介紹與簡(jiǎn)單實(shí)現(xiàn)Android和H5互調(diào)的方法
- Android實(shí)現(xiàn)視頻播放--騰訊瀏覽服務(wù)(TBS)功能
- Android在項(xiàng)目中接入騰訊TBS瀏覽器WebView的教程與注意的地方
相關(guān)文章
android BottomSheetDialog新控件解析實(shí)現(xiàn)知乎評(píng)論列表效果(實(shí)例代碼)
BottomSheetDialog是一個(gè)自定義的從底部滑入的對(duì)話框,這篇文章主要介紹了android BottomSheetDialog新控件解析實(shí)現(xiàn)知乎評(píng)論列表效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Android?Xml轉(zhuǎn)換為View過(guò)程詳解
這篇文章主要為大家介紹了Android?Xml轉(zhuǎn)換為View實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07Android實(shí)現(xiàn)3D標(biāo)簽云簡(jiǎn)單效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)3D標(biāo)簽云簡(jiǎn)單效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05Android入門之使用RecyclerView完美實(shí)現(xiàn)瀑布流界面詳解
網(wǎng)上充滿著不完善的基于RecyclerView的瀑布流實(shí)現(xiàn),要么根本是錯(cuò)的、要么就是只知其一不知其二。本文就來(lái)用RecyclerView完美實(shí)現(xiàn)瀑布流界面,希望大家有所幫助2023-02-02Android實(shí)現(xiàn)Activity、Service與Broadcaster三大組件之間互相調(diào)用的方法詳解
這篇文章主要介紹了Android實(shí)現(xiàn)Activity、Service與Broadcaster三大組件之間互相調(diào)用的方法,結(jié)合實(shí)例形式詳細(xì)分析了Activity、Service與Broadcaster三大組件相互調(diào)用的原理,實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-03-03Flutter利用注解生成可自定義的路由的實(shí)現(xiàn)
這篇文章主要介紹了Flutter利用注解生成可自定義的路由的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Kotlin?LinearLayout與RelativeLayout布局使用詳解
Kotlin?的基本特性就先寫到這里,我們這個(gè)系列的定位是基礎(chǔ),也就是能用就好,夠用就好,我們不會(huì)舉太多的例子,但是這些都是最經(jīng)常用到的特性。從這節(jié)開始就是Kotlin和android?進(jìn)行結(jié)合,使用Kotlin進(jìn)行安卓應(yīng)用的開發(fā)了2022-12-12android實(shí)現(xiàn)在橫豎屏切換時(shí)頁(yè)面信息不被重置的示例分享
這篇文章主要介紹了android實(shí)現(xiàn)在橫豎屏切換時(shí)頁(yè)面信息不被重置的示例,需要的朋友可以參考下2014-02-02Android自定義控件深入學(xué)習(xí) Android生成隨機(jī)驗(yàn)證碼
這篇文章主要再次為大家介紹了Android自定義控件,以及針對(duì)自定義view學(xué)習(xí),實(shí)戰(zhàn)演練了Android生成隨機(jī)驗(yàn)證碼的詳細(xì)過(guò)程,感興趣的小伙伴們可以參考一下2016-01-01