如何通过代码而不是程序来截取手机屏幕的选定区域的截图?
当前回答
这个问题的大多数答案使用Canvas绘图方法或绘图缓存方法。然而,View.setDrawingCache()方法在API 28中已弃用。目前,用于制作截图的推荐API是API 24提供的PixelCopy类(但接受Window参数的方法可从API 26 == Android 8.0 Oreo获得)。下面是一个检索位图的示例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
}
}
}
其他回答
只是扩展塔拉洛卡的答案。您必须添加以下行才能使其工作。我已将映像名称设置为静态。请确保您使用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 " / >
根据上面@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_565或Bitmap.Config.ARGB_8888。
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();
}
仅限系统应用!
Process process;
process = Runtime.getRuntime().exec("screencap -p " + outputPath);
process.waitFor();
注意:系统应用不需要执行“su”命令执行该命令。
捷径是
FrameLayout layDraw = (FrameLayout) findViewById(R.id.layDraw); /*Your root view to be part of screenshot*/
layDraw.buildDrawingCache();
Bitmap bmp = layDraw.getDrawingCache();
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件