Android 开发 常用工具类收藏(随时更新)

说在前面,以下工具类可以大大的提高安卓开发者的开发效率

1、偏好设置(ShareUtils)

import android.content.Context;
import android.content.SharedPreferences;

/**
 * Content:偏好设置工具类
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  15:44
 */
public class ShareUtils {
    public static final String NAME = "config.hxd";

    /**
     * 存入数据(String)
     */
    public static void putString(Context context, String key, String value) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        //向偏好设置内部添加数据并且提交
        spf.edit().putString(key, value).apply();
    }

    /**
     * 取数据(上下文,钥匙,未取得数据返回的默认值)(String)
     */
    public static String getString(Context context, String key, String value) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        //返回需要取得的数据
        return spf.getString(key, value);
    }

    /**
     * 存入数据(Int)
     */
    public static void putInt(Context context, String key, int value) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        //向偏好设置内部添加数据并且提交
        spf.edit().putInt(key, value).apply();
    }

    /**
     * 取数据(上下文,钥匙,未取得数据返回的默认值)(Int)
     */
    public static int getInt(Context context, String key, int value) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        //返回需要取得的数据
        return spf.getInt(key, value);
    }

    /**
     * 存入数据(Int)
     */
    public static void putBoolean(Context context, String key, boolean value) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        //向偏好设置内部添加数据并且提交
        spf.edit().putBoolean(key, value).apply();
    }

    /**
     * 取数据(上下文,钥匙,未取得数据返回的默认值)(Int)
     */
    public static boolean getBoolean(Context context, String key, boolean value) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        //返回需要取得的数据
        return spf.getBoolean(key, value);
    }

    /**
     * 删除单个偏好设置
     */
    public static void deleteShare(Context context, String key) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        spf.edit().remove(key).apply();
    }

    /**
     * 删除所有偏好设置
     */
    public static void deleteShareAll(Context context, String key) {
        //获得偏好设置
        SharedPreferences spf = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        spf.edit().clear().apply();
    }
}

鸿神的偏好设置工具类

具体地址为: https://blog.csdn.net/lmj623565791/article/details/38965311

import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
import java.util.Map;  
  
import android.content.Context;  
import android.content.SharedPreferences;  
  
public class SPUtils  
{  
    /** 
     * 保存在手机里面的文件名 
     */  
    public static final String FILE_NAME = "share_data";  
  
    /** 
     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法 
     *  
     * @param context 
     * @param key 
     * @param object 
     */  
    public static void put(Context context, String key, Object object)  
    {  
  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,  
                Context.MODE_PRIVATE);  
        SharedPreferences.Editor editor = sp.edit();  
  
        if (object instanceof String)  
        {  
            editor.putString(key, (String) object);  
        } else if (object instanceof Integer)  
        {  
            editor.putInt(key, (Integer) object);  
        } else if (object instanceof Boolean)  
        {  
            editor.putBoolean(key, (Boolean) object);  
        } else if (object instanceof Float)  
        {  
            editor.putFloat(key, (Float) object);  
        } else if (object instanceof Long)  
        {  
            editor.putLong(key, (Long) object);  
        } else  
        {  
            editor.putString(key, object.toString());  
        }  
  
        SharedPreferencesCompat.apply(editor);  
    }  
  
    /** 
     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值 
     *  
     * @param context 
     * @param key 
     * @param defaultObject 
     * @return 
     */  
    public static Object get(Context context, String key, Object defaultObject)  
    {  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,  
                Context.MODE_PRIVATE);  
  
        if (defaultObject instanceof String)  
        {  
            return sp.getString(key, (String) defaultObject);  
        } else if (defaultObject instanceof Integer)  
        {  
            return sp.getInt(key, (Integer) defaultObject);  
        } else if (defaultObject instanceof Boolean)  
        {  
            return sp.getBoolean(key, (Boolean) defaultObject);  
        } else if (defaultObject instanceof Float)  
        {  
            return sp.getFloat(key, (Float) defaultObject);  
        } else if (defaultObject instanceof Long)  
        {  
            return sp.getLong(key, (Long) defaultObject);  
        }  
  
        return null;  
    }  
  
    /** 
     * 移除某个key值已经对应的值 
     * @param context 
     * @param key 
     */  
    public static void remove(Context context, String key)  
    {  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,  
                Context.MODE_PRIVATE);  
        SharedPreferences.Editor editor = sp.edit();  
        editor.remove(key);  
        SharedPreferencesCompat.apply(editor);  
    }  
  
    /** 
     * 清除所有数据 
     * @param context 
     */  
    public static void clear(Context context)  
    {  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,  
                Context.MODE_PRIVATE);  
        SharedPreferences.Editor editor = sp.edit();  
        editor.clear();  
        SharedPreferencesCompat.apply(editor);  
    }  
  
    /** 
     * 查询某个key是否已经存在 
     * @param context 
     * @param key 
     * @return 
     */  
    public static boolean contains(Context context, String key)  
    {  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,  
                Context.MODE_PRIVATE);  
        return sp.contains(key);  
    }  
  
    /** 
     * 返回所有的键值对 
     *  
     * @param context 
     * @return 
     */  
    public static Map<String, ?> getAll(Context context)  
    {  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,  
                Context.MODE_PRIVATE);  
        return sp.getAll();  
    }  
  
    /** 
     * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类 
     *  
     * @author zhy 
     *  
     */  
    private static class SharedPreferencesCompat  
    {  
        private static final Method sApplyMethod = findApplyMethod();  
  
        /** 
         * 反射查找apply的方法 
         *  
         * @return 
         */  
        @SuppressWarnings({ "unchecked", "rawtypes" })  
        private static Method findApplyMethod()  
        {  
            try  
            {  
                Class clz = SharedPreferences.Editor.class;  
                return clz.getMethod("apply");  
            } catch (NoSuchMethodException e)  
            {  
            }  
  
            return null;  
        }  
  
        /** 
         * 如果找到则使用apply执行,否则使用commit 
         *  
         * @param editor 
         */  
        public static void apply(SharedPreferences.Editor editor)  
        {  
            try  
            {  
                if (sApplyMethod != null)  
                {  
                    sApplyMethod.invoke(editor);  
                    return;  
                }  
            } catch (IllegalArgumentException e)  
            {  
            } catch (IllegalAccessException e)  
            {  
            } catch (InvocationTargetException e)  
            {  
            }  
            editor.commit();  
        }  
    }  
  
}  

