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.
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:
- View v1 = getWindow().getDecorView().getRootView();
- View v1 = iv.getRootView();
- 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.
Born in New Delhi, India. A software engineer by profession, an android enthusiast and an evangelist. My motive here is to create a group of skilled developers, who can develop something new and good. Reason being programming is my passion, and also it feels good to make a device do something you want. In a very short span of time professionally I have worked with many tech firms. As of now too, I am employed as a senior engineer in a leading tech company. In total I may have worked on more than 20 projects professionally, and whenever I get spare time I share my thoughts here at Truiton.
Can I just say what a relief to obtain somebody who in fact knows what theyre talking about on the internet. You certainly know the best way to bring an concern to light and make it valuable. Far more folks really need to read this and comprehend this side of the story. I cant think youre not even more popular mainly because you unquestionably have the gift.
Thank you so much for this article. It’s really helpful.
One more question: I see when using your method to take screenshot, only app screen is taken while the status bar is empty. Is it Android bug?
Hi, I don’t think its an android bug, but since the app is not allowed to access anything outside its scope, its not being captured. I think maybe we’ll be able to access that too by JNI/Native code…perhaps.
Is it possible to take a screenshot of the Screen not the App screen through programmatically ?
Will do a research on it and if possible will post it as a tutorial.
Hi, i’ve been searching regarding the screenshot of the screen, i hope you put up the tutorial for this. very much appreciated for the use of applications.
Good post. But it doesn’t work with opened dialog((
Not Worked
Hi,
What part of it didn’t worked for you? I guess you must have not configured an email address on your device. Although its obvious, but to send an email from your device you need to have an email account configured beforehand.
Really good post Mohit 🙂
Hello, I developing a android medical application to monitor heart beat signals as graph and mail this graph to Doctors. I have done the graph but I need to take screenshot of this graph now. If you could send me your source code as zip, I will integrate with my code to complete project. Best Regards.
done 🙂
Thanx Mohit
Thanx Mohit,but i am getting a black image instead of screen image,plz help with that.
Thank you very much, works great!
Extremely Work’s , Great Job
Thank’s Alot You Saved Me,
Really very helpful.. You have saved my time. Thanks 🙂
Very Helpful and clean article.
Thanks Mohit for this good article!
Great job. I spend 10 hours around screenshots (that noob), only with this article I got there. Really thank you for taking the time to do such a great work.
What if a device has no SD card? Is there a way?
Thank you so much.
Sir
I am running the same code
Executing on my handset with Android 4.1. Getting Error “App stopped unfortunately”
Please find and resolve the issue
Sir,
How can i take a screen shot of my home screen through my app
Hi Mohit!
This article is very useful…
Is it possible to take a screenshot from a particular screen? say for example: when i open an app i should be able to take a screenshot of the settings screen and i should be able to mail the screenshot.
thanks Mohit, this is what exactly i needed. But i get the following error:
E/GREC: /storage/emulated/0/Pictures/screenshot.png (Permission denied)
java.io.FileNotFoundException: /storage/emulated/0/Pictures/screenshot.png (Permission denied)
any idea to fix this?
Thanks again