I have this code for take screenshot of current view, a fragment that lives into an activity, where the activity has only a background.
private File captureScreen() {
Bitmap screenshot = null;
try {
if (view != null) {
screenshot = Bitmap.createBitmap(view.getMeasuredWidth(),
view.getMeasuredHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(screenshot);
view.draw(canvas);
// save pics
File cache_dir = Environment.getExternalStorageDirectory();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
screenshot.compress(Bitmap.CompressFormat.PNG, 90, bytes);
File f = new File(cache_dir + File.separator + "screen.png");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.close();
return f;
}
} catch (Exception e) {
// TODO
}
return null;
}
but bitmap saved is not exactly what i'm expecting.
Screenshot take only fragment elements, but not activity background. How can i include it into screenshot?
From :How to programmatically take a screenshot in Android?
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + ACCUWX.IMAGE_APPEND;
// create bitmap screen capture
Bitmap bitmap;
View v1 = mCurrentUrlMask.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
OutputStream fout = null;
imageFile = new File(mPath);
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try this. it work for me. and for you too
Call this method, passing in the outer most ViewGroup that you want a screen shot of:
public Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
I've used it for a while in a few different apps and haven't had any issues. Hope it vll helps
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();
}
}
In my app i want to capturea a part of my android application UI and save it programmatically .
For example i want do this actions :
In Activity/Fragment user clicks one Button .
capture from a part of Layout for example a LinearLayout that have id="captureMe" .
Save captured image somewhere .
how i can implement it ?
You can simply use this function just pass your view object
public Bitmap viewToBitmap(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
Then Save this file
public void saveImage(Bitmap inImage) {
String root = Environment.getExternalStorageDirectory().toString();
File mydir = new File(root + "/demo/");
mydir.mkdirs();
String fname = "Image.jpeg";
File file = new File (mydir, fname);
String path2=file.getPath();
Uri uri=Uri.fromFile(file);
try {
FileOutputStream out = new FileOutputStream(file);
inImage.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
}catch (Exception e)
{
e.printStackTrace();
}
}
Try this, hope it works
LinearLayout captureMe = (LinearLayout)findViewById(R.id.captureMe);
captureMe.setDrawingCacheEnabled(true);
captureMe.buildDrawingCache();
bitmap = captureMe.getDrawingCache();
First Use this function to get bitmap of view that you want to capture:
public static Bitmap getViewBitmap(View v, int width, int height) {
Bitmap viewBitmap = Bitmap.createBitmap(width , height,
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(viewBitmap);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return viewBitmap;
}
Then use this code to save this bitmap to storage:
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOutputStream = null;
File file = new File(path + "/Captures/", "screen.jpg");
try {
fOutputStream = new FileOutputStream(file);
capturedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOutputStream);
fOutputStream.flush();
fOutputStream.close();
MediaStore.Images.Media.insertImage(getContentResolver(),
file.getAbsolutePath(), file.getName(), file.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, "Save Failed", Toast.LENGTH_SHORT).show();
return;
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Save Failed", Toast.LENGTH_SHORT).show();
return;
}
In my android app i have surface view on which i have canvas and user can draw on canvas.Now i want to capture canvas image and store it to sd card.
Below is my code -
Bitmap bitmap = Bitmap.createBitmap(maxX, maxY, Bitmap.Config.RGB_565);
canvas.setBitmap(bitmap);
String mFile = path+"/drawing.png";
Bitmap bitmap = drawBitmap();
File file = new File(mFile);
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
code is run but when i open sd card on image path file with name is created but when open image it is black.
How to capture image from canvas in android.
Just pass the your surface view object and file path where you want to store your snapshot. It is working perfectly.
public static void takeScreenshot(View view, String filePath) {
Bitmap bitmap = getBitmapScreenshot(view);
File imageFile = new File(filePath);
imageFile.getParentFile().mkdirs();
try {
OutputStream fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static Bitmap getBitmapScreenshot(View view) {
view.measure(MeasureSpec.makeMeasureSpec(view.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(view.getHeight(), MeasureSpec.EXACTLY));
view.layout((int)view.getX(), (int)view.getY(), (int)view.getX() + view.getMeasuredWidth(), (int)view.getY() + view.getMeasuredHeight());
view.setDrawingCacheEnabled(true);
view.buildDrawingCache(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bitmap;
}
I am developing an application in which I have to take screen-shot of app screen
right now I used below code it is not working. I am null bitmap image
Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/"+ "bs_score_img" +".png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();
String screenShot = Environment.getExternalStorageDirectory().toString()+"/bs_score_img.png";
Log.i("TAG:Score: screenShot path=", screenShot);
Bitmap bmp = BitmapFactory.decodeFile(new File(screenShot).getAbsolutePath());
try this :
Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();
then read img.png as bitmap and convert it jpg as follows
Bitmap screen = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+
File.separator +"img.png");
//my code for saving
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
screen.compress(Bitmap.CompressFormat.JPEG, 15, bytes);
//you can create a new file name "test.jpg" in sdcard folder.
File f = new File(Environment.getExternalStorageDirectory()+ File.separator + "test.jpg");
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
// remember close de FileOutput
fo.close();
Google has a library with which you can take screenshot without rooting, I tried that, But i am sure that it will eat out the memory as soon as possible.
Try http://code.google.com/p/android-screenshot-library/
or try this :
View v1 = L1.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bm = v1.getDrawingCache();
BitmapDrawable bitmapDrawable = new BitmapDrawable(bm);
image = (ImageView) findViewById(R.id.screenshots);
image.setBackgroundDrawable(bitmapDrawable);
I found this code from another post:
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + ACCUWX.IMAGE_APPEND;
// create bitmap screen capture
Bitmap bitmap;
View v1 = mCurrentUrlMask.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
OutputStream fout = null;
imageFile = new File(mPath);
try {
fout = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Let's say that you clicked on button
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Bitmap bitmap = takeScreenshot();
saveBitmap(bitmap);
}
});
After that you need this two methods
public Bitmap takeScreenshot() {
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
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);
}
}
public Bitmap screenShot(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
view.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
just call this method with the view you want a snapshot of.. so if you want the whole screen just pass in you top most ViewGroup. if you want the System controls also just call:
you can try this
private Bitmap getScreen(){
mDecorView = getWindow().getDecorView();
runOnUiThread(new Runnable() {
public void run() {
mDecorView.invalidate();
mDecorView.post(this);
}
});
View v1 = mDecorView.getRootView();
System.out.println("Root View : "+v1);
v1.setDrawingCacheEnabled(true);
return v1.getDrawingCache();
}
here mDecorView is View .
Here how you can capture screen and save it in your storage
give permissions for creating file in external storage
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
And this is code for activity.
private void takeScreenshot() {
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
try {
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
// create bitmap screen capture
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
File imageFile = new File(mPath);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
} catch (Throwable e) {
// Several error may come out with file handling or OOM
e.printStackTrace();
}
}
This is how you can capture the screen.
My application has a list view in relative layout. Now I need to take a screen shot of the entire layout including all the content available in the list view and also other contents like button and text view showing in the layout. But my code takes only the visible part of the screen. Here the view is parent layout.
public void screen(){
View v1 = findViewById(R.id.screenRoot);
rel.layout(0, 0, rel.getMeasuredWidth(),rel.getMeasuredHeight());
View v = v1.getRootView();
v.setDrawingCacheEnabled(true);
/* v.measure(MeasureSpec.makeMeasureSpec(w, w),
MeasureSpec.makeMeasureSpec(h, h));*/
// v.layout(0, 0, rel.getWidth(), rel.getHeight());
v.buildDrawingCache(true);
System.out.println("rel "+rel.getHeight()+" "+v.getHeight());
Bitmap b = v.getDrawingCache();
v.setDrawingCacheEnabled(false);
String extr = Environment.getExternalStorageDirectory().toString();
File myPath = new File(extr, "tiket"+".jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myPath);
b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
MediaStore.Images.Media.insertImage(getContentResolver(), b, "Screen", "screen");
System.out.println("my path "+myPath+" "+fos);
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), "Image Captured Successfully", 0).show();
}
Call getBitmapFromView from your Click event or any thing.
R.id.root is my main RelativeLayout So you can pass you main layout.
LayoutInflater inflater = (LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
RelativeLayout root = (RelativeLayout)inflater.inflate(R.layout.youlayourfile,null);
root.setDrawingCacheEnabled(true);
Bitmap bmp = getBitmapFromView(this.getWindow().getDecorView().findViewById(R.id.root).getRootView());
URI uri = storPrintFile(bmp);
This function returns the Bitmap of your layout. Now you just need to store the bitmap into your device and anywhere else.
public Bitmap getBitmapFromView(View v) {
v.setLayoutParams(new LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(), Bitmap.Config.RGB_565);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
Storing bitmap into device.
public URI storPrintFile(Bitmap bitmapToStore){
ContextWrapper cw = new ContextWrapper(getApplicationContext());
String path = cw.getDir("CapturedImages",Context.MODE_PRIVATE).getPath();
File file = new File(path);
boolean isFileCreated = false;
if (!file.exists()) {
isFileCreated = file.mkdir();
System.out.println("Directory created in Internal Storage is :" + path);
}
String current = "Screen.jpg";//uniqueId.replace(" ", "-").replace(":", "-") + ".jpeg";
System.out.println("Internal Storage path is : " + current);
File mypath = new File(file, current);
try {
FileOutputStream out = new FileOutputStream(mypath);
bitmapToStore.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return mypath.toURI();
}