年末较闲,就上个星期查找各方面的资料关于android截图事情,自已也测试一些代码,已改改进或者优化。接下来进行总结一下。其实,如果真正android系统截屏是需要root权限的。但要用户使用都root,似乎不可能,体验性太差了。这期间我稍微观察了QQ的截图。QQ的截图是摇一摇截图当前屏幕,这个是不需要root权限的。然而,如果你要截图页面不是当前页面,就需要root权限。可以使用360超级root尝试一下。
本文demo下载地址:http://download.csdn.net/detail/qq_16064871/9420810
1、直接使用getWindow().getDecorView().getRootView()
直接使用getWindow().getDecorView().getRootView()是获取当前屏幕的activity。然而对于系统状态栏的信息是截不了,出现一条空白的。如下图:
主要到没,有一条白色边就是系统状态栏。看一下代码,很简单都加了注释了。
-
- private void saveCurrentImage()
- {
-
- int width = getWindow().getDecorView().getRootView().getWidth();
- int height = getWindow().getDecorView().getRootView().getHeight();
-
- Bitmap temBitmap = Bitmap.createBitmap( width, height, Config.ARGB_8888 );
-
- View view = getWindow().getDecorView().getRootView();
-
- view.setDrawingCacheEnabled(true);
- view.buildDrawingCache();
-
- temBitmap = view.getDrawingCache();
-
-
- if (FileIOUtil.getExistStorage()) {
- FileIOUtil.GetInstance().onFolderAnalysis(FileIOUtil.GetInstance().getFilePathAndName());
- File file = new File(FileIOUtil.GetInstance().getFilePathAndName());
- try {
- if (!file.exists()) {
- file.createNewFile();
- }
- FileOutputStream foStream = new FileOutputStream(file);
- temBitmap.compress(Bitmap.CompressFormat.PNG, 100, foStream);
- foStream.flush();
- foStream.close();
- } catch (Exception e) {
- Log.i("Show", e.toString());
- }
- }
- }
2、自定义view控件的截图
自定义view控件都是继承view的吗,那么就有可以获取宽度,高度。生成图片,把它绘制出来的。我拿了直接写的自定义随机验证码的例子来截图。
-
- private void saveCustomViewBitmap() {
-
- Bitmap temBitmap = Bitmap.createBitmap(mCodeView.getWidth(), mCodeView.getHeight(), Config.ARGB_8888);
-
- Canvas canvas = new Canvas(temBitmap);
- mCodeView.onDraw(canvas);
-
-
- if (FileIOUtil.getExistStorage()) {
- FileIOUtil.GetInstance().onFolderAnalysis(FileIOUtil.GetInstance().getFilePathAndName());
- File file = new File(FileIOUtil.GetInstance().getFilePathAndName());
- try {
- if (!file.exists()) {
- file.createNewFile();
- }
- FileOutputStream foStream = new FileOutputStream(file);
- temBitmap.compress(Bitmap.CompressFormat.PNG, 100, foStream);
- foStream.flush();
- foStream.close();
- Toast.makeText(MainActivity.this, "截屏文件已保存至" + FileIOUtil.GetInstance().getFilePathAndName(), Toast.LENGTH_LONG).show();
- } catch (Exception e) {
- Log.i("Show", e.toString());
- }
- }
- }
有人根据这种思路,自定义整个布局的view,然后来截图。也是够拼的,我有点不赞成这样使用。
3、基于android ddmlib截屏
这个是java写的一个类,入口是mian函数。那么这种实现方式是要android连接着电脑,还需要android设备调试。这种不多说,搞android开发都懂。太麻烦了,我们也不使用。
- package com.example.screenshot;
-
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
- import com.android.ddmlib.AdbCommandRejectedException;
- import com.android.ddmlib.AndroidDebugBridge;
- import com.android.ddmlib.IDevice;
- import com.android.ddmlib.RawImage;
- import com.android.ddmlib.TimeoutException;
-
- public class ScreenShoddmlib {
- private BufferedImage image = null;
-
-
-
- public static void main(String[] args) {
-
- AndroidDebugBridge.init(false);
- ScreenShoddmlib screenshot = new ScreenShoddmlib();
- IDevice device = screenshot.getDevice();
-
- for (int i = 0; i < 10; i++) {
- Date date=new Date();
- SimpleDateFormat df=new SimpleDateFormat("MM-dd-HH-mm-ss");
- String nowTime = df.format(date);
- screenshot.getScreenShot(device, "Robotium" + nowTime);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
-
- e.printStackTrace();
- }
- }
- }
-
-
- public void getScreenShot(IDevice device,String filename) {
- RawImage rawScreen = null;
- try {
- rawScreen = device.getScreenshot();
- } catch (TimeoutException e) {
-
- e.printStackTrace();
- } catch (AdbCommandRejectedException e) {
-
- e.printStackTrace();
- } catch (IOException e) {
-
- e.printStackTrace();
- }
- if (rawScreen != null) {
- Boolean landscape = false;
- int width2 = landscape ? rawScreen.height : rawScreen.width;
- int height2 = landscape ? rawScreen.width : rawScreen.height;
- if (image == null) {
- image = new BufferedImage(width2, height2,
- BufferedImage.TYPE_INT_RGB);
- } else {
- if (image.getHeight() != height2 || image.getWidth() != width2) {
- image = new BufferedImage(width2, height2,
- BufferedImage.TYPE_INT_RGB);
- }
- }
- int index = 0;
- int indexInc = rawScreen.bpp >> 3;
- for (int y = 0; y < rawScreen.height; y++) {
- for (int x = 0; x < rawScreen.width; x++, index += indexInc) {
- int value = rawScreen.getARGB(index);
- if (landscape)
- image.setRGB(y, rawScreen.width - x - 1, value);
- else
- image.setRGB(x, y, value);
- }
- }
- try {
- ImageIO.write((RenderedImage) image, "PNG", new File("D:/"
- + filename + ".jpg"));
- } catch (IOException e) {
-
- e.printStackTrace();
- }
- }
- }
-
-
-
-
-
- private IDevice getDevice(){
- IDevice device;
- AndroidDebugBridge bridge = AndroidDebugBridge
- .createBridge("adb", true);
- waitDevicesList(bridge);
- IDevice devices[] = bridge.getDevices();
- device = devices[0];
- return device;
- }
-
-
-
-
-
- private void waitDevicesList(AndroidDebugBridge bridge) {
- int count = 0;
- while (bridge.hasInitialDeviceList() == false) {
- try {
- Thread.sleep(500);
- count++;
- } catch (InterruptedException e) {
- }
- if (count > 240) {
- System.err.print("等待获取设备超时");
- break;
- }
- }
- }
4、使用adb命令
需要系统权限,在APK中调用“adb shell screencap -pfilepath” 命令
需要获得系统权限:1、 在AndroidManifest.xml文件中添加 <uses-permissionandroid:name="android.permission.READ_FRAME_BUFFER"/>
2、修改APK为系统权限,将APK放到源码中编译, 修改Android.mk LOCAL_CERTIFICATE := platform
在这里我要说一下,搞过jni调用就知道Android.mk的作用。此举也是麻烦,效果也不是很好。
- public void takeScreenShot(){
- String mSavedPath = Environment.getExternalStorageDirectory()+File. separator + "screenshot.png" ;
- try {
- Runtime. getRuntime().exec("screencap -p " + mSavedPath);
- } catch (Exception e) {
- e.printStackTrace();
- }
5、看一下系统截屏是怎样的
相信大家都知道,三星的机子是同时按下 home键 + 电源键 3秒截图。
如果没有home键的机子是按下 音量键向下那个 + 电源键 3秒截图的。
获取物理键盘按下的源码:PhoneWindowManager.java
响应截屏的方法:
- private void interceptScreenshotChord() {
- if (mScreenshotChordEnabled
- && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
- final long now = SystemClock.uptimeMillis();
- if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
- && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
- mVolumeDownKeyConsumedByScreenshotChord = true;
- cancelPendingPowerKeyAction();
-
- mHandler.postDelayed(mScreenshotChordLongPress, getScreenshotChordLongPressDelay());
- }
- }
- }
-
- private long getScreenshotChordLongPressDelay() {
- if (mKeyguardMediator.isShowing()) {
-
- return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
- ViewConfiguration.getGlobalActionKeyTimeout());
- } else {
- return ViewConfiguration.getGlobalActionKeyTimeout();
- }
- }
接受响应的服务
- private final Runnable mScreenshotChordLongPress = new Runnable() {
- public void run() {
- takeScreenshot();
- }
- };
- private void takeScreenshot() {
- synchronized (mScreenshotLock) {
- if (mScreenshotConnection != null) {
- return;
- }
- ComponentName cn = new ComponentName("com.android.systemui",
- "com.android.systemui.screenshot.TakeScreenshotService");
- Intent intent = new Intent();
- intent.setComponent(cn);
- ServiceConnection conn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- synchronized (mScreenshotLock) {
- if (mScreenshotConnection != this) {
- return;
- }
- Messenger messenger = new Messenger(service);
- Message msg = Message.obtain(null, 1);
- final ServiceConnection myConn = this;
- Handler h = new Handler(mHandler.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- synchronized (mScreenshotLock) {
- if (mScreenshotConnection == myConn) {
- mContext.unbindService(mScreenshotConnection);
- mScreenshotConnection = null;
- mHandler.removeCallbacks(mScreenshotTimeout);
- }
- }
- }
- };
- msg.replyTo = new Messenger(h);
- msg.arg1 = msg.arg2 = 0;
- if (mStatusBar != null && mStatusBar.isVisibleLw())
- msg.arg1 = 1;
- if (mNavigationBar != null && mNavigationBar.isVisibleLw())
- msg.arg2 = 1;
- try {
- messenger.send(msg);
- } catch (RemoteException e) {
- }
- }
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {}
- };
- if (mContext.bindService(
- intent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) {
- mScreenshotConnection = conn;
- mHandler.postDelayed(mScreenshotTimeout, 10000);
- }
- }
- }
启动时这个服务 ComponentName cn = new ComponentName("com.android.systemui", "com.android.systemui.screenshot.TakeScreenshotService");
- package com.android.systemui.screenshot;
-
- import android.app.Service;
- import android.content.Intent;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.os.Messenger;
- import android.os.RemoteException;
-
- public class TakeScreenshotService extends Service {
- private static final String TAG = "TakeScreenshotService";
-
- private static GlobalScreenshot mScreenshot;
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case 1:
- final Messenger callback = msg.replyTo;
- if (mScreenshot == null) {
- mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
- }
- mScreenshot.takeScreenshot(new Runnable() {
- @Override public void run() {
- Message reply = Message.obtain(null, 1);
- try {
- callback.send(reply);
- } catch (RemoteException e) {
- }
- }
- }, msg.arg1 > 0, msg.arg2 > 0);
- }
- }
- };
-
- @Override
- public IBinder onBind(Intent intent) {
- return new Messenger(mHandler).getBinder();
- }
再往下就是底层库,需要编译出来才能看得到了。这些就先不研究了。
6、还有部分系统源码是截图的
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- package com.android.systemui.screenshot;
-
- import android.animation.Animator;
- import android.animation.AnimatorListenerAdapter;
- import android.animation.AnimatorSet;
- import android.animation.ValueAnimator;
- import android.animation.ValueAnimator.AnimatorUpdateListener;
- import android.app.Notification;
- import android.app.Notification.BigPictureStyle;
- import android.app.NotificationManager;
- import android.app.PendingIntent;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.Intent;
- import android.content.res.Resources;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.ColorMatrix;
- import android.graphics.ColorMatrixColorFilter;
- import android.graphics.Matrix;
- import android.graphics.Paint;
- import android.graphics.PixelFormat;
- import android.graphics.PointF;
- import android.media.MediaActionSound;
- import android.net.Uri;
- import android.os.AsyncTask;
- import android.os.Environment;
- import android.os.Process;
- import android.provider.MediaStore;
- import android.util.DisplayMetrics;
- import android.view.Display;
- import android.view.LayoutInflater;
- import android.view.MotionEvent;
- import android.view.Surface;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.WindowManager;
- import android.view.animation.Interpolator;
- import android.widget.ImageView;
-
- import com.android.systemui.R;
-
- import java.io.File;
- import java.io.OutputStream;
- import java.text.SimpleDateFormat;
- import java.util.Date;
-
-
-
-
- class SaveImageInBackgroundData {
- Context context;
- Bitmap image;
- Uri imageUri;
- Runnable finisher;
- int iconSize;
- int result;
- }
-
-
-
-
- class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
- SaveImageInBackgroundData> {
- private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
- private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
- private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
-
- private int mNotificationId;
- private NotificationManager mNotificationManager;
- private Notification.Builder mNotificationBuilder;
- private String mImageFileName;
- private String mImageFilePath;
- private long mImageTime;
- private BigPictureStyle mNotificationStyle;
-
-
-
-
-
-
- private static boolean mTickerAddSpace;
-
- SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
- NotificationManager nManager, int nId) {
- Resources r = context.getResources();
-
-
- mImageTime = System.currentTimeMillis();
- String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime));
- String imageDir = Environment.getExternalStoragePublicDirectory(
- Environment.DIRECTORY_PICTURES).getAbsolutePath();
- mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
- mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir,
- SCREENSHOTS_DIR_NAME, mImageFileName);
-
-
- int imageWidth = data.image.getWidth();
- int imageHeight = data.image.getHeight();
- int iconSize = data.iconSize;
-
- final int shortSide = imageWidth < imageHeight ? imageWidth : imageHeight;
- Bitmap preview = Bitmap.createBitmap(shortSide, shortSide, data.image.getConfig());
- Canvas c = new Canvas(preview);
- Paint paint = new Paint();
- ColorMatrix desat = new ColorMatrix();
- desat.setSaturation(0.25f);
- paint.setColorFilter(new ColorMatrixColorFilter(desat));
- Matrix matrix = new Matrix();
- matrix.postTranslate((shortSide - imageWidth) / 2,
- (shortSide - imageHeight) / 2);
- c.drawBitmap(data.image, matrix, paint);
- c.drawColor(0x40FFFFFF);
-
- Bitmap croppedIcon = Bitmap.createScaledBitmap(preview, iconSize, iconSize, true);
-
-
- mTickerAddSpace = !mTickerAddSpace;
- mNotificationId = nId;
- mNotificationManager = nManager;
- mNotificationBuilder = new Notification.Builder(context)
- .setTicker(r.getString(R.string.screenshot_saving_ticker)
- + (mTickerAddSpace ? " " : ""))
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setContentText(r.getString(R.string.screenshot_saving_text))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setWhen(System.currentTimeMillis());
-
- mNotificationStyle = new Notification.BigPictureStyle()
- .bigPicture(preview);
- mNotificationBuilder.setStyle(mNotificationStyle);
-
- Notification n = mNotificationBuilder.build();
- n.flags |= Notification.FLAG_NO_CLEAR;
- mNotificationManager.notify(nId, n);
-
-
-
-
- mNotificationBuilder.setLargeIcon(croppedIcon);
-
- mNotificationStyle.bigLargeIcon(null);
- }
-
- @Override
- protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
- if (params.length != 1) return null;
-
-
-
- Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
-
- Context context = params[0].context;
- Bitmap image = params[0].image;
- Resources r = context.getResources();
-
- try {
-
- ContentValues values = new ContentValues();
- ContentResolver resolver = context.getContentResolver();
- values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath);
- values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName);
- values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName);
- values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime);
- values.put(MediaStore.Images.ImageColumns.DATE_ADDED, mImageTime);
- values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, mImageTime);
- values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
- Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
-
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/png");
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
-
- Intent chooserIntent = Intent.createChooser(sharingIntent, null);
- chooserIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_ACTIVITY_NEW_TASK);
-
- mNotificationBuilder.addAction(R.drawable.ic_menu_share,
- r.getString(com.android.internal.R.string.share),
- PendingIntent.getActivity(context, 0, chooserIntent,
- PendingIntent.FLAG_CANCEL_CURRENT));
-
- OutputStream out = resolver.openOutputStream(uri);
- image.compress(Bitmap.CompressFormat.PNG, 100, out);
- out.flush();
- out.close();
-
-
- values.clear();
- values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length());
- resolver.update(uri, values, null, null);
-
- params[0].imageUri = uri;
- params[0].result = 0;
- } catch (Exception e) {
-
-
- params[0].result = 1;
- }
-
- return params[0];
- }
-
- @Override
- protected void onPostExecute(SaveImageInBackgroundData params) {
- if (params.result > 0) {
-
- GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager);
- } else {
-
- Resources r = params.context.getResources();
-
-
- Intent launchIntent = new Intent(Intent.ACTION_VIEW);
- launchIntent.setDataAndType(params.imageUri, "image/png");
- launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- mNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
- .setWhen(System.currentTimeMillis())
- .setAutoCancel(true);
-
- Notification n = mNotificationBuilder.build();
- n.flags &= ~Notification.FLAG_NO_CLEAR;
- mNotificationManager.notify(mNotificationId, n);
- }
- params.finisher.run();
- }
- }
-
-
-
-
-
-
-
- class GlobalScreenshot {
- private static final int SCREENSHOT_NOTIFICATION_ID = 789;
- private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
- private static final int SCREENSHOT_DROP_IN_DURATION = 430;
- private static final int SCREENSHOT_DROP_OUT_DELAY = 500;
- private static final int SCREENSHOT_DROP_OUT_DURATION = 430;
- private static final int SCREENSHOT_DROP_OUT_SCALE_DURATION = 370;
- private static final int SCREENSHOT_FAST_DROP_OUT_DURATION = 320;
- private static final float BACKGROUND_ALPHA = 0.5f;
- private static final float SCREENSHOT_SCALE = 1f;
- private static final float SCREENSHOT_DROP_IN_MIN_SCALE = SCREENSHOT_SCALE * 0.725f;
- private static final float SCREENSHOT_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.45f;
- private static final float SCREENSHOT_FAST_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.6f;
- private static final float SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET = 0f;
-
- private Context mContext;
- private WindowManager mWindowManager;
- private WindowManager.LayoutParams mWindowLayoutParams;
- private NotificationManager mNotificationManager;
- private Display mDisplay;
- private DisplayMetrics mDisplayMetrics;
- private Matrix mDisplayMatrix;
-
- private Bitmap mScreenBitmap;
- private View mScreenshotLayout;
- private ImageView mBackgroundView;
- private ImageView mScreenshotView;
- private ImageView mScreenshotFlash;
-
- private AnimatorSet mScreenshotAnimation;
-
- private int mNotificationIconSize;
- private float mBgPadding;
- private float mBgPaddingScale;
-
- private MediaActionSound mCameraSound;
-
-
-
-
-
- public GlobalScreenshot(Context context) {
- Resources r = context.getResources();
- mContext = context;
- LayoutInflater layoutInflater = (LayoutInflater)
- context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-
- mDisplayMatrix = new Matrix();
- mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
- mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
- mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
- mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
- mScreenshotLayout.setFocusable(true);
- mScreenshotLayout.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
-
- return true;
- }
- });
-
-
- mWindowLayoutParams = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
- WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
- WindowManager.LayoutParams.FLAG_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
- PixelFormat.TRANSLUCENT);
- mWindowLayoutParams.setTitle("ScreenshotAnimation");
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- mNotificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- mDisplay = mWindowManager.getDefaultDisplay();
- mDisplayMetrics = new DisplayMetrics();
- mDisplay.getRealMetrics(mDisplayMetrics);
-
-
- mNotificationIconSize =
- r.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
-
-
- mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
- mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
-
-
- mCameraSound = new MediaActionSound();
- mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
- }
-
-
-
-
- private void saveScreenshotInWorkerThread(Runnable finisher) {
- SaveImageInBackgroundData data = new SaveImageInBackgroundData();
- data.context = mContext;
- data.image = mScreenBitmap;
- data.iconSize = mNotificationIconSize;
- data.finisher = finisher;
- new SaveImageInBackgroundTask(mContext, data, mNotificationManager,
- SCREENSHOT_NOTIFICATION_ID).execute(data);
- }
-
-
-
-
- private float getDegreesForRotation(int value) {
- switch (value) {
- case Surface.ROTATION_90:
- return 360f - 90f;
- case Surface.ROTATION_180:
- return 360f - 180f;
- case Surface.ROTATION_270:
- return 360f - 270f;
- }
- return 0f;
- }
-
-
-
-
- void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
-
-
- mDisplay.getRealMetrics(mDisplayMetrics);
- float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
- float degrees = getDegreesForRotation(mDisplay.getRotation());
- boolean requiresRotation = (degrees > 0);
- if (requiresRotation) {
-
- mDisplayMatrix.reset();
- mDisplayMatrix.preRotate(-degrees);
- mDisplayMatrix.mapPoints(dims);
- dims[0] = Math.abs(dims[0]);
- dims[1] = Math.abs(dims[1]);
- }
-
-
- mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
- if (mScreenBitmap == null) {
- notifyScreenshotError(mContext, mNotificationManager);
- finisher.run();
- return;
- }
-
- if (requiresRotation) {
-
- Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(ss);
- c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
- c.rotate(degrees);
- c.translate(-dims[0] / 2, -dims[1] / 2);
- c.drawBitmap(mScreenBitmap, 0, 0, null);
- c.setBitmap(null);
- mScreenBitmap = ss;
- }
-
-
- mScreenBitmap.setHasAlpha(false);
- mScreenBitmap.prepareToDraw();
-
-
- startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
- statusBarVisible, navBarVisible);
- }
-
-
-
-
-
- private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible,
- boolean navBarVisible) {
-
- mScreenshotView.setImageBitmap(mScreenBitmap);
- mScreenshotLayout.requestFocus();
-
-
- if (mScreenshotAnimation != null) {
- mScreenshotAnimation.end();
- }
-
- mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
- ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
- ValueAnimator screenshotFadeOutAnim = createScreenshotDropOutAnimation(w, h,
- statusBarVisible, navBarVisible);
- mScreenshotAnimation = new AnimatorSet();
- mScreenshotAnimation.playSequentially(screenshotDropInAnim, screenshotFadeOutAnim);
- mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
-
- saveScreenshotInWorkerThread(finisher);
- mWindowManager.removeView(mScreenshotLayout);
- }
- });
- mScreenshotLayout.post(new Runnable() {
- @Override
- public void run() {
-
- mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
-
- mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mScreenshotView.buildLayer();
- mScreenshotAnimation.start();
- }
- });
- }
- private ValueAnimator createScreenshotDropInAnimation() {
- final float flashPeakDurationPct = ((float) (SCREENSHOT_FLASH_TO_PEAK_DURATION)
- / SCREENSHOT_DROP_IN_DURATION);
- final float flashDurationPct = 2f * flashPeakDurationPct;
- final Interpolator flashAlphaInterpolator = new Interpolator() {
- @Override
- public float getInterpolation(float x) {
-
- if (x <= flashDurationPct) {
- return (float) Math.sin(Math.PI * (x / flashDurationPct));
- }
- return 0;
- }
- };
- final Interpolator scaleInterpolator = new Interpolator() {
- @Override
- public float getInterpolation(float x) {
-
- if (x < flashPeakDurationPct) {
- return 0;
- }
- return (x - flashDurationPct) / (1f - flashDurationPct);
- }
- };
- ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
- anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mBackgroundView.setAlpha(0f);
- mBackgroundView.setVisibility(View.VISIBLE);
- mScreenshotView.setAlpha(0f);
- mScreenshotView.setTranslationX(0f);
- mScreenshotView.setTranslationY(0f);
- mScreenshotView.setScaleX(SCREENSHOT_SCALE + mBgPaddingScale);
- mScreenshotView.setScaleY(SCREENSHOT_SCALE + mBgPaddingScale);
- mScreenshotView.setVisibility(View.VISIBLE);
- mScreenshotFlash.setAlpha(0f);
- mScreenshotFlash.setVisibility(View.VISIBLE);
- }
- @Override
- public void onAnimationEnd(android.animation.Animator animation) {
- mScreenshotFlash.setVisibility(View.GONE);
- }
- });
- anim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (Float) animation.getAnimatedValue();
- float scaleT = (SCREENSHOT_SCALE + mBgPaddingScale)
- - scaleInterpolator.getInterpolation(t)
- * (SCREENSHOT_SCALE - SCREENSHOT_DROP_IN_MIN_SCALE);
- mBackgroundView.setAlpha(scaleInterpolator.getInterpolation(t) * BACKGROUND_ALPHA);
- mScreenshotView.setAlpha(t);
- mScreenshotView.setScaleX(scaleT);
- mScreenshotView.setScaleY(scaleT);
- mScreenshotFlash.setAlpha(flashAlphaInterpolator.getInterpolation(t));
- }
- });
- return anim;
- }
- private ValueAnimator createScreenshotDropOutAnimation(int w, int h, boolean statusBarVisible,
- boolean navBarVisible) {
- ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
- anim.setStartDelay(SCREENSHOT_DROP_OUT_DELAY);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mBackgroundView.setVisibility(View.GONE);
- mScreenshotView.setVisibility(View.GONE);
- mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
- }
- });
-
- if (!statusBarVisible || !navBarVisible) {
-
- anim.setDuration(SCREENSHOT_FAST_DROP_OUT_DURATION);
- anim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (Float) animation.getAnimatedValue();
- float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- - t * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_FAST_DROP_OUT_MIN_SCALE);
- mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
- mScreenshotView.setAlpha(1f - t);
- mScreenshotView.setScaleX(scaleT);
- mScreenshotView.setScaleY(scaleT);
- }
- });
- } else {
-
- final float scaleDurationPct = (float) SCREENSHOT_DROP_OUT_SCALE_DURATION
- / SCREENSHOT_DROP_OUT_DURATION;
- final Interpolator scaleInterpolator = new Interpolator() {
- @Override
- public float getInterpolation(float x) {
- if (x < scaleDurationPct) {
-
- return (float) (1f - Math.pow(1f - (x / scaleDurationPct), 2f));
- }
- return 1f;
- }
- };
-
-
- float halfScreenWidth = (w - 2f * mBgPadding) / 2f;
- float halfScreenHeight = (h - 2f * mBgPadding) / 2f;
- final float offsetPct = SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET;
- final PointF finalPos = new PointF(
- -halfScreenWidth + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenWidth,
- -halfScreenHeight + (SCREENSHOT_DROP_OUT_MIN_SCALE + offsetPct) * halfScreenHeight);
-
-
- anim.setDuration(SCREENSHOT_DROP_OUT_DURATION);
- anim.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = (Float) animation.getAnimatedValue();
- float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
- - scaleInterpolator.getInterpolation(t)
- * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_DROP_OUT_MIN_SCALE);
- mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
- mScreenshotView.setAlpha(1f - scaleInterpolator.getInterpolation(t));
- mScreenshotView.setScaleX(scaleT);
- mScreenshotView.setScaleY(scaleT);
- mScreenshotView.setTranslationX(t * finalPos.x);
- mScreenshotView.setTranslationY(t * finalPos.y);
- }
- });
- }
- return anim;
- }
-
- static void notifyScreenshotError(Context context, NotificationManager nManager) {
- Resources r = context.getResources();
-
-
- Notification n = new Notification.Builder(context)
- .setTicker(r.getString(R.string.screenshot_failed_title))
- .setContentTitle(r.getString(R.string.screenshot_failed_title))
- .setContentText(r.getString(R.string.screenshot_failed_text))
- .setSmallIcon(R.drawable.stat_notify_image_error)
- .setWhen(System.currentTimeMillis())
- .setAutoCancel(true)
- .getNotification();
- nManager.notify(SCREENSHOT_NOTIFICATION_ID, n);
- }
可以从这部分源码中,去寻找解决办法。
其中有一个很重要的方法就是
mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
这个是可以截图的,但是是隐藏的代码,不提供外面调用的。
注意需要在AndroidManifest.xml中加入代码:android:sharedUserId="android.uid.system" 进行后续开发。
先到这里,有时间后续再从这里往下研究。各位也可以yanjiuyxia
本文demo下载地址:http://download.csdn.net/detail/qq_16064871/9420810