一、时间类
/**
* 时间日期格式化工具类
*/
public class DateTimeUtil {
/**
* 日期格式:yyyy-MM-dd HH:mm:ss
**/
public static final String DF_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
/**
* 日期格式:yyyy-MM-dd HH:mm
**/
public static final String DF_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
/**
* 日期格式:yyyy.MM.dd HH:mm
**/
public static final String DF_YYYY_MM_DD_HH_MM_NODE = "yyyy.MM.dd HH:mm";
/**
* 日期格式:yyyy-MM-dd
**/
public static final String DF_YYYY_MM_DD = "yyyy-MM-dd";
/**
* 日期格式:HH:mm:ss
**/
public static final String DF_HH_MM_SS = "HH:mm:ss";
/**
* 日期格式:MM/dd
**/
public static final String DF_MM_dd = "MM/dd";
/**
* 日期格式:HH:mm
**/
public static final String DF_HH_MM = "HH:mm";
/**
* 日期格式:MM-dd HH:mm
*/
public static final String DF_MM_DD_HH_MM = "MM-dd HH:mm";
private final static long MINUTE = 60 * 1000;// 1分钟
private final static long HOUR = 60 * MINUTE;// 1小时
private final static long DAY = 24 * HOUR;// 1天
private final static long MONTH = 31 * DAY;// 月
private final static long YEAR = 12 * MONTH;// 年
/**
* Log输出标识
**/
private static final String TAG = DateTimeUtil.class.getSimpleName();
/**
* 将日期格式化成友好的字符串:几分钟前、几小时前、几天前、几月前、几年前、刚刚
*
* @param date
* @return
*/
public static String formatFriendly(Date date) {
if (date == null) {
return null;
}
long diff = new Date().getTime() - date.getTime();
long r = 0;
if (diff > YEAR) {
r = (diff / YEAR);
return r + "年前";
}
if (diff > MONTH) {
r = (diff / MONTH);
return r + "个月前";
}
if (diff > DAY) {
r = (diff / DAY);
return r + "天前";
}
if (diff > HOUR) {
r = (diff / HOUR);
return r + "小时前";
}
if (diff > MINUTE) {
r = (diff / MINUTE);
return r + "分钟前";
}
return "刚刚";
}
/**
* 将日期以yyyy-MM-dd HH:mm:ss格式化
*
* @param dateL 日期
* @return
*/
public static String formatDateTime(long dateL) {
SimpleDateFormat sdf = new SimpleDateFormat(DF_YYYY_MM_DD_HH_MM_SS);
Date date = new Date(dateL);
return sdf.format(date);
}
/**
* 将日期以yyyy-MM-dd HH:mm:ss格式化
*
* @param dateL 日期
* @return
*/
public static String formatDateTime(long dateL, String formater) {
SimpleDateFormat sdf = new SimpleDateFormat(formater);
return sdf.format(new Date(dateL));
}
/**
* 将日期以yyyy-MM-dd HH:mm:ss格式化
*
* @param date 日期
* @return
*/
public static String formatDateTime(Date date, String formater) {
SimpleDateFormat sdf = new SimpleDateFormat(formater);
return sdf.format(date);
}
/**
* 将日期字符串转成日期
*
* @param strDate 字符串日期
* @return java.util.date日期类型
*/
public static Date parseDate(String strDate) {
DateFormat dateFormat = new SimpleDateFormat(DF_YYYY_MM_DD_HH_MM_SS);
Date returnDate = null;
try {
returnDate = dateFormat.parse(strDate);
} catch (ParseException e) {
LogUtil.v(TAG, "parseDate failed !");
}
return returnDate;
}
/**
* 获取系统当前日期
*
* @return
*/
public static Date gainCurrentDate() {
return new Date();
}
/**
* 验证日期是否比当前日期早
*
* @param target1 比较时间1
* @param target2 比较时间2
* @return true 则代表target1比target2晚或等于target2,否则比target2早
*/
public static boolean compareDate(Date target1, Date target2) {
boolean flag = false;
try {
String target1DateTime = DateTimeUtil.formatDateTime(target1,
DF_YYYY_MM_DD_HH_MM_SS);
String target2DateTime = DateTimeUtil.formatDateTime(target2,
DF_YYYY_MM_DD_HH_MM_SS);
if (target1DateTime.compareTo(target2DateTime) <= 0) {
flag = true;
}
} catch (Exception e1) {
LogUtil.e(TAG, "比较失败,原因:" + e1.getMessage());
}
return flag;
}
/**
* 对日期进行增加操作
*
* @param target 需要进行运算的日期
* @param hour 小时
* @return
*/
public static Date addDateTime(Date target, double hour) {
if (null == target || hour < 0) {
return target;
}
return new Date(target.getTime() + (long) (hour * 60 * 60 * 1000));
}
/**
* 对日期进行相减操作
*
* @param target 需要进行运算的日期
* @param hour 小时
* @return
*/
public static Date subDateTime(Date target, double hour) {
if (null == target || hour < 0) {
return target;
}
return new Date(target.getTime() - (long) (hour * 60 * 60 * 1000));
}
private static SimpleDateFormat second = new SimpleDateFormat(
"yy-MM-dd hh:mm:ss");
private static SimpleDateFormat day = new SimpleDateFormat("yyyy-MM-dd");
private static SimpleDateFormat detailDay = new SimpleDateFormat("yyyy年MM月dd日");
private static SimpleDateFormat fileName = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
private static SimpleDateFormat tempTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static SimpleDateFormat excelDate = new SimpleDateFormat("yyyy/MM/dd");
/**
* 格式化excel中的时间
*
* @param date
* @return
*/
public static String formatDateForExcelDate(Date date) {
return excelDate.format(date);
}
/**
* 将日期格式化作为文件名
*
* @param date
* @return
*/
public static String formatDateForFileName(Date date) {
return fileName.format(date);
}
/**
* 格式化日期(精确到秒)
*
* @param date
* @return
*/
public static String formatDateSecond(Date date) {
return second.format(date);
}
/**
* 格式化日期(精确到秒)
*
* @param date
* @return
*/
public static String tempDateSecond(Date date) {
return tempTime.format(date);
}
public static Date tempDateSecond(String str) {
try {
return tempTime.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return new Date();
}
/**
* 格式化日期(精确到天)
*
* @param date
* @return
*/
public static String formatDateDay(Date date) {
return day.format(date);
}
/**
* 格式化日期(精确到天)
*
* @param date
* @return
*/
public static String formatDateDetailDay(Date date) {
return detailDay.format(date);
}
/**
* 将double类型的数字保留两位小数(四舍五入)
*
* @param number
* @return
*/
public static String formatNumber(double number) {
DecimalFormat df = new DecimalFormat();
df.applyPattern("#0.00");
return df.format(number);
}
/**
* 将字符串转换成日期
*
* @param date
* @return
* @throws Exception
*/
public static Date formateDate(String date) throws Exception {
return day.parse(date);
}
/**
* 将字符日期转换成Date
*
* @param date
* @return
* @throws Exception
*/
public static Date parseStringToDate(String date) throws Exception {
return day.parse(date);
}
public static String formatDoubleNumber(double number) {
DecimalFormat df = new DecimalFormat("#");
return df.format(number);
}
}
例子:
项目中要用这种形式展示,实现起来也很简单,第一步在Bean类里
private static final String DATE_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
public static final SimpleDateFormat FORMAT_FULL = new SimpleDateFormat(DATE_FORMAT_FULL);
public Date getPubTime() {
Date date = null;
try {
date = FORMAT_FULL.parse(pub_time);//pub_time 是后台字段
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
二、数字工具类( 以万为单位处理)
public class NumberFormatUtils {
public static StringBuffer formatNum(int num, Boolean b) {
StringBuffer sb = new StringBuffer();
BigDecimal b0 = new BigDecimal("100");
BigDecimal b1 = new BigDecimal("10000");
BigDecimal b2 = new BigDecimal("100000000");
BigDecimal b3 = new BigDecimal(num);
String formatNumStr = "";
String unit = "";
// 以百为单位处理
if (b) {
if (b3.compareTo(b0) == 0 || b3.compareTo(b0) == 1) {
return sb.append("99+");
}
return sb.append(num);
}
// 以万为单位处理
if (b3.compareTo(b1) == -1) {
formatNumStr = b3.toString();
} else if ((b3.compareTo(b1) == 0 && b3.compareTo(b1) == 1)
|| b3.compareTo(b2) == -1) {
unit = "万";
formatNumStr = b3.divide(b1).toString();
} else if (b3.compareTo(b2) == 0 || b3.compareTo(b2) == 1) {
unit = "亿";
formatNumStr = b3.divide(b2).toString();
}
if (!"".equals(formatNumStr)) {
int i = formatNumStr.indexOf(".");
if (i == -1) {
sb.append(formatNumStr).append(unit);
} else {
i = i + 1;
String v = formatNumStr.substring(i, i + 1);
if (!v.equals("0")) {
sb.append(formatNumStr.substring(0, i + 1)).append(unit);
} else {
sb.append(formatNumStr.substring(0, i - 1)).append(unit);
}
}
}
if (sb.length() == 0)
return sb.append("0");
return sb;
}
public static StringBuffer formatNum(long num, Boolean b) {
StringBuffer sb = new StringBuffer();
BigDecimal b0 = new BigDecimal("100");
BigDecimal b1 = new BigDecimal("10000");
BigDecimal b2 = new BigDecimal("100000000");
BigDecimal b3 = new BigDecimal(num);
String formatNumStr = "";
String unit = "";
// 以百为单位处理
if (b) {
if (b3.compareTo(b0) == 0 || b3.compareTo(b0) == 1) {
return sb.append("99+");
}
return sb.append(num);
}
// 以万为单位处理
if (b3.compareTo(b1) == -1) {
formatNumStr = b3.toString();
} else if ((b3.compareTo(b1) == 0 && b3.compareTo(b1) == 1)
|| b3.compareTo(b2) == -1) {
unit = "万";
formatNumStr = b3.divide(b1).toString();
} else if (b3.compareTo(b2) == 0 || b3.compareTo(b2) == 1) {
unit = "亿";
formatNumStr = b3.divide(b2).toString();
}
if (!"".equals(formatNumStr)) {
int i = formatNumStr.indexOf(".");
if (i == -1) {
sb.append(formatNumStr).append(unit);
} else {
i = i + 1;
String v = formatNumStr.substring(i, i + 1);
if (!v.equals("0")) {
sb.append(formatNumStr.substring(0, i + 1)).append(unit);
} else {
sb.append(formatNumStr.substring(0, i - 1)).append(unit);
}
}
}
if (sb.length() == 0)
return sb.append("0");
return sb;
}
}
文本类
package com.tencent.holmium.common.util;
import android.graphics.Typeface;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import androidx.annotation.ColorInt;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
public class SpanUtils {
private static final int COLOR_DEFAULT = 0xFEFFFFFF;
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private CharSequence mText;
private int flag; //设置标识
private int foregroundColor; //设置前景色
private int backgroundColor; //设置背景色
private int fontSize; // 字体大小
private boolean fontSizeIsDp; //是否dp
private boolean isStrikethrough; //设置删除线
private boolean isUnderline; //设置下划线
private boolean isBold; //设置粗体
private ClickableSpan clickSpan; //设置点击事件
private String url; //设置超链接
private SpannableStringBuilder mBuilder;
public SpanUtils() {
mBuilder = new SpannableStringBuilder();
mText = "";
setDefault();
}
private void setDefault() {
flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
foregroundColor = COLOR_DEFAULT;
backgroundColor = COLOR_DEFAULT;
fontSize = -1;
isStrikethrough = false;
isUnderline = false;
isBold = false;
clickSpan = null;
url = null;
}
/**
* 设置标识
*
* @param flag <ul>
* <li>{@link Spanned#SPAN_INCLUSIVE_EXCLUSIVE}</li>
* <li>{@link Spanned#SPAN_INCLUSIVE_INCLUSIVE}</li>
* <li>{@link Spanned#SPAN_EXCLUSIVE_EXCLUSIVE}</li>
* <li>{@link Spanned#SPAN_EXCLUSIVE_INCLUSIVE}</li>
* </ul>
* @return {@link SpanUtils}
*/
public SpanUtils setFlag(final int flag) {
this.flag = flag;
return this;
}
/**
* 设置前景色
*
* @param color 前景色
* @return {@link SpanUtils}
*/
public SpanUtils setForegroundColor(@ColorInt final int color) {
this.foregroundColor = color;
return this;
}
/**
* 设置背景色
*
* @param color 背景色
* @return {@link SpanUtils}
*/
public SpanUtils setBackgroundColor(@ColorInt final int color) {
this.backgroundColor = color;
return this;
}
/**
* 设置字体尺寸
*
* @param size 尺寸
* @return {@link SpanUtils}
*/
public SpanUtils setFontSize(@IntRange(from = 0) final int size) {
return setFontSize(size, false);
}
/**
* 设置字体尺寸
*
* @param size 尺寸
* @param isDp 是否使用 dip
* @return {@link SpanUtils}
*/
public SpanUtils setFontSize(@IntRange(from = 0) final int size, final boolean isDp) {
this.fontSize = size;
this.fontSizeIsDp = isDp;
return this;
}
/**
* 设置删除线
*
* @return {@link SpanUtils}
*/
public SpanUtils setStrikethrough() {
this.isStrikethrough = true;
return this;
}
/**
* 设置下划线
*
* @return {@link SpanUtils}
*/
public SpanUtils setUnderline() {
this.isUnderline = true;
return this;
}
/**
* 设置粗体
*
* @return {@link SpanUtils}
*/
public SpanUtils setBold() {
isBold = true;
return this;
}
/**
* 设置点击事件
* <p>需添加 view.setMovementMethod(LinkMovementMethod.getInstance())</p>
*
* @param clickSpan 点击事件
* @return {@link SpanUtils}
*/
public SpanUtils setClickSpan(@NonNull final ClickableSpan clickSpan) {
this.clickSpan = clickSpan;
return this;
}
/**
* 设置超链接
* <p>需添加 view.setMovementMethod(LinkMovementMethod.getInstance())</p>
*
* @param url 超链接
* @return {@link SpanUtils}
*/
public SpanUtils setUrl(@NonNull final String url) {
this.url = url;
return this;
}
/**
* 追加样式字符串
*
* @param text 样式字符串文本
* @return {@link SpanUtils}
*/
public SpanUtils append(@NonNull final CharSequence text) {
apply();
mText = text;
return this;
}
/**
* 追加一行样式字符串
*
* @return {@link SpanUtils}
*/
public SpanUtils appendLine(@NonNull final CharSequence text) {
apply();
mText = text + LINE_SEPARATOR;
return this;
}
private void apply() {
applyLast();
}
/**
* 创建样式字符串
*
* @return 样式字符串
*/
public SpannableStringBuilder create() {
applyLast();
return mBuilder;
}
/**
* 设置上一次的样式
*/
private void applyLast() {
updateCharCharSequence();
setDefault();
}
private void updateCharCharSequence() {
if (TextUtils.isEmpty(mText)) return;
int start = mBuilder.length();
mBuilder.append(mText);
int end = mBuilder.length();
//设置前景色
if (foregroundColor != COLOR_DEFAULT) {
mBuilder.setSpan(new ForegroundColorSpan(foregroundColor), start, end, flag);
}
//设置背景色
if (backgroundColor != COLOR_DEFAULT) {
mBuilder.setSpan(new BackgroundColorSpan(backgroundColor), start, end, flag);
}
// 字体大小
if (fontSize != -1) {
mBuilder.setSpan(new AbsoluteSizeSpan(fontSize, fontSizeIsDp), start, end, flag);
}
//设置删除线
if (isStrikethrough) {
mBuilder.setSpan(new StrikethroughSpan(), start, end, flag);
}
//设置下划线
if (isUnderline) {
mBuilder.setSpan(new UnderlineSpan(), start, end, flag);
}
//设置粗体
if (isBold) {
mBuilder.setSpan(new StyleSpan(Typeface.BOLD), start, end, flag);
}
//设置点击事件
if (clickSpan != null) {
mBuilder.setSpan(clickSpan, start, end, flag);
}
//设置超链接
if (url != null) {
mBuilder.setSpan(new URLSpan(url), start, end, flag);
}
}
}
使用
mLoginAgree.setText(new SpanUtils()
.append("登录即代表您已同意")
.append("《聚钬隐私保护指导》")
.setForegroundColor(getResources().getColor(R.color.black))
.setClickSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
}
}).create());
三、dialog
import android.app.Dialog;
import android.app.DialogFragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import pos.enhua.com.qmyposapp.R;
public class CustomDialog extends DialogFragment {
private Button mCancelButton, mConfirmButton;
private TextView mTitle;
private String mTitleText;
private ConfirmResultListener mConfirmResultListener;
public interface ConfirmResultListener {
void onConfirm();
void onCancel();
}
public void setConfirmResultListener(ConfirmResultListener confirmResultListener) {
mConfirmResultListener = confirmResultListener;
}
public void setTitle(String titleText) {
if (mTitle != null) {
mTitle.setText(titleText);
}
mTitleText = titleText;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_confirm_dialog, container);
initView(view);
initListener();
return view;
}
private void initView(View view) {
if (TextUtils.isEmpty(mTitleText)) {
mTitleText = "";
}
mCancelButton = view.findViewById(R.id.btn_dialog_cancel);
mConfirmButton = view.findViewById(R.id.btn_dialog_confirm);
mTitle = view.findViewById(R.id.tv_dialog_title);
mTitle.setText(mTitleText);
}
private void initListener() {
mConfirmButton.setOnClickListener(mOnClickListener);
mCancelButton.setOnClickListener(mOnClickListener);
}
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_dialog_confirm: {
if (mConfirmResultListener != null) {
mConfirmResultListener.onConfirm();
}
dismiss();
break;
}
case R.id.btn_dialog_cancel: {
if (mConfirmResultListener != null) {
mConfirmResultListener.onCancel();
}
dismiss();
break;
}
default: {
break;
}
}
}
};
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
dialog.getWindow().setLayout((int) (displayMetrics.widthPixels * 0.75), ViewGroup.LayoutParams.WRAP_CONTENT);
}
}
}
使用:
CustomDialog dialog = getConfirmDialog();
dialog.setConfirmResultListener(new CustomDialog.ConfirmResultListener() {
@Override
public void onConfirm() {
Toast.makeText(getActivity(), "sadasda", Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel() {
}
});
dialog.show(getActivity().getFragmentManager(), "config dialog");
4.定位工具类
package com.lt.utils;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.provider.Settings;
import androidx.core.app.ActivityCompat;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ToastUtils;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
/**
* 定位相关工具类
*/
public class LocationUtils {
private static OnLocationChangeListener mListener;
private static MyLocationListener myLocationListener;
private static LocationManager mLocationManager;
private LocationUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* 判断Gps是否可用
*
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isGpsEnabled(Context context) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
/**
* 判断定位是否可用
*
* @return {@code true}: 是<br>{@code false}: 否
*/
public static boolean isLocationEnabled(Context context) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) || lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
/**
* 打开Gps设置界面
*/
public static void openGpsSettings(Context context) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 注册
* <p>使用完记得调用{@link #unregister()}</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>}</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>}</p>
* <p>如果{@code minDistance}为0,则通过{@code minTime}来定时更新;</p>
* <p>{@code minDistance}不为0,则以{@code minDistance}为准;</p>
* <p>两者都为0,则随时刷新。</p>
*
* @param minTime 位置信息更新周期(单位:毫秒)
* @param minDistance 位置变化最小距离:当位置距离变化超过此值时,将更新位置信息(单位:米)
* @param listener 位置刷新的回调接口
* @return {@code true}: 初始化成功<br>{@code false}: 初始化失败
*/
public static boolean register(Context context, long minTime, long minDistance, OnLocationChangeListener listener) {
if (listener == null) return false;
mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
mListener = listener;
if (!isLocationEnabled(context)) {
ToastUtils.showLong("无法定位,请打开定位服务");
return false;
}
try {
String provider = mLocationManager.getBestProvider(getCriteria(), true);
Location location = mLocationManager.getLastKnownLocation(provider);
if (location != null) listener.getLastKnownLocation(location);
if (myLocationListener == null) myLocationListener = new MyLocationListener();
mLocationManager.requestLocationUpdates(provider, minTime, minDistance, myLocationListener);
} catch (SecurityException e) {
}
return true;
}
/**
* 注销
*/
public static void unregister() {
if (mLocationManager != null) {
if (myLocationListener != null) {
mLocationManager.removeUpdates(myLocationListener);
myLocationListener = null;
}
mLocationManager = null;
}
}
/**
* 设置定位参数
*
* @return {@link Criteria}
*/
private static Criteria getCriteria() {
Criteria criteria = new Criteria();
//设置定位精确度 Criteria.ACCURACY_COARSE比较粗略,Criteria.ACCURACY_FINE则比较精细
criteria.setAccuracy(Criteria.ACCURACY_FINE);
//设置是否要求速度
criteria.setSpeedRequired(false);
// 设置是否允许运营商收费
criteria.setCostAllowed(false);
//设置是否需要方位信息
criteria.setBearingRequired(false);
//设置是否需要海拔信息
criteria.setAltitudeRequired(false);
// 设置对电源的需求
criteria.setPowerRequirement(Criteria.POWER_LOW);
return criteria;
}
/**
* 根据经纬度获取地理位置
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return {@link Address}
*/
public static Address getAddress(Context context, double latitude, double longitude) {
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses.size() > 0) return addresses.get(0);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据经纬度获取所在国家
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return 所在国家
*/
public static String getCountryName(Context context, double latitude, double longitude) {
Address address = getAddress(context, latitude, longitude);
return address == null ? "unknown" : address.getCountryName();
}
/**
* 根据经纬度获取所在地
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return 所在地
*/
public static String getLocality(Context context, double latitude, double longitude) {
Address address = getAddress(context, latitude, longitude);
return address == null ? "unknown" : address.getLocality();
}
/**
* 根据经纬度获取所在街道
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return 所在街道
*/
public static String getStreet(Context context, double latitude, double longitude) {
Address address = getAddress(context, latitude, longitude);
return address == null ? "unknown" : address.getAddressLine(0);
}
private static class MyLocationListener
implements LocationListener {
/**
* 当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
*
* @param location 坐标
*/
@Override
public void onLocationChanged(Location location) {
if (mListener != null) {
mListener.onLocationChanged(location);
}
}
/**
* provider的在可用、暂时不可用和无服务三个状态直接切换时触发此函数
*
* @param provider 提供者
* @param status 状态
* @param extras provider可选包
*/
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
if (mListener != null) {
mListener.onStatusChanged(provider, status, extras);
}
switch (status) {
case LocationProvider.AVAILABLE:
LogUtils.d("onStatusChanged", "当前GPS状态为可见状态");
break;
case LocationProvider.OUT_OF_SERVICE:
LogUtils.d("onStatusChanged", "当前GPS状态为服务区外状态");
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
LogUtils.d("onStatusChanged", "当前GPS状态为暂停服务状态");
break;
}
}
/**
* provider被enable时触发此函数,比如GPS被打开
*/
@Override
public void onProviderEnabled(String provider) {
}
/**
* provider被disable时触发此函数,比如GPS被关闭
*/
@Override
public void onProviderDisabled(String provider) {
}
}
public interface OnLocationChangeListener {
/**
* 获取最后一次保留的坐标
*
* @param location 坐标
*/
void getLastKnownLocation(Location location);
/**
* 当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
*
* @param location 坐标
*/
void onLocationChanged(Location location);
/**
* provider的在可用、暂时不可用和无服务三个状态直接切换时触发此函数
*
* @param provider 提供者
* @param status 状态
* @param extras provider可选包
*/
void onStatusChanged(String provider, int status, Bundle extras);//位置状态发生改变
}
}
5.异常捕获工具类
package com.qhcloud.filetransfer.utils;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import com.qhcloud.filetransfer.R;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class CrashHandler implements UncaughtExceptionHandler {
public static final String TAG = "CrashHandler";
//存储根目录
public static final String PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
// CrashHandler实例
private static CrashHandler INSTANCE = new CrashHandler();
// 是否已经初始化
private static boolean isInit = false;
// 系统默认的UncaughtException处理类
private UncaughtExceptionHandler mDefaultHandler;
// 程序的Context对象
private Context mContext;
// 用来存储设备信息和异常信息
private Map<String, String> infos = new HashMap<>();
// 用于格式化日期,作为日志文件名的一部分
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
private String nameString;
/**
* 保证只有一个CrashHandler实例
*/
private CrashHandler() {
}
/**
* 获取CrashHandler实例 ,单例模式
*/
public static CrashHandler getInstance() {
return INSTANCE;
}
/**
* 初始化
*
* @param context
*/
public void init(Context context) {
mContext = context;
// Android M will check permission dynamically, avoid crush here.
if (!isInit && AndroidUtil.checkPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)) {
// 获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
isInit = true;
nameString = context.getString(R.string.app_name);
}
}
/**
* 当UncaughtException发生时会转入该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, "error : ", e);
}
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
// WonderMapApplication.getInstance().getSpUtil().setCrashLog(true);//
// 每次进入应用检查,是否有log,有则上传
// 使用Toast来显示异常信息
new Thread() {
@Override
public void run() {
/*
* Looper.prepare(); Toast.makeText(mContext,
* mContext.getString(R.string.crash_tip), Toast.LENGTH_LONG)
* .show(); Looper.loop();
*/
}
}.start();
// 收集设备参数信息
collectDeviceInfo(mContext);
// 保存日志文件
/* String fileName = */
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 (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) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : infos.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key).append("=").append(value).append("\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();
// Log.d(WModel.CrashUpload, result);
sb.append(result);
try {
Log.d("CrashHandler", "msg:"+result);
// long timestamp = System.currentTimeMillis();
String time = formatter.format(new Date());
String fileName = nameString + "-" + time + ".txt";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
String path = PATH + "/projectName/log/";
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
FileOutputStream fos = new FileOutputStream(path + fileName);
fos.write(sb.toString().getBytes());
fos.close();
onClearFile();
}
return fileName;
} catch (Exception e) {
Log.e(TAG, "an error occured while writing file...", e);
}
return null;
}
public void onClearFile() {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
String path = PATH+ "/projectName/log/";
File file = new File(path);
if (file.exists()) {
if (file.listFiles().length > 3) {
int index = 0;
for (File temp : file.listFiles()) {
long time = System.currentTimeMillis() - temp.lastModified();
if (time/1000 > 3600*24*3) {
temp.delete();
index++;
}
if (index >= file.listFiles().length - 3) break;
}
}
}
}
}
}
未完待续。。。。。。