Android - 分享功能,截图并保存图片到本地相册(适配小米

分享需求:生成二维码,并拼接部分截图到分享弹窗。点击保存按钮则保存图片到本地。

步骤:创建弹窗 -> 生成二维码- > 拿到并拼接截图-展示 -> 获取读写权限 -> 保存bitmap到本地
![分享弹窗布局](https://img-blog.csdnimg.cn/92f9d0754a0e4ed0bb20a840b55bc35c.pn

0. 创建弹窗

dialog_share_live.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    
    <LinearLayout
        android:id="@+id/ll_pic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:background="@color/white">

	    <ImageView
	        android:id="@+id/iv_code"
	        android:layout_width="35dp"
	        android:layout_height="35dp"/>
	
	     <ImageView
	        android:id="@+id/iv_screen"
	        android:layout_width="match_parent"
	        android:layout_height="wrap_content"
	        android:scaleType="fitXY"/>
	</LinearLayout>
	
    <TextView
        android:id="@+id/tv_save"
        android:layout_width="80dp"
        android:layout_height="35dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="@string/save"
        android:textSize="14dp"
        android:textColor="@color/white"
        android:background="@drawable/shape_dc3c23_23dp_rec"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>/>


avtivity.java

	private Bitmap shareQRCodeBitmap;
    private AlertDialog shareDialog;
    private Bitmap picBitmap;
    private View view1;
    private ImageView ivScreen;
    private LinearLayout ll_pic;
    private void shareScreen(){
    
    
        view1 = mActivity.getLayoutInflater().inflate(R.layout.dialog_share_live,null);
        ImageView ivCode = view1.findViewById(R.id.iv_code);//二维码
        ivScreen = view1.findViewById(R.id.iv_screen);//截图
        ll_pic = view1.findViewById(R.id.ll_pic);//需要下载的部分
        
        //生成二维码
        ......

        if(shareDialog == null){
    
    
            shareDialog = new AlertDialog.Builder(mActivity).setView(view1).create();
            shareDialog.setCancelable(true);
            shareDialog.setCanceledOnTouchOutside(true);
        }
        
		//拼接截图
        ......

        //展示弹窗
        shareDialog.setView(view1);
        shareDialog.show();

        DisplayMetrics dm = new DisplayMetrics();
        mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        Window w = shareDialog.getWindow();
        w.setLayout((int) (dm.widthPixels * 0.9), ViewGroup.LayoutParams.WRAP_CONTENT);

        w.findViewById(R.id.tv_save).setOnClickListener(v -> {
    
    
        	//保存图片
            ......
        });

        w.findViewById(R.id.ll_pic).setOnClickListener(v->{
    
    
            shareDialog.dismiss();
        });
    }
    
	//请求权限的回调
	@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    
    
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
    
    
            case 10004:
                for (int i = 0; i < grantResults.length; i++) {
    
    
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
    
    
                    	//是否狠狠拒绝
                        boolean flag = ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[i]);
                        ToastUtil.show(getString(flag?"Go to Settings to enable file storage permissions":"Please grant file storage permission first"));
                        return;
                    }
                }
                saveBitmapFile(mActivity,picBitmap);
                break;
            default:
                break;
        }
    }

1. 生成二维码

  1. 导入依赖:
