【问题标题】:How to programmatically take a screenshot on Android?如何以编程方式在 Android 上截屏?
【发布时间】:2011-02-09 07:57:21
【问题描述】:

如何不通过任何程序而是通过代码截取手机屏幕的选定区域?

【问题讨论】:

标签: android screenshot


【解决方案1】:

这是允许我的屏幕截图存储在 SD 卡上的代码,以便以后用于您的任何需求:

首先,您需要添加适当的权限来保存文件:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

这是代码(在 Activity 中运行):

private void takeScreenshot() {
    Date now = new Date();
    android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);

    try {
        // image naming and path  to include sd card  appending name you choose for file
        String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";

        // create bitmap screen capture
        View v1 = getWindow().getDecorView().getRootView();
        v1.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        File imageFile = new File(mPath);

        FileOutputStream outputStream = new FileOutputStream(imageFile);
        int quality = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
        outputStream.flush();
        outputStream.close();

        openScreenshot(imageFile);
    } catch (Throwable e) {
        // Several error may come out with file handling or DOM
        e.printStackTrace();
    }
}

您可以这样打开最近生成的图像:

private void openScreenshot(File imageFile) {
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    Uri uri = Uri.fromFile(imageFile);
    intent.setDataAndType(uri, "image/*");
    startActivity(intent);
}

如果您想在片段视图上使用它,请使用:

View v1 = getActivity().getWindow().getDecorView().getRootView();

而不是

View v1 = getWindow().getDecorView().getRootView();

关于takeScreenshot()函数

注意

如果您的对话框包含表面视图,则此解决方案不起作用。详情请查看以下问题的答案:

Android Take Screenshot of Surface View Shows Black Screen

【讨论】:

  • 您好,您能描述一下 mCurrentUrlMask 是什么吗?我已经尝试过这段代码,但它总是在 Bitmap.createBitmap(v1.getDrawingCache()) 处给我 NullPointerException,有人能告诉我我做错了什么吗?任何帮助表示赞赏。谢谢。
  • @MiteshSardhara mCurrentUrlMask 必须是 View,因为它是 Android API 中具有 getRootView() 方法的唯一类。可能是 UI 中的视图。
  • 你能告诉我mCurrentUrlMask是什么吗?
  • Insted of View v1 = mCurrentUrlMask.getRootView(); 我用过View v1 = getWindow().getDecorView().getRootView();,它对我有用。
  • 这个答案只截取了应用程序的屏幕截图——而不是问题中所问的“手机屏幕”——或者我做错了什么。
【解决方案2】:

调用此方法,传入您想要截屏的最外层 ViewGroup:

public Bitmap screenShot(View view) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
            view.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}

