package com.hdl.photovoltaic.widget.popupview; import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.content.ContentUris; import android.content.ContentValues; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.drawable.ColorDrawable; import android.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.provider.Settings; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.core.content.FileProvider; import com.hdl.photovoltaic.R; import com.hdl.photovoltaic.other.HdlDialogLogic; import com.hdl.photovoltaic.other.HdlThreadLogic; import com.hdl.photovoltaic.utils.PermissionUtils; import com.hdl.photovoltaic.utils.SharedPreUtils; import com.hdl.photovoltaic.widget.PermissionExplanationDialog; import com.hjq.permissions.OnPermissionCallback; import com.hjq.permissions.XXPermissions; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; /** * @Author : Zoro. * @Date : 2018/11/22. * @Describe :这个View中处理了很多异常捕获,直接结束就可以了,UI上面都已经处理好了 */ public class CameraAlbumPopWindow extends PopupWindow { public static final int TAKE_PHOTO = 100;//启动相机标识 public static final int SELECT_PHOTO = 200;//启动相册标识 private View mView; private Activity mContext; private TextView tv_mCamera; private TextView tv_Album; private TextView tv_mCancel; //默认图片最大为200k private int photo_Size = 200; private File hdl_Dir; private File outputImagepath;//存储拍完照后的图片 private Bitmap orc_bitmap;//拍照和相册获取图片的Bitmap private int MAX_WIDTH = 800, MAX_HEIGHT = 800; // private CameraAlbumListener cameraListener; public CameraAlbumPopWindow(Activity context, CameraAlbumListener cameraListener) { super(context); this.cameraListener = cameraListener; initView(context); } public CameraAlbumPopWindow(Activity context, int width, int height, CameraAlbumListener cameraListener) { super(context); this.cameraListener = cameraListener; this.MAX_HEIGHT = height; this.MAX_WIDTH = width; initView(context); } public CameraAlbumPopWindow(Activity context, int photo_Size, CameraAlbumListener cameraListener) { super(context); this.photo_Size = photo_Size; this.cameraListener = cameraListener; initView(context); } /** * @param context 上下文 * @param tag 0:拍照 1:相册 */ private void checkPermission_After(final Activity context, final int tag) { String permission = Manifest.permission.CAMERA; // 未授权 如果应用程序没有所需的权限,则显示解释说明 PermissionExplanationDialog.getInstance().showPortConflictPdDialog(context, context.getString(R.string.camera_storage_instructions), context.getString(R.string.camera_storage_purpose)); int status = PermissionUtils.getPermissionState(context, permission); switch (status) { case PermissionUtils.STATUS_SUCCESS: PermissionExplanationDialog.getInstance().dismiss(); dismiss(); if (0 == tag) { take_photo(); } else { select_photo(); } break; case PermissionUtils.STATUS_REFUSE: case PermissionUtils.STATUS_DEFAULT: XXPermissions.with(context) .permission(permission) .request(new OnPermissionCallback() { @Override public void onGranted(List permissions, boolean all) { PermissionExplanationDialog.getInstance().dismiss(); dismiss(); SharedPreUtils.putBoolean(permission, true); if (0 == tag) { take_photo(); } else { select_photo(); } } @Override public void onDenied(List permissions, boolean never) { PermissionExplanationDialog.getInstance().dismiss(); dismiss(); SharedPreUtils.putBoolean(permission, true); } }); break; case PermissionUtils.STATUS_REFUSE_PERMANENT: PermissionExplanationDialog.getInstance().dismiss(); // HdlThreadLogic.toast(mContext, R.string.permission_open); HdlDialogLogic.getInstance().showSettingPermissionDialog(mContext); break; } } private void initView(Activity context) { hdl_Dir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS); System.out.println("===========" + hdl_Dir.getAbsolutePath()); if (!hdl_Dir.exists()) { boolean mkdirs = hdl_Dir.mkdirs(); if (!mkdirs) { HdlThreadLogic.toast(mContext, R.string.camera_album_file_create_fial); } } mContext = context; mView = LayoutInflater.from(mContext).inflate(R.layout.view_camera_album, null); setContentView(mView); tv_mCamera = mView.findViewById(R.id.tv_Camera); tv_Album = mView.findViewById(R.id.tv_Album); tv_mCancel = mView.findViewById(R.id.tv_Cancel); this.setWidth(RelativeLayout.LayoutParams.MATCH_PARENT); this.setHeight(RelativeLayout.LayoutParams.WRAP_CONTENT); //点击空白地方关闭弹窗(3个要一起隐藏) this.setFocusable(true); this.setTouchable(true); this.setOutsideTouchable(true); this.setBackgroundDrawable(new ColorDrawable(0)); mView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int height = mView.findViewById(R.id.ll_Pop).getTop(); int y = (int) event.getY(); if (event.getAction() == MotionEvent.ACTION_UP) { if (y < height) { dismiss(); } } return true; } }); tv_mCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); tv_mCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { checkPermission_After(mContext, 0); } }); tv_Album.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { checkPermission_After(mContext, 1); } }); } /** * 拍照获取图片 **/ private void take_photo() { try { //获取系統版本 int currentapiVersion = Build.VERSION.SDK_INT; // 激活相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 判断存储卡是否可以用,可用进行存储 SimpleDateFormat timeStampFormat = new SimpleDateFormat( "yyyy_MM_dd_HH_mm_ss", Locale.ENGLISH); String filename = timeStampFormat.format(new Date()); outputImagepath = new File(hdl_Dir, filename + ".jpg"); if (currentapiVersion < 24) { // 从文件中创建uri Uri uri = Uri.fromFile(outputImagepath); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } else { // //兼容android7.0 使用共享文件的形式 // ContentValues contentValues = new ContentValues(1); // contentValues.put(MediaStore.Images.Media.DATA, outputImagepath.getAbsolutePath()); // Uri uri = mContext.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); // intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); // Uri photoURI = FileProvider.getUriForFile(mContext, "com.hdl.photovoltaic.dc.fileprovider", outputImagepath); // intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); //兼容android7.0 使用共享文件的形式 ContentValues contentValues = new ContentValues(1); contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, outputImagepath.getName()); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); Uri uri = mContext.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); Uri photoURI = FileProvider.getUriForFile(mContext, "com.hdl.photovoltaic.fileProvider", outputImagepath); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); } // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA ((Activity) mContext).startActivityForResult(intent, TAKE_PHOTO); } catch (Exception e) { HdlThreadLogic.toast(mContext, R.string.loading_not_supported); } } /** * 拍照获取完图片要执行的方法(根据图片路径显示图片) */ public void displayImage() { if (null == outputImagepath) { HdlThreadLogic.toast(mContext, R.string.camera_album_file_save_fial); } else { if (!TextUtils.isEmpty(outputImagepath.getAbsolutePath())) { //注意:(android13,14需要再设置-隐私-)特殊权限设置 orc_bitmap = BitmapFactory.decodeFile(outputImagepath.getAbsolutePath());//获取图片 saveBitmap(comp(ImgUpdateDirection(outputImagepath.getAbsolutePath()))); //压缩图片 } else { HdlThreadLogic.toast(mContext, R.string.camera_album_file_get_fial); } } } /** * 相册获取完图片要执行的方法(根据图片路径显示图片) */ private void displayImage(String imagePath) { if (!TextUtils.isEmpty(imagePath)) { orc_bitmap = BitmapFactory.decodeFile(imagePath);//获取图片 saveBitmap(comp(ImgUpdateDirection(imagePath))); //压缩图片 } else { HdlThreadLogic.toast(mContext, R.string.camera_album_file_get_fial); } } //比例压缩 private Bitmap comp(Bitmap image) { if (null == image) { HdlThreadLogic.toast(mContext, R.string.camera_album_system_fial); return null; } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos); // if (baos.toByteArray().length / 1024 > 1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出 // baos.reset();//重置baos即清空baos // image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中 // } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); BitmapFactory.Options newOpts = new BitmapFactory.Options(); //开始读入图片,此时把options.inJustDecodeBounds 设回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为 //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int be = 1;//be=1表示不缩放 while (((int) w / be) > MAX_WIDTH || ((int) h / be) > MAX_HEIGHT) { be++; } if (be <= 0) be = 1; newOpts.inSampleSize = be;//设置缩放比例 System.out.println("--------newOpts.inSampleSize==" + newOpts.inSampleSize); newOpts.inPreferredConfig = Bitmap.Config.RGB_565;//降低图片从ARGB888到RGB565 //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 isBm = new ByteArrayInputStream(baos.toByteArray()); bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); return bitmap;//压缩好比例大小后再进行质量压缩 } } /** * 质量压缩方法 * * @param image * @return */ private Bitmap compressImage(Bitmap image) { if (image != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 int options = 100; while (baos.toByteArray().length / 1024 > 100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 baos.reset();//重置baos即清空baos options -= 10;//每次都减少10 image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片 return bitmap; } else { return null; } } /** * 保存方法 */ private void saveBitmap(Bitmap bitmap) { if (null == bitmap) { HdlThreadLogic.toast(mContext, mContext.getResources().getString(R.string.camera_album_system_fial)); } else { SimpleDateFormat timeStampFormat = new SimpleDateFormat( "yyyy_MM_dd_HH_mm_ss", Locale.CHINESE); String filename = timeStampFormat.format(new Date()); File f = new File(hdl_Dir, filename + ".jpg"); if (f.exists()) { f.delete(); } try { FileOutputStream out = new FileOutputStream(f); bitmap.compress(Bitmap.CompressFormat.JPEG, 60, out); //进行数据的处理 out.flush(); out.close(); //保存好小图以后删除大图(拍照需要) deleteBigPhoto(); cameraListener.successCallBack(f); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 压缩图片保存之后需要删除原图 */ private void deleteBigPhoto() { if (null != outputImagepath) { outputImagepath.delete(); } } //改变拍完照后图片方向不正的问题 private Bitmap ImgUpdateDirection(String filepath) { int digree = 0;//图片旋转的角度 //根据图片的URI获取图片的绝对路径 //String filepath = ImgUriDoString.getRealFilePath(getApplicationContext(), uri); //根据图片的filepath获取到一个ExifInterface的对象 ExifInterface exif = null; try { exif = new ExifInterface(filepath); if (exif != null) { // 读取图片中相机方向信息 int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); // 计算旋转角度 switch (ori) { case ExifInterface.ORIENTATION_ROTATE_90: digree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: digree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: digree = 270; break; default: digree = 0; break; } } //如果图片不为0 if (digree != 0) { // 旋转图片 Matrix m = new Matrix(); m.postRotate(digree); orc_bitmap = Bitmap.createBitmap(orc_bitmap, 0, 0, orc_bitmap.getWidth(), orc_bitmap.getHeight(), m, true); } } catch (IOException e) { e.printStackTrace(); exif = null; } return orc_bitmap; } /** * 从相册中获取图片 */ private void select_photo() { String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE; int status = PermissionUtils.getPermissionState(mContext, permission); switch (status) { case PermissionUtils.STATUS_SUCCESS: openAlbum(); break; case PermissionUtils.STATUS_REFUSE: case PermissionUtils.STATUS_DEFAULT: XXPermissions.with(mContext) .permission(permission) .request(new OnPermissionCallback() { @Override public void onGranted(List permissions, boolean all) { SharedPreUtils.putBoolean(permission, true); openAlbum(); } @Override public void onDenied(List permissions, boolean never) { SharedPreUtils.putBoolean(permission, true); } }); break; case PermissionUtils.STATUS_REFUSE_PERMANENT: // HdlThreadLogic.toast(mContext, R.string.permission_open); HdlDialogLogic.getInstance().showSettingPermissionDialog(mContext); break; } } /** * 打开相册的方法 */ private void openAlbum() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); ((Activity) mContext).startActivityForResult(intent, SELECT_PHOTO); } /** * 4.4以下系统处理图片的方法 */ public void handleImageBeforeKitKat(Intent data) { Uri uri = data.getData(); String imagePath = getImagePath(uri, null); displayImage(imagePath); } /** * 4.4及以上系统处理图片的方法 */ @TargetApi(Build.VERSION_CODES.KITKAT) public void handleImgeOnKitKat(Intent data) { String imagePath = null; Uri uri = data.getData(); if (DocumentsContract.isDocumentUri(mContext, uri)) { String docId = DocumentsContract.getDocumentId(uri); //数据表里指定的行 if ("com.android.providers.media.documents".equals(uri.getAuthority())) { String id = docId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=" + id; imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection); } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); imagePath = getImagePath(contentUri, null); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { imagePath = getImagePath(uri, null); } else if ("file".equalsIgnoreCase(uri.getScheme())) { imagePath = uri.getPath(); } displayImage(imagePath); } /** * 通过uri和selection来获取真实的图片路径,从相册获取图片时要用 */ private String getImagePath(Uri uri, String selection) { String path = null; Cursor cursor = mContext.getContentResolver().query(uri, null, selection, null, null); if (cursor != null) { if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA); path = cursor.getString(columnIndex); } cursor.close(); } return path; } @Override public void dismiss() { super.dismiss(); backgroundAlpha(1f); } //用于popwindow显示隐藏时候背景的颜色更换 public void backgroundAlpha(float bgAlpha) { WindowManager.LayoutParams lp = ((Activity) mContext).getWindow().getAttributes(); ((Activity) mContext).getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); lp.alpha = bgAlpha; //0.0-1.0 ((Activity) mContext).getWindow().setAttributes(lp); } public void show(View view, int mode, int x, int y) { showAtLocation(view, mode, x, y); backgroundAlpha(0.5f); } public interface CameraAlbumListener { void successCallBack(File a); } }