没有UI的Fragment的妙用——截屏
来源:互联网 发布:得力美工刀片 编辑:程序博客网 时间:2024/06/06 00:24
最近测试了一下Android的截图工具,最开始是这么设计的:
public class ScreenCaptor{ public static final int REQUEST_CAPTURE = 4; public interface OnCaptureFinishedListener { void onCaptureSuccess(Bitmap bitmap); void onCaptureFailure(); } public void startCapture(int requestCode, OnCaptureFinishedListener onCaptureFinishedListener) { //... } public void setOnCaptureGranted(int resultCode, Intent resultData) { //... }}// 在Activity中使用时:public class ScreenCaptorTestActivity extends AppCompatActivity implements ScreenCaptor.OnCaptureFinishedListener { private ScreenCaptor mScreenCaptor; private ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_api_shot); mImageView = findViewById(R.id.image_view); mScreenCaptor = new ScreenCaptor(this); } public void onClick(View view) { switch (view.getId()) { case R.id.start_capture: mScreenCaptor.startCapture(REQUEST_CAPTURE,this); break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CAPTURE) { mScreenCaptor.setOnCaptureGranted(resultCode,data); } } @Override public void onCaptureSuccess(Bitmap bitmap) { mImageView.setImageBitmap(bitmap); } @Override public void onCaptureFailure() { }}
因为截图需要请求权限,在使用截图工具的Activity中都要重写onActivityResult(int,int,Intent)方法,调用ScreenCaptor的setOnCaptureGranted(int,Intent)。由此想到Fragment中也有onActivityResult方法,Fragment有不带UI的用法。于是截图工具可以这样做:
public class ScreenCaptureFragment extends Fragment { private static final String TAG = "ScreenCaptureFragment"; private static final int REQUEST_CAPTURE = 2; public interface OnCaptureFinishedListener { void onCaptureSuccess(Bitmap bitmap); void onCaptureFailure(); } private OnCaptureFinishedListener mOnCaptureFinishedListener; private MediaProjectionManager mMediaProjectionManager; private int mScreenWidth; private int mScreenHeight; private int mScreenDensity; private ImageReader mImageReader; private MediaProjection mMediaProjection; private Intent mResultData; private int mResultCode; private VirtualDisplay mVirtualDisplay; private ImageToBitmapAsyncTask mImageToBitmapTask; public ScreenCaptureFragment() { } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mMediaProjectionManager = ((MediaProjectionManager) getActivity().getSystemService(Context.MEDIA_PROJECTION_SERVICE)); setupImageReader(); } @TargetApi(Build.VERSION_CODES.KITKAT) private void setupImageReader() { DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics(); mScreenDensity = displayMetrics.densityDpi; mScreenWidth = displayMetrics.widthPixels; mScreenHeight = displayMetrics.heightPixels;// 图片格式PixelFormat.RGBA_8888不是乱写的,与Bitmap.Config的图片格式对应 mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 1); } /** * 启动截屏 * * @param onCaptureFinishedListener 截屏完成的监听器 */ public void startCapture(OnCaptureFinishedListener onCaptureFinishedListener) { mOnCaptureFinishedListener = onCaptureFinishedListener; if (mMediaProjection != null) {// 如果已经有令牌,直接拓印屏幕内容 setupVirtualDisplay(); } else if (mResultData != null && mResultCode != 0) {// 如果已经获得录屏权限,构建MediaProjection,然后拓印屏幕内容 setupMediaProjection(); setupVirtualDisplay(); } else {// 如果没有录屏权限:请求录屏权限 requestCapturePermission(REQUEST_CAPTURE); } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CAPTURE) { if (resultCode != RESULT_OK) { Log.e(TAG, "截屏权限被禁止!"); return; } mResultCode = resultCode; mResultData = data; setupMediaProjection(); setupVirtualDisplay(); } } /*获得MediaProjection:一个允许程序截取屏幕内容的令牌*/ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void setupMediaProjection() { mMediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, mResultData); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void requestCapturePermission(int requestCode) { startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), requestCode); } /*获得虚拟显示,可理解为拓印屏幕内容*/ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void setupVirtualDisplay() { if (mImageToBitmapTask != null && mImageToBitmapTask.isRunning()) { Log.e(TAG,"There is already a task running"); return; } Image image; do { mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCaptor", mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null); image = mImageReader.acquireNextImage(); } while (image == null); mImageToBitmapTask = new ImageToBitmapAsyncTask(mOnCaptureFinishedListener); mImageToBitmapTask.execute(image); } private static class ImageToBitmapAsyncTask extends AsyncTask<Image, Void, Bitmap> { private boolean isRunning; private WeakReference<OnCaptureFinishedListener> mListenerWeakReference; public ImageToBitmapAsyncTask(OnCaptureFinishedListener listener) { mListenerWeakReference = new WeakReference<>(listener); } @Override protected void onPreExecute() { isRunning = true; } @Override protected Bitmap doInBackground(Image... images) { Image image = null; if (images != null && images.length > 0) { image = images[0]; } if (image != null) { return imageToBitmap(images[0]); } return null; } @TargetApi(Build.VERSION_CODES.KITKAT) private Bitmap imageToBitmap(Image image) { if (image == null) { return null; } try { int width = image.getWidth(); int height = image.getHeight(); final Image.Plane[] planes = image.getPlanes(); final ByteBuffer buffer = planes[0].getBuffer(); //每个像素的间距 int pixelStride = planes[0].getPixelStride(); //总的间距 int rowStride = planes[0].getRowStride(); int rowPadding = rowStride - pixelStride * width; Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888); bitmap.copyPixelsFromBuffer(buffer); return Bitmap.createBitmap(bitmap, 0, 0, width, height); } catch (ArithmeticException e) { return null; } finally { image.close(); } } @Override protected void onPostExecute(Bitmap bitmap) { isRunning = false; OnCaptureFinishedListener listener = mListenerWeakReference.get(); if (listener == null) { return; } if (bitmap != null) { listener.onCaptureSuccess(bitmap); } else { listener.onCaptureFailure(); } } @Override protected void onCancelled() { isRunning = false; } public boolean isRunning() { return isRunning; } } @Override public void onPause() { super.onPause(); stopMediaProjection(); } @Override public void onDestroy() { super.onDestroy(); if (mImageToBitmapTask != null && !mImageToBitmapTask.isRunning()) { mImageToBitmapTask.cancel(true); mImageToBitmapTask = null; } releaseVirtualDisplay(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void stopMediaProjection() { if (mMediaProjection != null) { mMediaProjection.stop(); mMediaProjection = null; } } @TargetApi(Build.VERSION_CODES.KITKAT) private void releaseVirtualDisplay() { if (mVirtualDisplay == null) { return; } mVirtualDisplay.release(); mVirtualDisplay = null; }}
使用时不需要再重写onActivityResult方法了:
public class ScreenCaptureActivity extends AppCompatActivity implements ScreenCaptureFragment.OnCaptureFinishedListener { private ImageView mImageView; protected ScreenCaptureFragment mCaptureFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_api_shot); mImageView = findViewById(R.id.image_view); mCaptureFragment = new ScreenCaptureFragment(); getSupportFragmentManager().beginTransaction().add(mCaptureFragment,"capture").commit(); } public void onClick(View view) { switch (view.getId()) { case R.id.start_capture: mCaptureFragment.startCapture(this); break; } } @Override public void onCaptureSuccess(Bitmap bitmap) { mImageView.setImageBitmap(bitmap); } @Override public void onCaptureFailure() { }}
贴上源码地址:https://github.com/sheaye/ScreenCaptureTest
阅读全文
0 0
- 没有UI的Fragment的妙用——截屏
- Android Fragment——添加一个没有UI的Fragment
- Android Fragment---添加一个没有UI的Fragment
- Android Fragment---添加一个没有UI的Fragment
- Activity或者Fragment的onResume()方法妙用
- 封装代码和UI的利器—Fragment(一)
- Android UI 之TextView的妙用
- Android UI 之CheckBox的妙用
- 没有UI就是最好的UI
- 深入浅出SharePoint——InvokeWorkflow的妙用
- SAPUI5教程——MaskInput的妙用
- fragment的onActivityResult没有调用的解决方法
- Android UI 之ToggleTextView的妙用(自定义可切换TextView)
- Android布局属性android:clipToPadding的UI设计妙用
- Android布局属性android:clipToPadding的UI设计妙用
- 递归的妙用—遍历子控件
- 递归的妙用—遍历子控件
- 递归的妙用—遍历子控件
- 20. Valid Parentheses
- shell及linux基础
- java开发腾讯AI,共探人工智能
- 【米么推文素材】汇编语言示例 求斐波那契数
- Go语言解析Html
- 没有UI的Fragment的妙用——截屏
- oracle--8.分页查询
- Dynamics CRM Developer Extensions提升你的开发效率(Plug-in篇)
- 使用Keil 5,Keil4 烧录nrf51822,52832协议栈
- 如何将Apache日志文件按时间分隔存储
- Quantum Cascade Laser(QCL)
- flask-alchemy-pagination
- 面试官最爱的volatile关键字
- C++智能指针 shared_ptr 与 weak_ptr 原理