ViewShot.java 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package fr.greweb.reactnativeviewshot;
  2. import javax.annotation.Nullable;
  3. import android.graphics.Bitmap;
  4. import android.net.Uri;
  5. import android.util.Base64;
  6. import android.view.View;
  7. import com.facebook.react.bridge.Promise;
  8. import com.facebook.react.uimanager.NativeViewHierarchyManager;
  9. import com.facebook.react.uimanager.UIBlock;
  10. import java.io.ByteArrayOutputStream;
  11. import java.io.File;
  12. import java.io.FileOutputStream;
  13. import java.io.IOException;
  14. import java.io.OutputStream;
  15. /**
  16. * Snapshot utility class allow to screenshot a view.
  17. */
  18. public class ViewShot implements UIBlock {
  19. static final String ERROR_UNABLE_TO_SNAPSHOT = "E_UNABLE_TO_SNAPSHOT";
  20. private int tag;
  21. private Bitmap.CompressFormat format;
  22. private double quality;
  23. private Integer width;
  24. private Integer height;
  25. private File output;
  26. private boolean base64;
  27. private Promise promise;
  28. public ViewShot(
  29. int tag,
  30. Bitmap.CompressFormat format,
  31. double quality,
  32. @Nullable Integer width,
  33. @Nullable Integer height,
  34. File output,
  35. boolean base64,
  36. Promise promise) {
  37. this.tag = tag;
  38. this.format = format;
  39. this.quality = quality;
  40. this.width = width;
  41. this.height = height;
  42. this.output = output;
  43. this.base64 = base64;
  44. this.promise = promise;
  45. }
  46. @Override
  47. public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
  48. OutputStream os = null;
  49. View view = nativeViewHierarchyManager.resolveView(tag);
  50. try {
  51. if (base64) {
  52. os = new ByteArrayOutputStream();
  53. captureView(view, os);
  54. byte[] bytes = ((ByteArrayOutputStream) os).toByteArray();
  55. String data = Base64.encodeToString(bytes, Base64.NO_WRAP);
  56. promise.resolve(data);
  57. } else {
  58. os = new FileOutputStream(output);
  59. captureView(view, os);
  60. String uri = Uri.fromFile(output).toString();
  61. promise.resolve(uri);
  62. }
  63. }
  64. catch (Exception e) {
  65. promise.reject(ERROR_UNABLE_TO_SNAPSHOT, "Failed to snapshot view tag "+tag);
  66. }
  67. finally {
  68. if (os != null) {
  69. try {
  70. os.close();
  71. } catch (IOException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. }
  76. }
  77. /**
  78. * Screenshot a view and return the captured bitmap.
  79. * @param view the view to capture
  80. * @return the screenshot or null if it failed.
  81. */
  82. private void captureView (View view, OutputStream os) {
  83. int w = view.getWidth();
  84. int h = view.getHeight();
  85. if (w <= 0 || h <= 0) {
  86. throw new RuntimeException("Impossible to snapshot the view: view is invalid");
  87. }
  88. if (!view.isDrawingCacheEnabled())
  89. view.setDrawingCacheEnabled(true);
  90. Bitmap bitmap = view.getDrawingCache();
  91. if (width != null && height != null && (width != w || height != h)) {
  92. bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
  93. }
  94. if (bitmap == null) {
  95. throw new RuntimeException("Impossible to snapshot the view");
  96. }
  97. bitmap.compress(format, (int)(100.0 * quality), os);
  98. view.setDrawingCacheEnabled(false);
  99. }
  100. }