2、单位转换和屏幕尺寸获取工具类

import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;

/**
 * Content:单位转换和屏幕尺寸获取工具类
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  15:44
 */

public class DensityUtil {

    /**
     * 将px值转换为 dip或dp值,保证尺寸大小不变
     *
     * @param pxValue 像素值
     * @param context Context 对象
     * @return dp值
     */
    public static int px2dip(float pxValue, Context context) {
        float scale = getDensity(context);
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 将dip或dp值转换为px值,保证尺寸大小不变
     *
     * @param dipValue dip数值
     * @param context  Context 对象
     * @return 像素值
     */
    public static int dip2px(float dipValue, Context context) {
        float scale = getDensity(context);
        return (int) (dipValue * scale + 0.5f);
    }

    /**
     * 将px值转换为sp值,保证文字大小不变
     *
     * @param pxValue 像素值
     * @param context Context 对象
     * @return 返回sp数值
     */
    public static int px2sp(float pxValue, Context context) {
        float scale = getDensity(context);

        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 将sp值转换为px值,保证文字大小不变
     *
     * @param spValue sp数值
     * @param context Context 对象
     * @return 返回像素值
     */
    public static int sp2px(float spValue, Context context) {
        float scale = getDensity(context);
        return (int) (spValue * scale + 0.5f);
    }

    /**
     * 取得手机屏幕的密度
     *
     * @param context 上下文
     * @return 手机屏幕的密度
     */
    public static float getDensity(Context context) {
        float scale = context.getResources().getDisplayMetrics().density;
        return scale;
    }

    /**
     * 获取屏幕高
     * @param activity
     * @return 手机屏幕的高度
     */
    public static int getScreenHeight(Activity activity) {
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.heightPixels;
    }

    /**
     * 获取屏幕宽
     * @param activity
     * @return 手机屏幕的宽度
     */
    public static int getScreenWidth(Activity activity) {
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }
}

3、时间转换工具类

import android.annotation.SuppressLint;
import android.text.format.Time;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Content:时间转换工具类
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  15:44
 */
public class DateUtils {

    /**
     * 获取当前时间
     *
     * @return 年月日时分秒字符串
     */
    public static String getCurrentTime() {
        Time time = new Time("GMT+8");
        time.setToNow();
        String year = "" + time.year;
        int imonth = time.month + 1;
        String month = imonth > 9 ? "" + imonth : "0" + imonth;
        String day = time.monthDay > 9 ? "" + time.monthDay : "0"
                + time.monthDay;
        String hour = (time.hour + 8) > 9 ? "" + (time.hour + 8) : "0"
                + (time.hour + 8);
        String minute = time.minute > 9 ? "" + time.minute : "0" + time.minute;
        String sec = time.second > 9 ? "" + time.second : "0" + time.second;
        String currentTime = year + month + day + hour + minute + sec;
        return currentTime;
    }

    //获取 日期/时/分/秒
    @SuppressLint("SimpleDateFormat")
    public static String getDateTime(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = sdf.format(new Date(time));
        return date;
    }

    //获取 日期/时/分
    @SuppressLint("SimpleDateFormat")
    public static String getHourMinute(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
        String date = sdf.format(new Date(time));
        return date;
    }

    //获取 日期年月日
    @SuppressLint("SimpleDateFormat")
    public static String getYearMonthDay(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        String date = sdf.format(new Date(time));
        return date;
    }

    //获取日期年月
    public static String getYearMonth(long time){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月");
        String date = sdf.format(new Date(time));
        return date;
    }

    //获取日期年月
    public static String getYearMonth2(long time){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        String date = sdf.format(new Date(time));
        return date;
    }

    //获取日期年
    public static String getYear(long time){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年");
        String date = sdf.format(new Date(time));
        return date;
    }

    //获取  时/分
    public static String getTime(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        String date = sdf.format(new Date(time));
        return date;
    }

}

4、验证码倒计时及重新发送验证码的工具类

import android.os.CountDownTimer;
import android.widget.Button;

/**
 * Content:验证码倒计时及重新发送验证码的工具类
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  15:44
 */

public class MyCountDownTimer extends CountDownTimer {
    private Button mBtn;
    private int mEnable;
    private int mDisable;

    /**
     * @param millisInFuture    The number of millis in the future from the call
     *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
     *                          is called.
     * @param countDownInterval The interval along the way to receive
     *                          {@link #onTick(long)} callbacks.
     */
    public MyCountDownTimer(long millisInFuture, long countDownInterval, Button btn, int enable, int disable) {
        super(millisInFuture, countDownInterval);
        mBtn = btn;
        mEnable = enable;
        mDisable = disable;
    }

    //计时过程
    @Override
    public void onTick(long l) {
        //防止计时过程中重复点击
        mBtn.setClickable(false);
        mBtn.setText(l / 1000 + "s");
        //设置按钮背景色
        mBtn.setBackgroundResource(mDisable);
    }

    //计时完毕的方法
    @Override
    public void onFinish() {
        //重新给Button设置文字
        mBtn.setText("重新获取验证码");
        //设置可点击
        mBtn.setClickable(true);
        //设置按钮背景色
        mBtn.setBackgroundResource(mEnable);
    }
}

6、进度Dialog工具类

import android.app.ProgressDialog;
import android.content.Context;

/**
 * Content:进度Dialog工具类
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  15:44
 */

public class ProgressDlgUtil {
    private static ProgressDialog progressDlg = null;

    /**
     * 启动进度条
     * @param ctx 当前的activity
     * @param content 进度条显示的信息
     */
    public static void show(Context ctx, String content) {
        if (null == progressDlg) {
            progressDlg = new ProgressDialog(ctx);
            progressDlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);// 设置进度条的形式为圆形转动的进度条
            //progressDlg.setTitle("提示");//设置进度条标题
            progressDlg.setMessage(content);//提示的消息
            progressDlg.setIndeterminate(false);
            progressDlg.setCancelable(false);
            //progressDlg.setIcon(R.drawable.ic_launcher_scale);
            progressDlg.show();
        }
    }

    /**
     * 结束进度条
     */
    public static void dismiss() {
        if (null != progressDlg) {
            progressDlg.dismiss();
            progressDlg = null;
        }
    }
}

7、吐司工具类

import android.annotation.SuppressLint;
import android.content.Context;
import android.widget.Toast;

/**
 * Content:ToastUtils
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time: 2018/5/17 17:37
 */
public class ToastUtils {

