Android 各种 Utils工具类封装 Utils大全集合

本文集合了Android开发中的各种实用工具,如AppUtils获取ApplicationContext、BitmapUtil图片处理、Glide圆角加载、CrashHandler异常捕获、线程管理等,提高开发效率并避免代码冗余。


最近项目整合也是遇到很多工具类混乱 多个模块、组件工具类重复问题,喜欢点赞收藏、欢迎大佬提拔指点!

Utils大全集合

AppUtils 获取项目的Application context 方便每个Utils去init(); 一定要在Application中初始化

public class AppUtils {
   
   
    private static Context mContext;

    private AppUtils () {
   
   
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    public static void initContext(Context context){
   
   
        mContext = context;
    }

    public static Context getApplication() {
   
   
        if (mContext!=null){
   
   
            return mContext;
        }else {
   
   
            throw new UnsupportedOperationException("context 未初始化");
        }
    }
}

BitmapUtil ==》图片工具类

public class BitmapUtil {
   
   
    /**
     * 按图片的质量压缩
     *
     * @param filePath 需要压缩的图片路径
     * @param quality  压缩的质量 0 - 100
     * @return
     */

    public static String compressBitmapByQuality(String filePath, int quality) {
   
   
        Bitmap bm = BitmapFactory.decodeFile(filePath);
        int degree = readPictureDegree(filePath);//获取相片拍摄角度
        if (degree != 0) {
   
   //旋转照片角度,防止头像横着显示
            bm = rotateBitmap(bm, degree);
        }
        File imageFile = new File(LeoUtils.getApplication().getFilesDir().getAbsolutePath().toString() + "/" + TimeUtils.getStrByLong(System.currentTimeMillis(), "yyyy.MM.dd_HH:mm:ss:SSS") + "_atmancarm.jpg");
        try {
   
   
            imageFile.createNewFile();
            FileOutputStream out = new FileOutputStream(imageFile);
            bm.compress(Bitmap.CompressFormat.JPEG, quality, out);
        } catch (Exception e) {
   
   

        }

        String imgpath = imageFile.getPath();

        return imgpath;
    }

    /**
     * 按图片长宽压缩
     * 按传入的长宽后,计算出合适的压缩比如,压缩图片,此处指的是图片长宽大小的压缩
     */
    public static Bitmap compressBitmapBySize(String filePath, int requireWidth, int requireHeight) {
   
   
        final BitmapFactory.Options options = new BitmapFactory.Options();
        //设置整个属性后,不会加载bitmap,只会获取图片属性,比如宽高
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        // 计算缩放比()
        options.inSampleSize = calculateInSampleSize(options, requireWidth, requireHeight);
        // 完整解析图片返回bitmap
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }

    //与原图片比,长宽压缩多少倍数。 multiple  几倍数
    public static Bitmap compressBitmapBySourceSize(String filePath, double multiple) {
   
   
        final BitmapFactory.Options options = new BitmapFactory.Options();
        //设置整个属性后,不会加载bitmap,只会获取图片属性,比如宽高
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        int sourceHeight = options.outHeight;
        int sourceWidth = options.outWidth;
        int requireWidth = (int) (sourceWidth / multiple);
        int requireHeight = (int) (sourceHeight / multiple);

        // 计算缩放比()
        options.inSampleSize = calculateInSampleSize(options, requireWidth, requireHeight);
        // 完整解析图片返回bitmap
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }


    /**
     * 获取照片角度
     * 一般是拍摄照片的时候才会用到
     *
     * @param path
     * @return
     */

    public static int readPictureDegree(String path) {
   
   
        int degree = 0;
        try {
   
   
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
   
   
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
   
   
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 旋转照片
     * 一般是拍摄照片的时候才会用到
     *
     * @param bitmap
     * @param degress
     * @return
     */
    public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
   
   
        if (bitmap != null) {
   
   
            Matrix m = new Matrix();
            m.postRotate(degress);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
            return bitmap;
        }
        return bitmap;
    }


    // 计算缩放比()
    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
   
   
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
   
   
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }


