Compartir una imagen captura de sección de un activity

=Compartir una imagen de captura= Dicha funcionalidad se puede lograr con un screenshot directamente y recortando los bordes de la barra de tareas, etc. Pero con esta funcionalidad, se logra hacer una nativa a la App, quitando la necesidad de un recorte. Otra característica de esta implementación, es que por día, va a mantener una foto guardada en memoria, y si se quitan mas va a ir reescribiendo esta ultima, en el directorio de la App.

Implementación de la funcionalidad
Esta funcionalidad se implementa inicialmente con un botón de shared que aparece en la barra horizontal de la parte superior de la ventana de inicio. Al apretar este botón, se llama a ShareActivity.java, que es la clase que maneja esta funcionalidad. En resumen, en ella, se guarda el Chart del cual queremos compartir en un archivo en el directorio de la aplicación, y luego permite compartir la ultima imagen compartida.

Ahora podemos ir paso a paso como se van generando en las funciones las partes que llevan a cabo esta funcionalidad.

Con la primera función que nos encontramos es initializaChart encargada de inicializar el gráfico, esto mediante setUpChart(chart), que se pretende compartir y la función que hace la llamada a funciones que tienen como fin generar la imagen, que veremos más adelante en wasImageGeneratedSave, guardarla y compartir dicha imagen.

private void initializeChart throws IOException { lineChartSharing = findViewById(R.id.linechart_sharing); setUpChart(getLineChart); if (isExternalStorageWritable) { if (wasImageGeneratedSave) { Toast.makeText(this, String.format("The Image is correctly save in !!"), Toast.LENGTH_LONG).show; final View share = findViewById(R.id.imageShareCustomPlot); share.setOnClickListener(new View.OnClickListener {                   @Override                    public void onClick(View v) {                        startActivity(Intent.createChooser(getShareIntent, "Share images to.."));                    }                }); }else { Toast.makeText(this, String.format("The Image was NOT correctly save in !!"), Toast.LENGTH_LONG).show; }       }    }

Luego tenemos a la funcion wasImageGeneratedSave que es la que se encarga con dos funciones internas, generar la imagen y guardarla.

private boolean wasImageGeneratedSave { getLineChart.buildDrawingCache; Bitmap bitmap = getBitmapFromChart; getLineChart.destroyDrawingCache; if (bitmap != null) { try { //Crear la imagen a compartir store(bitmap); return true; } catch (Exception e) { Log.e(LOG_TAG, e.getMessage, e); }       }        return false; }

Viendo con mas detalle se puede ver que la siguiente función es la que genera el mapa de bits para generar la imagen junto con las medidas de la misma. Toma primero las medidas, largo y ancho, y luego edita algunas configuraciones como el color y el fondo.

private Bitmap getBitmapFromChart { getLineChart.buildDrawingCache; getLineChart.setDrawingCacheEnabled(true); int width = View.MeasureSpec.makeMeasureSpec(500, View.MeasureSpec.EXACTLY); int height = View.MeasureSpec.makeMeasureSpec(700, View.MeasureSpec.EXACTLY); getLineChart.measure(width, height); int measuredWidth = getLineChart.getMeasuredWidth; int measuredHeight = getLineChart.getMeasuredHeight; getLineChart.layout(0, 0, measuredWidth, measuredHeight); Bitmap chartBitmap = getLineChart.getDrawingCache; if (chartBitmap != null) { Bitmap chartBitmapResult = Bitmap.createBitmap(chartBitmap.getWidth, chartBitmap.getHeight, Bitmap.Config.ARGB_8888); // Make a canvas with which we can draw to the chartBitmap Canvas canvas = new Canvas(chartBitmapResult); canvas.drawColor(0xffffffff); canvas.drawBitmap(chartBitmap, 0, 0, null); canvas.save; return chartBitmapResult; } else { return null; }   }

Lo que nos queda ahora es guardar dicha imagen para poder abrirla con un Intent y elegir la imagen que vamos a guardar de la siguiente manera:

public boolean store(Bitmap bitmap) throws IOException { try { writeBitmapToFile(this, bitmap); return true; }catch (Exception e) { e.printStackTrace; return false; }   }

Yendo un poco más abajo podemos ver como se guarda en forma de Bytes la informacion del mapa de bytes, que anteriormente se formateo con un formato .png y con una calidad del 100%.

public void writeBitmapToFile(Context context, Bitmap bitmap) { ByteArrayOutputStream stream = new ByteArrayOutputStream; bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray; OutputStream os = null; try { File rootDirectory = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); File imageFileName = new File(rootDirectory, String.format("mboehao-%s.png", Utils.getFormattedDate(new Date))); if(imageFileName.exists){ imageFileName.delete; }           os = new FileOutputStream(imageFileName); os.write(byteArray); closeStream(os); } catch (IOException e) { e.printStackTrace; }   }

Convenciones a la hora de implementar una funcionalidad de este tipo
Se pueden tener complicaciones a la hora de generar los archivos donde uno quiere guardar los archivos de las imágenes, por problemas de permisos o de la no existencia del directorio. Es necesario tener en cuenta, que es una buena manera de evitar estos problemas usando el paquete Environment que nos permite llegar a directorios que el usuario tiene permisos y ademas de no tener problemas con los nombre de directorios que podrían llegar a no existir. Esto de igual manera se puede solucionar creando la linea de directorios hasta el lugar necesario por el usuario, pero de vuelta se pueden tener problemas si no existe el permiso para tales tareas.