I am having an issue where I create a Bitmap from a View by calling view.getDrawingCache(); The bitmap is almost perfect but when I set the bitmap to an ImageView there is some added "space" or "padding" to the top and bottom of the Bitmap.
Here is how I am capturing the view. The view in question has many different views added on top of it to make a sort of stacked effect.
Is there a way to set the bounds that the bitmap is capturing? or to remove this padding that is added?
What I have found
It appears as if the extra padding is being added due to the "fill_parent" attributes and the "android:scaleType:fitCenter". When I change the scaleType to fitXY the image no longer has padding. The only problem I have with that is that it stretches the image and does not maintain the aspect ratio required.
view.setDrawingCacheEnabled(true);
view.buildDrawingCache(true);
Bitmap bitmap = view.getDrawingCache();
Here is the code that I am calling to save the bitmap
private void saveToInternalStorage(Bitmap bitmapImage) {
ContextWrapper cw = new ContextWrapper(this);
File root = new File(Environment.getExternalStorageDirectory()
+ File.separator + "Pictures" + File.separator + "P"
+ File.separator);
if (!root.exists()) {
root.mkdirs();
Log.e("ROOT", "DIRECTORY DOES NOT EXIST");
} else {
Log.e("ROOT", "DIRECTORY EXISTS");
File sdImageMainDirectory = new File(root, "p_"
+ (System.currentTimeMillis() / 1000L) + ".png");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(sdImageMainDirectory);
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
Intent intent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(sdImageMainDirectory));
this.sendBroadcast(intent);
Log.e("DIRECTORY", "" + sdImageMainDirectory.getAbsolutePath());
} catch (NullPointerException e) {
} finally {
Intent shareIntent = new Intent(this, SubmissionActivity.class);
shareIntent.putExtra("URI", Uri.fromFile(sdImageMainDirectory));
startActivity(shareIntent);
finish();
}
// change activity to something to share the picture
}
}
XML for the layout containing the ImageView
<FrameLayout
android:id="#+id/root_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<ImageView
android:id="#+id/imageViewEdit"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="#drawable/abc_ab_solid_dark_holo" />
</FrameLayout>
Related
I tried to take a screenshot of a imageview programatically! When the image is saved to folder it is producing black image! when i tried to take screenshot of my entire scroll view, I am able to take screenshot. Please help:
my Code is:
private void saveop(){
RelativeLayout parent = (RelativeLayout) findViewById(R.id.opimagelayout);// which includes your view or buttons?
Bitmap bitmap = Bitmap.createBitmap(384,
100, Bitmap.Config.ARGB_8888);
Canvas bitmapHolder = new Canvas(bitmap);
parent.draw(bitmapHolder);
try {
final File f = savebitmaps(bitmap,"operator","");
} catch (IOException e) {
e.printStackTrace();
}
}
public static File savebitmaps(Bitmap bmp,String transno, String currentDateandTime) throws IOException {
Bitmap out = BITMAP_RESIZER(bmp, 384,112);
File folder = new File(Environment.getExternalStorageDirectory() + "/MobeeLoad");
File file = new File(folder, transno+".jpg");
FileOutputStream fOut;
try {
fOut = new FileOutputStream(file);
out.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
fOut.close();
bmp.recycle();
out.recycle();
} catch (Exception e) {
}
bmp.recycle();
return file;
}
Layout xml:
<RelativeLayout
android:id="#+id/opimagelayout"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_below="#+id/date"
android:layout_height="90dp">
<ImageView
android:id="#+id/opimage"
android:layout_width="90dp"
android:src="#drawable/check"
android:layout_centerHorizontal="true"
android:layout_height="90dp" />
</RelativeLayout>
I use below code to take screen shot from my layout and share it via android intent but the captured screen shot in the selected app is not showing any thing.
#Override
public void onClick(View view) {
shareBitmap(this,takeScreenshot());
}
public Bitmap takeScreenshot() {
try{
View rootView = getWindow().getDecorView().findViewById(R.id.lyt_main_report_activity);
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}catch (Exception ex){
ex.printStackTrace();
}
return null;
}
public static void shareBitmap(Context context, Bitmap bitmap){
//save to sd card
try {
File cachePath = new File(context.getCacheDir(), "images");
cachePath.mkdirs(); // don't forget to make the directory
FileOutputStream stream = new FileOutputStream(cachePath + "/image.png"); // overwrites this image every time
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try{
//start share activity
File imagePath = new File(context.getCacheDir(), "images");
File newFile = new File(imagePath, "image.png");
Uri contentUri = Uri.fromFile(newFile); //FileProvider.getUriForFile(context, "com.persianswitch.apmb.app.fileprovider", newFile);
if (contentUri != null) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
//shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
// shareIntent.setDataAndType(contentUri, context. getContentResolver().getType(contentUri));
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.setType("image/*");
context.startActivity(Intent.createChooser(shareIntent, context.getResources().getString(R.string.share_using)));
}
}catch (Exception ex){
ex.printStackTrace();
}
}
Please use this code this is tested code :
public static void takeScreenshot(Context context, View view) {
String path = Environment.getExternalStorageDirectory().toString() +
"/" + "test.png";
View v = view.findViewById(android.R.id.content).getRootView();
v.setDrawingCacheEnabled(true);
v.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false);
OutputStream out = null;
File imageFile = new File(path);
try {
out = new FileOutputStream(imageFile);
// choose JPEG format
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
} catch (FileNotFoundException e) {
// manage exception
} catch (IOException e) {
// manage exception
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception exc) {}
}
// onPauseVideo();
Intent share = new Intent(Intent.ACTION_SEND);
share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
share.setType("image/png");
((Activity) context).startActivityForResult(
Intent.createChooser(share, "Share Drawing"), 111);
}
Since DrawingCache() deprecated above 28 so using Canvas will sort the issues for many. below answer can be used for share Screenshot including text without requesting for permissions.
To take the Screenshot
private 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;
}
To share the Screenshot
private void shareContent(Bitmap bitmap) {
String bitmapPath = MediaStore.Images.Media.insertImage(
binding.getRoot().getContext().getContentResolver(), bitmap, "title", "");
Uri uri = Uri.parse(bitmapPath);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "App");
shareIntent.putExtra(Intent.EXTRA_TEXT, "Currently a new version of KiKi app is available.");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
binding.getRoot().getContext().startActivity(Intent.createChooser(shareIntent, "Share"));
}
if nothing happens it means your Bitmap is null kindly check that. or you could also fall on View.buildDrawingCache(); which will draw the View to Bitmap and then call your View.getDrawingCache();
also When hardware acceleration is turned on, enabling the drawing cache has no effect on rendering because the system uses a different mechanism for acceleration which ignores the flag. If you want to use a Bitmap for the view, even when hardware acceleration is enabled, see setLayerType(int, android.graphics.Paint) for information on how to enable software and hardware layers.
the quote was taken from the documented page
hope it helps
Tipp:The checked answer works when your device has external storage. On the Samsung 6 for example, it doesnt. Therefore you need to work with fileprovider.
Just incase somebody fell into this trap like me. The problem is that you are putting the name of the image twice.
FileOutputStream stream = new FileOutputStream(cachePath + "/image.png");
and than again.
File newFile = new File(imagePath, "image.png");
Change The seconed one to
File newFile = new File(imagePath);
Otherwise the contentUri give you the bitmap of your screenshot. I hope this helps someone. Took me 3 hours to figure it out :)
This is my code and im trying to capture screenshot of my application.I have background as animation(hearts falling)which looks like a live wallpaper.I want to take screenshot of current page>But its not working.I have used a button to take scrrenshot and imageview to show preview.when button is clicked nothing happens>Iam new to android.Plz help.Thanks in advance!!
View view = findViewById(R.id.Flayout);
view.setDrawingCacheEnabled(true);
Bitmap bitmap = view.getDrawingCache();
BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
imgshot = (ImageView) findViewById(R.id.imagescreen);
// set screenshot bitmapdrawable to imageview
imgshot.setBackgroundDrawable(bitmapDrawable);
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState()))
{
// we check if external storage is available, otherwise
// display an error message to the user using Toast Message
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File(sdCard.getAbsolutePath()
+ "/ScreenShots");
directory.mkdirs();
String filename = "screenshot" + i + ".jpg";
File yourFile = new File(directory, filename);
while (yourFile.exists())
{
i++;
filename = "screenshot" + i + ".jpg";
yourFile = new File(directory, filename);
}
if (!yourFile.exists())
{
if (directory.canWrite())
{
try
{
FileOutputStream out = new FileOutputStream(
yourFile, true);
bitmap.compress(Bitmap.CompressFormat.PNG, 90,
out);
out.flush();
out.close();
Toast.makeText(
ResultActivity.this,
"File exported to /sdcard/ScreenShots/screenshot"
+ i + ".jpg",
Toast.LENGTH_SHORT).show();
i++;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
} else
{
Toast.makeText(ResultActivity.this,
"Sorry SD Card not available in your Device!",
Toast.LENGTH_SHORT).show();
}
break;
}
}
}
Well, check this out:
How to programmatically take a screenshot in Android?
Here looks like what you want to do (as i understand), so test it out.
you have not get the root view. try this code
File file = new File(Environment.getExternalStorageDirectory()+ File.separator + "myimage.jpg");
// create bitmap
Bitmap bitmap;
View v1 = getWindow().getDecorView().getRootView(); //if this didnt work then try sol -3 at the bottom of this answer
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.close();
if this didnt work
View v1 = mCurrentUrlMask.getRootView();
then try this
View v1 = getWindow().getDecorView().getRootView();
or you can do
sol -3 ) View v1 = findViewById(R.id.linear_layout_id);// add the root view id
Don't forget to add permissions or it wont work:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
In this question ImageView will reset to original state after rotating, I know how to rotate an imageView and keep it after rotating.
But now, I need to do some scaling based on the rotated image. When scaling, the image will reset to original one before rotating, this is not what I want.
So I want to get the bitmap from ImageView after rotating, and let the ImageView use the new one. The question is:
How to get the bitmap from ImageView after rotating?
To get bitmap from imageview:
imageview.buildDrawingCache();
Bitmap bm=imageview.getDrawingCache();
To save it in a file:
OutputStream fOut = null;
Uri outputFileUri;
try {
File root = new File(Environment.getExternalStorageDirectory()
+ File.separator + "folder_name" + File.separator);
root.mkdirs();
File sdImageMainDirectory = new File(root, "myPicName.jpg");
outputFileUri = Uri.fromFile(sdImageMainDirectory);
fOut = new FileOutputStream(sdImageMainDirectory);
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
try {
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
}
Hi StackOverflow community,
in my application I'd like to have a button which allows the user to capture the current view.
For that reason, I've written the following method (oriented towards: Android save view to jpg or png ):
private LinearLayout container;
public void createImageOfCurrentView(View v) {
if (isExternalStoragePresent()) {
container = (LinearLayout) findViewById(R.id.container);
container.setDrawingCacheEnabled(true);
Bitmap b = container.getDrawingCache();
File dir = new File(Environment.getExternalStorageDirectory().getPath()
+ "/" + getPackageName() + "/");
dir.mkdirs();
File file = new File(dir, "image.jpg");
FileOutputStream fos;
try {
fos = new FileOutputStream(file);
b.compress(CompressFormat.JPEG, 95, fos); // NullPointerException!
Toast.makeText(this, "The current view has been succesfully saved "
+ "as image.", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
Toast.makeText(this, "Unfortunatly an error occured and this "
+ "action failed.", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "Bacause of lacking access to the storage "
+ "of this device, the current view couldn't be saved as an image.",
Toast.LENGTH_LONG).show();
}
}
The problem is according to LogCat that there occured a NullPointerException when trying to create the jpeg. So probably the method container.getDrawingCache() is not working. On the phone the file is generated. However with the size of 0 bytes and no visible image. I would appreciate any suggestions what I have to do in order to make it work as I want.
Try it -
public static Bitmap convertViewToBitmap(View view) {
Bitmap result = null;
try {
result = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
view.draw(new Canvas(result));
}catch(Exception e) {}
return result;
}
Try it -
view.setDrawingCacheEnabled(true);
Bitmap = bm = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);