android 常用工具库 备份
一些常用的库,在这里做个备份。部分代码摘抄自网络,经由封装删改后已经记不得出处了,希望原作者谅解。
未捕获异常处理类,因为现在第三方框架(友盟,takingdata等)已经集成了异常统计,所以这个类基本不用了,理解下处理流程就好。
/** * 异常处理工具类 * Created by sy on 2015/4/22. */ public class ExceptionUtil implements Thread.UncaughtExceptionHandler { /** * 是否开启日志输出, 在Debug状态下开启, 在Release状态下关闭以提升程序性能 */ private final static boolean DEBUG = true; /** * CrashHandler实例 */ private static ExceptionUtil INSTANCE; /** * 程序的Context对象 */ private Context mContext; /** * 系统默认的UncaughtException处理类 */ private Thread.UncaughtExceptionHandler mDefaultHandler; //用来存储设备信息和异常信息 private Map<String, String> infos = new HashMap<String, String>(); private static final String VERSION_NAME = "versionName"; private static final String VERSION_CODE = "versionCode"; /** * 错误报告文件的扩展名 */ private static final String CRASH_REPORTER_EXTENSION = ".txt"; /** * 保证只有一个ExceptionUtil实例 */ private ExceptionUtil() { } /** * 获取ExceptionUtil实例 ,单例模式 */ public static ExceptionUtil getInstance() { if (INSTANCE == null) INSTANCE = new ExceptionUtil(); return INSTANCE; } /** * 初始化,注册Context对象, 获取系统默认的UncaughtException处理器, 设置该CrashHandler为程序的默认处理器 */ public void init(Context ctx) { mContext = ctx; mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } /** * 当UncaughtException发生时会转入该函数来处理 */ @Override public void uncaughtException(Thread thread, Throwable ex) { if (!handleException(ex) && mDefaultHandler != null) { // 如果用户没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); } else System.exit(0); } /** * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑 * * @return true:如果处理了该异常信息;否则返回false */ private boolean handleException(Throwable ex) { if (ex == null) { return true; } // final String msg = ex.getLocalizedMessage(); // // 使用Toast来显示异常信息 // new Thread() { // @Override // public void run() { // // Toast 显示需要出现在一个线程的消息队列中 // Looper.prepare(); // Toast.makeText(mContext, "出现异常,即将关闭", Toast.LENGTH_LONG).show(); // Looper.loop(); // } // }.start(); // 收集设备信息 collectCrashDeviceInfo(mContext); // 保存错误报告文件 saveCrashInfoToFile(ex); // 发送错误报告到服务器 //sendCrashReportsToServer(mContext); return false; } /** * 收集程序崩溃的设备信息 */ public void collectCrashDeviceInfo(Context ctx) { try { // Class for retrieving various kinds of information related to the // application packages that are currently installed on the device. // You can find this class through getPackageManager(). PackageManager pm = ctx.getPackageManager(); // getPackageInfo(String packageName, int flags) // Retrieve overall information about an application package that is installed on the system. // public static final int GET_ACTIVITIES // Since: API Level 1 PackageInfo flag: return information about activities in the package in activities. PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); if (pi != null) { // public String versionName The version name of this package, // as specified by the <manifest> tag's versionName attribute. infos.put(VERSION_NAME, pi.versionName == null ? "not set" : pi.versionName); // public int versionCode The version number of this package, // as specified by the <manifest> tag's versionCode attribute. infos.put(VERSION_CODE, pi.versionCode + ""); } } catch (PackageManager.NameNotFoundException e) { Log.e(StaticConstant.TAG, "Error while collect package info", e); } // 使用反射来收集设备信息.在Build类中包含各种设备信息, // 例如: 系统版本号,设备生产商 等帮助调试程序的有用信息 // 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段 Field[] fields = Build.class.getDeclaredFields(); for (Field field : fields) { try { // setAccessible(boolean flag) // 将此对象的 accessible 标志设置为指示的布尔值。 // 通过设置Accessible属性为true,才能对私有变量进行访问,不然会得到一个IllegalAccessException的异常 field.setAccessible(true); infos.put(field.getName(), field.get(null) + ""); if (DEBUG) { Log.d(StaticConstant.TAG, field.getName() + " : " + field.get(null)); } } catch (Exception e) { Log.e(StaticConstant.TAG, "Error while collect crash info", e); } } } /** * 保存错误信息到文件中 */ private String saveCrashInfoToFile(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 info = new StringWriter(); PrintWriter printWriter = new PrintWriter(info); ex.printStackTrace(printWriter); // getCause() 返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null。 Throwable cause = ex.getCause(); while (cause != null) { cause.printStackTrace(printWriter); cause = cause.getCause(); } String result = info.toString(); printWriter.close(); sb.append(result); try { long timestamp = System.currentTimeMillis(); String fileName = "crash-" + timestamp + CRASH_REPORTER_EXTENSION; // 保存文件 FileOutputStream fos = GetFOPStream(fileName);//mContext.openFileOutput(fileName, Context.MODE_PRIVATE); fos.write(sb.toString().getBytes()); fos.flush(); fos.close(); return fileName; } catch (Exception e) { Log.e(StaticConstant.TAG, "写入异常文件时发生异常...", e); } return null; } /** * 获取输出流,sd卡可用就存放到sd卡,否则就存放在本地存储空间 */ FileOutputStream GetFOPStream(String fileName) throws Exception { String sdStatus = Environment.getExternalStorageState(); if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { return mContext.openFileOutput(fileName, Context.MODE_PRIVATE); } else { final String pathName = Environment.getExternalStorageDirectory().getPath()+"/czbd/"; File path = new File(pathName); File file = new File(pathName + fileName); if (!path.exists()) { path.mkdir(); } if (!file.exists()) { file.createNewFile(); } return new FileOutputStream(file, true); } } /** * 把错误报告发送给服务器,包含新产生的和以前没发送的. */ private void sendCrashReportsToServer(Context ctx) { String[] crFiles = getCrashReportFiles(ctx); if (crFiles != null && crFiles.length > 0) { TreeSet<String> sortedFiles = new TreeSet<String>(); sortedFiles.addAll(Arrays.asList(crFiles)); for (String fileName : sortedFiles) { File cr = new File(ctx.getFilesDir(), fileName); postReport(cr); cr.delete();// 删除已发送的报告 } } } /** * 获取错误报告文件名 * * @param ctx * @return */ private String[] getCrashReportFiles(Context ctx) { File filesDir = ctx.getFilesDir(); // 实现FilenameFilter接口的类实例可用于过滤器文件名 FilenameFilter filter = new FilenameFilter() { // accept(File dir, String name) // 测试指定文件是否应该包含在某一文件列表中。 public boolean accept(File dir, String name) { return name.endsWith(CRASH_REPORTER_EXTENSION); } }; // list(FilenameFilter filter) // 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录 return filesDir.list(filter); } private void postReport(File file) { // TODO 使用HTTP Post 发送错误报告到服务器 } /** * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告 */ public void sendPreviousReportsToServer() { sendCrashReportsToServer(mContext); } }
屏幕密度单位转换类,动态添加控件时用的挺多的。
/**
* 单位转换工具类
* Created by sy on 2015/4/21.
*/
public class DensityUtil {
/**
* dp转px
*
*/
public static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/**
* sp转px
*/
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/**
* px转dp
*/
public static float px2dp(Context context, float pxVal) {
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
/**
* px转sp
*/
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}
命令行工具类,需要手机root使用,当初写这个类是因为手机网络偶发性请求失败,为了确认是请求失败时能否ping通服务器。调试偶发性bug时这个类有点用,可以收集出现异常时的手机状况。
/**
* 命令行工具
* Created by sy on 2015/8/6.
*/
public class CommandUtil {
public static final String TAG = CommandUtil.class.getSimpleName();
public static final String COMMAND_SH = "sh";
public static final String COMMAND_LINE_END = "\n";
public static final String COMMAND_EXIT = "exit\n";
private static final boolean ISDEBUG = true;
/**
* 执行单条命令
*
* @param command
* @return
*/
public static List<String> execute(String command) {
return execute(new String[] { command });
}
/**
* 可执行多行命令(bat)
*
* @param commands
* @return
*/
public static List<String> execute(String[] commands) {
List<String> results = new ArrayList<String>();
int status = -1;
if (commands == null || commands.length == 0) {
return null;
}
debug("execute command start : " + commands);
Process process = null;
BufferedReader successReader = null;
BufferedReader errorReader = null;
StringBuilder errorMsg = null;
DataOutputStream dos = null;
try {
process = Runtime.getRuntime().exec(COMMAND_SH);
dos = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command == null) {
continue;
}
dos.write(command.getBytes());
dos.writeBytes(COMMAND_LINE_END);
dos.flush();
}
dos.writeBytes(COMMAND_EXIT);
dos.flush();
status = process.waitFor();
errorMsg = new StringBuilder();
successReader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
errorReader = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
String lineStr;
while ((lineStr = successReader.readLine()) != null) {
results.add(lineStr);
debug(" command line item : " + lineStr);
}
while ((lineStr = errorReader.readLine()) != null) {
errorMsg.append(lineStr);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (dos != null) {
dos.close();
}
if (successReader != null) {
successReader.close();
}
if (errorReader != null) {
errorReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
debug(String.format(Locale.CHINA,
"execute command end,errorMsg:%s,and status %d: ", errorMsg,
status));
return results;
}
/**
* DEBUG LOG
*
* @param message
*/
private static void debug(String message) {
if (ISDEBUG) {
Log.d(TAG, message);
}
}
}
app缓存大小相关类,用来处理清理手机缓存的需求,使用这个类的时候要注意清除自己添加的sd卡中的缓存文件
/**
* 缓存清除工具
* <p/>
* Created by sy on 2015/7/7.
*/
public class CacheCleanUtil {
public static String getTotalCacheSize(Context context) throws Exception {
long cacheSize = getFolderSize(context.getCacheDir());
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cacheSize += getFolderSize(context.getExternalCacheDir());
}
return getFormatSize(cacheSize);
}
public static void clearAllCache(Context context) {
deleteDir(context.getCacheDir());
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
deleteDir(context.getExternalCacheDir());
}
}
private static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return dir.delete();
}
// 获取文件
//Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
//Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
private static long getFolderSize(File file) throws Exception {
long size = 0;
try {
File[] fileList = file.listFiles();
for (int i = 0; i < fileList.length; i++) {
// 如果下面还有文件
if (fileList[i].isDirectory()) {
size = size + getFolderSize(fileList[i]);
} else {
size = size + fileList[i].length();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return size;
}
/**
* 格式化单位
*
* @param size
* @return
*/
private static String getFormatSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
return "0K";
}
double megaByte = kiloByte / 1024;
if (megaByte < 1) {
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
.toPlainString() + "KB";
}
double gigaByte = megaByte / 1024;
if (gigaByte < 1) {
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
.toPlainString() + "MB";
}
double teraBytes = gigaByte / 1024;
if (teraBytes < 1) {
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
.toPlainString() + "GB";
}
BigDecimal result4 = new BigDecimal(teraBytes);
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()
+ "TB";
}
}
网络相关类,获取手机运营商类型和检测网络是否连接和跳转网络设置类
/**
* 网络相关工具类
* Created by sy on 2015/4/21.
*/
public class NetUtil {
/**
* 获取网络类型
*
* @return
*/
public static String getNetState(Context context) {
String result = "";
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (null != info) {
if (cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
result = "wifi";
} else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
switch (info.getSubtype()) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN: //api<8 : replace by 11
result = "2G";
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B: //api<9 : replace by 14
case TelephonyManager.NETWORK_TYPE_EHRPD: //api<11 : replace by 12
case TelephonyManager.NETWORK_TYPE_HSPAP: //api<13 : replace by 15
result = "3G";
break;
case TelephonyManager.NETWORK_TYPE_LTE: //api<11 : replace by 13
result = "4G";
break;
default:
result = info.getSubtypeName();
// 中国移动 联通 电信 三种3G制式
if (result.equalsIgnoreCase("TD-SCDMA") ||
result.equalsIgnoreCase("WCDMA") ||
result.equalsIgnoreCase("CDMA2000")) {
result = "3G";
}
break;
}
}
} else{
result = "没有网络连接";
}
return result;
}
/**
* 判断网络是否连接
*/
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 false;
return cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
}
/**
* 打开网络设置界面
*/
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);
}
}
屏幕相关类
/**
* 屏幕操作工具类
* Created by sy on 2015/4/21.
*/
public class ScreenUtil {
/**
* 获得屏幕高度
*/
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 获得屏幕宽度
*/
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
/**
* 获得状态栏的高度
*/
public static int getStatusHeight(Context context) {
int statusHeight = -1;
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int height = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}
/**
* 获取当前屏幕截图,包含状态栏
*/
public static Bitmap snapShotWithStatusBar(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
view.destroyDrawingCache();
return bp;
}
/**
* 获取当前屏幕截图,不包含状态栏
*/
public static Bitmap snapShotWithoutStatusBar(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return bp;
}
}
sd相关类,混入了一个保存图片文件的方法,懒的去抽象,就这么放着吧~
/**
* sd卡工具类
* Created by sy on 2015/4/21.
*/
public class SDCardUtil {
/**
* 判断SDCard是否可用
*/
public static boolean isSDCardEnable() {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
/**
* 获取SD卡路径
*/
public static String getSDCardPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator;
}
/**
* 获取SD卡的剩余容量 单位MB
*/
public static long getSDCardAllSize() {
if (isSDCardEnable()) {
StatFs stat = new StatFs(getSDCardPath());
// 获取空闲的数据块的数量
long availableBlocks = (long) stat.getAvailableBlocks() - 4;
// 获取单个数据块的大小(byte)
long freeBlocks = stat.getAvailableBlocks();
return freeBlocks * availableBlocks / 1024 / 1024;
}
return 0;
}
/**
* 获取指定路径所在空间的剩余可用容量字节数,单位MB
*/
public static long getFreeBytes(String filePath) {
// 如果是sd卡的下的路径,则获取sd卡可用容量
if (filePath.startsWith(getSDCardPath())) {
filePath = getSDCardPath();
} else {// 如果是内部存储的路径,则获取内存存储的可用容量
filePath = Environment.getDataDirectory().getAbsolutePath();
}
StatFs stat = new StatFs(filePath);
long availableBlocks = (long) stat.getAvailableBlocks() - 4;
return stat.getBlockSize() * availableBlocks/ 1024 / 1024;
}
/**
* 获取系统存储路径
*
* @return
*/
public static String getRootDirectoryPath() {
return Environment.getRootDirectory().getAbsolutePath();
}
//保存文件到本地
public static void SaveBitmapToFile(String path, String name, Bitmap bm) {
// 判断文件夹是否已经存在
File cacheDir = new File(path);
FileOutputStream os = null;
try {
//判断文件夹是否已经存在
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
File cachefile = new File(path + name);
cachefile.delete();
cachefile.createNewFile();
os = new FileOutputStream(cachefile);
//JPEG格式降质保存
bm.compress(Bitmap.CompressFormat.JPEG, 80,
new BufferedOutputStream(os));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
sharedpreference类,封装了操作,对外提供静态put,get,remove方法,实际使用中感觉挺好。
public class SPUtil {
public static void put(Context context, String key, Object object) {
SharedPreferences sp = context.getSharedPreferences(StaticConstant.SPFILENAME,
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);
}
public static Object get(Context context, String key, Object defaultObject) {
if (contains(context, key)) {
SharedPreferences sp = context.getSharedPreferences(StaticConstant.SPFILENAME,
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 defaultObject;
} else {
return defaultObject;
}
}
public static void remove(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(StaticConstant.SPFILENAME,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.remove(key);
SharedPreferencesCompat.apply(editor);
}
public static void clear(Context context) {
SharedPreferences sp = context.getSharedPreferences(StaticConstant.SPFILENAME,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.clear();
SharedPreferencesCompat.apply(editor);
}
public static boolean contains(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(StaticConstant.SPFILENAME,
Context.MODE_PRIVATE);
return sp.contains(key);
}
public static Map<String, ?> getAll(Context context) {
SharedPreferences sp = context.getSharedPreferences(StaticConstant.SPFILENAME,
Context.MODE_PRIVATE);
return sp.getAll();
}
/**
* commit方法是同步的,apply方法是异步的,所以尽量使用apply方法.
* 但是apply是new api,为了兼容低版本客户端,使用以下兼容方案
*/
private static class SharedPreferencesCompat {
@SuppressWarnings({"unchecked", "rawtypes"})
private static Method findApplyMethod() {
try {
Class clz = SharedPreferences.Editor.class;
return clz.getMethod("apply");
} catch (NoSuchMethodException e) {
}
return null;
}
public static void apply(SharedPreferences.Editor editor) {
try {
Method sApplyMethod = findApplyMethod();
if (sApplyMethod != null) {
sApplyMethod.invoke(editor);
return;
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
e.printStackTrace();
}
editor.commit();
}
}
}
下载更新类,这个类写的很差,里面有比较多的地方耦合了其他工具类,目前懒的改,日后有心情再重构下。
/**
* 更新类
* Created by sy on 2015/8/5.
*/
public class UpdataUtil {
public static int lastProgress = 0;
public final static int updateId = 88888;
public static void updateApk(final Context context, String url) {
StaticMethod.debugEMSG(StaticMethod.getApkPath());
if (!(Boolean) SPUtil.get(context, "isUpdate", false)) {
//锁定下载更新
SPUtil.put(context, "isUpdate", true);
//发送通知
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
final Notification notification = new Notification(R.drawable.push, "正在下载", System.currentTimeMillis());
notification.contentView = new RemoteViews(context.getPackageName(), R.layout.update_notification_layout);
notification.flags = Notification.FLAG_ONGOING_EVENT;
notification.contentView.setTextViewText(R.id.update_title, context.getResources().getString(R.string.app_name) + "正在更新");
notificationManager.notify(updateId, notification);
//开始下载
HttpUtil.mHttpClient.get(url, new BinaryHttpResponseHandler() {
@Override
public void onProgress(long bytesWritten, long totalSize) {
super.onProgress(bytesWritten, totalSize);
int nowProgress = (int) ((bytesWritten / (double) totalSize) * 100);
if (nowProgress != lastProgress) {
notification.contentView.setTextViewText(R.id.update_tv, nowProgress + "%");
notification.contentView.setProgressBar(R.id.update_pb, 100, nowProgress, false);
notificationManager.notify(updateId, notification);
}
lastProgress = nowProgress;
}
@Override
public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] binaryData) {
StaticMethod.debugEMSG("下载成功");
notificationManager.cancel(updateId);
//解锁下载更新
SPUtil.put(context, "isUpdate", false);
//把数据存到sd上
File file = new File(StaticMethod.getApkPath());
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(binaryData, 0, binaryData.length);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//开始安装
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
context.startActivity(intent);
}
@Override
public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers, byte[] binaryData, Throwable error) {
StaticMethod.showMSG(context, "更新失败,错误代码:" + statusCode);
SPUtil.put(context, "isUpdate", false);
}
});
} else {
StaticMethod.showMSG(context, "正在下载更新包,请稍后");
}
}
}
浙公网安备 33010602011771号