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

标签:android,截屏
0
投稿

猜你喜欢

  • Java文件读写IO/NIO及性能比较详细代码及总结

    2021-11-28 12:56:30
  • java高并发InterruptedException异常引发思考

    2022-09-09 20:15:34
  • Android13 加强Intent filters 的安全性

    2022-06-17 03:15:55
  • C#使用默认浏览器打开网页的方法

    2022-02-16 10:39:34
  • 在RecyclerView中实现button的跳转功能

    2023-06-17 20:21:14
  • C#实现策略模式

    2022-02-09 17:19:01
  • Unity实现切割图集工具

    2021-07-03 23:14:57
  • Android 虚拟按键适配动态调整布局的方法

    2022-03-03 07:20:24
  • Spring中SmartLifecycle和Lifecycle的作用和区别

    2023-11-18 22:55:50
  • mybatis中的if test判断入参的值问题

    2023-11-16 08:13:44
  • 解析C#设计模式编程中外观模式Facade Pattern的应用

    2021-08-08 05:10:37
  • c# 抓取Web网页数据分析

    2022-11-10 06:44:57
  • C#中datagridview的EditingControlShowing事件用法实例

    2021-05-27 23:08:43
  • C#基于TCP协议的服务器端和客户端通信编程的基础教程

    2023-08-20 13:09:55
  • java启动jar包修改JVM默认内存问题

    2022-03-17 21:50:09
  • Android开发之搜索框SearchView用法示例

    2021-10-30 03:40:19
  • C#利用递归算法解决汉诺塔问题

    2022-04-29 23:04:10
  • Java微信公众平台开发(11) 微信三大平台的关联

    2022-10-15 06:55:56
  • WinForm自定义函数FindControl实现按名称查找控件

    2021-09-23 17:27:25
  • java编程实现根据EXCEL列名求其索引的方法

    2022-04-24 03:08:03
  • asp之家 软件编程 m.aspxhome.com