implementation 'com.google.zxing:core:3.3.0'
  1. 创建工具方法:UIUtil.java
	/**
     * 根据地址生成二维码图片
     */
    public static Bitmap createQrCode(String url,final int width,final int height) {
    
    
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, String> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.MARGIN, 0+"");//去除白边
        try {
    
    
            BitMatrix encode = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, width, height, hints);

            int[] pixels = new int[width * height];
            for (int i = 0; i < height; i++) {
    
    
                for (int j = 0; j < width; j++) {
    
    
                    if (encode.get(j, i)) {
    
    
                        pixels[i * width + j] = 0x00000000;
                    } else {
    
    
                        pixels[i * width + j] = 0xffffffff;
                    }
                }
            }
            Bitmap bitmap=Bitmap.createBitmap(width,height, Bitmap.Config.RGB_565);
            bitmap.setPixels(pixels,0,width,0,0,width,height);
            return bitmap;
        } catch (WriterException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
  1. 生成二维码:activity.java
 private void shareScreen(){
    
    
        ......
        //生成二维码
        if(shareQRCodeBitmap == null){
    
    
            shareQRCodeBitmap = createQrCode(SHARE_LIVE_URL,UIUtil.dip2px(mActivity,35),UIUtil.dip2px(mActivity,35));
        }
        ivCode.setImageBitmap(shareQRCodeBitmap);
        ......
 }

2. 截图

找到需要截图的容器:ll_main

 private void shareScreen(){
    
    
        ......
		//拼接截图
        //这种截图方式有缓存,且短视频和直播源画面空白,我们是用封面替代
        ll_main.setDrawingCacheEnabled(true);
        Bitmap bitmap = ll_main.getDrawingCache();
        ivScreen.setImageBitmap(bitmap);
        ......        
}

3. 保存图片到本地

  1. 创建工具方法 保存图片:UiUtils.java (可直接看最终法)

方式一:现有测试机里华为、魅族都ok,谷歌和小米不行,且无报错信息o(╥﹏╥)o

public static File saveBitmapFile(Activity activity,Bitmap bit) {
    
    
        //先判断权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    
    
            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
    
    
                ActivityCompat.requestPermissions(activity, new String[]{
    
    Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 10004);
                return null;
            }
        }

        if(bit == null){
    
    
            return null;
        }

        if (bit.isRecycled()) {
    
    
            return null;
        }

        String path = Environment.getExternalStorageDirectory().getPath();
        if (Build.VERSION.SDK_INT > 29) {
    
    
            path = activity.getExternalFilesDir(null).getAbsolutePath() ;
        }

        File file = new File(path, "share_live_"+System.currentTimeMillis()+".jpg");
        try {
    
    
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            //压缩Bitmap,不支持png图片的压缩
            bit.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();
            bos.close();
            // 把文件插入到系统图库
            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
            Uri uri = activity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

            // 通知图库更新
            activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
            ToastUtil.show(activity.getString(R.string.save_success));

            return file;
        } catch (IOException e) {
    
    
            e.printStackTrace();
            ToastUtil.show(activity.getString(R.string.save_failed));
        }
        return null;
    }

方式二:换个访问路径,谷歌行,小米不行,报错:ENOENT (No such file or directory)

ERROR FileNotFoundException:/storage/emulated/0/Android/data/com.xxx.live/files/DCIM/Camera、share_live_1677650698438.jpg: open failed: ENOENT (No such file or directory)

public static File saveBitmapFile(Activity activity,Bitmap bit) {
    
    
        //先判断权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    
    
            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
    
    
                ActivityCompat.requestPermissions(activity, new String[]{
    
    Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 10004);
                return null;
            }
        }

        if(bit == null){
    
    
            return null;
        }

        if (bit.isRecycled()) {
    
    
            return null;
        }

        String path = Environment.getExternalStorageDirectory().getPath();// Meizu 、Oppo
        //1.路径
        if (Build.BRAND.equals("Xiaomi")) {
    
     // 小米手机brand.equals("xiaomi")
            path = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/" ;
        } else if (Build.BRAND.equalsIgnoreCase("Huawei")) {
    
    
            path = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/" ;
        }

        File file = new File(path, "share_live_"+System.currentTimeMillis()+".jpg");
        try {
    
    
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            //压缩Bitmap,不支持png图片的压缩,PNG格式的不能显示在相册中
            bit.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();
            bos.close();
            // 把文件插入到系统图库
            if(Build.VERSION.SDK_INT >= 29){
    
    
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
                values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
                Uri uri = activity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            }else{
    
    
                MediaStore.Images.Media.insertImage(activity.getContentResolver(), file.getAbsolutePath(), "", null);
            }
            // 通知图库更新
            activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
            ToastUtil.show(activity.getString(R.string.save_success));
            return file;
        }catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
            ToastUtil.show(activity.getString(R.string.save_failed));
        } catch (IOException e) {
    
    
            e.printStackTrace();
            ToastUtil.show(activity.getString(R.string.save_failed));
        } catch (Exception e) {
    
    
            e.printStackTrace();
            ToastUtil.show(activity.getString(R.string.save_failed));
        }
        return null;
    }

最终法:插入一张图片到图库中,再刷新 都通过(用这个就行)

