ViewShot.java 4.9KB

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