#java #android #webview
#java #Android #webview
Вопрос:
Я хочу сохранить изображение из WebView в галерею. Сначала я пытаюсь получить растровое изображение из WebView, но мой метод getBitmapFromWebView (WebView WebView) выдает указанную выше ошибку. Это означает, что measuredWidth и measuredHeight равны 0, хотя я вызываю метод из onResume (), который был наиболее часто предлагаемым решением проблемы в похожих потоках (я читал похожие вопросы, но не нашел решения). Не могли бы вы, пожалуйста, сказать мне, что я делаю не так и как это исправить? Я должен сделать снимок экрана webview и сохранить его в галерее. Это мой код: MainActivity.java:
package com.example.fractal;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Picture;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView myBrowser=(WebView) findViewById(R.id.mybrowser);
myBrowser.getSettings().setBuiltInZoomControls(true);
//myBrowser.getSettings().setUseWideViewPort(true);
myBrowser.getSettings().setJavaScriptEnabled(true);
// myBrowser.getSettings().setLoadWithOverviewMode(true);
// myBrowser.getSettings().setDomStorageEnabled(true);
// myBrowser.setWebViewClient(new WebViewClient());
// myBrowser.setWebChromeClient(new WebChromeClient());
myBrowser.loadUrl("file:///android_asset/fractal.html");
}
public void saveButton(View view) {
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
}
//YES button from SecondActivity
public static Bitmap getBitmapFromWebView(WebView webView) {
try {
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
//Measure WebView's content
webView.measure(widthMeasureSpec, heightMeasureSpec);
webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight());
//Build drawing cache and store its size
webView.buildDrawingCache();
int measuredWidth = webView.getMeasuredWidth();
int measuredHeight = webView.getMeasuredHeight();
//Creates the bitmap and draw WebView's content on in
Bitmap bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
Paint paint = new Paint();
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(bitmap, 0, bitmap.getHeight(), paint);
webView.draw(canvas);
webView.destroyDrawingCache();
return bitmap;
} catch (Exception | OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
private void save(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root "/saved_images");
myDir.mkdirs();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fname = "fractal_" timeStamp ".jpg";
File file = new File(myDir, fname);
if (file.exists()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
//add to gallery
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
MediaScannerConnection.scanFile(this, new String[]{file.toString()}, new String[]{file.getName()}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
public void saveTempBitmap(Bitmap bitmap) {
if (isExternalStorageWritable()) {
save(bitmap);
}else{
//prompt the user or do something
}
}
@Override
protected void onResume(){
super.onResume();
WebView wb=(WebView) findViewById(R.id.mybrowser);
Bitmap mybitmap=getBitmapFromWebView(wb);
saveTempBitmap(mybitmap);
}
}
Изображение, отображаемое в WebView: fractal.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=0;" />
<title>My HTML</title>
</head>
<body>
<script>
(function() {
// Create Canvas
var myCanvas = document.createElement("canvas");
myCanvas.width=260;
myCanvas.height=250;
document.body.appendChild(myCanvas);
var ctx = myCanvas.getContext("2d");
// Start drawing
function checkIfBelongsToMandelbrotSet(x, y) {
// TO DO
var realComponentOfResult = x;
var imaginaryComponentOfResult = y;
var maxIterations = 100;
for(var i = 0; i < maxIterations; i ) {
var tempRealComponent = realComponentOfResult * realComponentOfResult
- imaginaryComponentOfResult * imaginaryComponentOfResult
x;
var tempImaginaryComponent = 2 * realComponentOfResult * imaginaryComponentOfResult
y;
realComponentOfResult = tempRealComponent;
imaginaryComponentOfResult = tempImaginaryComponent;
// Return a number as a percentage
if(realComponentOfResult * imaginaryComponentOfResult > 5)
return (i/maxIterations * 100);
}
return 0; // Return zero if in set
}
var magnificationFactor = 85;
var panX = 2;
var panY = 1.5;
for(var x=0; x < myCanvas.width; x ) {
for(var y=0; y < myCanvas.height; y ) {
var belongsToSet =
checkIfBelongsToMandelbrotSet(x/magnificationFactor - panX,
y/magnificationFactor - panY);
if(belongsToSet == 0) {
ctx.fillStyle = "violet";
ctx.fillRect(x,y, 1,1); // Draw a black pixel
} else {
ctx.fillStyle = 'hsl(310, 100%, ' belongsToSet '%)';
ctx.fillRect(x,y, 1,1); // Draw a colorful pixel
}
}
}
})();
</script>
</body>
</html>
Файл макета: activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<WebView
android:id="@ id/mybrowser"
android:layout_width="match_parent"
android:layout_height="300dp" />
<Button
android:id="@ id/button3"
android:layout_width="wrap_content"
android:layout_height="89dp"
android:layout_alignTop="@ id/mybrowser"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginStart="140dp"
android:layout_marginLeft="140dp"
android:layout_marginTop="380dp"
android:layout_marginEnd="140dp"
android:layout_marginRight="140dp"
android:layout_marginBottom="50dp"
android:onClick="saveButton"
android:text="@string/save_image" />
</RelativeLayout>
Комментарии:
1. Таким образом,
makeMeasureSpec
вызовы метода возвращают значение <=0. Почему? И какое это имеет отношение к onResume?2. В похожих вопросах (об одной и той же ошибке) Я читал, что, вероятно, измерения равны 0, потому что изображение еще не было отрисовано, но вызов метода в onResume () должен гарантировать, что действие загружено, а виды уже отрисованы и представлены пользователю. О makeMeasureSpec я не знаю, я просто использовал этот метод link и применил его к моему WebView.
3. В моем приложении есть 2 действия. Я выполняю сохранение изображения по возвращении из моего второго действия. Рендеринг фрактала в WebView и переключение между действиями с помощью кнопок работают нормально, но операция сохранения вызывает эту проблему, которую я не могу решить самостоятельно. Я новичок в разработке Android, любая помощь приветствуется.