    //压缩图片到 指定大小
    public static Bitmap compressTargetBitmap(Bitmap bitmap) {
   
   
        double maxSize = 500.00;//KB
        //将bitmap放至数组中,意在bitmap的大小(与实际读取的原文件要大)
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] b = baos.toByteArray();
        //将字节换成KB
        double mid = b.length / 1024;
        //判断bitmap占用空间是否大于允许最大空间  如果大于则压缩 小于则不压缩
        if (mid > maxSize) {
   
   
            //获取bitmap大小 是允许最大大小的多少倍
            double i = mid / maxSize;
            //开始压缩  此处用到平方根 将宽带和高度压缩掉对应的平方根倍 (1.保持刻度和高度和原bitmap比率一致,压缩后也达到了最大大小占用空间的大小)
            bitmap = zoomBitmap(bitmap, bitmap.getWidth() / Math.sqrt(i),
                    bitmap.getHeight() / Math.sqrt(i));
        }
        return bitmap;
    }


    public static Bitmap zoomBitmap(Bitmap bgimage, double newWidth,
                                    double newHeight) {
   
   
        // 获取这个图片的宽和高
        float width = bgimage.getWidth();
        float height = bgimage.getHeight();
        // 创建操作图片用的matrix对象
        Matrix matrix = new Matrix();
        // 计算宽高缩放率
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 缩放图片动作
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
                (int) height, matrix, true);
        return bitmap;
    }


}

GlideRoundTransform ==》glide加载任意想加载的圆角

public class GlideRoundTransform implements Transformation<Bitmap> {
   
   
    private BitmapPool mBitmapPool;

    private float radius;

    private boolean isLeftTop, isRightTop, isLeftBottom, isRightBotoom;

    /**
     * 需要设置圆角的部分
     *
     * @param leftTop     左上角
     * @param rightTop    右上角
     * @param leftBottom  左下角
     * @param rightBottom 右下角
     */
    public void setNeedCorner(boolean leftTop, boolean rightTop, boolean leftBottom, boolean rightBottom) {
   
   
        isLeftTop = leftTop;
        isRightTop = rightTop;
        isLeftBottom = leftBottom;
        isRightBotoom = rightBottom;
    }

    /**
     * @param context 上下文
     * @param radius  圆角幅度
     */
    public GlideRoundTransform(Context context, float radius) {
   
   
        this.mBitmapPool = Glide.get(context).getBitmapPool();
        this.radius = radius;
    }

    @NonNull
    @Override
    public Resource<Bitmap> transform(@NonNull Context context, @NonNull Resource<Bitmap> resource, int outWidth, int outHeight) {
   
   

        Bitmap source = resource.get();
        int finalWidth, finalHeight;
        //输出目标的宽高或高宽比例
        float scale;
        if (outWidth > outHeight) {
   
   
            //如果 输出宽度 > 输出高度 求高宽比

            scale = (float) outHeight / (float) outWidth;
            finalWidth = source.getWidth();
            //固定原图宽度,求最终高度
            finalHeight = (int) ((float) source.getWidth() * scale);
            if (finalHeight > source.getHeight()) {
   
   
                //如果 求出的最终高度 > 原图高度 求宽高比

                scale = (float) outWidth / (float) outHeight;
                finalHeight = source.getHeight();
                //固定原图高度,求最终宽度
                finalWidth = (int) ((float) source.getHeight() * scale);
            }
        } else if (outWidth < outHeight) {
   
   
            //如果 输出宽度 < 输出高度 求宽高比

            scale = (float) outWidth / (float) outHeight;
            finalHeight = source.getHeight();
            //固定原图高度,求最终宽度
            finalWidth = (int) ((float) source.getHeight() * scale);
            if (finalWidth > source.getWidth()) {
   
   
                //如果 求出的最终宽度 > 原图宽度 求高宽比

                scale = (float) outHeight / (float) outWidth;
                finalWidth = source.getWidth();
                finalHeight = (int) ((float) source.getWidth() * scale);
            }
        } else {
   
   
            //如果 输出宽度=输出高度
            finalHeight = source.getHeight();
            finalWidth = finalHeight;
        }

        //修正圆角
        this.radius *= (float) finalHeight / (float) outHeight;
        Bitmap outBitmap = this.mBitmapPool.get(finalWidth, finalHeight, Bitmap.Config.ARGB_8888);
        if (outBitmap == null) {
   
   
            outBitmap = Bitmap.createBitmap(finalWidth, finalHeight, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(outBitmap);
        Paint paint = new Paint();
        //关联画笔绘制的原图bitmap
        BitmapShader shader = new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        //计算中心位置,进行偏移
        int width = (source.getWidth() - finalWidth) / 2;
        int height = (source.getHeight() - finalHeight) / 2;
        if (width != 0 || height != 0) {
   
   
            Matrix matrix = new Matrix();
            matrix.setTranslate((float) (-width), (float) (-height));
            shader.setLocalMatrix(matrix);
        }

        paint.setShader(shader);
        paint.setAntiAlias(true);
        RectF rectF = new RectF(0.0F, 0.0F, (float) canvas.getWidth(), (float) canvas.getHeight());
        //先绘制圆角矩形
        canvas.drawRoundRect(rectF, this.radius, this.radius, paint);

        //左上角圆角
        if (!isLeftTop) {
   
   
            canvas.drawRect(0, 0, radius, radius, paint);
        }
        //右上角圆角
        if (!isRightTop) {
   
   
            canvas.drawRect(canvas.getWidth() - radius, 0, canvas.getWidth(), radius, paint);
        }
        //左下角圆角
        if (!isLeftBottom) {
   
   
            canvas.drawRect(0, canvas.getHeight() - radius, radius, canvas.getHeight(), paint);
        }
        //右下角圆角
        if (!isRightBotoom) {
   
   
            canvas.drawRect(canvas.getWidth() - radius, canvas.getHeight() - radius, canvas.getWidth(), canvas.getHeight(), paint);
        }

        return BitmapResource.obtain(outBitmap, this.mBitmapPool);
    }


    @Override
    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
   
   

    }
}

CrashHandler ==》异常捕获

