Android Take Screenshot Programmatically and Email


Android take screenshot and email programmatically

In this tutorial I would be explaining how to take screenshot in android programmatically and email it. I was developing an app for Truiton and was searching the internet for a tutorial which could teach me how to take a snap shot of current app screen, found allot of em, but trust me none of them tells you what to do and what not to do. This is an attempt on how to correctly capture a screen on android programmatically and email it. Lets start with a basic layout which would be used to capture the screenshot.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/truiton" />

</RelativeLayout>

This is a basic layout in which we would be using the reference of ImageView to get the root view of the activity by getRootView() method. After designing layout it should look something like this.

Android InApp Mail
MainActivity_for_screenshot

In this tutorial I am capturing the screenshot by code in the onOptionsItemSelected method, which is used to capture the click event of the menu item. Menu Items are simple to create you can create your menu item in an XML file which would be placed as res/menu/activity_main.xml.

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/menu_mail"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="@string/menu_mailtext"/>
</menu>

Now lets include the menu code which would be included in MainActivity.java

@Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

 switch (item.getItemId()) {
 case R.id.menu_mail:
 final ImageView iv = (ImageView) findViewById(R.id.imageView1);
 View v1 = getWindow().getDecorView().getRootView();
 // View v1 = iv.getRootView(); //even this works
 // View v1 = findViewById(android.R.id.content); //this works too
 // but gives only content
 v1.setDrawingCacheEnabled(true);
 myBitmap = v1.getDrawingCache();
 saveBitmap(myBitmap);
 return true;

 default:
 return super.onOptionsItemSelected(item);
 }
 }

Now let us have a closer look at the onOptionsItemSelected method, here I have written the code to programmatically capture the screenshot of the activity. Here we can capture the screenshot via three ways:

  1. View v1 = getWindow().getDecorView().getRootView();
  2. View v1 = iv.getRootView();
  3. View v1 = findViewById(android.R.id.content);

You can choose whichever way is most suitable to you, just remember if you are going to choose (2) you need to instantiate a reference to a view in the activity.

The point to be noted here is that, this code will not execute in the onCreate method of this activity, reason being we cannot get root view until the activity is in in running state (wish I knew this I spent hours realizing wheres the NullPointerException is coming from).

As of now we have taken the screenshot of our activity, its in myBitmap variable, hence we proceed to save it in an image file, by calling saveBitmap method.

public void saveBitmap(Bitmap bitmap) {
 String filePath = Environment.getExternalStorageDirectory()
 + File.separator + "Pictures/screenshot.png";
 File imagePath = new File(filePath);
 FileOutputStream fos;
 try {
 fos = new FileOutputStream(imagePath);
 bitmap.compress(CompressFormat.PNG, 100, fos);
 fos.flush();
 fos.close();
 sendMail(filePath);
 } catch (FileNotFoundException e) {
 Log.e("GREC", e.getMessage(), e);
 } catch (IOException e) {
 Log.e("GREC", e.getMessage(), e);
 }
 }

In this saveBitmap method we are saving the captured screenshot/bitmap in a compressed format which is recognized by most of the devices. Also in this we are writing in the file in SD Card, therefore we also need to add this permission in the app manifest:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Now that we have our screenshot compressed and saved we can move on to the email part, to email this screenshot with the sendMail method.

public void sendMail(String path) {
 Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
 emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
 new String[] { "[email protected]" });
 emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
 "Truiton Test Mail");
 emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
 "This is an autogenerated mail from Truiton's InAppMail app");
 emailIntent.setType("image/png");
 Uri myUri = Uri.parse("file://" + path);
 emailIntent.putExtra(Intent.EXTRA_STREAM, myUri);
 startActivity(Intent.createChooser(emailIntent, "Send mail..."));
 }

In this method we are passing the image path as an argument, which is used to parse the URI and is sent as an extra in the emailIntent. Email intent is created by android.content.Intent.ACTION_SEND and to attach an image in an email intent we have to set the type of intent by setType(“image/png”) or setType(“image/*”). To invoke an email intent we have to create a chooser by Intent.createChooser(emailIntent, “Send mail…”).

Please Note :Although its obvious, but to send an email from your device you need to have an email account configured beforehand.

Your app should look something like this:

Code for MainActivity:

package com.truiton.inappmail;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends Activity {
 Bitmap myBitmap;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 }

 public void saveBitmap(Bitmap bitmap) {
 String filePath = Environment.getExternalStorageDirectory()
 + File.separator + "Pictures/screenshot.png";
 File imagePath = new File(filePath);
 FileOutputStream fos;
 try {
 fos = new FileOutputStream(imagePath);
 bitmap.compress(CompressFormat.PNG, 100, fos);
 fos.flush();
 fos.close();
 sendMail(filePath);
 } catch (FileNotFoundException e) {
 Log.e("GREC", e.getMessage(), e);
 } catch (IOException e) {
 Log.e("GREC", e.getMessage(), e);
 }
 }

 public void sendMail(String path) {
 Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
 emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
 new String[] { "[email protected]" });
 emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
 "Truiton Test Mail");
 emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
 "This is an autogenerated mail from Truiton's InAppMail app");
 emailIntent.setType("image/png");
 Uri myUri = Uri.parse("file://" + path);
 emailIntent.putExtra(Intent.EXTRA_STREAM, myUri);
 startActivity(Intent.createChooser(emailIntent, "Send mail..."));
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

 switch (item.getItemId()) {
 case R.id.menu_mail:
 final ImageView iv = (ImageView) findViewById(R.id.imageView1);
 View v1 = getWindow().getDecorView().getRootView();
 // View v1 = iv.getRootView(); //even this works
 // View v1 = findViewById(android.R.id.content); //this works too
 // but gives only content
 v1.setDrawingCacheEnabled(true);
 myBitmap = v1.getDrawingCache();
 saveBitmap(myBitmap);
 return true;

 default:
 return super.onOptionsItemSelected(item);
 }
 }
}

Here is the code for whole activity. In this app we are capturing a screenshot of the activity by getRootView method then we are compressing it to a PNG format which is further saved in the external files directory and emailed to the appropriate receiver. In this process I would also suggest that do not save the bitmap/screenshot in the internal files directory as if we do that our native phone’s email app wont be able to access it, as android does not allow applications to access files local to other applications, doing so wont throw an error but as a result- image will not be attached to the email. Hope this article make sense to those in need, like our Facebook page to keep in touch.

About Mohit Gupt

An android enthusiast, and an iPhone user with a keen interest in development of innovative applications.


Leave a comment

Your email address will not be published. Required fields are marked *

25 thoughts on “Android Take Screenshot Programmatically and Email