android实现手机截屏并保存截图功能
作者:loveheronly 发布时间:2022-07-16 01:47:46
标签:android,截屏
本文实例为大家分享了android实现手机截屏并保存截图功能的具体代码,供大家参考,具体内容如下
一、准备一张图片
拷贝screenshot_panel.9.png放在目录drawable-xhdpi下
二、activity_main.xml
代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/main_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Shot"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
三、新建xml文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:id="@+id/global_screenshot_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@android:color/black"
android:visibility="gone" />
<ImageView android:id="@+id/global_screenshot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/screenshot_panel"
android:visibility="gone"
android:adjustViewBounds="true" />
<ImageView android:id="@+id/global_screenshot_flash"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@android:color/white"
android:visibility="gone" />
</FrameLayout>
四、在dimens.xml添加一项
<dimen name="global_screenshot_bg_padding">20dp</dimen>
五、后台代码
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设置权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
来源:https://blog.csdn.net/loveheronly/article/details/44828177?utm_source=blogxgwz0


猜你喜欢
- SpringMVC 中,文件的上传,是通过 MultipartResolver 实现的。 所以,如果要实现文件的上传,只要在 spring-
- 利用apache ftp工具实现文件的上传下载和删除,具体如下1、下载相应的jar包 com
- Fragment的主要意义就是提供与Activity绑定的生命周期回调。Fragment不一定要向Activity的视图层级中添加View.
- 前言前一段时间做了一个项目,需要解决中文、繁体、英文的国际化问题,所以本文将详细介绍springboot页面国际化配置的过程方法如下1.引入
- 本文实例为大家分享了struts2实现多文件上传的具体代码,供大家参考,具体内容如下首先搭建好struts2的开发环境,导入struts2需
- 具体代码如下所示:***web.xml***<?xml version="1.0" encoding="
- 前言设计模式在我看来更像是一种设计思维或设计思想,它就像《孙子兵法》一样,为你的项目工程提供方向,让你的项目工程更加健壮、灵活,延续生命力。
- socket 编程时的发送与接收数据时的问题在编写一个测试方法时,需要用启动一个程序监听一个端口,测试发送的数据是事正常,但是总是出现两个问
- 很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的QQ,用户可以设置是否允许陌生人添加自己为好友。对于软件配置参数的保存,
- 需要记录日志的地方包括:进入方法的时候,传参的时候,统计执行时间,方法返回参数的时候,退出语句块的时候,出现异常的时候,等等。先来体验不使用
- PS: 之前写过一篇关于 SpringBoo 中使用配置文件的一些姿势,不过嘛,有句话(我)说的好:曾见小桥流水,未睹观音坐莲!所以再写一篇
- JDK * :利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。CGlib * :利用AS
- Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。Field 成员变量的介
- 本文实例讲述了Spring Bean的初始化和销毁。分享给大家供大家参考,具体如下:一 点睛在开发过程中,经常遇到在Bean使用之前或者之后
- Lua是目前国内使用最多的热更语言,基于Lua的热更框架也非常多,最近学习了一下ToLua的热更框架,主要使用的问题在于C#和Lua之间的互
- 在项目开始之前,我的环境已配置完成,具体环境如何配置可参考网络教程。下面我们开始项目的实现库的导入#include<iostream&
- Spring MVC 为开发者提供了方便的开发方式和丰富的功能。其中,HttpMessageConverter 是Spring MVC中非常
- 之前接了需求要让视频播放时可以像优酷视频那样在悬浮窗里播放,并且悬浮窗和主播放页面之间要实现无缝切换,项目中使用的是自封装的ijkplaye
- 在网络信息高速发展的今天,移动设备的方便快捷已经深入人心,越来越多的开发人员会选择在移动设备上查看或编辑源代码。于是,Android平台上大
- 本文实例讲述了JAVA设计模式之建造者模式定义与用法。分享给大家供大家参考,具体如下:建造者模式:将复杂对象的构造与它的实现相分离,让相同的