蓝桉云顶

Good Luck To You!

如何在Android中实现手机截屏并保存截图功能?

在 android 中,可以通过使用 mediaprojection api 截取屏幕内容并保存为图片。首先需要申请权限,然后使用 imagereader 获取截图数据,最后将数据保存为图片文件。

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

在Android开发中,实现手机截屏并保存截图的功能是一个常见的需求,本文将详细介绍如何使用Android SDK来实现这一功能,包括获取屏幕截图、保存截图到本地存储以及处理相关权限等。

一、准备工作

添加权限

需要在AndroidManifest.xml文件中添加读取和写入外部存储的权限:

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

检查和请求权限

从Android 6.0(API级别23)开始,需要在运行时动态请求这些权限,以下是一个简单的示例代码来检查和请求权限:

private static final int PERMISSION_REQUEST_CODE = 1;
public boolean hasStoragePermission() {
    String[] permissions = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    for (String permission : permissions) {
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}
public void requestStoragePermission() {
    ActivityCompat.requestPermissions(this, new String[]{
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
        }, PERMISSION_REQUEST_CODE);
}

onCreate方法中调用hasStoragePermission()方法来检查权限,如果没有权限则调用requestStoragePermission()方法请求权限:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (!hasStoragePermission()) {
        requestStoragePermission();
    } else {
        takeScreenshot();
    }
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, grantResults);
    if (requestCode == PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            takeScreenshot();
        } else {
            Toast.makeText(this, "需要存储权限", Toast.LENGTH_SHORT).show();
        }
    }
}

二、获取屏幕截图

1. 使用MediaProjection API

从Android 5.0(API级别21)开始,可以使用MediaProjection API来捕获屏幕内容,以下步骤展示了如何使用这个API:

1.1 启动屏幕捕获

需要启动一个活动来请求屏幕捕获权限:

Intent intent = new Intent(MediaProjectionManager.ACTION_SCREEN_CAPTURE);
startActivityForResult(intent, SCREEN_CAPTURE_PERMISSION_CODE);

1.2 处理结果

onActivityResult方法中处理用户的选择:

@Override
protected void onActivityResult(int requestCode, resultCode, packageName, Intent data) {
    super.onActivityResult(requestCode, resultCode, packageName, data);
    if (requestCode == SCREEN_CAPTURE_PERMISSION_CODE) {
        if (resultCode == RESULT_OK && data != null) {
            imageReader = ImageReader.newInstance(displayWidth, displayHeight, PixelFormat.RGBA_8888, null);
            mediaProjection = (MediaProjection) getIntent().getExtras().get("data");
            mediaProjection.createVirtualDisplay("screencap", displayWidth, displayHeight, displayDensity, surface, null, null);
        } else {
            Toast.makeText(this, "用户拒绝屏幕捕获权限", Toast.LENGTH_SHORT).show();
        }
    }
}

1.3 创建虚拟显示并捕获帧数据

创建一个Surface对象并将其传递给createVirtualDisplay方法:

ImageReader.OnImageAvailableListener imageListener = new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        Image image = null;
        try {
            image = reader.acquireLatestImage();
            if (image != null) {
                // 将图像转换为Bitmap并保存到本地存储
                Image.Plane[] planes = image.getPlanes();
                ByteBuffer buffer = planes[0].getBuffer();
                byte[] bytes = new byte[buffer.remaining()];
                buffer.get(bytes);
                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                saveBitmap(bitmap);
                image.close();
            }
        } finally {
            if (image != null) {
                image.close();
            }
        }
    }
};

三、保存截图到本地存储

创建文件并写入数据

使用Bitmap对象的compress方法将其保存为文件:

private void saveBitmap(Bitmap bitmap) {
    FileOutputStream out = null;
    try {
        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "screenshot_" + System.currentTimeMillis() + ".png");
        out = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        Toast.makeText(this, "截图已保存:" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null) {
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

四、处理不同屏幕方向和分辨率

为了确保截图能够适应不同的屏幕方向和分辨率,可以在启动屏幕捕获之前获取设备的显示参数:

WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int displayWidth = size.x;
int displayHeight = size.y;
int displayDensity = display.getDensityDpi();

五、完整示例代码

以下是一个完整的示例代码,展示了如何实现上述功能:

public class MainActivity extends AppCompatActivity {
    private static final int SCREEN_CAPTURE_PERMISSION_CODE = 2;
    private MediaProjection mediaProjection; null;
    private ImageReader imageReader = null;
    private Surface surface = null;
    private int displayWidth;
    private int displayHeight;
    private int displayDensity;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (!hasStoragePermission()) {
            requestStoragePermission();
        } else {
            takeScreenshot();
        }
    }
    private boolean hasStoragePermission() {
        String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }
    private void requestStoragePermission() {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, SCREEN_CAPTURE_PERMISSION_CODE);
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, grantResults) {
        super.onRequestPermissionsResult(requestCode, grantResults);
        if (requestCode == SCREEN_CAPTURE_PERMISSION_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                takeScreenshot();
            } else {
                Toast.makeText(this, "需要存储权限", Toast.LENGTH_SHORT).show();
            }
        }
    }
    private void takeScreenshot() {
        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        displayWidth = size.x;
        displayHeight = size.y;
        displayDensity = display.getDensityDpi();
        Intent intent = new Intent(MediaProjectionManager.ACTION_SCREEN_CAPTURE);
        startActivityForResult(intent, SCREEN_CAPTURE_PERMISSION_CODE);
    }
    @Override
    protected void onActivityResult(int requestCode, resultCode, packageName, Intent data) {
        super.onActivityResult(requestCode, resultCode, packageName, data);
        if (requestCode == SCREEN_CAPTURE_PERMISSION_CODE) {
            if (resultCode == RESULT_OK && data != null) {
                imageReader = ImageReader.newInstance(displayWidth, displayHeight, PixelFormat.RGBA_8888, null);
                mediaProjection = (MediaProjection) getIntent().getExtras().get("data");
                mediaProjection.createVirtualDisplay("screencap", displayWidth, displayHeight, displayDensity, surface, null, null);
            } else {
                Toast.makeText(this, "用户拒绝屏幕捕获权限", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

小伙伴们,上文介绍了“android实现手机截屏并保存截图功能”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。

  •  心愿
     发布于 2024-01-13 14:28:29  回复该评论
  • 了解前置或专项审批内容类型的填写方法,对于具有文章评论功能的个人网站,是属于博客还是论坛,这是个值得深思的问题。
  •  沉默
     发布于 2024-01-27 20:17:08  回复该评论
  • 关于前置或专项审批内容类型的填写,以及个人网站文章评论功能属于博客还是论坛的问题,建议您查阅相关政策法规或咨询专业人士以确保合规。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

«    2024年11月    »
123
45678910
11121314151617
18192021222324
252627282930
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接