I am making an application in Android in which I have to take screenshot of one of my activities and mail it as attachment.
I want to take screenshot of the current
I wanted mine in the action bar so I created a share_menu.xml file:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/share_item"
app:showAsAction="always|withText"
android:title="Share"
android:icon="@drawable/share_icon"
android:actionProviderClass=
"android.widget.ShareActionProvider" />
</menu>
This adds a button in the action bar with my share_icon and the text.
I did this inside a fragment so I added the code below to my fragment file. If you are inside an activity then you override public boolean onCreateOptionsMenu(Menu menu)
instead.
@Override
public void onCreateOptionsMenu(
Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.share_menu, menu);
}
if you are doing this with a fragment then in onCreate()
you have to add:
setHasOptionsMenu(true);
This is what is going to kick off the sharing.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.share_item){
Bitmap bm = screenShot(this.getView());
File file = saveBitmap(bm, "mantis_image.png");
Log.i("chase", "filepath: "+file.getAbsolutePath());
Uri uri = Uri.fromFile(new File(file.getAbsolutePath()));
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, "Check out my app.");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "share via"));
}
return super.onOptionsItemSelected(item);
}
Notice this calls two magic methods:
screenShot():
private Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
private static File saveBitmap(Bitmap bm, String fileName){
final String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Screenshots";
File dir = new File(path);
if(!dir.exists())
dir.mkdirs();
File file = new File(dir, fileName);
try {
FileOutputStream fOut = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 90, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
To your AndroidManifest.xml
, you have to add:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
or the screenshot won't be saved, and gmail will think you are trying to attach an empty file.
Also, a lot of SO answers say to use "*/*"
for shareIntent.setType()
but this creates an issue with facebook sharing, so it's best to leave it as "image/*"
.
Try this for taking screenshot of current Activity:
Android 2.2 :
private static Bitmap takeScreenShot(Activity activity)
{
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
DisplayMetrics displaymetrics = new DisplayMetrics();
mContext.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height - statusBarHeight);
view.destroyDrawingCache();
return b;
}
private static void savePic(Bitmap b, String strFileName)
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(strFileName);
if (null != fos)
{
b.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
If by "screenshot of current page" you mean "screenshot of one of my activities", you can arrange to render your Views to a bitmap-backed Canvas, then save an image from the bitmap.
If by "screenshot of current page" you mean "screenshot of somebody else's activity", that is not supported by the Android SDK, for obvious privacy and security reasons. There are various techniques that rooted device users can use to take screenshots.
This is how I captured the screen and shared it. Take a look if you are interested.
public Bitmap takeScreenshot() {
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
And the method that saves the bitmap image to external storage:
public void saveBitmap(Bitmap bitmap) {
File imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png");
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}}
see more in : https://www.youtube.com/watch?v=LRCRNvzamwY&feature=youtu.be
Kotlin complete solution Code with permission check :
1- Use this nice library to take screen shot with java / Kotlin / Rx functionality, add library dependency : InstaCapture github link
implementation "com.github.tarek360:instacapture:2.0.1"
2- Must check permission for compatibility on all android versions:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) { // Needs permission so request it
DeviceUtil.showAlertMsg(this, GeneralDicModel.shareMsgScreenShot!!)
requestPermissions(
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
) //callback result to onRequestPermissionsResult
} else { //Has got the permission before or doesn't need
screenShotAndShareIt()
}
3- Check permission result :
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>,
grantResults: IntArray
) {
when (requestCode) {
PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
screenShotAndShareIt()
} else {
// toast("Permission must be granted in order to save scrrenshot file")
}
}
}
}
4- Func call for take Screenshot & Share it by intent :
fun screenShotAndShareIt() {
Instacapture.capture(this, object : SimpleScreenCapturingListener() {
override fun onCaptureComplete(bitmap: Bitmap) {
val state = Environment.getExternalStorageState()
if (Environment.MEDIA_MOUNTED == state) {
val path: String = Environment.getExternalStorageDirectory().toString()
val picDir = File(path.plus("/myPic"))
if (!picDir.exists()) {
picDir.mkdir()
}
var bitmapScreenShot = bitmap
val fileName = "screenshot" + ".jpg"
val picFile = File(picDir.path.plus("/" + fileName))
try {
picFile.createNewFile()
val picOut = FileOutputStream(picFile)
bitmapScreenShot =
Bitmap.createBitmap(bitmapScreenShot, 0, 0, bitmapScreenShot.width, bitmapScreenShot.height)
val saved: Boolean = bitmapScreenShot.compress(Bitmap.CompressFormat.JPEG, 100, picOut)
if (saved) {
Log.i(
TAG,
"ScreenShotAndShareIt : Image saved to your device Pictures " + "directory! + ${picFile.absolutePath}"
)
} else {
Log.i(TAG, "ScreenShotAndShareIt Error on Save! + ${picFile.absolutePath}")
}
picOut.close()
// share via intent
val intent: Intent = Intent(android.content.Intent.ACTION_SEND)
intent.type = "image/jpeg"
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(picFile.absolutePath))
startActivity(Intent.createChooser(intent, "Sharing"))
} catch (e: Exception) {
Log.i(TAG, "ScreenShotAndShareIt Error catch : " + e.printStackTrace())
}
} else {
//Error
Log.i(TAG, "ScreenShotAndShareIt Error Environment.MEDIA_MOUNTED == state : " )
}
}
})
5- Declare this variable :
val PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 100
6- Do not forget to Add this permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>