ViewShot.java 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package fr.greweb.reactnativeviewshot;
  2. import javax.annotation.Nullable;
  3. import android.app.Activity;
  4. import android.graphics.Bitmap;
  5. import android.graphics.Canvas;
  6. import android.net.Uri;
  7. import android.util.Base64;
  8. import android.view.View;
  9. import android.widget.ScrollView;
  10. import com.facebook.react.bridge.Promise;
  11. import com.facebook.react.uimanager.NativeViewHierarchyManager;
  12. import com.facebook.react.uimanager.UIBlock;
  13. import java.io.ByteArrayOutputStream;
  14. import java.io.File;
  15. import java.io.FileOutputStream;
  16. import java.io.IOException;
  17. import java.io.OutputStream;
  18. /**
  19. * Snapshot utility class allow to screenshot a view.
  20. */
  21. public class ViewShot implements UIBlock {
  22. static final String ERROR_UNABLE_TO_SNAPSHOT = "E_UNABLE_TO_SNAPSHOT";
  23. private int tag;
  24. private String extension;
  25. private Bitmap.CompressFormat format;
  26. private double quality;
  27. private Integer width;
  28. private Integer height;
  29. private File output;
  30. private String result;
  31. private Promise promise;
  32. private Boolean isScrollView;
  33. public ViewShot(
  34. int tag,
  35. String extension,
  36. Bitmap.CompressFormat format,
  37. double quality,
  38. @Nullable Integer width,
  39. @Nullable Integer height,
  40. File output,
  41. String result,
  42. Boolean isScrollView,
  43. Promise promise) {
  44. this.tag = tag;
  45. this.extension = extension;
  46. this.format = format;
  47. this.quality = quality;
  48. this.width = width;
  49. this.height = height;
  50. this.output = output;
  51. this.result = result;
  52. this.isScrollView = isScrollView;
  53. this.promise = promise;
  54. }
  55. @Override
  56. public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
  57. OutputStream os = null;
  58. View view = nativeViewHierarchyManager.resolveView(tag);
  59. if (view == null) {
  60. promise.reject(ERROR_UNABLE_TO_SNAPSHOT, "No view found with reactTag: "+tag);
  61. return;
  62. }
  63. try {
  64. if ("file".equals(result)) {
  65. os = new FileOutputStream(output);
  66. captureView(view, os);
  67. String uri = Uri.fromFile(output).toString();
  68. promise.resolve(uri);
  69. }
  70. else if ("base64".equals(result)) {
  71. os = new ByteArrayOutputStream();
  72. captureView(view, os);
  73. byte[] bytes = ((ByteArrayOutputStream) os).toByteArray();
  74. String data = Base64.encodeToString(bytes, Base64.NO_WRAP);
  75. promise.resolve(data);
  76. }
  77. else if ("data-uri".equals(result)) {
  78. os = new ByteArrayOutputStream();
  79. captureView(view, os);
  80. byte[] bytes = ((ByteArrayOutputStream) os).toByteArray();
  81. String data = Base64.encodeToString(bytes, Base64.NO_WRAP);
  82. data = "data:image/"+extension+";base64," + data;
  83. promise.resolve(data);
  84. }
  85. else {
  86. promise.reject(ERROR_UNABLE_TO_SNAPSHOT, "Unsupported result: "+result+". Try one of: file | base64 | data-uri");
  87. }
  88. }
  89. catch (Exception e) {
  90. e.printStackTrace();
  91. promise.reject(ERROR_UNABLE_TO_SNAPSHOT, "Failed to capture view snapshot");
  92. }
  93. finally {
  94. if (os != null) {
  95. try {
  96. os.close();
  97. } catch (IOException e) {
  98. e.printStackTrace();
  99. }
  100. }
  101. }
  102. }
  103. /**
  104. * Screenshot a view and return the captured bitmap.
  105. * @param view the view to capture
  106. * @return the screenshot or null if it failed.
  107. */
  108. private void captureView (View view, OutputStream os) {
  109. int w = view.getWidth();
  110. int h = view.getHeight();
  111. if (w <= 0 || h <= 0) {
  112. throw new RuntimeException("Impossible to snapshot the view: view is invalid");
  113. }
  114. //evaluate real height
  115. if (this.isScrollView){
  116. h=0;
  117. ScrollView scrollView = (ScrollView)view;
  118. for (int i = 0; i < scrollView.getChildCount(); i++) {
  119. h += scrollView.getChildAt(i).getHeight();
  120. }
  121. }
  122. Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  123. Canvas c = new Canvas(bitmap);
  124. view.draw(c);
  125. if (width != null && height != null && (width != w || height != h)) {
  126. bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
  127. }
  128. if (bitmap == null) {
  129. throw new RuntimeException("Impossible to snapshot the view");
  130. }
  131. bitmap.compress(format, (int)(100.0 * quality), os);
  132. }
  133. }