Android: ошибка java.lang.illegalargumentexception: ширина и высота должны быть> 0, хотя вызов метода происходит в onResume()

#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, любая помощь приветствуется.