【讨论】:

  • 这似乎比公认的答案更简洁。它的性能是否也一样?
  • 我在几个不同的应用程序中使用了一段时间,没有遇到任何问题。
  • 如果你想得到手机的截图,你的应用在后台,你传递的view是什么?`
  • 传递getWindow().getDecorView().getRootView() 作为视图会导致只截取应用程序而不是屏幕的屏幕截图。
  • 疯狂的是,这个解决方案在 2020 年仍然有效,无需请求许可,处理任何高级配置或 api 限制。 Android 让我感到惊讶。
【解决方案3】:

注意:仅适用于root手机

您可以通过编程方式运行adb shell /system/bin/screencap -p /sdcard/img.png,如下所示

Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + "/sdcard/img.png").getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();    

然后将img.png 读作Bitmap 并按照您的意愿使用。

【讨论】:

  • 是否需要root权限?
  • 是的,您需要 root 访问权限。请检查标题处的注释
  • 嗨,我收到了System.err : java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null ,我的设备是android 5.0
  • @Eddy 这取决于你的设备
  • 有没有办法直接读取输出而不将结果保存到文件中然后再次读取? stackoverflow.com/questions/43914035
【解决方案4】:

无需root权限无需大编码


在 adb shell 上使用下面的命令你可以截屏。

input keyevent 120

此命令不需要任何root权限,因此您也可以从android应用程序的java代码执行。

Process process;
process = Runtime.getRuntime().exec("input keyevent 120");

更多关于 android 中的 keyevent 代码见http://developer.android.com/reference/android/view/KeyEvent.html

这里我们用过。 KEYCODE_SYSRQ 其值为 120,用于 System Request / Print Screen 键。


正如CJBS所说,输出的图片会保存在/sdcard/Pictures/Screenshots

【讨论】:

  • 输出图片会保存在这里:/sdcard/Pictures/Screenshots
  • 是否需要root权限??
  • 它适用于棉花糖吗?还是在服务背景下工作@JeegarPatel
  • 不是以编程方式工作,而是在 shell 中工作。试过牛轧糖。
  • su -c "input keyevent 120" 没问题!!
【解决方案5】:

Mualig 的答案非常好,但我遇到了 Ewoks 描述的同样问题,我没有了解背景。所以有时就足够了,有时我会在黑色背景上看到黑色文本(取决于主题)。

此解决方案主要基于 Mualig 代码和我在 Robotium 中找到的代码。我通过直接调用 draw 方法来放弃使用绘图缓存。在此之前,我将尝试从当前活动中获取可绘制的背景以首先绘制它。

// Some constants
final static String SCREENSHOTS_LOCATIONS = Environment.getExternalStorageDirectory().toString() + "/screenshots/";

// Get device dimmensions
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);

// Get root view
View view = mCurrentUrlMask.getRootView();

// Create the bitmap to use to draw the screenshot
final Bitmap bitmap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ARGB_4444);
final Canvas canvas = new Canvas(bitmap);

// Get current theme to know which background to use
final Activity activity = getCurrentActivity();
final Theme theme = activity.getTheme();
final TypedArray ta = theme
    .obtainStyledAttributes(new int[] { android.R.attr.windowBackground });
final int res = ta.getResourceId(0, 0);
final Drawable background = activity.getResources().getDrawable(res);

// Draw background
background.draw(canvas);

// Draw views
view.draw(canvas);

// Save the screenshot to the file system
FileOutputStream fos = null;
try {
    final File sddir = new File(SCREENSHOTS_LOCATIONS);
    if (!sddir.exists()) {
        sddir.mkdirs();
    }
    fos = new FileOutputStream(SCREENSHOTS_LOCATIONS
            + System.currentTimeMillis() + ".jpg");
    if (fos != null) {
        if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)) {
            Log.d(LOGTAG, "Compress/Write failed");
        }
        fos.flush();
        fos.close();
    }

} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

【讨论】:

  • 我的活动中有一个带有 android:cacheColorHint="#00000000" 的列表视图,我使用这段代码截图,我仍然有黑色背景,因为我发现从主题获得的背景是black ,我该如何处理这个列表视图?
  • Activity 活动 = getCurrentActivity 给 Eroor 未定义的方法。
【解决方案6】:

作为参考,捕获屏幕(而不仅仅是您的应用活动)的一种方法是捕获 帧缓冲区(设备 /dev/graphics/fb0)。为此,您必须具有 root 权限,或者您的应用程序必须是具有 signature permissions 的应用程序(“仅当请求应用程序使用与声明权限的应用程序相同的证书签名时,系统才会授予该权限”) - 其中除非您自己编译 ROM,否则不太可能。

从我测试过的几台设备中捕获的每个帧缓冲区都包含恰好一个屏幕截图。人们报告它包含更多,我想这取决于框架/显示大小。

我尝试连续读取帧缓冲区,但它似乎返回了固定数量的读取字节。在我的例子中是 (3 410 432) 字节,这足以存储 854*480 RGBA(3 279 360 字节)的显示帧。是的,从 fb0 输出的二进制帧在我的设备中是 RGBA。这很可能取决于设备。这对你解码很重要=)

在我的设备 /dev/graphics/fb0 权限中,只有 root 和图形组中的用户才能读取 fb0。

graphics 是一个受限组,因此您可能只能使用 su 命令通过 root 手机访问 fb0。

Android 应用具有 用户 id (uid) = app_##组 id (guid) = app_##

adb shelluid = shellguid = shell,其权限比应用程序多得多。您实际上可以在 /system/permissions/platform.xml 中检查这些权限

这意味着您将能够在没有 root 的情况下在 adb shell 中读取 fb0,但在没有 root 的情况下您将无法在应用程序中读取它。

此外,在 AndroidManifest.xml 上授予 READ_FRAME_BUFFER 和/或 ACCESS_SURFACE_FLINGER 权限对于常规应用没有任何作用,因为这些仅适用于“signature”应用。

也可以查看此closed thread了解更多详情。

【讨论】:

  • 这在某些手机上有效(有效?),但请注意,基于 GPU 的手机不一定为应用处理器提供线性帧缓冲区。
【解决方案7】:
private void captureScreen() {
    View v = getWindow().getDecorView().getRootView();
    v.setDrawingCacheEnabled(true);
    Bitmap bmp = Bitmap.createBitmap(v.getDrawingCache());
    v.setDrawingCacheEnabled(false);
    try {
        FileOutputStream fos = new FileOutputStream(new File(Environment
                .getExternalStorageDirectory().toString(), "SCREEN"
                + System.currentTimeMillis() + ".png"));
        bmp.compress(CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

在清单中添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

如需支持Marshmallow或以上版本,请在activity onCreate方法中添加如下代码

ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},00);

【讨论】:

  • 要求:
  • 这个答案只截取应用程序的屏幕截图 - 而不是问题中提出的“手机屏幕” - 还是我做错了什么?
  • 如果我需要一个列表视图的截图呢?
  • 我想从适配器捕获任何想法我该怎么做?
【解决方案8】:

我的解决办法是:

public static Bitmap loadBitmapFromView(Context context, View v) {
    DisplayMetrics dm = context.getResources().getDisplayMetrics(); 
    v.measure(MeasureSpec.makeMeasureSpec(dm.widthPixels, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(dm.heightPixels, MeasureSpec.EXACTLY));
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    Bitmap returnedBitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
            v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(returnedBitmap);
    v.draw(c);

    return returnedBitmap;
}

public void takeScreen() {
    Bitmap bitmap = ImageUtils.loadBitmapFromView(this, view); //get Bitmap from the view
    String mPath = Environment.getExternalStorageDirectory() + File.separator + "screen_" + System.currentTimeMillis() + ".jpeg";
    File imageFile = new File(mPath);
    OutputStream fout = null;
    try {
        fout = new FileOutputStream(imageFile);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
        fout.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        fout.close();
    }
}

图像保存在外部存储文件夹中。

【讨论】:

  • 您应该在 finally 块中关闭 FileOutputStream。如果您现在遇到异常,则不会关闭流。
  • 你传递给ImageUtils.loadBitmapFromView(this, view)view是什么?
  • 为什么要使用 v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); ?这不会改变视图 (v) 吗?
【解决方案9】:

您可以尝试以下库: http://code.google.com/p/android-screenshot-library/ Android 屏幕截图库 (ASL) 能够以编程方式从 Android 设备捕获屏幕截图,而无需拥有 root 访问权限。相反,ASL 使用在后台运行的本机服务,每次设备启动时通过 Android 调试桥 (ADB) 启动一次。

【讨论】:

  • 我试过这个。但它只截取正在运行的应用程序的屏幕截图。如果我想截取主屏幕的屏幕截图,它无济于事。您如何使用该代码截取主屏幕的屏幕截图?
  • @Janardhanan.S:这就是问题所要求的。你能不能用一个新的答案来详细说明,而不是问一个单独的问题。
  • 我遇到同样的问题..“本机服务未运行!!”
  • 和我一样“本机服务未运行!!”....有人可以在这里添加帮助文本吗?
  • 这里也一样! “本机服务未运行!!”在最新版本 1.2 中,他们使用 API LEVEL 19 类,例如 Socket。
【解决方案10】:

根据上面@JustinMorris 和@NiravDangi 这里https://stackoverflow.com/a/8504958/2232148 的回答,我们必须将视图的背景和前景组合起来,如下所示:

public static Bitmap takeScreenshot(View view, Bitmap.Config quality) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), quality);
    Canvas canvas = new Canvas(bitmap);

    Drawable backgroundDrawable = view.getBackground();
    if (backgroundDrawable != null) {
        backgroundDrawable.draw(canvas);
    } else {
        canvas.drawColor(Color.WHITE);
    }
    view.draw(canvas);

    return bitmap;
}

质量参数采用 Bitmap.Config 常量,通常为 Bitmap.Config.RGB_565Bitmap.Config.ARGB_8888

【讨论】:

  • 在背景为空的情况下用白色绘制画布对我有用。谢谢奥利弗
【解决方案11】:
public class ScreenShotActivity extends Activity{

private RelativeLayout relativeLayout;
private Bitmap myBitmap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    relativeLayout = (RelativeLayout)findViewById(R.id.relative1);
    relativeLayout.post(new Runnable() {
        public void run() {

            //take screenshot
            myBitmap = captureScreen(relativeLayout);

            Toast.makeText(getApplicationContext(), "Screenshot captured..!", Toast.LENGTH_LONG).show();

            try {
                if(myBitmap!=null){
                    //save image to SD card
                    saveImage(myBitmap);
                }
                Toast.makeText(getApplicationContext(), "Screenshot saved..!", Toast.LENGTH_LONG).show();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    });

}

public static Bitmap captureScreen(View v) {

    Bitmap screenshot = null;
    try {

        if(v!=null) {

            screenshot = Bitmap.createBitmap(v.getMeasuredWidth(),v.getMeasuredHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(screenshot);
            v.draw(canvas);
        }

    }catch (Exception e){
        Log.d("ScreenShotActivity", "Failed to capture screenshot because:" + e.getMessage());
    }

    return screenshot;
}

public static void saveImage(Bitmap bitmap) throws IOException{

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 40, bytes);
    File f = new File(Environment.getExternalStorageDirectory() + File.separator + "test.png");
    f.createNewFile();
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
    fo.close();
}

}

添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

【讨论】:

  • 这个答案只截取应用程序的屏幕截图 - 而不是问题中提出的“手机屏幕” - 还是我做错了什么?
【解决方案12】:

你可以尝试做这样的事情,

通过执行类似的操作从布局或视图中获取位图缓存 首先你必须setDrawingCacheEnabled 到一个布局(一个线性布局或相对布局,或一个视图)

然后

Bitmap bm = layout.getDrawingCache()

然后你可以对位图做任何你想做的事情。要么将其转换为图像文件,要么将位图的 uri 发送到其他地方。

【讨论】:

  • 如果您正在将应用程序写入位图,这是最好的方法。另外,请注意在获取缓存之前有延迟的方法...例如用于列表视图的 Notify...()。
  • 不仅如此。布局必须首先显示在屏幕上。毕竟这是你得到的“缓存”。尝试隐藏视图并在后台截屏(理论上),但没有成功。
  • 比其他解决方案高效得多
【解决方案13】:

捷径是

FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();

【讨论】:

    【解决方案14】:

    这个问题的大部分答案都使用Canvas绘图方法或绘图缓存方法。但是,View.setDrawingCache() method is deprecated in API 28。目前推荐的用于制作屏幕截图的 API 是 API 24 提供的 PixelCopy 类(但接受 Window 参数的方法可从 API 26 == Android 8.0 Oreo 获得)。这是用于检索Bitmap 的示例 Kotlin 代码:

    @RequiresApi(Build.VERSION_CODES.O)
    fun saveScreenshot(view: View) {
        val window = (view.context as Activity).window
        if (window != null) {
            val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
            val locationOfViewInWindow = IntArray(2)
            view.getLocationInWindow(locationOfViewInWindow)
            try {
                PixelCopy.request(window, Rect(locationOfViewInWindow[0], locationOfViewInWindow[1], locationOfViewInWindow[0] + view.width, locationOfViewInWindow[1] + view.height), bitmap, { copyResult ->
                    if (copyResult == PixelCopy.SUCCESS) {
                        saveBitmap(bitmap)
                    }
                    // possible to handle other result codes ...
                }, Handler())
            } catch (e: IllegalArgumentException) {
                // PixelCopy may throw IllegalArgumentException, make sure to handle it
            }
        }
    }
    

    【讨论】:

    • 在 drawingCache 解决方案中 PixelCopy 的问题是,它似乎只捕获可见像素。其余的对我来说都是黑色的。因此,无法共享可滚动且部分超出框架的内容。您对此有解决方案吗?
    • 你是对的。同样,如果另一个视图显示在我要截屏的视图上方(例如,当抽屉打开时),它可能会导致问题。在这些情况下,我只使用旧的 Canvas 方法 :(
    • 是否可以使用 PixelCopy 在任何正在运行的应用上截屏?
    • @AmirRezaei 当然,它仅用于当前应用程序。对于其他人来说,有不同的方式......
    【解决方案15】:

    对于那些想要捕获 GLSurfaceView 的人,getDrawingCache 或绘图到画布方法将不起作用。

    您必须在帧被渲染后读取 OpenGL 帧缓冲区的内容。有个好答案here

    【讨论】:

      【解决方案16】:

      我创建了一个简单的库,它从View 截取屏幕截图,并为您提供一个位图对象或将其直接保存到您想要的任何路径

      https://github.com/abdallahalaraby/Blink

      【讨论】:

      • 是否需要root手机?
      • 无需生根:)
      • 在使用中你提到了Screenshot.takeScreenshot(view, mPath); imageView.setImageBitmap(Screenshot.getBitmapScreenshot(view, mPath)); 如何查看当前活动。我不想使用 xml 的 id。
      • 改用takeScreenshotForScreen()
      【解决方案17】:

      如果您想从fragment 截取屏幕截图,请按照以下步骤操作:

      1. 覆盖onCreateView()

                 @Override
                public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                         Bundle savedInstanceState) {
                    // Inflate the layout for this fragment
                    View view = inflater.inflate(R.layout.fragment_one, container, false);
                    mView = view;
                }
        
      2. 截图逻辑:

         button.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             View view =  mView.findViewById(R.id.scrollView1);
              shareScreenShotM(view, (NestedScrollView) view); 
         }
        
      3. 方法shareScreenShotM)():

        public void shareScreenShotM(View view, NestedScrollView scrollView){
        
             bm = takeScreenShot(view,scrollView);  //method to take screenshot
            File file = savePic(bm);  // method to save screenshot in phone.
            }
        
      4. 方法 takeScreenShot():

                 public Bitmap takeScreenShot(View u, NestedScrollView z){
        
                    u.setDrawingCacheEnabled(true);
                    int totalHeight = z.getChildAt(0).getHeight();
                    int totalWidth = z.getChildAt(0).getWidth();
        
                    Log.d("yoheight",""+ totalHeight);
                    Log.d("yowidth",""+ totalWidth);
                    u.layout(0, 0, totalWidth, totalHeight);
                    u.buildDrawingCache();
                    Bitmap b = Bitmap.createBitmap(u.getDrawingCache());
                    u.setDrawingCacheEnabled(false);
                    u.destroyDrawingCache();
                     return b;
                }
        
      5. 方法 savePic():

         public static File savePic(Bitmap bm){
        
                ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                bm.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
                 File sdCardDirectory =  new File(Environment.getExternalStorageDirectory() + "/Foldername");
        
               if (!sdCardDirectory.exists()) {
                    sdCardDirectory.mkdirs();
              }
               //  File file = new File(dir, fileName);
              try {
                 file = new File(sdCardDirectory, Calendar.getInstance()
                    .getTimeInMillis() + ".jpg");
                file.createNewFile();
                new FileOutputStream(file).write(bytes.toByteArray());
                Log.d("Fabsolute", "File Saved::--->" + file.getAbsolutePath());
                 Log.d("Sabsolute", "File Saved::--->" + sdCardDirectory.getAbsolutePath());
             } catch (IOException e) {
                  e.printStackTrace();
              }
             return file;
           }
        

      对于活动,您可以简单地使用View v1 = getWindow().getDecorView().getRootView(); 而不是mView

      【讨论】:

        【解决方案18】:

        只是扩展 taraloca 的答案。您必须添加以下行才能使其工作。 我已将图像名称设为静态。如果您需要动态图像名称,请确保使用 taraloca 的时间戳变量。

            // Storage Permissions
        private static final int REQUEST_EXTERNAL_STORAGE = 1;
        private static String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
        
        private void verifyStoragePermissions() {
            // Check if we have write permission
            int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // We don't have permission so prompt the user
                ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            }else{
                takeScreenshot();
            }
        }
        
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (requestCode == REQUEST_EXTERNAL_STORAGE) {
                    takeScreenshot();
                }
            }
        }
        

        并且在 AndroidManifest.xml 文件中必须有以下条目:

        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        

        【讨论】:

          【解决方案19】:

          全页滚动截图

          如果您想捕获完整的视图屏幕截图(其中包含滚动视图左右),请查看此库

          https://github.com/peter1492/LongScreenshot

          你所要做的就是导入Gradel,并创建一个BigScreenshot对象

          BigScreenshot longScreenshot = new BigScreenshot(this, x, y);

          将收到一个回调,其中包含在自动滚动屏幕视图组并最终组合在一起时拍摄的屏幕截图的位图。

          @Override public void getScreenshot(Bitmap bitmap) {}

          哪些可以保存到画廊中,或者在他们之后需要任何使用

          【讨论】:

            【解决方案20】:

            仅适用于系统应用程序!

            Process process;
            process = Runtime.getRuntime().exec("screencap -p " + outputPath);
            process.waitFor();
            

            注意:系统应用程序不需要运行“su”来执行该命令。

            【讨论】:

              【解决方案21】:

              参数视图是根布局对象。

              public static Bitmap screenShot(View view) {
                                  Bitmap bitmap = null;
                                  if (view.getWidth() > 0 && view.getHeight() > 0) {
                                      bitmap = Bitmap.createBitmap(view.getWidth(),
                                              view.getHeight(), Bitmap.Config.ARGB_8888);
                                      Canvas canvas = new Canvas(bitmap);
                                      view.draw(canvas);
                                  }
                                  return bitmap;
                              }
              

              【讨论】:

                【解决方案22】:

                从 Android 11(API 级别 30)开始,您可以使用无障碍服务截屏:

                takeScreenshot - 截取指定显示的屏幕截图并通过 AccessibilityService.ScreenshotResult 返回。

                【讨论】:

                  【解决方案23】:

                  在android中截取一个视​​图。

                  public static Bitmap getViewBitmap(View v) {
                      v.clearFocus();
                      v.setPressed(false);
                  
                      boolean willNotCache = v.willNotCacheDrawing();
                      v.setWillNotCacheDrawing(false);
                  
                      int color = v.getDrawingCacheBackgroundColor();
                      v.setDrawingCacheBackgroundColor(0);
                  
                      if (color != 0) {
                          v.destroyDrawingCache();
                      }
                      v.buildDrawingCache();
                      Bitmap cacheBitmap = v.getDrawingCache();
                      if (cacheBitmap == null) {
                          return null;
                      }
                  
                      Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
                  
                      v.destroyDrawingCache();
                      v.setWillNotCacheDrawing(willNotCache);
                      v.setDrawingCacheBackgroundColor(color);
                  
                      return bitmap;
                  }
                  

                  【讨论】:

                    【解决方案24】:

                    如果要截取视图的屏幕截图,请使用View::drawToBitmap扩展功能:

                    val bitmap = myTargetView.drawToBitmap(/*Optional:*/ Bitmap.Config.ARGB_8888)
                    

                    请务必使用 -ktx 版本的AndroidX Core 库:

                    implementation("androidx.core:core-ktx:1.6.0")
                    

                    我已经回答过类似的问题here

                    【讨论】:

                    • 1.2.0版本也有,不用升级了
                    【解决方案25】:

                    如果您想捕获 RelativeLayoutLinearLayout 等视图或布局。

                    只需使用代码:

                    LinearLayout llMain = (LinearLayout) findViewById(R.id.linearlayoutMain);
                    Bitmap bm = loadBitmapFromView(llMain);
                    

                    现在您可以通过以下方式将此位图保存在设备存储中:

                    FileOutputStream outStream = null;
                    File f=new File(Environment.getExternalStorageDirectory()+"/Screen Shots/");
                    f.mkdir();
                    String extStorageDirectory = f.toString();
                    File file = new File(extStorageDirectory, "my new screen shot");
                    pathOfImage = file.getAbsolutePath();
                    try {
                        outStream = new FileOutputStream(file);
                        bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
                        Toast.makeText(getApplicationContext(), "Saved at "+f.getAbsolutePath(), Toast.LENGTH_LONG).show();
                        addImageGallery(file);
                        //mail.setEnabled(true);
                        flag=true;
                    } catch (FileNotFoundException e) {e.printStackTrace();}
                    try {
                        outStream.flush();
                        outStream.close();
                    } catch (IOException e) {e.printStackTrace();}
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2011-12-07
                      • 2011-11-22
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-12-15
                      • 2011-01-13
                      • 2013-10-09
                      • 2015-02-26
                      相关资源
                      最近更新 更多