I want to extract webview screenshot (even if there is a scroll) and to save it.
My problem is after webview.draw() method called, webview is now an image an is unusable as a webview.
If there a way to prevent that behavior ?
Important : I can't just reload webview because user enters fields.
Here's my code :
protected void onClicked() {
mWebView.measure(View.MeasureSpec.makeMeasureSpec(
View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mWebView.layout(0, 0, mWebView.getMeasuredWidth(),
mWebView.getMeasuredHeight());
mWebView.setDrawingCacheEnabled(true);
mWebView.buildDrawingCache();
generateWebViewCapture();
}
/**
* Create capture of all webview.
*/
#Background
void generateWebViewCapture() {
Bitmap bm = Bitmap.createBitmap(mWebView.getMeasuredWidth(),
mWebView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint paint = new Paint();
int iHeight = bm.getHeight();
canvas.drawBitmap(bm, 0, iHeight, paint);
mWebView.draw(canvas);
runOnUiThread(new Runnable() {
#Override
public void run() {
mWebView.setDrawingCacheEnabled(false);
mWebView.invalidate();
}
});
try {
String path = getReportPath();
File file = new File(path, "/report-"+System.currentTimeMillis()+".png");
OutputStream fOut = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
EDIT :
To fix the problem, remove that line :
mWebView.layout(0, 0, mWebView.getMeasuredWidth(),
mWebView.getMeasuredHeight());
Just mWebView.setDrawingCacheEnabled(false) after you get the bitmap!
mWebView.setDrawingCacheEnabled(true);
// remove mWebView.buildDrawingCache();
Bitmap bm= mWebView.getDrawingCache();
//remove generateWebViewCapture();
try {
String path = getReportPath();
File file = new File(path, "/report-"+System.currentTimeMillis()+".png");
OutputStream fOut = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
mWebView.setDrawingCacheEnabled(false);
This code is worked on my mobile:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testm);
final WebView mWebView = (WebView) findViewById(R.id.webview);
mWebView.loadUrl("http://www.csdn.net/");
findViewById(R.id.iv_0).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.setDrawingCacheEnabled(true);
// remove mWebView.buildDrawingCache();
Bitmap bm= mWebView.getDrawingCache();
//remove generateWebViewCapture();
try {
String path = getFilesDir().getPath();
File file = new File(path, "/report-"+System.currentTimeMillis()+".png");
OutputStream fOut = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
mWebView.setDrawingCacheEnabled(false);
}
});
}
}
It does not work on Android R.
WebView.enableSlowWholeDocumentDraw()
Add ScrollView, It works.
<ScrollView
android:layout_marginStart="#dimen/margin_8"
android:layout_marginEnd="#dimen/margin_8"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/web_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
Related
When I am taking snapshot of particular view in android. My whole view going to be blank after taking the screenshot. please check my whole code where I did wrong. I have searched so many quotes in Google but not able to solve my problem. Please someone help me.
// here is my code
fb_share_btn.setOnClickListener (new View.OnClickListener ( ) {
#Override
public void onClick(View view) {
boolean checkPermission = checkPermission();
/*Bitmap bitmap = takeScreenshot();*/
Bitmap bitmap = loadBitMapFromView(findViewById (R.id.tv_screenshot),findViewById (R.id.tv_screenshot).getWidth (),findViewById (R.id.tv_screenshot).getHeight ());
saveBitmap(bitmap);
shareIt();
}
});
// save bitmap function
public void saveBitmap(Bitmap bitmap) {
imagePath = new File (Environment.getExternalStorageDirectory ()+ "/screenshot.png");
Log.i ("Message","Testingabc:"+ imagePath);
FileOutputStream fos;
try {
fos = new FileOutputStream (imagePath);
bitmap.compress(Bitmap.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);
}
}
private Bitmap loadBitMapFromView(View v, int width, int height) {
Bitmap b = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas (b);
c.drawColor (Color.WHITE);
v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
v.draw(c);
return b;
}
private void shareIt() {
Uri uri = FileProvider.getUriForFile(TimeCounter.this, BuildConfig.APPLICATION_ID + ".provider",imagePath);
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("image/*");
String shareBody = "In Tweecher, My highest score with screen shot";
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "My Tweecher score");
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
sharingIntent.setPackage("com.facebook.katana");
startActivity(sharingIntent);
}
}
use this code with AsycTask
#Override
protected void onPreExecute() {
try {
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected Integer doInBackground(Integer... integers) {
try {
File root = new File(Environment.getExternalStorageDirectory(), "/Screenshot/");
if (!root.exists()) {
root.mkdirs();
}
imageFile = new File(root.toString() + "/" + imageName + ".jpg");
FileOutputStream outputStream = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 75, outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}
I want to print the whole WebView on Button Click.
I used Citizen Printer.
I tried Below way.
private Bitmap CitizenWebPrint(WebView webView) {
Bitmap bitmapCitizen = null;
Picture capturePicture = webView.capturePicture();
int width = capturePicture.getWidth();
int height = capturePicture.getHeight();
try {
bitmapCitizen = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
} catch (OutOfMemoryError e) {
Toast.makeText(getApplicationContext(),"2",Toast.LENGTH_LONG).show();
}
capturePicture.draw(new Canvas(bitmapCitizen));
return bitmapCitizen;
}
But Problem is,
This can print only visible part of WebView.
How can I print the whole WebView?
Draw the DecorView object of the current window, and then draw the Bitmap object.
And you can do like this.
Before doing it ,you can do this.
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(true);
webView.requestFocusFromTouch();
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
webView.loadUrl("your url");
And check version.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkSdkVersion();
setContentView(R.layout.activity_webview_capture);
}
// check version
private void checkSdkVersion() {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
WebView.enableSlowWholeDocumentDraw();
}
}
Add permission in your manifest.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Way 1
private void getScreenshot() {
float scale = webView.getScale();
int webViewHeight = (int) (webView.getContentHeight() * scale + 0.5);
Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(), webViewHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);
// save to the File
try {
String fileName = Environment.getExternalStorageDirectory().getPath() + "/webview_capture1.jpg";
FileOutputStream fos = new FileOutputStream(fileName);
// Save
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
fos.close();
Toast.makeText(WebviewFromDraw.this, "Screenshot OK", Toast.LENGTH_LONG).show();
bitmap.recycle();
} catch (Exception e) {
e.getMessage();
}
}
Way 2 use webView.getDrawingCache();
private void getScreenshot() {
bitmap = webView.getDrawingCache();
try {
String fileName = Environment.getExternalStorageDirectory().getPath()+"/webview_capture2.jpg";
FileOutputStream fos = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
fos.close();
Toast.makeText(WebviewFromDrawCache.this, "Screenshot OK", Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e("TAG", e.getMessage());
}
}
#Override
protected void onDestroy() {
super.onDestroy();
//recycle
if(bitmap!=null) {
bitmap.recycle();
}
}
Way 3 the same to yours,it works well in my device.
private void getScreenshot() {
Picture picture = webView.capturePicture();
int width = picture.getWidth();
int height = picture.getHeight();
if (width > 0 && height > 0) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
picture.draw(canvas);
try {
String fileName = Environment.getExternalStorageDirectory().getPath()+"/webview_capture3.jpg";
FileOutputStream fos = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
fos.close();
Toast.makeText(WebviewFromCapture.this, "Screenshot ok", Toast.LENGTH_LONG).show();
bitmap.recycle();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
}
I have recently made an app memegenerator
screenshot : enter image description here
I want whenever I click on the button to create meme
it should automatically save that picture below (which is a fragment)
How do I do that I have no idea?
This is what I found on internet to place in my code
Should I add this on my mainactivity file or the fragment java file
` public void createBitmap()
{
//Log.d(Const.DEBUG,"Creating a Bitmap");
Bitmap bmp;
ViewGroup v = (ViewGroup)((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0);
v.setDrawingCacheEnabled(true);
bmp = Bitmap.createBitmap(v.getDrawingCache());
File directory = new File(Environment.getExternalStorageDirectory()+ File.separator);
File file = new File(directory,"DankMeme");
try{
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.JPEG,100,out);
out.flush();
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
v.destroyDrawingCache();
v.setDrawingCacheEnabled(false);
}`
**update This my fragment code **
public class BottomSectionFragment extends Fragment {
private static TextView topMemeText;
private static TextView bottomMemeText;
private View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.bottom_picture_fragment,container,false);
topMemeText = (TextView)view.findViewById(R.id.topMemeText);
bottomMemeText = (TextView)view.findViewById(R.id.bottomMemeText);
return view;
}
public void setMemeText(String top,String bottom)
{
topMemeText.setText(top);
bottomMemeText.setText(bottom);
//createBitmap();
// I am calling tackeAndSaveScreenshot func here because when user press button it comes to this func
// to change text and right after I want screenshot
tackeAndSaveScreenShot();
}
//Screenshot
public void tackeAndSaveScreenShot() {
View MainView = getActivity().getWindow().getDecorView();
MainView.setDrawingCacheEnabled(true);
MainView.buildDrawingCache();
Bitmap MainBitmap = MainView.getDrawingCache();
Rect frame = new Rect();
getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
//to remove statusBar from the taken sc
int statusBarHeight = frame.top;
//using screen size to create bitmap
int width = getActivity().getWindowManager().getDefaultDisplay().getWidth();
int height = getActivity().getWindowManager().getDefaultDisplay().getHeight();
Bitmap OutBitmap = Bitmap.createBitmap(MainBitmap, 0, statusBarHeight, width, height - statusBarHeight);
MainView.destroyDrawingCache();
try {
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
//you can also using current time to generate name
String name="YourName";
File file = new File(path, name + ".png");
fOut = new FileOutputStream(file);
OutBitmap.compress(Bitmap.CompressFormat.PNG, 90, fOut);
fOut.flush();
fOut.close();
//this line will add the saved picture to gallery
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
This method will take screenshot from your mobile screen. you can change the MainView to your view that you want to take screenshot from.
Don't forget to add "Write external storage" permission to manifest
public void tackeAndSaveScreenShot(Activity mActivity) {
View MainView = mActivity.getWindow().getDecorView();
MainView.setDrawingCacheEnabled(true);
MainView.buildDrawingCache();
Bitmap MainBitmap = MainView.getDrawingCache();
Rect frame = new Rect();
mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
//to remove statusBar from the taken sc
int statusBarHeight = frame.top;
//using screen size to create bitmap
int width = mActivity.getWindowManager().getDefaultDisplay().getWidth();
int height = mActivity.getWindowManager().getDefaultDisplay().getHeight();
Bitmap OutBitmap = Bitmap.createBitmap(MainBitmap, 0, statusBarHeight, width, height - statusBarHeight);
MainView.destroyDrawingCache();
try {
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
//you can also using current time to generate name
String name="YourName";
File file = new File(path, name + ".png");
fOut = new FileOutputStream(file);
OutBitmap.compress(Bitmap.CompressFormat.PNG, 90, fOut);
fOut.flush();
fOut.close();
//this line will add the saved picture to gallery
MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
calling method by using :
Button memeDanke = (Button) view.findViewById(R.id.memeDanke);
memeDanke.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tackeAndSaveScreenShot(getActivity());
}
});
I want to save a created bitmap after a button clicked
How can I do that? and if possible to a specific location
Here are my codes:
quoteimage.requestLayout();
if (quoteimage.getViewTreeObserver().isAlive()) {
quoteimage.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
// we check which build version we are using
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
quoteimage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
quoteimage.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
viewToBitmap(quoteimage); ///this one creates the bitmap
}
});
}
share.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
///Here I want to save the bitmap
}
});
Call save() in onClick():
protected void save(){
FileOutputStream out = null;
try {
out = new FileOutputStream(filename);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}}
Use this method to save your bitmap, also pass the file name and location as U like
private createDirectoryAndSaveFile(Bitmap imageToSave, String fileName,String location) {
File direct = new File(Environment.getExternalStorageDirectory() + "/"+location);
if (!direct.exists()) {
File wallpaperDirectory = new File("/sdcard/"+location+"/");
wallpaperDirectory.mkdirs();
}
File file = new File(new File("/sdcard/"+location+"/"), fileName+".jpg");
if (file.exists()) {
file.delete();
}
try {
FileOutputStream out = new FileOutputStream(file);
imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
File externalFile = new File(Environment.getExternalStorageDirectory(),"your/location/"+fileName+".jpg");
externaluri = Uri.parse(externalFile.getPath());
Log.d("externaluri", externaluri.toString());
}
Example
createDirectoryAndSaveFile(yourbitmap, "your_image_name" ,"your/location");
Android Saving created bitmap to directory on sd card
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
_bitmapScaled.compress(Bitmap.CompressFormat.JPEG, 40, 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();
I'm trying to screenshot a ScrollView and simply copy+pasted the solution from here: Taking a "screenshot" of a specific layout in Android . Unfortunately I'm getting a NP # Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
My XML is
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/scrollingProfile"
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="wrap_content"
android:background="#drawable/tile_tan_repeat">
<LinearLayout
android:id="#+id/paidLayoutLinearParent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--......-->
</LinearLayout>
</ScrollView>
Anyone have any ideas of why this is happening? I've never really worked with saving files like this so debugging this code is pretty unfamiliar to me.
Thank you!
Edit:This is the code I'm using
public void onClick(View v) {
if(v.getId()==R.id.screenshot){//source: https://stackoverflow.com/questions/10650049/taking-a-screenshot-of-a-specific-layout-in-android
View u = findViewById(R.id.scrollingProfilePaid);
u.setDrawingCacheEnabled(true);
ScrollView z = (ScrollView) findViewById(R.id.scrollingProfilePaid);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
u.layout(0, 0, totalWidth, totalHeight);
u.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
u.setDrawingCacheEnabled(false);
//Save bitmap
String extr = Environment.getExternalStorageDirectory().toString() + File.separator + "Folder";
//String fileName = new SimpleDateFormat("yyyyMMddhhmm'profile.jpg'").format(new Date());
String fileName = "profile.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(getContentResolver(), b, "Screen", "screen");
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
just put the code inside
scrollview.post(
new Runnable()
{
#Override
public void run()
{
//this method will call after scrollview's onDraw method
// so the view is ready to generarte bitmap at this point
//put here your screen shot code
}
});