    private ToastUtils() {
        throw new UnsupportedOperationException("禁止实例化");
    }

    private static boolean isShow = true;
    private static Toast toast;

    /**
     * 短时间显示Toast
     *
     * @param context 上下文
     * @param msg     显示内容
     */
    @SuppressLint("ShowToast")
    public static void showToast(Context context, String msg) {
        if (isShow && toast == null) {
            //第一次创建
            toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
        } else {
            //如果toast存在,只修改文字,防止点的次数多一直弹出
            toast.setText(msg);
        }
        toast.show();
    }

    /**
     * 短时间显示Toast
     *
     * @param context  上下文
     * @param msgResID 显示内容
     */
    @SuppressLint("ShowToast")
    public static void showToast(Context context, int msgResID) {

        if (isShow && toast == null) {
            toast = Toast.makeText(context, msgResID, Toast.LENGTH_SHORT);
        } else {
            toast.setText(msgResID);
        }
        toast.show();
    }


    /**
     * 长时间显示Toast
     *
     * @param context 上下文
     * @param message 显示内容
     */
    @SuppressLint("ShowToast")
    public static void showLong(Context context, CharSequence message) {
        if (isShow && toast == null) {
            toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        } else {
            toast.setText(message);
        }
        toast.show();
    }

    /**
     * 长时间显示Toast
     *
     * @param context 上下文
     * @param message 显示内容
     */
    @SuppressLint("ShowToast")
    public static void showLong(Context context, int message) {
        if (isShow && toast == null) {
            toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        } else {
            toast.setText(message);
        }
        toast.show();
    }

    /**
     * 自定义显示Toast时间
     *
     * @param context  上下文
     * @param message  显示内容
     * @param duration 显示时间
     */
    public static void show(Context context, CharSequence message, int duration) {
        if (isShow) Toast.makeText(context, message, duration).show();
    }

    /**
     * 自定义显示Toast时间
     *
     * @param context  上下文
     * @param message  显示内容
     * @param duration 显示时间
     */
    public static void show(Context context, int message, int duration) {
        if (isShow) Toast.makeText(context, message, duration).show();
    }

8、软键盘操作工具类

mport android.content.Context;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

/**
 * Content:打开关闭软键盘
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time: 2018/5/17 17:37
 */
public class KeyBoardUtils {
    /**
     * 打卡软键盘
     *
     * @param mEditText 输入框
     * @param mContext  上下文
     */
    public static void openKeyBord(EditText mEditText, Context mContext) {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        assert imm != null;
        imm.showSoftInput(mEditText, InputMethodManager.RESULT_SHOWN);
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    }

    /**
     * 关闭软键盘
     *
     * @param mEditText 输入框
     * @param mContext  上下文
     */
    public static void closeKeyBord(Context mContext ,  EditText mEditText ) {
        InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        assert imm != null;
        imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }

    /**
     * 判断软键盘是否弹出
     *
     * @param context 上下文
     * @param v       控件
     * @return 是否关闭
     */
    public static boolean isSHowKeyboard(Context context, View v) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        assert imm != null;
        if (imm.hideSoftInputFromWindow(v.getWindowToken(), 0)) {
            imm.showSoftInput(v, 0);
            return true;
            //软键盘已弹出
        } else {
            return false;
            //软键盘未弹出
        }
    }

}

9、网络相关工具类

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

/**
 * Content:网络相关判断操作
 * Actor:鸿神
 * Time:2018/3/30
 */

public class NetUtils {

