Basically, I want to take a screenshot of an entire scrollView. I've tried so many methods, but couldn't find the perfect one.
I've tried following:
public void takeScreenShot() {
mbitmap = getBitmapOFRootView();
createImage(mbitmap);
}
public void createImage(Bitmap bmp) {
String path = Environment.getExternalStorageDirectory().toString() + "/screenshot.jpg";
try {
FileOutputStream outputStream = new FileOutputStream(new File(path));
bmp.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public Bitmap getBitmapOFRootView() {
mScrollView.setDrawingCacheEnabled(true);
int totalHeight = mScrollView.getChildAt(0).getHeight();
int totalWidth = mScrollView.getChildAt(0).getWidth();
mScrollView.layout(0,0, totalWidth, totalHeight);
mScrollView.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(mScrollView.getDrawingCache());
mScrollView.setDrawingCacheEnabled(false);
return b;
}
This method almost works, but it's just showing me only 2 views and a button, other than that whole screen is black:
my xml contains so many views, it's view hierarchy is something like this:
<ScrollView>
<ConstraintLayout>
<Views>
....
<Views>
</ConstraintLayout>
</ScrollView>
I've referred so many StackOverflow post, but it didn't work.
So can anybody help me with it?
Update:
Finally found a solution for it. So, it was an issue with the background, solved it by drawing canvas over it. Like below:
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return bitmap;
You should be using a canvas for the same
public static Bitmap saveBitmapFromView(View view, int width, int height) {
Bitmap bmp = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
view.layout(0, 0, view.getLayoutParams().width, view.getLayoutParams().height);
view.draw(canvas);
return bmp;
}
Taking and Sharing screenshot in android programmatically
I've searched everywhere but found this one working
takeAndShareScreenshot()
private void takeAndShareScreenshot(){
Bitmap ss = takeScreenshot();
saveBitmap(ss);
shareIt();
}
takeScreenshot()
private Bitmap takeScreenshot() {
View view = // decore view of the activity/fragment;
view.setDrawingCacheEnabled(true);
return view.getDrawingCache();
}
saveBitmap()
private void saveBitmap(Bitmap bitmap) {
// path to store screenshot and name of the file
imagePath = new File(requireContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" + "name_of_file" + ".jpg");
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
shareIt()
private void shareIt() {
try {
Uri uri = Uri.fromFile(imagePath);
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("image/*");
String shareBody = getString(R.string.share_body_text);
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, R.string.subject);
sharingIntent.putExtra(Intent.EXTRA_TEXT, shareBody);
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(sharingIntent, "Share via"));
} catch (Exception e) {
e.printStackTrace();
}
}
Note:
In recent versions of android (>Marshmallow I guess), you may need `write
access to external directory`
Related
I am taking screenshot programmatically using the following code:
public static Bitmap takeScreenshot(View view)
{
try
{
// create bitmap screen capture
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bitmap;
}
catch (Throwable e)
{
CustomLogHandler.printError(e);
}
return null;
}
private static void copyFile(Bitmap bitmap)
{
File dstFile = getShareResultFile();
//Delete old file if exist.
if(dstFile.exists()) {
dstFile.delete();
}
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(dstFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, fos);
fos.flush();
}
catch (Exception e) {
CustomLogHandler.printError(e);
}
finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ioe) {
CustomLogHandler.printError(ioe);
}
}
}
}
There are several problem like:
Back arrow, title and share menu background color is not correct. It looks messy.
Background color of toolbar is totally changed.
Image quality is too poor and list items rounded drawable has not smooth corners.
Background of layout is not taken that I set as background of my parent layout.
I am taking the screenshot from the root view.
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, fos);
First, you are saving this as a JPEG. JPEG is designed for photos, and your screenshot is not a photo.
Second, you are saving this with a quality factor of 0. JPEG uses a lossy compression algorithm, and a quality factor of 0 says "please feel free to make this image be really poor, but compress it as far as you can".
I suggest switching to:
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
PNG is a better image format for a screenshot with the contents shown in your question. I don't think PNG uses the quality factor value; I put in 100 just to indicate that you want the best possible quality.
public static Bitmap takeScreenshot(View view)
{
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
This code can save view as bitmap.
But after you update your question with save code I see that you set 0 for quality, and what you expect?
#param quality Hint to the compressor, 0-100. 0 meaning compress for
* small size, 100 meaning compress for max quality. Some
* formats, like PNG which is lossless, will ignore the
* quality setting
just use your Ctrl button + click on method name to read doc about params
the answer is set second parameter 100 instead of 0!
Try using this:
public static Bitmap loadBitmapFromView(Context context, View v) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(returnedBitmap);
v.draw(c);
return returnedBitmap;
}
and
public void takeScreen() {
Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view
String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg";
File imageFile = new File(mPath);
OutputStream fout = null;
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
fout.close();
}
}
Images are saved in the external storage folder.
try this
private void captureScreen() {
View v = this.getWindow().getDecorView().findViewById(android.R.id.content);
v.setDrawingCacheEnabled(true);
Bitmap bitmap = v.getDrawingCache();
String extr = Environment.getExternalStorageDirectory().toString();
File file = new File(extr, getString(R.string.free_tiket) + ".jpg");
FileOutputStream f = null;
try {
f = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, f);
f.flush();
f.close();
MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Screen", "screen");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
I have a code to take, save then share the screenshot of an Activity. My problem is I want just take the center of the activity so I add this code
private Bitmap cropBitmap(Bitmap bitmap) {
Bitmap bm = Bitmap.createBitmap(bitmap, 10, 10, 500, 500);
return bm;
}
But it still the original screenshot, please help me i try much solutions but it seems like I don't know how to apply this solutions because i'm very amateur in coding . So i hope to help me please give me the right solution dependent on my code .Thank you very very much
#Override
public void onClick(View v) {
Bitmap bitmap = takeScreenshot();
cropBitmap(bitmap);
saveBitmap(bitmap);
shareIt();
}
public Bitmap takeScreenshot() {
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
return bitmap;
}
private Bitmap cropBitmap(Bitmap bitmap) {
Bitmap bm = Bitmap.createBitmap(bitmap, 10, 10, 500, 500);
return bm;
}
private void saveBitmap(Bitmap bitmap) {
imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshot.png"); ////File imagePath
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
private void shareIt() {
Uri myUri = Uri.fromFile(imagePath);
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("image/*");
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
String shareBody = "My highest score with screen shot";
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Catch score");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri);
startActivity(Intent.createChooser(sharingIntent, "Share via"));
}
});
displayResults();
Try like this:
Bitmap bitmap = takeScreenshot();
Bitmap bitmapCropped = cropBitmap(bitmap);
saveBitmap(bitmapCropped );
I am trying screenshot of webview in above Api 21 and it only capture content from webview that is visible on screen, other part is also getting captured but without any content. Means it shows white space.
I am using below code for taking screenshot.
public static String getScreenShotOf(View view, Context context) {
try {
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return storeImage(context, bitmap);
}
catch (Exception e) {
UtillsG.showToast("Error while taking screenshot.", context, false);
}
return null;
}
This things works perfectly in LOLLIPOP or below versions.
See screenshot of kitkat and marshmallow devices.
Can anybody help me out for this?
Any support will be appreciated.
You can use root layout as webview and try with below code.
public Bitmap takeScreenshot() {
View rootView = getWindow().getDecorView().findViewById(R.id.PP_Ll);
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
public void saveBitmap(Bitmap bitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File newDir = new File(root + "/Folder");
newDir.mkdirs();
Random gen = new Random();
int n = 10000;
n = gen.nextInt(n);
String fotoname = "Photo-" + n + ".jpg";
File file = new File(newDir, fotoname);
if (file.exists())
file.delete();
try {
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
Toast.makeText(getApplicationContext(),
"Saved in folder: 'Folder'", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am using a scroll View in my activity.I want to share the whole activity screen but not able to do that.Am able to share the visible part of the screen but not the full screen of the activity.Is it possible to take the screenshot of the full activity.I have tried like this but its sharing only the visible part of the activity.Plz help me out of this.Thank You
ShareImageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//View v1 = getWindow().getDecorView();
View v1 = findViewById(android.R.id.content);
v1.setDrawingCacheEnabled(true);
myBitmap = v1.getDrawingCache();
saveBitmap(myBitmap);
}
});
Saving the Screenshot taken ::
public void saveBitmap(Bitmap bitmap) {
String filePath = Environment.getExternalStorageDirectory()
+ File.separator + "Pictures/screencapture.png";
File imagePath = new File(filePath);
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
share(filePath);
} catch (FileNotFoundException e) {
Log.e("exception1", e.getMessage(), e);
} catch (IOException e) {
Log.e("exception2", e.getMessage(), e);
}
}
try this:
public static Bitmap loadBitmapFromView(View v, int width, int height) {
Bitmap b = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
I use below code to convert, but it seems can only get the content in the display screen and can not get the content not in the display screen.
Is there a way to get all the content even out of scroll?
Bitmap viewBitmap = Bitmap.createBitmap(mScrollView.getWidth(),mScrollView.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(viewBitmap);
mScrollView.draw(canvas);
We can convert all the contents of a scrollView to a bitmap image using the code shown below
private void takeScreenShot()
{
View u = ((Activity) mContext).findViewById(R.id.scroll);
HorizontalScrollView z = (HorizontalScrollView) ((Activity) mContext).findViewById(R.id.scroll);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
Bitmap b = getBitmapFromView(u,totalHeight,totalWidth);
//Save bitmap
String extr = Environment.getExternalStorageDirectory()+"/Folder/";
String fileName = "report.jpg";
File myPath = new File(extr, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
MediaStore.Images.Media.insertImage(mContext.getContentResolver(), b, "Screen", "screen");
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Bitmap getBitmapFromView(View view, int totalHeight, int totalWidth) {
Bitmap returnedBitmap = Bitmap.createBitmap(totalWidth,totalHeight , Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
view.draw(canvas);
return returnedBitmap;
}
The Pops answer is really good, but in some case you could have to create a really big bitmap which could trigger a OutOfMemoryException when you create the bitmap.
So I made a little optimization to be gently with the memory :)
public static Bitmap getBitmapFromView(View view, int totalHeight, int totalWidth) {
int height = Math.min(MAX_HEIGHT, totalHeight);
float percent = height / (float)totalHeight;
Bitmap canvasBitmap = Bitmap.createBitmap((int)(totalWidth*percent),(int)(totalHeight*percent), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(canvasBitmap);
Drawable bgDrawable = view.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
canvas.save();
canvas.scale(percent, percent);
view.draw(canvas);
canvas.restore();
return canvasBitmap;
}
This one works for me
To save the bitmap check runtime permission first
#OnClick(R.id.donload_arrow)
public void DownloadBitMap()
{
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
{
downloadData();
Log.e("callPhone: ", "permission" );
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
Toast.makeText(this, "need permission", Toast.LENGTH_SHORT).show();
}
}
To get bitmap
private void downloadData() {
ScrollView iv = (ScrollView) findViewById(R.id.scrollView);
Bitmap bitmap = Bitmap.createBitmap(
iv.getChildAt(0).getWidth()*2,
iv.getChildAt(0).getHeight()*2,
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
c.scale(2.0f, 2.0f);
c.drawColor(getResources().getColor(R.color.colorPrimary));
iv.getChildAt(0).draw(c);
// Do whatever you want with your bitmap
saveBitmap(bitmap);
}
To save the bitmap
public void saveBitmap(Bitmap bitmap) {
File folder = new File(Environment.getExternalStorageDirectory() +
File.separator + "SidduInvoices");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdirs();
}
if (success) {
// Do something on success
} else {
// Do something else on failure
}
File imagePath = new File(Environment.getExternalStorageDirectory() + "/SidduInvoices/Siddus.png");
if(imagePath.exists())
{
imagePath=new File(Environment.getExternalStorageDirectory() + "/SidduInvoices/Siddus"+custamername.getText().toString()+".png");
}
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
progressBar.cancel();
final File finalImagePath = imagePath;
new SweetAlertDialog(this, SweetAlertDialog.SUCCESS_TYPE)
.setTitleText("Saved")
.setContentText("Do you want to share this with whatsapp")
.setCancelText("No,cancel !")
.setConfirmText("Yes,share it!")
.showCancelButton(true)
.setConfirmClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sweetAlertDialog) {
sweetAlertDialog.cancel();
shareImage(finalImagePath);
}
})
.setCancelClickListener(new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sDialog) {
sDialog.cancel();
}
})
.show();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
You need get the total width and height of the scrollview, or you created viewBitmap is too small to contain the full content of the scrollview.
check this link
Android: Total height of ScrollView
The issue here is that the only actual pixel content that ever exists is that which is visible on the display screen. Android and other mobile platforms are very careful about memory use and one of the ways a scrolling view can maintain performance is to not draw anything that is offscreen. So there is no "full" bitmap anywhere -- the memory containing the content that moves offscreen is recycled.