android实现手机截屏并保存截图功能

作者:袖梨 2022-06-25

本文实例为大家分享了android实现手机截屏并保存截图功能的具体代码,供大家参考,具体内容如下

一、准备一张图片

拷贝screenshot_panel.9.png放在目录drawable-xhdpi下

二、activity_main.xml

代码如下:


 
  
  
  

三、新建xml文件


 

  
  
  flash"
    android:layout_
    android:layout_
    android:src="@android:color/white"
    android:visibility="gone" />

四、在dimens.xml添加一项

 20dp

五、后台代码

1)SurfaceControl.java

import android.graphics.Bitmap;
import android.view.View;
 
public class SurfaceControl {
 
  public static Bitmap screenshot(View view) {
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bmp = view.getDrawingCache();
    return bmp;
  }
}

2)GlobalScreenShot.java代码如下,其中SavePicture方法有保存截图的路径

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
 
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.Toast;
 
/**
 * POD used in the AsyncTask which saves an image in the background.
 */
class SaveImageInBackgroundData {
  Context context;
  Bitmap image;
  Uri imageUri;
  Runnable finisher;
  int iconSize;
  int result;
 
  void clearImage() {
    image = null;
    imageUri = null;
    iconSize = 0;
  }
 
  void clearContext() {
    context = null;
  }
}
 
 
/**
 * TODO:
 * - Performance when over gl surfaces? Ie. Gallery
 * - what do we say in the Toast? Which icon do we get if the user uses another
 * type of gallery?
 */
class GlobalScreenshot {
  private static final String TAG = "GlobalScreenshot";
 
  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 Display mDisplay;
  private DisplayMetrics mDisplayMetrics;
 
  private Bitmap mScreenBitmap;
  private View mScreenshotLayout;
  private ImageView mBackgroundView;
  private ImageView mScreenshotView;
  private ImageView mScreenshotFlash;
 
  private AnimatorSet mScreenshotAnimation;
 
  private float mBgPadding;
  private float mBgPaddingScale;
 