    private NetUtils() {
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    /**
     * 判断网络是否连接
     *
     * @param context
     * @return
     */
    public static boolean isConnected(Context context) {
        ConnectivityManager connectivity = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);

        if (null != connectivity) {
            NetworkInfo info = connectivity.getActiveNetworkInfo();
            if (null != info && info.isConnected()) {
                if (info.getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断是否是wifi连接
     */
    public static boolean isWifi(Context context) {

        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context
                .CONNECTIVITY_SERVICE);
        if (cm == null) {
            return cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
        }
        return false;

    }

    /**
     * 打开网络设置界面
     */
    public static void openSetting(Activity activity) {
        Intent intent = new Intent("/");
        ComponentName cm = new ComponentName("com.android.settings",
                "com.android.settings.WirelessSettings");
        intent.setComponent(cm);
        intent.setAction("android.intent.action.VIEW");
        activity.startActivityForResult(intent, 0);
    }
}

10、dp、px、sp之间的转换工具类

import android.content.Context;
import android.util.DisplayMetrics;

/**
 * Used 尺寸转换工具类(全)
 */
public class DensityUtil {
    public static float RATIO = 0.95F;//缩放比例值

    /**
     * px 转 dp【按照一定的比例】*/
    public static int px2dipRatio(Context context, float pxValue) {
        float scale = getScreenDendity(context) * RATIO;
        return (int)((pxValue / scale) + 0.5f);
    }

    /**
     * dp转px【按照一定的比例】*/
    public static int dip2pxRatio(Context context, float dpValue) {
        float scale = getScreenDendity(context) * RATIO;
        return (int)((dpValue * scale) + 0.5f);
    }

    /**
     * px 转 dp
     * 48px - 16dp
     * 50px - 17dp*/
    public static int px2dip(Context context, float pxValue) {
        float scale = getScreenDendity(context);
        return (int)((pxValue / scale) + 0.5f);
    }

    /**
     * dp转px
     * 16dp - 48px
     * 17dp - 51px*/
    public static int dip2px(Context context, float dpValue) {
        float scale = getScreenDendity(context);
        return (int)((dpValue * scale) + 0.5f);
    }

    /**获取屏幕的宽度(像素)*/
    public static int getScreenWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;//1080
    }

    /**获取屏幕的宽度(dp)*/
    public static int getScreenWidthDp(Context context) {
        float scale = getScreenDendity(context);
        return (int)(context.getResources().getDisplayMetrics().widthPixels / scale);//360
    }

    /**获取屏幕的高度(像素)*/
    public static int getScreenHeight(Context context) {
        return context.getResources().getDisplayMetrics().heightPixels;//1776
    }

    /**获取屏幕的高度(像素)*/
    public static int getScreenHeightDp(Context context) {
        float scale = getScreenDendity(context);
        return (int)(context.getResources().getDisplayMetrics().heightPixels / scale);//592
    }
    /**屏幕密度比例*/
    public static float getScreenDendity(Context context){
        return context.getResources().getDisplayMetrics().density;//3
    }

    /**获取状态栏的高度 72px
     * http://www.2cto.com/kf/201501/374049.html*/
    public static int getStatusBarHeight(Context context) {
        int statusHeight = -1;
        try {
            Class<?> aClass = Class.forName("com.android.internal.R$dimen");
            Object object = aClass.newInstance();
            int height = Integer.parseInt(aClass.getField("status_bar_height").get(object).toString());
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;

        //依赖于WMS(窗口管理服务的回调)【不建议使用】
        /*Rect outRect = new Rect();
        ((Activity)context).getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);
        return outRect.top;*/
    }

    /**
     * 指定机型(displayMetrics.xdpi)下dp转px
     * 18dp - 50px*/
    public static int dpToPx(Context context, int dp) {
        return Math.round(((float)dp * getPixelScaleFactor(context)));
    }

    /**
     * 指定机型(displayMetrics.xdpi)下px 转 dp
     * 50px - 18dp*/
    public static int pxToDp(Context context, int px) {
        return Math.round(((float)px / getPixelScaleFactor(context)));
    }

    /**获取水平方向的dpi的密度比例值
     * 2.7653186*/
    public static float getPixelScaleFactor(Context context) {
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        return (displayMetrics.xdpi / 160.0f);
    }
}

11、自用Log工具类

import android.util.Log;

/**
 * Content:
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  2018/6/29 9:31
 * Update:
 * Time: 2018/6/29 9:31
 */
public class LogUtils {
    private static final String TAG = "HXD";

    private static final int LOG_LEVEL_VERBOSE = 0;
    private static final int LOG_LEVEL_DEBUG = 1;
    private static final int LOG_LEVEL_INFO = 2;
    private static final int LOG_LEVEL_WARN = 3;
    private static final int LOG_LEVEL_ERROR = 4;

    private static int outputLevel = LOG_LEVEL_VERBOSE;

    private LogUtils() {
        super();
    }

    /**
     * 控制原生Log是否打印
     * level>4 则不打印原生     日志,反之则打印原生日志
     *
     * @param level 控制标志位
     */
    public static void setOutputLevel(int level) {
        outputLevel = level;
    }

    public static void v(String tag, String msg) {
        if (outputLevel <= LOG_LEVEL_VERBOSE) {
            Log.v(tag, msg);
        }
    }

    public static void v(String msg) {
        v(TAG, msg);
    }

    public static void d(String tag, String msg) {
        if (outputLevel <= LOG_LEVEL_DEBUG) {
            Log.d(tag, msg);
        }
    }

    public static void d(String msg) {
        d(TAG, msg);
    }

    public static void i(String tag, String msg) {
        if (outputLevel <= LOG_LEVEL_INFO) {
            Log.i(tag, msg);
        }
    }

    public static void i(String msg) {
        i(TAG, msg);
    }

    public static void w(String tag, String msg) {
        if (outputLevel <= LOG_LEVEL_WARN) {
            Log.w(tag, msg);
        }
    }

    public static void w(String msg) {
        w(TAG, msg);
    }

    public static void e(String tag, String msg) {
        if (outputLevel <= LOG_LEVEL_ERROR) {
            Log.e(tag, msg);
        }
    }

    public static void e(String msg) {
        e(TAG, msg);
    }

}

12、文字变色工具类

import android.content.Context;
import android.graphics.Color;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.widget.TextView;

/**
 * Content: 一段文字多种颜色
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  2018/7/23 17:34
 * Update:
 * Time:
 */
public class TextColorChangeUtils {
    /***
     *通过Resources内的颜色实现文字变色龙
     *
     * @param context 上下文
     * @param textView 文字变色控件
     * @param textColor  文字固有颜色
     * @param startColor 开始半段文字color
     * @param endColor 结束半段 文字color
     * @param startStart 前半段开始变色文字下标
     * @param startEnd 前半段结束变色文字下标
     * @param endStart 后半段开始变色文字下标
     * @param endEnd 后半段结束变色文字下标
     * @param text 变色的文字内容
     * @return 返回变色结果
     */

    public static TextView interTextColorForResources(Context context, TextView textView, int textColor, int startColor,
                                                      int endColor, int startStart, int startEnd, int endStart, int endEnd, String text) {
        textView.setTextColor(context.getResources().getColor(textColor));
        SpannableStringBuilder style = new SpannableStringBuilder(text);
        style.setSpan(new ForegroundColorSpan(context.getResources().getColor(startColor)), startStart, startEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        style.setSpan(new ForegroundColorSpan(context.getResources().getColor(endColor)), endStart, endEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        textView.setText(style);
        return textView;
    }

    /**
     * 通过 ParseColor 的形式实现变色
     *
     * @param textView   文字变色控件
     * @param textColor  文字固有颜色
     * @param startColor 开始半段文字color
     * @param endColor   结束半段文字color
     * @param startStart 前半段开始变色文字下标
     * @param startEnd   后半段开始变色文字下标
     * @param endStart   后半段结束变色文字下标
     * @param endEnd     后半段结束变色文字下标
     * @param text       变色的文字内容
     * @return 返回变色结果
     */
    public static TextView interTextColorForParseColor(TextView textView, String textColor, String startColor, String endColor, int startStart, int startEnd, int endStart, int endEnd, String text) {
        textView.setTextColor(Color.parseColor(textColor));
        SpannableStringBuilder style = new SpannableStringBuilder(text);
        style.setSpan(new ForegroundColorSpan(Color.parseColor(startColor)), startStart, startEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        style.setSpan(new ForegroundColorSpan(Color.parseColor(endColor)), endStart, endEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return textView;
    }

}

使用例子

 tvHiddenNum = TextColorChangeUtils.interTextColorForResources(this, tvHiddenNum, R.color.colorRed,
                R.color.colorBlue, R.color.colorYellow, 0, 2, num.length() - 1, num.length(), num);

使用结果:
使用结果

13、调用相册获取图片路径

import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

/**
 * Content:从相册内获取照片转化工具类
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  2018/08/18 18:54
 * Update:
 * Time:
 */
public class getPhotoFromPhotoAlbum {
    /**
     * 根据Uri获取图片的绝对路径
     *
     * @param context 上下文对象
     * @param uri     图片的Uri
     * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
     */
    public static String getRealPathFromUri(Context context, Uri uri) {
        int sdkVersion = Build.VERSION.SDK_INT;
        if (sdkVersion >= 19) { 
            return getRealPathFromUriAboveApi19(context, uri);
        } else {
            return getRealPathFromUriBelowAPI19(context, uri);
        }
    }

    /**
     * 适配api19以下(不包括api19),根据uri获取图片的绝对路径
     *
     * @param context 上下文对象
     * @param uri     图片的Uri
     * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
     */
    private static String getRealPathFromUriBelowAPI19(Context context, Uri uri) {
        return getDataColumn(context, uri, null, null);
    }

    /**
     * 适配api19及以上,根据uri获取图片的绝对路径
     *
     * @param context 上下文对象
     * @param uri     图片的Uri
     * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
     */
    @SuppressLint("NewApi")
    private static String getRealPathFromUriAboveApi19(Context context, Uri uri) {
        String filePath = null;
        if (DocumentsContract.isDocumentUri(context, uri)) {
            // 如果是document类型的 uri, 则通过document id来进行处理
            String documentId = DocumentsContract.getDocumentId(uri);
            if (isMediaDocument(uri)) {
                // 使用':'分割
                String id = documentId.split(":")[1];

                String selection = MediaStore.Images.Media._ID + "=?";
                String[] selectionArgs = {id};
                filePath = getDataColumn(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, selectionArgs);
            } else if (isDownloadsDocument(uri)) { 
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));
                filePath = getDataColumn(context, contentUri, null, null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // 如果是 content 类型的 Uri
            filePath = getDataColumn(context, uri, null, null);
        } else if ("file".equals(uri.getScheme())) {
            // 如果是 file 类型的 Uri,直接获取图片对应的路径
            filePath = uri.getPath();
        }
        return filePath;
    }

    /**
     * 获取数据库表中的 _data 列,即返回Uri对应的文件路径
     *
     */
    private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        String path = null;

        String[] projection = new String[]{MediaStore.Images.Media.DATA};
        Cursor cursor = null;
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                int columnIndex = cursor.getColumnIndexOrThrow(projection[0]);
                path = cursor.getString(columnIndex);
            }
        } catch (Exception e) {
            if (cursor != null) {
                cursor.close();
            }
        }
        return path;
    }

    /**
     * @param uri the Uri to check
     * @return Whether the Uri authority is MediaProvider
     */
    private static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri the Uri to check
     * @return Whether the Uri authority is DownloadsProvider
     */
    private static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }
}

14、结局部分手机拍照后照片自动旋转问题

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.support.media.ExifInterface;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Content:解决部分手机调用系统相机照片旋转问题
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  2018/11/01 09:42
 * Update:
 * Time:
 */
public class RotatingImagesUtils {

    /**
     * 获得照片的旋转角度
     *
     * @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;
    }

    /**
     * 旋转bitmap
     *
     * @param bitmap 传入bitmap
     * @param rotate 旋转角度
     * @return 返回 bitmap
     */
    public static Bitmap rotateBitmap(Bitmap bitmap, int rotate) {
        if (bitmap == null)
            return null;
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Matrix mtx = new Matrix();
        mtx.postRotate(rotate);
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
    }

    /**
     * 把bitmap 转file
     *
     * @param bitmap   需要存储的 bitmap
     * @param filepath 图片的路径
     */
    public static File saveBitmapFile(Bitmap bitmap, String filepath) {
        File file = new File(filepath);//将要保存图片的路径
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(file));
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
            bos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    /**
     * 根据 路径 得到 file 得到 bitmap
     *
     * @param filePath 路径
     * @return bitmap
     */
    public static Bitmap decodeFile(String filePath) {
        Bitmap b = null;
        int IMAGE_MAX_SIZE = 600;

        File f = new File(filePath);
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(f);
            BitmapFactory.decodeStream(fis, null, o);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        int scale = 1;
        if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
            scale = (int) Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        try {
            fis = new FileInputStream(f);
            b = BitmapFactory.decodeStream(fis, null, o2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return b;
    }
}

15、将崩溃日志打印到手机存储内

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * 异常处理
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private String TAG = getClass().getSimpleName();
    private static CrashHandler sInstance = new CrashHandler();
    //系统默认的异常处理(默认情况下,系统会终止当前的异常程序)
    private Thread.UncaughtExceptionHandler mDefaultCrashHandler;
    private Context mContext;
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    private Map<String, String> infos = new HashMap<>();

    //构造方法私有,防止外部构造多个实例,即采用单例模式
    private CrashHandler() {
    }

    public static CrashHandler getInstance() {
        if (sInstance == null)
            sInstance = new CrashHandler();
        return sInstance;
    }

    //这里主要完成初始化工作
    public void init(Context context) {
        mContext = context;
        //获取系统默认的异常处理器
        save = false;
        mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        //将当前实例设为系统默认的异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 当程序中有未被捕获的异常,系统将会自动调用#uncaughtException方法
     * thread为出现未捕获异常的线程,ex为未捕获的异常,有了这个ex,我们就可以得到异常信息。
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        //如果系统提供了默认的异常处理器,则交给系统去结束我们的程序,否则就由我们自己结束自己
        saveCrashInfo2File(ex);
        try {
            if (handleException(ex) && mDefaultCrashHandler != null) {
                mDefaultCrashHandler.uncaughtException(thread, ex);
            } else {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                }
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(0);
            }
        }catch (Exception e){
            saveCrashInfo2File(e);
        }
    }

    /**
     * 自定义错误处理,收集错误信息,发送错误报告等操作均在此完成
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回 false
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        // 收集设备参数信息
        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) {
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {
                Log.e("incarmeida", "an error occured when collect crash info", e);
            }
        }
    }

    private static boolean save;

    /**
     * 保存错误信息到文件中 *
     *
     * @param ex
     * @return 返回文件名称, 便于将文件传送到服务器
     */
    private String saveCrashInfo2File(Throwable ex) {
        if (save) {
            return null;
        }
        save = true;
        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);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();

        String result = writer.toString();
        sb.append(result);
        try {
            long timestamp = System.currentTimeMillis();
            String time = formatter.format(new Date());
            String fileName = "error-" + time + "-" + timestamp + ".log";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = Environment.getExternalStorageDirectory().getPath()+"/";
//                Toast.makeText(mContext, path, Toast.LENGTH_LONG).show();
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(path + fileName);
                fos.write(String.valueOf(sb).getBytes());
                fos.flush();
                fos.close();
            }
            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "saveCrashInfo2File an error occured while writing file...   " + e.getMessage());
        }
        return null;
    }
}

使用方式 在Application 内进行初始化

CrashHandler.getInstance().init(this);

16、 Android 获取手机的厂商、型号、Android系统版本号、IMEI、当前系统语言等工具类

import android.app.Activity;
import android.content.Context;
import android.telephony.TelephonyManager;

import java.util.Locale;

/**
 * CreateTime: 2019/6/25 10:56
 * Author: hxd
 * Content:获取手机系统的相关信息
 * UpdateTime:
 * UpdateName;
 * UpdateContent:
 */
public class SystemUtil {
    
