I tried a lot and even searched a lot, but I did not find a solution to the black screen that I get, getting a cache view of the surface view . if there is any other way to capture the screen then let me know about it. if I use another control and get the retrievable cache of this control, it also returns null .. this is the code I used to get the image on the screen ....
try { // Button btn = new Button(mActivity.getApplicationContext()); view.buildDrawingCache(); view.setDrawingCacheEnabled(true); Bitmap b = view.getDrawingCache(); b.compress(CompressFormat.JPEG, 100, new FileOutputStream( "/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG")); } catch (Exception e) { e.printStackTrace(); }
I used this with the touch_up action of the surface view .....
EDIT:
public class DroidReaderActivity extends Activity { private static final boolean LOG = false; private static final int REQUEST_CODE_PICK_FILE = 1; private static final int REQUEST_CODE_OPTION_DIALOG = 2; private static final int DIALOG_GET_PASSWORD = 1; private static final int DIALOG_ABOUT = 2; private static final int DIALOG_GOTO_PAGE = 3; private static final int DIALOG_WELCOME = 4; private static final int DIALOG_ENTER_ZOOM = 5; private static final String PREFERENCE_EULA_ACCEPTED = "eula.accepted"; private static final String PREFERENCES_EULA = "eula"; protected DroidReaderView mReaderView = null; protected DroidReaderDocument mDocument = null; protected Menu m_ZoomMenu; FrameLayout fl; private String mFilename; private String mTemporaryFilename; private String mPassword; private int mPageNo; private SQLiteDatabase db; static DatabaseConnectionAPI db_api; private boolean mDocumentIsOpen = false; private boolean mLoadedDocument = false; private boolean mWelcomeShown = false; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_CODE_PICK_FILE: if (resultCode == RESULT_OK && data != null) { // Theoretically there could be a case where OnCreate() is called // again with the intent that was originally used to open the app, // which would revert to a previous document. Use setIntent // to update the intent that will be supplied back to OnCreate(). setIntent(data); mTemporaryFilename = data.getDataString(); if (mTemporaryFilename != null) { if (mTemporaryFilename.startsWith("file://")) { mTemporaryFilename = mTemporaryFilename.substring(7); } mPassword = ""; openDocumentWithDecodeAndLookup(); } } break; case REQUEST_CODE_OPTION_DIALOG: readPreferences(); tryLoadLastFile(); break; } } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); System.out.println("ONCREATE"); db_api = new DatabaseConnectionAPI(this); try { db_api.createDataBase(); db_api.openDataBase(); } catch (IOException e) { e.printStackTrace(); } // first, show the welcome if it hasn't been shown already: final SharedPreferences preferences = getSharedPreferences(PREFERENCES_EULA, Context.MODE_PRIVATE); if (!preferences.getBoolean(PREFERENCE_EULA_ACCEPTED, false)) { mWelcomeShown = true; preferences.edit().putBoolean(PREFERENCE_EULA_ACCEPTED, true).commit(); showDialog(DIALOG_WELCOME); } if (mDocument == null) mDocument = new DroidReaderDocument(); // Initialize the PdfRender engine PdfRender.setFontProvider(new DroidReaderFontProvider(this)); // then build our layout. it so simple that we don't use // XML for now. fl = new FrameLayout(this); mReaderView = new DroidReaderView(this, null, mDocument); // add the viewing area and the navigation fl.addView(mReaderView); setContentView(fl); readPreferences(); if (savedInstanceState != null) { mFilename = savedInstanceState.getString("filename"); if ((new File(mFilename)).exists()) { mPassword = savedInstanceState.getString("password"); mDocument.mZoom = savedInstanceState.getFloat("zoom"); mDocument.mRotation = savedInstanceState.getInt("rotation"); mPageNo = savedInstanceState.getInt("page"); mDocument.mMarginOffsetX = savedInstanceState.getInt("marginOffsetX"); mDocument.mMarginOffsetY = savedInstanceState.getInt("marginOffsetY"); mDocument.mContentFitMode = savedInstanceState.getInt("contentFitMode"); openDocument(); mLoadedDocument = true; } savedInstanceState.clear(); } Timer mTimer = new Timer(); mTimer.schedule(new TimerTask() { @Override public void run() { try { Bitmap saveBitmap = Bitmap.createBitmap(fl.getWidth(), fl.getHeight(), Bitmap.Config.ARGB_8888); saveBitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream("/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG")); } catch (Exception e) { e.printStackTrace(); } } }, 4000); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if ((mDocument != null) && mDocument.isPageLoaded()) { outState.putFloat("zoom", mDocument.mZoom); outState.putInt("rotation", mDocument.mRotation); outState.putInt("page", mDocument.mPage.no); outState.putInt("offsetX", mDocument.mOffsetX); outState.putInt("offsetY", mDocument.mOffsetY); outState.putInt("marginOffsetX", mDocument.mMarginOffsetX); outState.putInt("marginOffsetY", mDocument.mMarginOffsetY); outState.putInt("contentFitMode", mDocument.mContentFitMode); outState.putString("password", mPassword); outState.putString("filename", mFilename); mDocument.closeDocument(); } } public void onTap(float X, float Y) { float left, right, top, bottom; float width = mDocument.mDisplaySizeX; float height = mDocument.mDisplaySizeY; boolean prev = false; boolean next = false; if (mDocumentIsOpen) { left = width * (float) 0.25; right = width * (float) 0.75; top = height * (float) 0.25; bottom = height * (float) 0.75; if ((X < left) && (Y < top)) prev = true; if ((X < left) && (Y > bottom)) next = true; if ((X > right) && (Y < top)) prev = true; if ((X > right) && (Y > bottom)) next = true; if ((X > left) && (X < right) && (Y > bottom)) { Log.d("DroidReaderMetrics", String.format("Zoom = %5.2f%%", mDocument.mZoom * 100.0)); Log.d("DroidReaderMetrics", String.format("Page size = (%2.0f,%2.0f)", mDocument.mPage.mMediabox[2] - mDocument.mPage.mMediabox[0], mDocument.mPage.mMediabox[3] - mDocument.mPage.mMediabox[1])); Log.d("DroidReaderMetrics", String.format( "Display size = (%d,%d)", mDocument.mDisplaySizeX, mDocument.mDisplaySizeY)); Log.d("DroidReaderMetrics", String.format("DPI = (%d, %d)", mDocument.mDpiX, mDocument.mDpiY)); Log.d("DroidReaderMetrics", String.format("Content size = (%2.0f,%2.0f)", mDocument.mPage.mContentbox[2] - mDocument.mPage.mContentbox[0], mDocument.mPage.mContentbox[3] - mDocument.mPage.mContentbox[1])); Log.d("DroidReaderMetrics", String.format("Content offset = (%2.0f,%2.0f)", mDocument.mPage.mContentbox[0], mDocument.mPage.mContentbox[1])); Log.d("DroidReaderMetrics", String.format( "Document offset = (%d,%d)", mDocument.mOffsetX, mDocument.mOffsetY)); } if (next) { if (mDocument.havePage(1, true)) openPage(1, true); } else if (prev) { if (mDocument.havePage(-1, true)) openPage(-1, true); } } } protected void openDocument() { // Store the view details for the previous document and close it. if (mDocumentIsOpen) { mDocument.closeDocument(); mDocumentIsOpen = false; } try { this.setTitle(mFilename); mDocument.open(mFilename, mPassword, mPageNo); openPage(0, true); mDocumentIsOpen = true; } catch (PasswordNeededException e) { showDialog(DIALOG_GET_PASSWORD); } catch (WrongPasswordException e) { Toast.makeText(this, R.string.error_wrong_password, Toast.LENGTH_LONG).show(); } catch (Exception e) { Toast.makeText(this, R.string.error_opening_document, Toast.LENGTH_LONG).show(); } } protected void openDocumentWithDecodeAndLookup() { try { mTemporaryFilename = URLDecoder.decode(mTemporaryFilename, "utf-8"); // Do some sanity checks on the supplied filename. File f = new File(mTemporaryFilename); if ((f.exists()) && (f.isFile()) && (f.canRead())) { mFilename = mTemporaryFilename; openDocumentWithLookup(); } else { Toast.makeText(this, R.string.error_file_open_failed, Toast.LENGTH_LONG).show(); } } catch (Exception e) { Toast.makeText(this, R.string.error_opening_document, Toast.LENGTH_LONG).show(); } } protected void openDocumentWithLookup() { readOrWriteDB(false); openDocument(); } protected void openPage(int no, boolean isRelative) { try { if (!(no == 0 && isRelative)) mDocument.openPage(no, isRelative); this.setTitle(new File(mFilename).getName() + String.format(" (%d/%d)", mDocument.mPage.no, mDocument.mDocument.pagecount)); mPageNo = mDocument.mPage.no; } catch (PageLoadException e) { } } private void readPreferences() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); if (prefs.getString("zoom_type", "0").equals("0")) { float zoom = Float.parseFloat(prefs.getString("zoom_percent", "50")); if ((1 <= zoom) && (1000 >= zoom)) { mDocument.setZoom(zoom / 100, false); } } else { mDocument.setZoom(Float.parseFloat(prefs.getString("zoom_type", "0")), false); } if (prefs.getBoolean("dpi_auto", true)) { // read the display DPI mDocument.setDpi((int) metrics.xdpi, (int) metrics.ydpi); } else { int dpi = Integer.parseInt(prefs.getString("dpi_manual", "160")); if ((dpi < 1) || (dpi > 4096)) dpi = 160; // sanity check fallback mDocument.setDpi(dpi, dpi); } if (prefs.getBoolean("tilesize_by_factor", true)) { // set the tile size for rendering by factor Float factor = Float.parseFloat(prefs.getString("tilesize_factor", "1.5")); mDocument.setTileMax((int) (metrics.widthPixels * factor), (int) (metrics.heightPixels * factor)); } else { int tilesize_x = Integer.parseInt(prefs.getString("tilesize_x", "640")); int tilesize_y = Integer.parseInt(prefs.getString("tilesize_x", "480")); if (metrics.widthPixels < metrics.heightPixels) { mDocument.setTileMax(tilesize_x, tilesize_y); } else { mDocument.setTileMax(tilesize_y, tilesize_x); } } boolean invert = prefs.getBoolean("invert_display", false); mDocument.setDisplayInvert(invert); mReaderView.setDisplayInvert(invert); if (prefs.getBoolean("full_screen", false)) { this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } else { this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } mDocument.mHorizontalScrollLock = prefs.getBoolean("horizontal_scroll_lock", false); } protected void setZoom(float newZoom) { newZoom = newZoom / (float) 100.0; if (newZoom > 16.0) newZoom = (float) 16.0; if (newZoom < 0.0625) newZoom = (float) 0.0625; mDocument.setZoom(newZoom, false); } protected void tryLoadLastFile() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); mFilename = prefs.getString("last_open_file", ""); if (mFilename != null) { if ((mFilename.length() > 0) && ((new File(mFilename)).exists())) { // Don't URL-decode the filename, as that presumably already been done. mPassword = ""; openDocumentWithLookup(); mLoadedDocument = true; } } } }
DroidReaderView:
public class DroidReaderView extends SurfaceView implements OnGestureListener, SurfaceHolder.Callback, DroidReaderDocument.RenderListener { public static Path mPath = new Path(); private static StringBuffer sbx = new StringBuffer(); private static StringBuffer sby = new StringBuffer(); public static Paint mPaint = new Paint(); public static Paint nullpaint = new Paint(); private String sx, sy, sbx_str, sby_str; public static Canvas mCanvas = new Canvas(); private int pid = 1; /** * Debug helper */ protected final static String TAG = "DroidReaderView"; protected final static boolean LOG = false; /** * our view thread which does the drawing */ public DroidReaderViewThread mThread; /** * our gesture detector */ protected final GestureDetector mGestureDetector; /** * our context */ protected final DroidReaderActivity mActivity; /** * our SurfaceHolder */ protected final SurfaceHolder mSurfaceHolder; public static DroidReaderDocument mDocument; protected boolean mDisplayInvert; /** * constructs a new View * * @param context * Context for the View * @param attrs * attributes (may be null) */ public DroidReaderView(final DroidReaderActivity activity, AttributeSet attrs, DroidReaderDocument document) { super(activity, attrs); mActivity = activity; mSurfaceHolder = getHolder(); mDocument = document; mDocument.mRenderListener = this; mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); // tell the SurfaceHolder to inform this thread on // changes to the surface mSurfaceHolder.addCallback(this); mGestureDetector = new GestureDetector(this); } /* event listeners: */ @Override protected void onDraw(Canvas canvas) { mThread.c = canvas; mThread.c = mSurfaceHolder.lockCanvas(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(12); mThread.c.drawPath(mPath, mPaint); mSurfaceHolder.unlockCanvasAndPost(mThread.c); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (LOG) Log.d(TAG, "onFling(): notifying ViewThread"); mThread.mScroller.fling(0, 0, -(int) velocityX, -(int) velocityY, -4096, 4096, -4096, 4096); mThread.triggerRepaint(); return true; } /* keyboard events: */ @Override public boolean onKeyDown(int keyCode, KeyEvent msg) { if (LOG) Log.d(TAG, "onKeyDown(), keycode " + keyCode); return false; } @Override public boolean onKeyUp(int keyCode, KeyEvent msg) { if (LOG) Log.d(TAG, "onKeyUp(), keycode " + keyCode); return false; } /* interface for the GestureListener: */ @Override public void onLongPress(MotionEvent e) { if (LOG) Log.d(TAG, "onLongPress(): ignoring!"); } @Override public void onNewRenderedPixmap() { if (LOG) Log.d(TAG, "new rendered pixmap was signalled"); mThread.triggerRepaint(); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (LOG) Log.d(TAG, "onScroll(), distance vector: " + distanceX + "," + distanceY); mDocument.offset((int) distanceX, (int) distanceY, true); mThread.triggerRepaint(); return true; } @Override public void onShowPress(MotionEvent e) { if (LOG) Log.d(TAG, "onShowPress(): ignoring!"); } @Override public boolean onSingleTapUp(MotionEvent e) { // Pass the tap, and the window dimensions, to the activity to process. mActivity.onTap(e.getX(), e.getY()); return true; } private float mX, mY; private static final float TOUCH_TOLERANCE = 4; private void touch_start(float x, float y) { mPath.moveTo(x, y); mX = x; sx = Float.toString(mX); sbx.append(sx); sbx.append(","); mY = y; sy = Float.toString(mY); sby.append(sy); sby.append(","); sbx_str = sbx.toString(); sby_str = sby.toString(); } private void draw_move(float x, float y) { float dx = Math.abs(x - mX); float dy = Math.abs(y - mY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); mX = x; sx = Float.toString(mX); sbx.append(sx); sbx.append(","); mY = y; sy = Float.toString(mY); sby.append(sy); sby.append(","); } } private void touch_up() { mPath.lineTo(mX, mY); sx = Float.toString(mX); sbx.append(sx); sbx.append(","); sy = Float.toString(mY); sby.append(sy); sby.append(","); mPath.reset(); sbx_str = sbx.toString().trim(); sby_str = sby.toString().trim(); insert(TAGS.presentation_id, mDocument.mPage.no, sbx_str, sby_str); sbx = new StringBuffer(); sby = new StringBuffer(); System.out.println(sbx_str.trim()); System.out.println(sby_str.trim()); } @Override public boolean onTouchEvent(final MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touch_start(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: draw_move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touch_up(); invalidate(); try { // Button btn = new Button(mActivity.getApplicationContext()); // buildDrawingCache(); // setDrawingCacheEnabled(true); // Bitmap b = getDrawingCache(); // b.compress(CompressFormat.JPEG, 100, new FileOutputStream( // "/mnt/sdcard/documents/" + new Date().getTime() + ".JPEG")); } catch (Exception e) { e.printStackTrace(); } break; } invalidate(); if (LOG) { Log.d(TAG, "onTouchEvent(): notifying mGestureDetector"); invalidate(); } if (mGestureDetector.onTouchEvent(event)) { invalidate(); return true; } return true; } @Override public boolean onTrackballEvent(MotionEvent event) { if (LOG) Log.d(TAG, "onTouchEvent(): notifying ViewThread"); mDocument .offset((int) event.getX() * 20, (int) event.getY() * 20, true); mThread.triggerRepaint(); return true; } /* surface events: */ public void setDisplayInvert(boolean invert) { if (mThread != null) mThread.setPainters(invert); mDisplayInvert = invert; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (LOG) Log.d(TAG, "surfaceChanged(): size " + width + "x" + height); mDocument.startRendering(width, height); } @Override public void surfaceCreated(SurfaceHolder holder) { if (LOG) Log.d(TAG, "surfaceCreated(): starting ViewThread"); mThread = new DroidReaderViewThread(holder, mActivity, mDocument); mThread.setPainters(mDisplayInvert); mThread.start(); } /* render events */ @Override public void surfaceDestroyed(SurfaceHolder holder) { if (LOG) Log.d(TAG, "surfaceDestroyed(): dying"); mDocument.stopRendering(); boolean retry = true; mThread.mRun = false; mThread.interrupt(); while (retry) { try { mThread.join(); retry = false; } catch (InterruptedException e) { } } } @Override public boolean onDown(MotionEvent e) { return false; }
DroidReaderViewThread:
A theme that takes care to bring glittery pixels to the canvas and handle scrolling
class DroidReaderViewThread extends Thread { public Canvas c = new Canvas(); private Cursor mCursor; private Path mPath1 = new Path(); private StringBuffer sbx_read, sby_read; public static Paint mPaint2 = new Paint(); public static Paint mPaint3 = new Paint(); Path old_path = new Path(); protected final static String TAG = "DroidReaderViewThread"; protected final static boolean LOG = false; protected final SurfaceHolder mSurfaceHolder; protected final Paint mEmptyPaint; protected final Paint mNoPagePaint; protected final Paint mStatusPaint; protected boolean mRun = true; protected final Scroller mScroller; protected final DroidReaderDocument mDocument; public DroidReaderViewThread(SurfaceHolder holder, Context context, DroidReaderDocument document) {