当前位置:首页 > 行业动态 > 正文

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

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

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

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

在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实现手机截屏并保存截图功能”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。

推荐想看:
0

相关推荐

  • 如何在Android上实现全屏截图或长截屏功能?
  • 如何在Android中实现Banner轮播图功能?
  • 如何在Android中实现截取长截图的功能?
  • 如何发送手机截图
  • 如何在Android平台上实现手机拍照功能?
  • 如何在Android平台上实现手写签名功能?
  • Python截屏_截屏
  • 如何在Android设备上实现手机游戏隐藏虚拟按键?
  • aapt 在文章中通常指代 Android Asset Packaging Tool,这是一个用于Android应用打包的工具。假设文章讨论了该工具的使用、功能、优势或更新等相关内容,以下是一个可能的原创疑问句标题,,如何有效利用aapt优化Android应用的性能和资源管理?
  • 如何在DedeCMS中实现手机WAP浏览功能?
  • 遇到Windows 10截图功能失效,我该如何修复?
  • processes_镜像保存时报错“there are processes in 'D' status, please check process status using 'ps aux' and kill all the 'D' status processes”或“Buildimge,False,Error response from daemon,Cannot pause container xxx”如何解决?
  • 易语言如何实现截图功能,源码揭秘?
  • 如何深入理解Android截屏功能的源码实现?
  • android传递数据android_Android