    /**
     * 获取当前手机系统语言。 
     *
     * @return 返回当前系统语言。例如:当前设置的是“中文-中国”,则返回“zh-CN” 
     */
    public static String getSystemLanguage() {
        return Locale.getDefault().getLanguage();
    }

    /**
     * 获取当前系统上的语言列表(Locale列表) 
     *
     * @return  语言列表
     */
    public static Locale[] getSystemLanguageList() {
        return Locale.getAvailableLocales();
    }

    /**
     * 获取当前手机系统版本号 
     *
     * @return  系统版本号
     */
    public static String getSystemVersion() {
        return android.os.Build.VERSION.RELEASE;
    }

    /**
     * 获取手机型号 
     *
     * @return  手机型号
     */
    public static String getSystemModel() {
        return android.os.Build.MODEL;
    }

    /**
     * 获取手机厂商 
     *
     * @return  手机厂商
     */
    public static String getDeviceBrand() {
        return android.os.Build.BRAND;
    }

    /**
     * 获取手机IMEI(需要“android.permission.READ_PHONE_STATE”权限) 
     *
     * @return  手机IMEI
     */
    public static String getIMEI(Context ctx) {
        TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Activity.TELEPHONY_SERVICE);
        if (tm != null) {
            return tm.getDeviceId();
        }
        return null;
    }
}