  private MediaActionSound mCameraSound;
 
 
  /**
   * @param context everything needs a context :(
   */
  public GlobalScreenshot(Context context) {
    Resources r = context.getResources();
    mContext = context;
    LayoutInflater layoutInflater = (LayoutInflater)
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
    // Inflate the screenshot layout
    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) {
        // Intercept and ignore all touch events
        return true;
      }
    });
 
    // Setup the window that we are going to use
    mWindowLayoutParams = new WindowManager.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
        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);
 
    mDisplay = mWindowManager.getDefaultDisplay();
    mDisplayMetrics = new DisplayMetrics();
    mDisplay.getRealMetrics(mDisplayMetrics);
 
    // Scale has to account for both sides of the bg
    mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
    mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
 
    // Setup the Camera shutter sound
    mCameraSound = new MediaActionSound();
    mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
  }
 
 
 
  /**
   * Takes a screenshot of the current display and shows an animation.
   */
  void takeScreenshot(View view, Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
    // Take the screenshot
   Log.d("debug","takeScreenshot start");
    mScreenBitmap = SurfaceControl.screenshot(view);
   Log.d("debug","takeScreenshot 1");
    if (mScreenBitmap == null) {
      notifyScreenshotError(mContext);
      finisher.run();
      return;
    }
    
    // Optimizations
    mScreenBitmap.setHasAlpha(false);
    mScreenBitmap.prepareToDraw();
 
    Log.d("debug","takeScreenshot 2");
 
    
    Log.d("debug","takeScreenshot 3");
    // Start the post-screenshot animation
    startAnimation(finisher, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
        statusBarVisible, navBarVisible);
  
    Log.d("debug","takeScreenshot end");
  }
 
  private void SavePicture(){
   Log.d("debug","SavePicture 1");
    mScreenshotView.setDrawingCacheEnabled(true);
    Log.d("debug","SavePicture 2");
    Bitmap obmp = Bitmap.createBitmap(mScreenshotView.getDrawingCache());
    Log.d("debug","SavePicture 3");
     
    if (obmp != null) {
     // 图片存储路径
   String SavePath = getSDCardPath() + "/test/ScreenImages";
   // 保存Bitmap
   Log.d("debug","SavePath = "+SavePath);
   try {
    File path = new File(SavePath);
    // 文件
    String filepath = SavePath + "/Screen_1.png";
    Log.d("debug","filepath = "+filepath);
    File file = new File(filepath);
    if (!path.exists()) {
    Log.d("debug","path is not exists");
    path.mkdirs();
    }
    if (!file.exists()) {
    Log.d("debug","file create new ");
    file.createNewFile();
    }
    FileOutputStream fos = null;
    fos = new FileOutputStream(file);
    if (null != fos) {
    obmp.compress(Bitmap.CompressFormat.PNG, 90, fos);
    fos.flush();
    fos.close();
    Log.d("debug","save ok");
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
 }
    
  }
  
  /**
 * 获取SDCard的目录路径功能
 * 
 * @return
 */
 private String getSDCardPath() {
 File sdcardDir = null;
 // 判断SDCard是否存在
 boolean sdcardExist = Environment.getExternalStorageState().equals(
  android.os.Environment.MEDIA_MOUNTED);
 if (sdcardExist) {
  sdcardDir = Environment.getExternalStorageDirectory();
 }
 return sdcardDir.toString();
 }
 
  /**
   * Starts the animation after taking the screenshot
   */
  private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible,
                boolean navBarVisible) {
    // Add the view for the animation
    mScreenshotView.setImageBitmap(mScreenBitmap);
    mScreenshotLayout.requestFocus();
 
    // Setup the animation with the screenshot just taken
    if (mScreenshotAnimation != null) {
      mScreenshotAnimation.end();
      mScreenshotAnimation.removeAllListeners();
    }
 
    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) {
        // Save the screenshot once we have a bit of time now
        saveScreenshotInWorkerThread(finisher);
        mWindowManager.removeView(mScreenshotLayout);
 
        SavePicture();
        // Clear any references to the bitmap
        mScreenBitmap = null;
        mScreenshotView.setImageBitmap(null);
      }
    });
    mScreenshotLayout.post(new Runnable() {
      @Override
      public void run() {
        // Play the shutter sound to notify that we've taken a screenshot
        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) {
        // Flash the flash view in and out quickly
        if (x <= flashDurationPct) {
          return (float) Math.sin(Math.PI * (x / flashDurationPct));
        }
        return 0;
      }
    };
    final Interpolator scaleInterpolator = new Interpolator() {
      @Override
      public float getInterpolation(float x) {
        // We start scaling when the flash is at it's peak
        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) {
      // There is no status bar/nav bar, so just fade the screenshot away in place
      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 {
      // In the case where there is a status bar, animate to the origin of the bar (top-left)
      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) {
            // Decelerate, and scale the input accordingly
            return (float) (1f - Math.pow(1f - (x / scaleDurationPct), 2f));
          }
          return 1f;
        }
      };
      // Determine the bounds of how to scale
      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);
      // Animate the screenshot to the status bar
      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;
  }
  private void notifyScreenshotError(Context context) {
  }
  private void saveScreenshotInWorkerThread(Runnable runnable) {
  }
}

3)在MainActivity.java调用

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
 
public class MainActivity extends Activity {
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 
   final GlobalScreenshot screenshot = new GlobalScreenshot(this);
     findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
       
         screenshot.takeScreenshot(getWindow().getDecorView(), new Runnable() {
           @Override
           public void run() {
 
           }
         }, true, true);
       }
     });
 }
  @Override
   public boolean onCreateOptionsMenu(Menu menu) {
     // Inflate the menu; this adds items to the action bar if it is present.
     getMenuInflater().inflate(R.menu.main, menu);
     return true;
   }
 
   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
     // Handle action bar item clicks here. The action bar will
     // automatically handle clicks on the Home/Up button, so long
     // as you specify a parent activity in AndroidManifest.xml.
     int id = item.getItemId();
     if (id == R.id.action_settings) {
       return true;
     }
     return super.onOptionsItemSelected(item);
   }
 
}

六、AndroidManifest.xml设置权限


相关文章

精彩推荐