	要打开存储权限.(加入后,一旦程序崩溃,崩溃日志会自动保存在手机内部存储里)
	CrashHandler crashHandler = CrashHandler.getInstance();
	crashHandler.init(getApplicationContext());
public class CrashHandler implements Thread.UncaughtExceptionHandler {
   
   
    public static final String TAG = "CrashHandler";

    //系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    //CrashHandler实例
    private static CrashHandler INSTANCE = new CrashHandler();
    //程序的Context对象
    private Context mContext;
    Class<?> mCls;
    //用来存储设备信息和异常信息
    private Map<String, String> infos = new HashMap<String, String>();

    //用于格式化日期,作为日志文件名的一部分
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

    /**
     * 保证只有一个CrashHandler实例
     */
    private CrashHandler() {
   
   
    }

    /**
     * 获取CrashHandler实例 ,单例模式
     */
    public static CrashHandler getInstance() {
   
   
        return INSTANCE;
    }

    /**
     * 初始化
     *
     * @param context
     */


    public void init(Context context) {
   
   
        init(context, null);
    }

    public void init(Context context, Class<?> cls) {
   
   
        mCls = cls;
        mContext = context;
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 当UncaughtException发生时会转入该函数来处理
     */

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
   
   

        if (!handleException(ex) && mDefaultHandler != null) {
   
   
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
   
   
            if (mCls == null) {
   
   
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(0);
            } else {
   
   
                new Handler().postDelayed(new Runnable() {
   
   
                    @Override
                    public void run() {
   
   

                        Intent intent = new Intent(mContext, mCls);
//                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(intent);

                    }
                }, 1000);
            }
        }
    }


    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
   
   
        if (ex == null) {
   
   
            return false;
        }
        //使用Toast来显示异常信息
        new Thread() {
   
   
            @Override
            public void run() {
   
   
                Looper.prepare();
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将重启.", Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();
        //收集设备参数信息
        collectDeviceInfo(mContext);
        //保存日志文件
        saveCrashInfo2File(ex);
        return true;
    }

    /**
     * 收集设备参数信息
     *
     * @param ctx
     */
    public void collectDeviceInfo(Context ctx) {
   
   
        try {
   
   
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
   
   
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
   
   
            Log.e(TAG, "an error occured when collect package info", e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
   
   
            try {
   
   
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
   
   
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return 返回文件名称, 便于将文件传送到服务器
     */
    private String saveCrashInfo2File(Throwable ex) {
   
   

        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
   
   
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android诚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值