public static File saveBitmapFile(Activity activity,Bitmap bit) {
    
    
        //先判断权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    
    
            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
    
    
                ActivityCompat.requestPermissions(activity, new String[]{
    
    Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 10004);
                return null;
            }
        }

        if(bit == null){
    
    
            return null;
        }

        if (bit.isRecycled()) {
    
    
            return null;
        }

        try {
    
    
            String result = MediaStore.Images.Media.insertImage(activity.getContentResolver(), bit, "share_live_"+System.currentTimeMillis()+".jpeg", "share_live");
            Intent scannerIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse(result));
            activity.sendBroadcast(scannerIntent);
            ToastUtil.show(activity.getString(R.string.save_success));
        }catch (Exception e) {
    
    
            Log.e("Exception", "ltt saveBitmapFile0 Exception:" + e.getMessage().toString());
            e.printStackTrace();
            ToastUtil.show(activity.getString(R.string.save_failed));
        }
        return null;
    }

虽然还是不知道为啥用前面两种方法小米会找不到路径,先记录下来…

  1. 获取bitmap对象,需要保存的是ll_pic,不需要按钮
 private void shareScreen(){
    
    
			......
        	//保存图片
            if(picBitmap==null){
    
    
                picBitmap = convertViewToBitmap(ll_pic);
            }
            
            if(saveBitmapFile(mActivity,picBitmap)!=null){
    
    
                shareDialog.dismiss();
            }
        	.......
 }

UIUtils.java

	/**
     * 获取view的Bitmap
     */
    public static Bitmap convertViewToBitmap(View view){
    
    
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
    }

ok结束


另外增加需求:系统分享图片到第三方

将图片保存在缓存中,再分享出去。

  1. UIUtils.java
	/**
     * 保存图片到缓存
     */
    public static String saveTitmapToCache(Context context , Bitmap bitmap){
    
    
        // 默认保存在应用缓存目录里 Context.getCacheDir()
        File file=new File(context.getCacheDir(),System.currentTimeMillis()+".png");
        try {
    
    
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);
            bos.flush();
            bos.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return file.getPath();
    }
    
    /**
     * 调用系统分享图片
     */
    public static boolean sharePictureFile(Activity activity, Bitmap bitmap) {
    
    
        //先判断权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    
    
            if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
    
    
                ActivityCompat.requestPermissions(activity, new String[]{
    
    Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 10005);
                return false;
            }
        }
        //压缩前要防止 Can’t compress a recycled bitmap
        if (bitmap.isRecycled()) {
    
    
            return false;
        }
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
//        Bitmap bitmap = Bitmap.createBitmap(((BitmapDrawable) context.getDrawable(R.mipmap.xxx)).getBitmap());

        String imgpath = saveTitmapToCache(getApplicationContext(), bitmap);
        if(!TextUtils.isEmpty(imgpath)){
    
    
            Uri uri = FileProvider.getUriForFile(activity, activity.getPackageName() + ".fileProvider", new File(imgpath));
            intent.setDataAndType(uri, "image/*");
            intent.putExtra(Intent.EXTRA_STREAM, uri);
            intent.setType("image/*");
            activity.startActivity(Intent.createChooser(intent, "Share to..."));
        }
        return true;
    }
  1. activiity.java
	w.findViewById(R.id.tv_share).setOnClickListener(v -> {
    
    
			//分享到第三方
            if(picBitmap==null){
    
    
                picBitmap = convertViewToBitmap(ll_pic);
            }
            if(sharePictureFile(mActivity,picBitmap)){
    
    
                shareDialog.dismiss();
            }

        });

另外增加需求:系统分享链接(文本)到第三方

activity.java

	w.findViewById(R.id.tv_url).setOnClickListener(v -> {
    
    
	     //分享链接
	     ShareUtil.shareText(mActivity,"",);
	     Intent intent = new Intent(Intent.ACTION_SEND);
	     intent.setType("text/plain");
	     intent.putExtra(Intent.EXTRA_TEXT, "分享链接");
	     context.startActivity(Intent.createChooser(intent, "title"));
	});

ok,三种分享方式都做完了(分享图片、文字到第三方、保存图片)

猜你喜欢

转载自blog.csdn.net/czssltt/article/details/129303326
今日推荐