17、获取 Android app相关信息的 工具类

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

import com.vehicle.MsApplication;

/**
 * CreateTime: 2019/6/19 11:32
 * Author: hxd
 * Content: 和app 的固件相关的工具类
 * UpdateTime:
 * UpdateName;
 * UpdateContent:
 */
public class AppUtils {


    /**
     * 获取应用程序名称
     */
    public static synchronized String getAppName(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(
                    context.getPackageName(), 0);
            int labelRes = packageInfo.applicationInfo.labelRes;
            return context.getResources().getString(labelRes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * [获取应用程序版本名称信息]
     *
     * @return 当前应用的版本名称
     */
    public static synchronized String getVersionName() {
        try {
            PackageManager packageManager = MsApplication.getInstance().getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(
                    MsApplication.getInstance().getPackageName(), 0);
            return String.valueOf(packageInfo.versionName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    

    /**
     * [获取应用程序版本名称信息]
     *
     * @return 当前应用的版本名称
     */
    public static synchronized int getVersionCode() {
        try {
            PackageManager packageManager = MsApplication.getInstance().getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(
                    MsApplication.getInstance().getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }


    /**
     * [获取应用程序版本名称信息]
     *
     * @param context
     * @return 当前应用的版本名称
     */
    public static synchronized String getPackageName(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(
                    context.getPackageName(), 0);
            return packageInfo.packageName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取图标 bitmap
     *
     * @param context
     */
    public static synchronized Bitmap getBitmap(Context context) {
        PackageManager packageManager = null;
        ApplicationInfo applicationInfo = null;
        try {
            packageManager = context.getApplicationContext()
                    .getPackageManager();
            applicationInfo = packageManager.getApplicationInfo(
                    context.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            applicationInfo = null;
        }
        Drawable d = packageManager.getApplicationIcon(applicationInfo); //xxx根据自己的情况获取drawable
        BitmapDrawable bd = (BitmapDrawable) d;
        Bitmap bm = bd.getBitmap();
        return bm;
    }

}

18、打开 第三方地图(百度、高德、腾讯、浏览器) 并且进行导航

package com.ms.online.utils;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;

import com.baidu.mapapi.model.LatLng;

import java.io.File;

/**
 * CreateTime:2019/12/26 11:29
 * Author: hxd
 * Content: 打开第三方地图或浏览器 并 导航
 * UpdateTime:
 * UpdateName;
 * UpdateContent:
 */
public class NavigationUtils {


    private static final String PN_GAODE_MAP = "com.autonavi.minimap";// 高德地图包名
    private static final String PN_BAIDU_MAP = "com.baidu.BaiduMap"; // 百度地图包名
    private static final String PN_TENCENT_MAP = "com.tencent.map"; // 腾讯地图包名

    /**
     * 检查地图应用是否安装
     */
    public static boolean isGdMapInstalled() {
        return isInstallPackage(PN_GAODE_MAP);
    }

    public static boolean isBaiduMapInstalled() {
        return isInstallPackage(PN_BAIDU_MAP);
    }

    public static boolean isTencentMapInstalled() {
        return isInstallPackage(PN_TENCENT_MAP);
    }

    private static boolean isInstallPackage(String packageName) {
        return new File("/data/data/" + packageName).exists();
    }

    /**
     * 百度转高德
     *
     * @param bd_lat 经度
     * @param bd_lon 纬度
     */
    public static double[] bdToGaoDe(double bd_lat, double bd_lon) {
        double[] gd_lat_lon = new double[2];
        double PI = 3.14159265358979324 * 3000.0 / 180.0;
        double x = bd_lon - 0.0065, y = bd_lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI);
        gd_lat_lon[0] = z * Math.cos(theta);
        gd_lat_lon[1] = z * Math.sin(theta);
        return gd_lat_lon;
    }

    /**
     * 高德、腾讯转百度
     *
     * @param gd_lon 经度
     * @param gd_lat 纬度
     */
    private static double[] gaoDeToBaidu(double gd_lon, double gd_lat) {
        double[] bd_lat_lon = new double[2];
        double PI = 3.14159265358979324 * 3000.0 / 180.0;
        double x = gd_lon, y = gd_lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * PI);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * PI);
        bd_lat_lon[0] = z * Math.cos(theta) + 0.0065;
        bd_lat_lon[1] = z * Math.sin(theta) + 0.006;
        return bd_lat_lon;
    }

    /**
     * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
     * 即 百度 转 谷歌、高德
     *
     * @param latLng 经纬度对象
     * @return 使用此方法需要下载导入百度地图的BaiduLBS_Android.jar包
     */
    public static LatLng BD09ToGCJ02(LatLng latLng) {
        double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        double x = latLng.longitude - 0.0065;
        double y = latLng.latitude - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double gg_lat = z * Math.sin(theta);
        double gg_lng = z * Math.cos(theta);
        return new LatLng(gg_lat, gg_lng);
    }

    /**
     * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
     * 即谷歌、高德 转 百度
     *
     * @param latLng 经纬度对象
     * @return  需要百度地图的BaiduLBS_Android.jar包
     */
    public static LatLng GCJ02ToBD09(LatLng latLng) {
        double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        double z = Math.sqrt(latLng.longitude * latLng.longitude + latLng.latitude * latLng.latitude) + 0.00002 * Math.sin(latLng.latitude * x_pi);
        double theta = Math.atan2(latLng.latitude, latLng.longitude) + 0.000003 * Math.cos(latLng.longitude * x_pi);
        double bd_lat = z * Math.sin(theta) + 0.006;
        double bd_lng = z * Math.cos(theta) + 0.0065;
        return new LatLng(bd_lat, bd_lng);
    }

    /**
     * 打开高德地图导航功能
     *
     * @param context
     * @param slat    起点纬度
     * @param slon    起点经度
     * @param sname   起点名称 可不填(0,0,null)
     * @param dlat    终点纬度
     * @param dlon    终点经度
     * @param dname   终点名称 必填
     */
    public static void openGaoDeNavi(Context context, double slat, double slon, String sname, double dlat, double dlon, String dname) {
        String uriString;
        StringBuilder builder = new StringBuilder("amapuri://route/plan?sourceApplication=maxuslife");
        if (slat != 0) {
            builder.append("&sname=").append(sname)
                    .append("&slat=").append(slat)
                    .append("&slon=").append(slon);
        }
        builder.append("&dlat=").append(dlat)
                .append("&dlon=").append(dlon)
                .append("&dname=").append(dname)
                .append("&dev=0")
                .append("&t=0");
        uriString = builder.toString();
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setPackage(PN_GAODE_MAP);
        intent.setData(Uri.parse(uriString));
        context.startActivity(intent);
    }

    /**
     * 打开腾讯地图
     * params 参考http://lbs.qq.com/uri_v1/guide-route.html
     *
     * @param context
     * @param slat    起点纬度
     * @param slon    起点经度
     * @param sname   起点名称 可不填(0,0,null)
     * @param dlat    终点纬度
     * @param dlon    终点经度
     * @param dname   终点名称 必填
     *                驾车:type=drive,policy有以下取值
     *                0:较快捷
     *                1:无高速
     *                2:距离
     *                policy的取值缺省为0
     *                &from=" + dqAddress + "&fromcoord=" + dqLatitude + "," + dqLongitude + "
     */
    public static void openTencentMap(Context context, double slat, double slon, String sname, double dlat, double dlon, String dname) {
        String uriString;
        StringBuilder builder = new StringBuilder("qqmap://map/routeplan?type=drive&policy=0&referer=zhongshuo");
        if (slat != 0) {
            builder.append("&from=").append(sname)
                    .append("&fromcoord=").append(slat)
                    .append(",")
                    .append(slon);
        }
        builder.append("&to=").append(dname)
                .append("&tocoord=").append(dlat)
                .append(",")
                .append(dlon);
        uriString = builder.toString();
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setPackage(PN_TENCENT_MAP);
        intent.setData(Uri.parse(uriString));
        context.startActivity(intent);
    }

    /**
     * 打开百度地图导航功能(默认坐标点是高德地图,需要转换)
     *
     * @param context
     * @param slat    起点纬度
     * @param slon    起点经度
     * @param sname   起点名称 可不填(0,0,null)
     * @param dlat    终点纬度
     * @param dlon    终点经度
     * @param dname   终点名称 必填
     */
    public static void openBaiDuNavi(Context context, double slat, double slon, String sname, double dlat, double dlon, String dname) {
        String uriString;
        //终点坐标转换
        //        此方法需要百度地图的BaiduLBS_Android.jar包
        //        LatLng destination = new LatLng(dlat,dlon);
        //        LatLng destinationLatLng = GCJ02ToBD09(destination);
        //        dlat = destinationLatLng.latitude;
        //        dlon = destinationLatLng.longitude;

        double[] destination = gaoDeToBaidu(dlat, dlon);
        dlat = destination[0];
        dlon = destination[1];

        StringBuilder builder = new StringBuilder("baidumap://map/direction?mode=driving&");
        if (slat != 0) {
            //起点坐标转换
            //            LatLng origin = new LatLng(slat,slon);
            //            LatLng originLatLng = GCJ02ToBD09(origin);
            //            slat = originLatLng.latitude;
            //            slon = originLatLng.longitude;

            double[] origin = gaoDeToBaidu(slat, slon);
            slat = origin[0];
            slon = origin[1];

            builder.append("origin=latlng:")
                    .append(slat)
                    .append(",")
                    .append(slon)
                    .append("|name:")
                    .append(sname);
        }
        builder.append("&destination=latlng:")
                .append(dlat)
                .append(",")
                .append(dlon)
                .append("|name:")
                .append(dname);
        uriString = builder.toString();
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setPackage(PN_BAIDU_MAP);
        intent.setData(Uri.parse(uriString));
        context.startActivity(intent);
    }

    /**
     * 打开网页版 导航
     *
     * @param context
     * @param myLatLng           起点经纬度
     * @param myAddress          起点地址名展示 可以不写
     * @param destination        终点经纬度
     * @param destinationAddress 终点地址名展示
     */
    public static void openBrowserMap(Context context, LatLng myLatLng, String myAddress, LatLng destination,
                                      String destinationAddress) {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.VIEW");
        intent.setData(Uri.parse("http://uri.amap.com/navigation?" +
                "from=" + myLatLng.longitude + "," + myLatLng.latitude + "," + myAddress +
                "to=" + destination.longitude + "," + destination.latitude + "," + destinationAddress +
                "&mode=car&policy=1&src=mypage&coordinate=gaode&callnative=0"));
        context.startActivity(intent);
    }
}

调用方法

  private void toNav() {
        LatLng latLng1 = NavigationUtils.BD09ToGCJ02(mLatLng);
        LatLng latLng2 = NavigationUtils.BD09ToGCJ02(endLatLng);
        //判断是否安装高德
        if (!NavigationUtils.isGdMapInstalled()) {
            //判断是否安装百度
            if (!NavigationUtils.isBaiduMapInstalled()) {
                //判断是否安装腾讯
                if (!NavigationUtils.isTencentMapInstalled()) {
                    //                    ToastUtils.showLong("您未安装任何 导航应用");
                    if (getActivity() != null)
                        NavigationUtils.openBrowserMap(getActivity(), mLatLng, null, endLatLng, mStringName);
                } else {
                    NavigationUtils.openTencentMap(getActivity(), latLng1.latitude, latLng1.longitude, null, latLng2.latitude, latLng2.longitude, mStringName);
                }
            } else {
                NavigationUtils.openBaiDuNavi(getActivity(), mLatLng.latitude, mLatLng.longitude, null, endLatLng.latitude, endLatLng.longitude, mStringName);
            }
        } else {
            NavigationUtils.openGaoDeNavi(getActivity(), latLng1.latitude, latLng1.longitude, null, latLng2.latitude, latLng2.longitude, mStringName);
        }
    }

欢迎关注

猜你喜欢

转载自blog.csdn.net/xiangshiweiyu_hd/article/details/103714073