现在有一个需求是要求截屏,下载自己二维码,拼接图片,在分享,截屏俩种方式,代码如下。如有疑问(993987402)
private JointBitmap view; private ImageView mView; // 加载成功 private static final int LOAD_SUCCESS = 1; // 加载失败 private static final int LOAD_ERROR = -1; // 用于异步的显示图片 private Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { //下载成功 case 1: // 获取图片的文件对象 File file = new File(Environment.getExternalStorageDirectory(), "pic.jpg"); FileInputStream fis = null; try { fis = new FileInputStream(file); Bitmap bitmap = BitmapFactory.decodeStream(fis); // image.setImageBitmap(bitmap); setNewBimap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } break; //下载失败 case 0: Log.d("TAG","失败了"); Toast.makeText(MainActivity.this, "加载失败", Toast.LENGTH_SHORT).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); permissionHelper = PermissionHelper.getInstance(this); mView= (ImageView) findViewById(R.id.image_view); findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { setPermission(); } }); } /** * 请求权限 */ private void setPermission(){ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ //请求权限 setPommisions(); view(); }else{ //不需要 permissionsAllowed(); } } /** * 请求权限 */ private void setPommisions(){ //setForceAccepting 是否强制让用户接受权限 permissionHelper.setForceAccepting(false).request(PERMISSIONS_STORAGE); } /** * 权限申请 */ private PermissionHelper permissionHelper; public String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE }; /** * 不用申请权限(6.0权限以下) */ private void permissionsAllowed(){ view(); } /** * 获取权限返回是否通过 * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); permissionHelper.onActivityForResult(requestCode); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); permissionHelper.onRequestPermissionsResult(requestCode,permissions,grantResults); } /** * 下面是所有的定义的接口类的方法。 * @param permissionName * 第一个是代表不用申请权限许可的 */ @Override public void onPermissionGranted(@NonNull String[] permissionName) { permissionsAllowed(); } @Override public void onPermissionPreGranted(@NonNull String permissionsName) { permissionsAllowed(); } /** * 关于权限被拒绝(拒绝的时候再次 申请) * @param permissionName */ @Override public void onPermissionDeclined(@NonNull String[] permissionName) { } /** * 许可需要说明 * @param permissionName */ @Override public void onPermissionNeedExplanation(@NonNull String permissionName) { } /** * 在权限上被拒绝 * @param permissionName */ @Override public void onPermissionReallyDeclined(@NonNull String permissionName) { } /** * 不限制权限 */ @Override public void onNoPermissionNeeded() { } /** * 截屏显示 */ private Bitmap screenshot() { // 获取屏幕 View dView = getWindow().getDecorView(); dView.setDrawingCacheEnabled(true); dView.buildDrawingCache(); Bitmap bmp = dView.getDrawingCache(); if (bmp != null) { try { // 获取内置SD卡路径 String sdCardPath = Environment.getExternalStorageDirectory().getPath(); // 图片文件路径 String filePath = sdCardPath + File.separator + "screenshot.png"; File file = new File(filePath); FileOutputStream os = new FileOutputStream(file); bmp.compress(Bitmap.CompressFormat.PNG, 100, os); os.flush(); os.close(); } catch (Exception e) { } } return bmp; } /** * 组合图片拼接 * @param bit2 */ private void setNewBimap(Bitmap bit2){ Bitmap bm =screenshot(); // 将图片显示到ImageView中 view = new JointBitmap(this, bm, bit2); Bitmap bitmap = view.newBitmap(bm, bit2);//imageView_joint if (bitmap != null) { try { // 获取内置SD卡路径 String sdCardPath = Environment.getExternalStorageDirectory().getPath(); // 图片文件路径 String filePath = sdCardPath + File.separator + "sharepicure.png"; File file = new File(filePath); FileOutputStream os = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); os.flush(); os.close(); } catch (Exception e) { } } mView.setImageBitmap(bitmap); } /** * 点击下载图片 */ public void view(){ // 开启新的线程用于下载图片 new Thread(new Runnable() { public void run() { getPicture(); } }).start(); } //下载图片的主方法 private void getPicture() { URL url = null; InputStream is = null; FileOutputStream fos = null; try { //构建图片的url地址 url = new URL("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1504262170401&di=e8bcb963760c37dc7fd5ddee48cb40cd&imgtype=0&src=http%3A%2F%2Fwww.zhlzw.com%2FUploadFiles%2FArticle_UploadFiles%2F201204%2F20120412123921838.jpg"); //开启连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时的时间,5000毫秒即5秒 conn.setConnectTimeout(5000); //设置获取图片的方式为GET conn.setRequestMethod("GET"); //响应码为200,则访问成功 if (conn.getResponseCode() == 200) { //获取连接的输入流,这个输入流就是图片的输入流 is = conn.getInputStream(); //构建一个file对象用于存储图片 File file = new File(Environment.getExternalStorageDirectory(), "pic.jpg"); fos = new FileOutputStream(file); int len = 0; byte[] buffer = new byte[1024]; //将输入流写入到我们定义好的文件中 while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } //将缓冲刷入文件 fos.flush(); //告诉handler,图片已经下载成功 mHandler.sendEmptyMessage(1); } } catch (Exception e) { //告诉handler,图片已经下载失败 mHandler.sendEmptyMessage(0); e.printStackTrace(); } finally { //在最后,将各种流关闭 try { if (is != null) { is.close(); } if (fos != null) { fos.close(); } } catch (Exception e) { mHandler.sendEmptyMessage(0); e.printStackTrace(); } } }
这个事拼接图片;
private Bitmap bitmap; public JointBitmap(Context context, Bitmap bit1, Bitmap bit2) { super(context); // bitmap = newBitmap(bit1,bit2); } /** * 拼接图片 * * @param bit1 * @param bit2 * @return 返回拼接后的Bitmap */ public Bitmap newBitmap(Bitmap bit1, Bitmap bit2) { int width = bit1.getWidth(); int height = bit1.getHeight() + bit2.getHeight(); //创建一个空的Bitmap(内存区域),宽度等于第一张图片的宽度,高度等于两张图片高度总和 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); //将bitmap放置到绘制区域,并将要拼接的图片绘制到指定内存区域 Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(bit1, 0, 0, null); canvas.drawBitmap(bit2, 0, bit1.getHeight(), null); return bitmap; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(bitmap, 0, 0, null); bitmap.recycle(); } public JointBitmap(Context context) { super(context); } public JointBitmap(Context context, AttributeSet attrs) { super(context, attrs); } public JointBitmap(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
5.0以上截屏大家都这么做。
private static final String TAG ="otouzi"; private static final int REQUEST_CODE = 100; private static String STORE_DIRECTORY; private static int IMAGES_PRODUCED; private static final String SCREENCAP_NAME = "screencap"; private static final int VIRTUAL_DISPLAY_FLAGS = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; private static MediaProjection sMediaProjection; private MediaProjectionManager mProjectionManager; private ImageReader mImageReader; private Handler mHandler; private Display mDisplay;//显示 private VirtualDisplay mVirtualDisplay; private int mDensity; private int mWidth; private int mHeight; private int mRotation; private OrientationChangeCallback mOrientationChangeCallback; private String path; private ImageView imageView; private ImageView text_imageView2; private Bitmap mBitmap;//ImageLoate本地的图片 private Handler mHandlerWolder=new Handler(){ @Override public void handleMessage(Message msg) { if (msg.what==1){ setImageview(); } } }; /****************************************** Activity Lifecycle methods ************************/ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_testview); /** * 系统向用户请求屏幕录制的相关权限,首先获取MediaProjectionManager, * 和其他的Manager一样通过 Context.getSystemService() 传入参数MEDIA_PROJECTION_SERVICE获得实例。 */ mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); imageView= (ImageView) findViewById(R.id.text_imageView); text_imageView2= (ImageView) findViewById(R.id.text_imageView2); // 开始 Button startButton = (Button)findViewById(R.id.startButton); startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startProjection(); } }); // stop projection Button stopButton = (Button)findViewById(R.id.stopButton); stopButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopProjection(); } }); String mImageViewPath="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1503047905115&di=624821829abdf2761d3c276834a6366e&imgtype=0" + "&src=http%3A%2F%2Fwww.zhlzw.com%2FUploadFiles%2FArticle_UploadFiles%2F201204%2F20120412123914329.jpg"; // mBitmap=ImageLoader.getInstance().loadImageSync(mImageViewPath); // start capture handling thread new Thread() { @Override public void run() { Looper.prepare(); mHandler = new Handler(); Looper.loop(); } }.start(); } /** * 设置图片 */ private boolean mFlag=false; private void setImageview(){ boolean isSdCardExist = Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED);// 判断sdcard是否存在 if (isSdCardExist) { // textView1.setText("sd卡是存在的。以下是sdcard下的img25.jpg!");File.separator String filepath = STORE_DIRECTORY +"/myscreen_" + IMAGES_PRODUCED + ".png"; File file = new File(filepath); if (file.exists()) { Bitmap bm = BitmapFactory.decodeFile(filepath); // 将图片显示到ImageView中 /** * 这里使用BitmapFactory.decodeStream(InputStream is);方法加载图片可以有效的防止 * 当内存过大时出现内存溢出的情况 */ if (mFlag=true){ imageView.setImageBitmap(bm); } } } else { // textView1.setText("sd卡不存在!"); } } /** * 截图成功保存成bitmap */ @TargetApi(Build.VERSION_CODES.KITKAT) private class ImageAvailableListener implements ImageReader.OnImageAvailableListener { @Override public void onImageAvailable(ImageReader reader) { Image image = null; FileOutputStream fos = null; Bitmap bitmap = null; try { image = mImageReader.acquireLatestImage(); if (image != null) { Image.Plane[] planes = image.getPlanes(); ByteBuffer buffer = planes[0].getBuffer(); int pixelStride = planes[0].getPixelStride(); int rowStride = planes[0].getRowStride(); int rowPadding = rowStride - pixelStride * mWidth; bitmap=takeScreenShot(TestActivity.this,mWidth + rowPadding / pixelStride);//修改的 // create bitmap原来的 //bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888); bitmap.copyPixelsFromBuffer(buffer); // write bitmap to a file fos = new FileOutputStream(STORE_DIRECTORY + "/myscreen_" + IMAGES_PRODUCED + ".png"); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); stopProjection(); //IMAGES_PRODUCED++; Log.e(TAG, "captured image: " + IMAGES_PRODUCED); mHandlerWolder.sendEmptyMessage(1); } } catch (Exception e) { e.printStackTrace(); } finally { if (fos!=null) { try { fos.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } if (bitmap!=null) { bitmap.recycle(); } if (image!=null) { image.close(); } } } } /** * 去掉标题栏 */ public static Bitmap takeScreenShot(Activity activity, int mWidth) { // View是你需要截图的View View view = activity.getWindow().getDecorView(); // view.setDrawingCacheEnabled(true); view.setDrawingCacheEnabled(false); view.buildDrawingCache(); Bitmap b1 = view.getDrawingCache(); // 获取状态栏高度 Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; // 获取屏幕长和高 int width = activity.getWindowManager().getDefaultDisplay().getWidth(); int height = activity.getWindowManager().getDefaultDisplay() .getHeight(); //用bitmap的高度,不用屏幕的高度,不然有可能报错,因为有的手机(魅族手机)底部有占高度 height=b1.getHeight(); // 去掉标题栏 // Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455); Bitmap b = Bitmap.createBitmap(mWidth, height-statusBarHeight-100, Bitmap.Config.ARGB_8888); view.destroyDrawingCache(); return b; } private class OrientationChangeCallback extends OrientationEventListener { public OrientationChangeCallback(Context context) { super(context); } @TargetApi(Build.VERSION_CODES.KITKAT) @Override public void onOrientationChanged(int orientation) { synchronized (this) { final int rotation = mDisplay.getRotation(); if (rotation != mRotation) { mRotation = rotation; try { // clean up if(mVirtualDisplay != null) mVirtualDisplay.release(); if(mImageReader != null) mImageReader.setOnImageAvailableListener(null, null); // re-create virtual display depending on device width / height createVirtualDisplay(); } catch (Exception e) { e.printStackTrace(); } } } } } /** * 截屏改变方向 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private class MediaProjectionStopCallback extends MediaProjection.Callback { @Override public void onStop() { Log.e("ScreenCapture", "stopping projection."); mHandler.post(new Runnable() { @Override public void run() { if(mVirtualDisplay != null) mVirtualDisplay.release(); if(mImageReader != null) mImageReader.setOnImageAvailableListener(null, null); if(mOrientationChangeCallback != null) mOrientationChangeCallback.disable(); sMediaProjection.unregisterCallback(MediaProjectionStopCallback.this); } }); } } /** * 如果授权成功,通过MediaProjectionManager.getMediaProjection(int resultCode, Intent resultData) * 获取MediaProjection实例,通过MediaProjection.createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, * VirtualDisplay.Callback callback, Handler handler) * 创建VirtualDisplay实例。实际上在上述方法中传入的surface参数,是真正用来截屏或者录屏的。 * @param data */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE) { sMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);//主要的类获取这个类 if (sMediaProjection != null) { STORE_DIRECTORY = Environment.getExternalStorageDirectory().getAbsolutePath() + "/screenshots/";//内存卡地址 File storeDirectory = new File(STORE_DIRECTORY); if (!storeDirectory.exists()) { boolean success = storeDirectory.mkdirs(); if(!success) { Log.e(TAG, "failed to create file storage directory."); return; }else { Log.e(TAG,"成功"); } } //获取屏幕大小等 DisplayMetrics metrics = getResources().getDisplayMetrics(); mDensity = metrics.densityDpi; mDisplay = getWindowManager().getDefaultDisplay(); //设置宽高 createVirtualDisplay(); /** *截屏顺序,改变回调 */ mOrientationChangeCallback = new OrientationChangeCallback(this); if (mOrientationChangeCallback.canDetectOrientation()) { mOrientationChangeCallback.enable(); } // 截屏开始,注册回调接口 sMediaProjection.registerCallback(new MediaProjectionStopCallback(), mHandler); } } } /** * 第二部 * 接着调用MediaProjectionManager.createScreenCaptureIntent()弹出dialog询问用户是否授权应用捕捉屏幕, * 同时覆写onActivityResult()获取授权结果 * **/ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void startProjection() { startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); } /** * 停止 */ private void stopProjection() { mHandler.post(new Runnable() { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void run() { if (sMediaProjection != null) { sMediaProjection.stop(); } } }); } /** * 宽高显示截屏大小 * 截屏这里用到ImageReader类,这个类的getSurface()方法获取到surface直接传入MediaProjection.createVirtualDisplay()方法中, * 此时就可以执行截取。通过ImageReader.acquireLatestImage()方法即可获取当前屏幕的Image,经过简单处理之后即可保存为Bitmap。 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void createVirtualDisplay() { // get width and height Point size = new Point(); mDisplay.getSize(size); mWidth = size.x; mHeight = size.y; //创建截取类 mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2); //编译器 mVirtualDisplay = sMediaProjection.createVirtualDisplay(SCREENCAP_NAME, mWidth, mHeight, mDensity, VIRTUAL_DISPLAY_FLAGS, mImageReader.getSurface(), null, mHandler); //回调 mImageReader.setOnImageAvailableListener(new ImageAvailableListener(), mHandler); } }