├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs └── org.eclipse.jdt.core.prefs ├── AndroidManifest.xml ├── README.md ├── proguard-project.txt ├── project.properties └── src └── com └── ihgoo └── allinone ├── cache ├── ACache.java └── ImageSDCacher.java ├── collection ├── DoubleKeyValueMap.java ├── KeyExpiryMap.java ├── NoDuplicatesArrayList.java └── NoDuplicatesLinkedList.java ├── data ├── Base64.java ├── EncodeUtil.java ├── EncryptUtil.java └── MD5.java ├── exception ├── BaseException.java └── MathException.java ├── image ├── BitmapFIFOCache.java ├── BitmapTool.java ├── BitmapUtils.java ├── GuideImage.java └── ImageUtil.java └── support ├── AppUtil.java ├── AsyncRun.java ├── CharsetUtils.java ├── Check.java ├── IOUtil.java ├── JsonUtil.java ├── LogUtils.java ├── MathUtil.java ├── MediaUtils.java ├── MimeTypeUtils.java ├── NetUtil.java ├── NullUtil.java ├── OtherUtils.java ├── ParseUtil.java ├── Persistence.java ├── PhoneUtils.java ├── PreferencesCookieStore.java ├── ResourceUtil.java ├── ScreenUtil.java ├── SharePreferenceUtil.java ├── ShareUtil.java ├── ShellUtil.java ├── SilentInstaller.java ├── SpanFormatter.java ├── StringUtil.java ├── StringUtils.java ├── TimeUtil.java ├── TrafficUtils.java └── ViewUtil.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /gen/ 3 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AllInOne 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/com/ihgoo/allinone/util/LogUtils.java=UTF-8 3 | encoding/=UTF-8 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##All In One 2 | -------------- 3 | AIO(all in one简称) 4 | --------------- 5 | 6 | 7 | ### 1.1.1 8 | 9 | - 新增大量工具类方法 10 | - 去掉Volley源码以及注入框架源码(按需配置,注入框架可用butterknife或者AndroidAnnotations等) 11 | 12 | ### 1.1.0 13 | 14 | - 去掉了冗余方法 15 | - 去掉了jar包依赖,导入源码 16 | - 导入更简单 17 | 18 | ### 1.1.0 19 | 20 | - 初版,将原项目中使用到的工具整理到此项目中 21 | 22 | 23 | 24 | 简介 25 | ------- 26 | 此项目都是工作中整理的一些很常用的一些方法,在此开源出来是让更多的人开发更方便,更快捷。有很多借鉴别人的,在这里要感谢前辈无私奉献。也希望大家可以提出批评建议。 27 | 28 | 29 | 30 | 图像处理 31 | -------- 32 | - GuideImage 在activity表面添加了一层图层,作为引导图层用,可添加透明图层 33 | 34 | - BitmapUtils 对Bitmap二次处理,避免OOM异常出现 35 | - getBitmap(String imagePath, int width, int height) 36 | - getBitmap(Resources res, InputStream is, int width,int height)等方法 37 | - getBitmapByViewSize 根据View大小获取自适应的bitmap对象 38 | 39 | - Bitmap缓存 40 | - FIFOCache 置换算法 41 | - LRUCache SDK自带推荐使用 42 | 43 | 44 | 网络请求 45 | ------- 46 | 47 | - 推荐使用[`VolleyPlus`](https://github.com/DWorkS/VolleyPlus),如接口是REST接口推荐使用[`retrofit`](https://github.com/square/retrofit)这个框架。重点简单说下retrofit优点: 48 | - 采用动态代理机制和反射,使代码写起来特别简单,看起来也很清晰。 49 | - 可以配合OkHttp拦截器,很方便的在header加token或者处理cookie等等。 50 | - 可配合RxJava,可以让多个接口调用组合变的更简单。 51 | 52 | 53 | 缓存 54 | ------- 55 | - ACache 可以缓存网络请求数据,比如oschina的android客户端可以缓存http请求的新闻内容,缓存时间假设为1个小时,超时后自动失效,让客户端重新请求新的数据,减少客户端流量,同时减少服务器并发量。 56 | 57 | 58 | DB 59 | ------- 60 | - 推荐使用GreenDao,优点: 61 | - 使用java工程生成JavaObject,熟练后非常方便 62 | - 数据库操作便捷,开发效率高 63 | - 内存消耗最少,性能最佳 64 | - 使用教程 参考个人博客 [`GreenDao学习`](http://xunhou.me/greendao/) 65 | 66 | 67 | 其他工具类 68 | ------- 69 | - AppUtil 获取关于app的一些参数,如 版本号版本名称 70 | 71 | - Check 检查类,检查sd卡是否存在等。 72 | 73 | - EncodeUtil(EncryptUtil) 加密解密 74 | 75 | - NetUtil 网络判断,检查使用何种方式联网,以及网络是否可用(连接) 76 | 77 | - LogUtils 自定义log日志,省略参数key,可定位到哪个类第几行 78 | 79 | - ScreenUtil 和屏幕大小有关工具类 80 | 81 | - Base64、Md5 82 | 83 | - BitmapTool 关于图片的工具类 84 | 85 | - EncryptUtils 加密工具类 des加密 86 | 87 | - LogUtils 省略了传入tag的log(建议使用Log4j) 88 | 89 | - SharePreferenceUtil 对SharePreference封装简单get&put方法 90 | 91 | - PhoneUtils 获取手机信息的工具类,诸如获取手机型号获取手机sd卡大小等 92 | 93 | - StringUtils 对字符串处理的工具类 94 | 95 | - TimeUtil 时间格式化/计算时间差值 96 | 97 | - TrafficUtil 流量统计 98 | 99 | - ViewUtil 处理View的一些方法 100 | 101 | 102 | License 103 | ======= 104 | 105 | MIT License -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-18 15 | android.library=true 16 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/cache/ImageSDCacher.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.cache; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.OutputStream; 10 | import java.util.Arrays; 11 | import java.util.Comparator; 12 | 13 | import android.graphics.Bitmap; 14 | import android.graphics.BitmapFactory; 15 | import android.os.Handler; 16 | import android.os.HandlerThread; 17 | 18 | import com.ihgoo.allinone.image.BitmapTool; 19 | import com.ihgoo.allinone.support.LogUtils; 20 | import com.ihgoo.allinone.support.OtherUtils; 21 | import com.ihgoo.allinone.support.PhoneUtils; 22 | 23 | 24 | public class ImageSDCacher { 25 | 26 | private final static String TAG = ImageSDCacher.class.getSimpleName(); 27 | private static ImageSDCacher mInstance; 28 | private final static int FREE_SD_SPACE_NEEDED_TO_CACHE = 50; // Mb 29 | private final static int MAX_CACHE_SIZE_NEEDED = 30; // Mb 30 | private final static String WHOLESALE_CONV = ".jpg"; 31 | private final static long CACHE_EXPIRE_THRESHOLD = 3600 * 24 * 7; // one 32 | HandlerThread mHandlerThread = null; 33 | private Handler mHandler = null; 34 | private BitmapTool mBitmapTool = new BitmapTool(); 35 | 36 | private ImageSDCacher() { 37 | mHandlerThread = new HandlerThread("sdcacher_thread"); 38 | mHandlerThread.start(); 39 | } 40 | 41 | public static ImageSDCacher getImageSDCacher() { 42 | if (mInstance == null) { 43 | mInstance = new ImageSDCacher(); 44 | } 45 | return mInstance; 46 | } 47 | 48 | /** 49 | * 根据图片缓存路径返回Bitmap 50 | * 51 | * @param url 52 | * 图片缓存路径 53 | * @param cachePath 54 | * 本地缓存父路径
PathCommonDefines.PHOTOCACHE_FOLDER 程序缓存图片路径;
55 | * PathCommonDefines.MY_FAVOURITE_FOLDER 我的收藏图片路径 56 | * @return bitmap 57 | */ 58 | public Bitmap getBitmapByCachePath(String url, String cachePath) { 59 | 60 | Bitmap bitmap = null; 61 | if (isImageSDCachedByPath(url, cachePath)) { 62 | String filePath = url != null && url.startsWith("http://") ? (cachePath 63 | + File.separator + convertUrlToFileName(url)) 64 | : url; 65 | bitmap = mBitmapTool.CreateImage(filePath); 66 | } else { 67 | LogUtils.w("Pictures don't cached into SDCard."); 68 | } 69 | 70 | return bitmap; 71 | } 72 | 73 | /** 74 | * 判断图片是否存在 75 | * 76 | * @param url 77 | * 图片链接 78 | * @param cachePath 79 | * 本地缓存父路径
PathCommonDefines.PHOTOCACHE_FOLDER 程序缓存图片路径;
80 | * PathCommonDefines.MY_FAVOURITE_FOLDER 我的收藏图片路径 81 | * @return 是否存在 82 | */ 83 | public boolean isImageSDCachedByPath(String url, String cachePath) { 84 | if (url == null || url.trim().length() <= 0) { 85 | LogUtils.e("img url is null"); 86 | return false; 87 | } 88 | 89 | String fileName = url.startsWith("http://") ? convertUrlToFileName(url) 90 | : url; 91 | // Logger.i(TAG, "isImageSDCachedByPath+url:" + url); 92 | // Logger.d(TAG, "isImageSDCachedByPath+fileName:" + fileName); 93 | // Create Path 94 | File file = new File(cachePath + File.separator); 95 | if (!file.exists()) { 96 | file.mkdirs(); 97 | } 98 | if (fileName != null) { 99 | String filePath = url.startsWith("http://") ? (cachePath 100 | + File.separator + fileName) : fileName; 101 | File f = new File(filePath); 102 | 103 | if (f.exists()) { 104 | LogUtils.d("File sdCard cached_myimg exits:" + url); 105 | return true; 106 | } 107 | } 108 | return false; 109 | } 110 | 111 | /** 112 | * 保存Bitmap到指定的目录下 113 | * 114 | * @param bitmap 115 | * 保存的bitmap 116 | * @param url 117 | * 图片网络路径 118 | * @param cachePath 119 | * 本地缓存父路径
PathCommonDefines.PHOTOCACHE_FOLDER 程序缓存图片路径;
120 | * PathCommonDefines.MY_FAVOURITE_FOLDER 我的收藏图片路径 121 | * @param isJpg 122 | * 是否是JPG 123 | * @param quality 124 | * 缩放比 125 | * @return 是否成功 126 | */ 127 | public boolean saveBitmapToSDCard(Bitmap bitmap, String url, 128 | String cachePath, boolean isJpg, int quality) { 129 | 130 | boolean result = false; 131 | 132 | if (bitmap == null) { 133 | LogUtils.w(" trying to save null bitmap"); 134 | return false; 135 | } 136 | 137 | if (FREE_SD_SPACE_NEEDED_TO_CACHE > PhoneUtils.freeSpaceOnSd()) { 138 | LogUtils.w( "Low free space onsd, do not cache"); 139 | 140 | return false; 141 | } 142 | 143 | if (url == null || (url != null && url.equals(""))) { 144 | return false; 145 | } 146 | 147 | File makeDirectoryPathFile = new File(cachePath); 148 | 149 | if (!makeDirectoryPathFile.isDirectory()) { 150 | makeDirectoryPathFile.mkdirs(); 151 | } 152 | 153 | String filename = convertUrlToFileName(url); 154 | 155 | File file = new File(cachePath + File.separator + filename); 156 | 157 | // Logger.d(TAG, "url:" + url); 158 | // Logger.i(TAG, "fileName:" + filename); 159 | 160 | try { 161 | 162 | file.createNewFile(); 163 | 164 | OutputStream outStream = new FileOutputStream(file); 165 | 166 | if (isJpg) { 167 | // 输出 168 | bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream); 169 | } else { 170 | // 输出 171 | bitmap.compress(Bitmap.CompressFormat.PNG, quality, outStream); 172 | } 173 | 174 | result = true; 175 | 176 | } catch (IOException e) { 177 | 178 | LogUtils.e("saveBitmapToSDCard():" + e.getMessage(), e); 179 | 180 | result = false; 181 | 182 | } 183 | 184 | // 清理缓存 185 | removeCache(cachePath); 186 | 187 | return result; 188 | } 189 | 190 | public void copyFile(File sourceFile, File targetFile) { 191 | try { 192 | 193 | // 新建文件输入流并对它进行缓冲 194 | 195 | FileInputStream input = new FileInputStream(sourceFile); 196 | 197 | BufferedInputStream inBuff = new BufferedInputStream(input); 198 | 199 | // 新建文件输出流并对它进行缓冲 200 | 201 | FileOutputStream output = new FileOutputStream(targetFile); 202 | 203 | BufferedOutputStream outBuff = new BufferedOutputStream(output); 204 | 205 | // 缓冲数组 206 | 207 | byte[] b = new byte[1024 * 5]; 208 | 209 | int len; 210 | 211 | while ((len = inBuff.read(b)) != -1) { 212 | 213 | outBuff.write(b, 0, len); 214 | 215 | } 216 | 217 | // 刷新此缓冲的输出流 218 | 219 | outBuff.flush(); 220 | 221 | // 关闭流 222 | 223 | inBuff.close(); 224 | 225 | outBuff.close(); 226 | 227 | output.close(); 228 | 229 | input.close(); 230 | } catch (IOException e) { 231 | } 232 | 233 | } 234 | 235 | /** 236 | * 将用户选中的图片拷贝到指定的缓存目录 237 | * 238 | * @param originalPath 239 | * 原始目录 240 | * @return 指定的缓存目录 241 | */ 242 | // public String saveAvatarTemptoSDCard(String originalPath, int type) { 243 | // String fileName = ""; 244 | // String tempPath = ""; 245 | // String tempPath_fileName = ""; 246 | // if (originalPath != null && !originalPath.equals("")) { 247 | // 248 | // fileName = originalPath 249 | // .substring(originalPath.lastIndexOf("/") + 1); 250 | // 251 | // switch (type) { 252 | // case OrdinaryCommonDefines.TRIP_ID_FROM_NEWACCOUNT:// 用户头像 253 | // case OrdinaryCommonDefines.TRIP_ID_FROM_PROFILE_AVATAR: 254 | // tempPath = PathCommonDefines.USER_AVATAR_FOLDER 255 | // + File.separator; 256 | // 257 | // break; 258 | // case OrdinaryCommonDefines.TRIP_ID_FROM_PROFILE_CAMERA:// 259 | // ProfileActivity中的camera拍照(不编辑) 260 | // case OrdinaryCommonDefines.TRIP_ID_FROM_FEATUREDFEED:// 非用户头像 261 | // case OrdinaryCommonDefines.TRIP_ID_FROM_ILIKE: 262 | // case OrdinaryCommonDefines.TRIP_ID_FROM_MYTRIPS: 263 | // case OrdinaryCommonDefines.TRIP_ID_FROM_NEWTRIP: 264 | // case OrdinaryCommonDefines.TRIP_ID_FROM_PICKCOVER: 265 | // case OrdinaryCommonDefines.TRIP_ID_FROM_TRIPDETAIL: 266 | // 267 | // tempPath = PathCommonDefines.DCIM_FOTO_FOLDER + File.separator; 268 | // break; 269 | // default: 270 | // break; 271 | // } 272 | // 273 | // tempPath_fileName = tempPath + fileName; 274 | // try { 275 | // 276 | // File files = new File(tempPath); 277 | // 278 | // File sourceFile = new File(originalPath); 279 | // File targetFile = new File(tempPath_fileName); 280 | // 281 | // files.mkdirs(); 282 | // targetFile.createNewFile(); 283 | // 284 | // copyFile(sourceFile, targetFile); 285 | // 286 | // } catch (Exception e) { 287 | // e.printStackTrace(); 288 | // tempPath_fileName = ""; 289 | // } 290 | // } 291 | // return tempPath_fileName; 292 | // } 293 | /*** Method to calculate the sample size for the bitmap **/ 294 | public static int computeSampleSize(BitmapFactory.Options options, 295 | int minSideLength, int maxNumOfPixels) { 296 | int initialSize = computeInitialSampleSize(options, minSideLength, 297 | maxNumOfPixels); 298 | 299 | int roundedSize; 300 | if (initialSize <= 8) { 301 | roundedSize = 1; 302 | while (roundedSize < initialSize) { 303 | roundedSize <<= 1; 304 | } 305 | } else { 306 | roundedSize = (initialSize + 7) / 8 * 8; 307 | } 308 | 309 | return roundedSize; 310 | } 311 | 312 | /*** Method to calculate the sample size for the bitmap **/ 313 | private static int computeInitialSampleSize(BitmapFactory.Options options, 314 | int minSideLength, int maxNumOfPixels) { 315 | double w = options.outWidth; 316 | double h = options.outHeight; 317 | 318 | int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math 319 | .sqrt(w * h / maxNumOfPixels)); 320 | int upperBound = (minSideLength == -1) ? 128 : (int) Math.min( 321 | Math.floor(w / minSideLength), Math.floor(h / minSideLength)); 322 | 323 | if (upperBound < lowerBound) { 324 | // return the larger one when there is no overlapping zone. 325 | return lowerBound; 326 | } 327 | 328 | if ((maxNumOfPixels == -1) && (minSideLength == -1)) { 329 | return 1; 330 | } else if (minSideLength == -1) { 331 | return lowerBound; 332 | } else { 333 | return upperBound; 334 | } 335 | } 336 | 337 | private String convertUrlToFileName(String url) { 338 | String fn = null; 339 | if (url != null && url.trim().length() > 0) { 340 | 341 | if (url.contains(".png")) { 342 | 343 | fn = String.valueOf(url.hashCode()) + ".png"; 344 | 345 | } else { 346 | 347 | fn = String.valueOf(url.hashCode()) + ".jpg"; 348 | 349 | } 350 | 351 | } 352 | return fn; 353 | } 354 | 355 | /** 356 | * 清理缓存 357 | * 358 | * @param cachePath 359 | * 本地缓存父路径
PathCommonDefines.PHOTOCACHE_FOLDER 程序缓存图片路径;
360 | * PathCommonDefines.MY_FAVOURITE_FOLDER 我的收藏图片路径 361 | */ 362 | private void removeCache(String cachePath) { 363 | String dirPath = cachePath; 364 | File dir = new File(dirPath); 365 | File[] files = dir.listFiles(); 366 | if (files == null) { 367 | return; 368 | } 369 | int dirSize = 0; 370 | for (int i = 0; i < files.length; i++) { 371 | if (files[i].getName().contains(WHOLESALE_CONV)) { 372 | dirSize += files[i].length(); 373 | } 374 | } 375 | if (dirSize > MAX_CACHE_SIZE_NEEDED * 1024 * 1024 376 | || FREE_SD_SPACE_NEEDED_TO_CACHE > PhoneUtils.freeSpaceOnSd()) { 377 | int removeFactor = (int) ((0.4 * files.length) + 1); 378 | 379 | Arrays.sort(files, new FileLastModifSort()); 380 | LogUtils.i("Clear some expiredcache files "); 381 | 382 | for (int i = 0; i < removeFactor; i++) { 383 | 384 | if (files[i].getName().contains(WHOLESALE_CONV)) { 385 | files[i].delete(); 386 | } 387 | } 388 | } 389 | } 390 | 391 | protected void removeExpiredCache(String dirPath, String filename) { 392 | 393 | File file = new File(dirPath, filename); 394 | if (System.currentTimeMillis() - file.lastModified() > CACHE_EXPIRE_THRESHOLD) { 395 | LogUtils.i( "Clear some expired cache files "); 396 | file.delete(); 397 | } 398 | } 399 | 400 | class FileLastModifSort implements Comparator { 401 | @Override 402 | public int compare(File arg0, File arg1) { 403 | if (arg0.lastModified() > arg1.lastModified()) { 404 | return 1; 405 | } else if (arg0.lastModified() == arg1.lastModified()) { 406 | return 0; 407 | } else { 408 | return -1; 409 | } 410 | } 411 | } 412 | } 413 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/collection/DoubleKeyValueMap.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.collection; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.Set; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | public class DoubleKeyValueMap { 9 | 10 | private ConcurrentHashMap> k1_k2V_map; 11 | 12 | public DoubleKeyValueMap() { 13 | this.k1_k2V_map = new ConcurrentHashMap>(); 14 | } 15 | 16 | public void put(K1 key1, K2 key2, V value) { 17 | if (key1 == null || key2 == null || value == null) return; 18 | if (k1_k2V_map.containsKey(key1)) { 19 | ConcurrentHashMap k2V_map = k1_k2V_map.get(key1); 20 | if (k2V_map != null) { 21 | k2V_map.put(key2, value); 22 | } else { 23 | k2V_map = new ConcurrentHashMap(); 24 | k2V_map.put(key2, value); 25 | k1_k2V_map.put(key1, k2V_map); 26 | } 27 | } else { 28 | ConcurrentHashMap k2V_map = new ConcurrentHashMap(); 29 | k2V_map.put(key2, value); 30 | k1_k2V_map.put(key1, k2V_map); 31 | } 32 | } 33 | 34 | public Set getFirstKeys() { 35 | return k1_k2V_map.keySet(); 36 | } 37 | 38 | public ConcurrentHashMap get(K1 key1) { 39 | return k1_k2V_map.get(key1); 40 | } 41 | 42 | public V get(K1 key1, K2 key2) { 43 | ConcurrentHashMap k2_v = k1_k2V_map.get(key1); 44 | return k2_v == null ? null : k2_v.get(key2); 45 | } 46 | 47 | public Collection getAllValues(K1 key1) { 48 | ConcurrentHashMap k2_v = k1_k2V_map.get(key1); 49 | return k2_v == null ? null : k2_v.values(); 50 | } 51 | 52 | public Collection getAllValues() { 53 | Collection result = null; 54 | Set k1Set = k1_k2V_map.keySet(); 55 | if (k1Set != null) { 56 | result = new ArrayList(); 57 | for (K1 k1 : k1Set) { 58 | Collection values = k1_k2V_map.get(k1).values(); 59 | if (values != null) { 60 | result.addAll(values); 61 | } 62 | } 63 | } 64 | return result; 65 | } 66 | 67 | public boolean containsKey(K1 key1, K2 key2) { 68 | if (k1_k2V_map.containsKey(key1)) { 69 | return k1_k2V_map.get(key1).containsKey(key2); 70 | } 71 | return false; 72 | } 73 | 74 | public boolean containsKey(K1 key1) { 75 | return k1_k2V_map.containsKey(key1); 76 | } 77 | 78 | public int size() { 79 | if (k1_k2V_map.size() == 0) return 0; 80 | 81 | int result = 0; 82 | for (ConcurrentHashMap k2V_map : k1_k2V_map.values()) { 83 | result += k2V_map.size(); 84 | } 85 | return result; 86 | } 87 | 88 | public void remove(K1 key1) { 89 | k1_k2V_map.remove(key1); 90 | } 91 | 92 | public void remove(K1 key1, K2 key2) { 93 | ConcurrentHashMap k2_v = k1_k2V_map.get(key1); 94 | if (k2_v != null) { 95 | k2_v.remove(key2); 96 | } 97 | } 98 | 99 | public void clear() { 100 | if (k1_k2V_map.size() > 0) { 101 | for (ConcurrentHashMap k2V_map : k1_k2V_map.values()) { 102 | k2V_map.clear(); 103 | } 104 | k1_k2V_map.clear(); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/collection/KeyExpiryMap.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.collection; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | public class KeyExpiryMap extends ConcurrentHashMap { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | private static final int DEFAULT_CONCURRENCY_LEVEL = 16; 10 | 11 | public KeyExpiryMap(int initialCapacity, float loadFactor, 12 | int concurrencyLevel) { 13 | super(initialCapacity, loadFactor, concurrencyLevel); 14 | } 15 | 16 | public KeyExpiryMap(int initialCapacity, float loadFactor) { 17 | super(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL); 18 | } 19 | 20 | public KeyExpiryMap(int initialCapacity) { 21 | super(initialCapacity); 22 | } 23 | 24 | public KeyExpiryMap() { 25 | super(); 26 | } 27 | 28 | @Override 29 | public synchronized Long get(Object key) { 30 | if (this.containsKey(key)) { 31 | return super.get(key); 32 | } else { 33 | return null; 34 | } 35 | } 36 | 37 | @Override 38 | public synchronized Long put(K key, Long expiryTimestamp) { 39 | if (this.containsKey(key)) { 40 | this.remove(key); 41 | } 42 | return super.put(key, expiryTimestamp); 43 | } 44 | 45 | @Override 46 | public synchronized boolean containsKey(Object key) { 47 | boolean result = false; 48 | Long expiryTimestamp = super.get(key); 49 | if (expiryTimestamp != null 50 | && System.currentTimeMillis() < expiryTimestamp) { 51 | result = true; 52 | } else { 53 | this.remove(key); 54 | } 55 | return result; 56 | } 57 | 58 | @Override 59 | public synchronized Long remove(Object key) { 60 | return super.remove(key); 61 | } 62 | 63 | @Override 64 | public synchronized void clear() { 65 | super.clear(); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/collection/NoDuplicatesArrayList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Twidere - Twitter client for Android 3 | * 4 | * Copyright (C) 2012-2014 Mariotaku Lee 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | package com.ihgoo.allinone.collection; 21 | 22 | import java.util.ArrayList; 23 | import java.util.Collection; 24 | 25 | public class NoDuplicatesArrayList extends ArrayList { 26 | 27 | public NoDuplicatesArrayList() { 28 | } 29 | 30 | public NoDuplicatesArrayList(final Collection collection) { 31 | addAll(collection); 32 | } 33 | 34 | public NoDuplicatesArrayList(final int capacity) { 35 | super(capacity); 36 | } 37 | 38 | @Override 39 | public boolean add(final E e) { 40 | return !contains(e) && super.add(e); 41 | } 42 | 43 | @Override 44 | public void add(final int index, final E element) { 45 | if (!contains(element)) { 46 | super.add(index, element); 47 | } 48 | } 49 | 50 | @Override 51 | public boolean addAll(final Collection collection) { 52 | final Collection copy = new ArrayList(collection); 53 | copy.removeAll(this); 54 | return super.addAll(copy); 55 | } 56 | 57 | @Override 58 | public boolean addAll(final int index, final Collection collection) { 59 | final Collection copy = new ArrayList(collection); 60 | copy.removeAll(this); 61 | return super.addAll(index, copy); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/collection/NoDuplicatesLinkedList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Twidere - Twitter client for Android 3 | * 4 | * Copyright (C) 2012-2014 Mariotaku Lee 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | package com.ihgoo.allinone.collection; 21 | 22 | import java.util.Collection; 23 | import java.util.LinkedList; 24 | 25 | public class NoDuplicatesLinkedList extends LinkedList { 26 | 27 | public NoDuplicatesLinkedList() { 28 | super(); 29 | } 30 | 31 | public NoDuplicatesLinkedList(final Collection collection) { 32 | super(collection); 33 | } 34 | 35 | @Override 36 | public void add(final int index, final E element) { 37 | if (!contains(element)) { 38 | super.add(index, element); 39 | } 40 | } 41 | 42 | @Override 43 | public boolean add(final E e) { 44 | return !contains(e) && super.add(e); 45 | } 46 | 47 | @Override 48 | public boolean addAll(final int index, final Collection collection) { 49 | final Collection copy = new LinkedList(collection); 50 | copy.removeAll(this); 51 | return super.addAll(index, copy); 52 | } 53 | 54 | @Override 55 | public boolean addAll(final Collection collection) { 56 | final Collection copy = new LinkedList(collection); 57 | copy.removeAll(this); 58 | return super.addAll(copy); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/data/EncodeUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.data; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.SecureRandom; 6 | 7 | import javax.crypto.Cipher; 8 | import javax.crypto.SecretKey; 9 | import javax.crypto.SecretKeyFactory; 10 | import javax.crypto.spec.DESKeySpec; 11 | 12 | 13 | /** 14 | * Created by ihgoo on 2015/6/16. 15 | */ 16 | public class EncodeUtil { 17 | 18 | /** 19 | * @param str md5加密 20 | * @return 21 | */ 22 | public static String md5s(String str) { 23 | if (str == null || str.length() == 0) { 24 | throw new IllegalArgumentException("String to encript cannot be null or zero length"); 25 | } 26 | 27 | StringBuffer hexString = new StringBuffer(); 28 | 29 | try { 30 | MessageDigest md = MessageDigest.getInstance("MD5"); 31 | md.update(str.getBytes()); 32 | byte[] hash = md.digest(); 33 | int length = hash.length; 34 | for (int i = 0; i < length; i++) { 35 | if ((0xff & hash[i]) < 0x10) { 36 | hexString.append("0" + Integer.toHexString((0xFF & hash[i]))); 37 | } else { 38 | hexString.append(Integer.toHexString(0xFF & hash[i])); 39 | } 40 | } 41 | } catch (NoSuchAlgorithmException e) { 42 | e.printStackTrace(); 43 | } 44 | 45 | return hexString.toString(); 46 | } 47 | 48 | public static String encrypt(String private_key,String input) throws Exception { 49 | return base64Encode(desEncrypt(private_key,input.getBytes())); 50 | } 51 | 52 | private static String base64Encode(byte[] s) { 53 | if (s == null) 54 | return null; 55 | 56 | return Base64.encodeBytes(s); 57 | } 58 | 59 | 60 | private static byte[] desEncrypt(String private_key,byte[] plainText) throws Exception { 61 | SecureRandom sr = new SecureRandom(); 62 | byte rawKeyData[] = private_key.getBytes(); 63 | DESKeySpec dks = new DESKeySpec(rawKeyData); 64 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 65 | SecretKey key = keyFactory.generateSecret(dks); 66 | Cipher cipher = Cipher.getInstance("DES"); 67 | cipher.init(Cipher.ENCRYPT_MODE, key, sr); 68 | byte data[] = plainText; 69 | byte encryptedData[] = cipher.doFinal(data); 70 | return encryptedData; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/data/EncryptUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.data; 2 | 3 | import java.security.SecureRandom; 4 | 5 | import javax.crypto.Cipher; 6 | import javax.crypto.SecretKey; 7 | import javax.crypto.SecretKeyFactory; 8 | import javax.crypto.spec.DESKeySpec; 9 | 10 | /** 11 | * 加密工具类 12 | * @author Kelvin 13 | * 14 | */ 15 | public class EncryptUtil { 16 | 17 | /** 18 | * Des加密 19 | * @param private_key 私钥 20 | * @param plainText 明文密码 21 | * @return 22 | * @throws Exception 23 | */ 24 | private static byte[] desEncrypt(String private_key, byte[] plainText) throws Exception { 25 | SecureRandom sr = new SecureRandom(); 26 | byte rawKeyData[] = private_key.getBytes(); 27 | DESKeySpec dks = new DESKeySpec(rawKeyData); 28 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 29 | SecretKey key = keyFactory.generateSecret(dks); 30 | Cipher cipher = Cipher.getInstance("DES"); 31 | cipher.init(Cipher.ENCRYPT_MODE, key, sr); 32 | byte data[] = plainText; 33 | byte encryptedData[] = cipher.doFinal(data); 34 | return encryptedData; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/data/MD5.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.data; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.InputStream; 5 | import java.io.UnsupportedEncodingException; 6 | import java.security.MessageDigest; 7 | import java.security.NoSuchAlgorithmException; 8 | 9 | /** 10 | * 提取文件MD5值 11 | * @author music 12 | * 13 | */ 14 | public class MD5 { 15 | private static final char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 16 | 'A', 'B', 'C', 'D', 'E', 'F' }; 17 | 18 | 19 | public static String toHexString(byte[] b) { 20 | StringBuilder sb = new StringBuilder(b.length * 2); 21 | for (int i = 0; i < b.length; i++) { 22 | sb.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]); 23 | sb.append(HEX_DIGITS[b[i] & 0x0f]); 24 | } 25 | return sb.toString(); 26 | } 27 | 28 | //文件加密 29 | public static String md5sum(String filename) { 30 | InputStream fis; 31 | byte[] buffer = new byte[1024]; 32 | int numRead = 0; 33 | MessageDigest md5; 34 | try{ 35 | fis = new FileInputStream(filename); 36 | md5 = MessageDigest.getInstance("MD5"); 37 | while((numRead=fis.read(buffer)) > 0) { 38 | md5.update(buffer,0,numRead); 39 | } 40 | fis.close(); 41 | return toHexString(md5.digest()); 42 | } catch (Exception e) { 43 | System.out.println("error"); 44 | return null; 45 | } 46 | } 47 | 48 | 49 | //字符串加密 50 | public static String md5(String string) { 51 | byte[] hash; 52 | try { 53 | hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8")); 54 | } catch (NoSuchAlgorithmException e) { 55 | throw new RuntimeException("Huh, MD5 should be supported?", e); 56 | } catch (UnsupportedEncodingException e) { 57 | throw new RuntimeException("Huh, UTF-8 should be supported?", e); 58 | } 59 | 60 | StringBuilder hex = new StringBuilder(hash.length * 2); 61 | for (byte b : hash) { 62 | if ((b & 0xFF) < 0x10) hex.append("0"); 63 | hex.append(Integer.toHexString(b & 0xFF)); 64 | } 65 | return hex.toString(); 66 | } 67 | 68 | 69 | 70 | 71 | } -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/exception/BaseException.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.exception; 2 | 3 | public class BaseException extends Exception{ 4 | 5 | private static final long serialVersionUID = 1L; 6 | public BaseException() { 7 | } 8 | 9 | public BaseException(String detailMessage) { 10 | super(detailMessage); 11 | } 12 | 13 | public BaseException(String detailMessage, Throwable throwable) { 14 | super(detailMessage, throwable); 15 | } 16 | 17 | public BaseException(Throwable throwable) { 18 | super(throwable); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/exception/MathException.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.exception; 2 | 3 | public class MathException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | public MathException() { 7 | } 8 | 9 | public MathException(String detailMessage) { 10 | super(detailMessage); 11 | } 12 | 13 | public MathException(String detailMessage, Throwable throwable) { 14 | super(detailMessage, throwable); 15 | } 16 | 17 | public MathException(Throwable throwable) { 18 | super(throwable); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/image/BitmapFIFOCache.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.image; 2 | 3 | import java.util.HashMap; 4 | import java.util.Queue; 5 | 6 | import android.graphics.Bitmap; 7 | import android.graphics.Bitmap.Config; 8 | 9 | /** 10 | * 先进先出 置换算法 缓存 11 | * 12 | * @author Kelvin 13 | * 14 | */ 15 | public class BitmapFIFOCache { 16 | private Queue mCacheQueue; 17 | private HashMap mCache; 18 | 19 | /**总共缓存最大空间,单位kb**/ 20 | private int mCacheMaxSize; 21 | 22 | /**现在缓存中占用的大小,单位kb**/ 23 | private int mCurrtSize = 0; 24 | 25 | public BitmapFIFOCache(int cacheMaxSize) { 26 | if (0 <= cacheMaxSize) { 27 | throw new IllegalArgumentException( 28 | "CacheMaxSize must be greater than 0"); 29 | } 30 | mCacheMaxSize = cacheMaxSize; 31 | } 32 | 33 | public void putBitmap(String key, Bitmap bitmap) { 34 | putIntoCache(key, bitmap); 35 | } 36 | 37 | private void putIntoCache(String key, Bitmap bitmap) { 38 | if (mCache.containsKey(key)) { 39 | return; 40 | } 41 | 42 | if (mCacheQueue.contains(key)) { 43 | mCacheQueue.remove(key); 44 | mCache.remove(key); 45 | mCacheQueue.offer(key); 46 | mCache.put(key, new Ref(bitmap, this.sizeOf(bitmap))); 47 | } else { 48 | putIntoQueue(key, bitmap); 49 | } 50 | } 51 | 52 | private void putIntoQueue(String key,Bitmap bitmap){ 53 | if (this.hasFree(bitmap)) { // 有空闲空间 54 | mCurrtSize = mCurrtSize + this.sizeOf(bitmap); // 统计缓存大小 55 | mCacheQueue.offer(key); // 从头插入 56 | mCache.put(key, new Ref(bitmap, this.sizeOf(bitmap))); 57 | }else { 58 | String pollKey = mCacheQueue.poll(); // poll队列最后一个值 59 | mCurrtSize = mCurrtSize - mCache.get(pollKey).mSize; // 计算目前缓存大小 60 | mCache.remove(pollKey); //移除掉最后一个 61 | this.putIntoCache(key, bitmap); // 递归插入 62 | } 63 | } 64 | 65 | private boolean hasFree(Bitmap bitmap){ 66 | int bitmapSize = this.sizeOf(bitmap); 67 | if (mCacheMaxSize <= bitmapSize + mCurrtSize) { 68 | return false; 69 | } 70 | return true; 71 | } 72 | 73 | /** 74 | * Cal the bitmap size; 75 | * 76 | * @param bitmap 77 | * @return size of kb. 78 | */ 79 | private int sizeOf(Bitmap bitmap) { 80 | Config config = bitmap.getConfig(); 81 | int size = 0; 82 | if (config == Bitmap.Config.ALPHA_8) { 83 | size = 1; 84 | } else if (config == Bitmap.Config.ARGB_4444) { 85 | size = 2; 86 | } else if (config == Bitmap.Config.ARGB_8888) { 87 | size = 4; 88 | } else if (config == Bitmap.Config.RGB_565) { 89 | size = 2; 90 | } 91 | return bitmap.getWidth() * bitmap.getHeight() * size / 1024; 92 | } 93 | 94 | public Bitmap getBitmap(String key) { 95 | 96 | if (mCache.get(key) == null) { 97 | return null; 98 | }else { 99 | return mCache.get(key).mBitmap; 100 | } 101 | 102 | } 103 | 104 | class Ref { 105 | private Bitmap mBitmap; 106 | private int mSize; 107 | 108 | public Ref(Bitmap bitmap, int size) { 109 | mBitmap = bitmap; 110 | mSize = size; 111 | } 112 | } 113 | 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/image/BitmapUtils.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.image; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.FileInputStream; 6 | import java.io.FileNotFoundException; 7 | import java.io.InputStream; 8 | 9 | import com.ihgoo.allinone.cache.ImageSDCacher; 10 | import com.ihgoo.allinone.support.LogUtils; 11 | import com.ihgoo.allinone.support.ScreenUtil; 12 | import com.ihgoo.allinone.support.ScreenUtil.Screen; 13 | 14 | import android.R.integer; 15 | import android.content.res.Resources; 16 | import android.graphics.Bitmap; 17 | import android.graphics.BitmapFactory; 18 | import android.graphics.drawable.BitmapDrawable; 19 | import android.graphics.drawable.Drawable; 20 | import android.util.Log; 21 | import android.view.View; 22 | import android.widget.ImageView; 23 | 24 | /** 25 | * 对Bitmap二次处理,避免OOM异常出现, 26 | * 27 | * getBitmap()、decodeSampledBitmapFromResource() 28 | * 29 | * @author Kelvin 30 | * 31 | */ 32 | public class BitmapUtils { 33 | 34 | private static final int TEMP_STORAGE_SIZE = 1024 * 100; 35 | 36 | /** 37 | * Return bitmap through by imagePath. 38 | * 39 | * @param imagePath 40 | * @param width 41 | * @param height 42 | * @return bitmap 43 | */ 44 | public static Bitmap getBitmap(String imagePath, int width, int height) { 45 | if (imagePath == null || "".equals(imagePath)) { 46 | return null; 47 | } 48 | BitmapFactory.Options options = new BitmapFactory.Options(); 49 | options.inTempStorage = new byte[TEMP_STORAGE_SIZE]; 50 | options.inPreferredConfig = Bitmap.Config.RGB_565; 51 | options.inPurgeable = true; 52 | options.inInputShareable = true; 53 | options.inSampleSize = calculateInSampleSize(options, width, height); 54 | options.inJustDecodeBounds = false; 55 | return BitmapFactory.decodeFile(imagePath, options); 56 | } 57 | 58 | /** 59 | * Return bitmap through by resources. 60 | * 61 | * @param res 62 | * @param is 63 | * @param width 64 | * @param height 65 | * @return bitmap 66 | */ 67 | public static Bitmap getBitmap(InputStream is, int width, int height) { 68 | BitmapFactory.Options options = new BitmapFactory.Options(); 69 | options.inTempStorage = new byte[TEMP_STORAGE_SIZE]; 70 | options.inPreferredConfig = Bitmap.Config.RGB_565; 71 | options.inPurgeable = true; 72 | options.inInputShareable = true; 73 | options.inSampleSize = calculateInSampleSize(options, width, height); 74 | options.inJustDecodeBounds = false; 75 | return BitmapFactory.decodeStream(is, null, options); 76 | } 77 | 78 | /** 79 | * 根据View得到自适应的bitmap对象 80 | * 81 | * @param imagePath 82 | * @param view 83 | * @return bitmap 84 | */ 85 | public static Bitmap getBitmapByViewSize(String imagePath, View view) { 86 | if (imagePath == null || "".equals(imagePath)) { 87 | return null; 88 | } 89 | 90 | if (view == null) { 91 | return null; 92 | } 93 | 94 | return getBitmap(imagePath, view.getWidth(), view.getHeight()); 95 | } 96 | 97 | /** 98 | * 根据View得到自适应的bitmap对象 99 | * 100 | * @param imagePath 101 | * @param view 102 | * @return bitmap 103 | */ 104 | public static Bitmap getBitmapByViewSize(InputStream is, View view) { 105 | if (view == null) { 106 | return null; 107 | } 108 | 109 | return getBitmap(is, view.getWidth(), view.getHeight()); 110 | } 111 | 112 | /** 113 | * bitmap转drawable 114 | * 115 | * @param bitmap 116 | * @return drawable 117 | */ 118 | public static Drawable convertBitmap2Drawable(Resources res, Bitmap bitmap) { 119 | BitmapDrawable bd = new BitmapDrawable(res, bitmap); 120 | return bd; 121 | } 122 | 123 | /** 124 | * 通过简单处理后获取res中的bitmap对象 125 | * 126 | * @param paramResources 127 | * @param res 128 | * @param width 129 | * 长度 130 | * @param height 131 | * 高度 132 | * @return bitmap 对象 133 | */ 134 | public static Bitmap decodeSampledBitmapFromResource( 135 | Resources paramResources, int res, int width, int height) { 136 | InputStream localInputStream = paramResources.openRawResource(res); 137 | BitmapFactory.Options localOptions = new BitmapFactory.Options(); 138 | localOptions.inTempStorage = new byte[TEMP_STORAGE_SIZE]; 139 | localOptions.inPreferredConfig = Bitmap.Config.RGB_565; 140 | localOptions.inPurgeable = true; 141 | localOptions.inInputShareable = true; 142 | localOptions.inSampleSize = calculateInSampleSize(localOptions, width, 143 | height); 144 | localOptions.inJustDecodeBounds = false; 145 | return BitmapFactory.decodeStream(localInputStream, null, localOptions); 146 | } 147 | 148 | /** 149 | * 根据屏幕计算缩放比率 150 | * 151 | * @param paramOptions 152 | * @param width 153 | * 长度 154 | * @param height 155 | * 高度 156 | * @return 缩放比率 157 | */ 158 | public static int calculateInSampleSize(BitmapFactory.Options paramOptions, 159 | int width, int height) { 160 | int i = paramOptions.outHeight; 161 | int j = paramOptions.outWidth; 162 | int k = 1; 163 | if ((i > width) || (j > width)) { 164 | int m = Math.round(i / height); 165 | int n = Math.round(j / width); 166 | if (m < n) 167 | ; 168 | for (k = m;; k = n) { 169 | float f1 = j * i; 170 | float f2 = 2 * (width * height); 171 | while (f1 / (k * k) > f2) 172 | k++; 173 | } 174 | } 175 | return k; 176 | } 177 | 178 | /** 179 | * 手动回收imageView图片资源 180 | * 181 | * @param imageView 182 | */ 183 | public static void releaseImageViewResouce(ImageView imageView) { 184 | if (imageView == null) 185 | return; 186 | Drawable drawable = imageView.getDrawable(); 187 | if (drawable != null && drawable instanceof BitmapDrawable) { 188 | BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; 189 | Bitmap bitmap = bitmapDrawable.getBitmap(); 190 | if (bitmap != null && !bitmap.isRecycled()) { 191 | bitmap.recycle(); 192 | } 193 | } 194 | } 195 | 196 | 197 | /** 198 | * 根据图像URL创建Bitmap 199 | * 200 | * @param url 201 | * URL地址 202 | * @return bitmap 203 | */ 204 | public Bitmap CreateImage(String url) { 205 | // Logger.d("ImageDownloader", 206 | // "开始调用CreateImage():" + System.currentTimeMillis()); 207 | Bitmap bitmap = null; 208 | if (url == null || url.equals("")) { 209 | return null; 210 | } 211 | try { 212 | // Logger.d( 213 | // "ImageDownloader", 214 | // "C Before SDCard decodeStream==>" + "Heap:" 215 | // + (Debug.getNativeHeapSize() / 1024) + "KB " 216 | // + "FreeHeap:" 217 | // + (Debug.getNativeHeapFreeSize() / 1024) + "KB " 218 | // + "AllocatedHeap:" 219 | // + (Debug.getNativeHeapAllocatedSize() / 1024) 220 | // + "KB" + " url:" + url); 221 | 222 | FileInputStream fis = new FileInputStream(url); 223 | BitmapFactory.Options opts = new BitmapFactory.Options(); 224 | opts.inPreferredConfig = Bitmap.Config.ARGB_4444; 225 | opts.inTempStorage = new byte[100 * 1024]; 226 | opts.inPurgeable = true; 227 | opts.inInputShareable = true; 228 | bitmap = BitmapFactory.decodeStream(fis, null, opts); 229 | 230 | // Logger.d( 231 | // "ImageDownloader", 232 | // "C After SDCard decodeStream==>" + "Heap:" 233 | // + (Debug.getNativeHeapSize() / 1024) + "KB " 234 | // + "FreeHeap:" 235 | // + (Debug.getNativeHeapFreeSize() / 1024) + "KB " 236 | // + "AllocatedHeap:" 237 | // + (Debug.getNativeHeapAllocatedSize() / 1024) 238 | // + "KB" + " url:" + url); 239 | } catch (OutOfMemoryError e) { 240 | LogUtils.e("OutOfMemoryError", e); 241 | System.gc(); 242 | } catch (FileNotFoundException e) { 243 | LogUtils.e("FileNotFoundException", e); 244 | } 245 | // Logger.d("ImageDownloader", 246 | // "结束调用CreateImage():" + System.currentTimeMillis()); 247 | return bitmap; 248 | } 249 | 250 | /** 251 | * 图片缩放处理,并保存到SDCard 252 | * 253 | * @param byteArrayOutputStream 254 | * 图片字节流 255 | * @param screen 256 | * 屏幕宽高 257 | * @param url 258 | * 图片网络路径 259 | * @param cachePath 260 | * 本地缓存父路径
PathCommonDefines.PHOTOCACHE_FOLDER 程序缓存图片路径;
261 | * PathCommonDefines.MY_FAVOURITE_FOLDER 我的收藏图片路径 262 | * @param isJpg 263 | * 是否是Jpg 264 | * @return 缩放后的图片bitmap 265 | */ 266 | public static Bitmap saveZoomBitmapToSDCard( 267 | ByteArrayOutputStream byteArrayOutputStream, Screen screen, 268 | String url, String cachePath, boolean isJpg) { 269 | 270 | Bitmap bitmap = null; 271 | try { 272 | 273 | byte[] byteArray = byteArrayOutputStream.toByteArray(); 274 | 275 | BitmapFactory.Options options = new BitmapFactory.Options(); 276 | 277 | options.inTempStorage = new byte[16 * 1024]; 278 | 279 | // 只加载图片的边界 280 | options.inJustDecodeBounds = true; 281 | 282 | // 获取Bitmap信息 283 | BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, 284 | options); 285 | 286 | // 获取屏幕的宽和高 287 | int screenWidth = screen.widthPixels; 288 | int screenHeight = screen.heightPixels; 289 | 290 | // 屏幕最大像素个数 291 | int maxNumOfPixels = screenWidth * screenHeight; 292 | 293 | // 计算采样率 294 | int sampleSize = computeSampleSize(options, -1, maxNumOfPixels); 295 | 296 | options.inSampleSize = sampleSize; 297 | 298 | options.inJustDecodeBounds = false; 299 | 300 | // 重新读入图片,此时为缩放后的图片 301 | bitmap = BitmapFactory.decodeByteArray(byteArray, 0, 302 | byteArray.length, options); 303 | 304 | // 压缩比例 305 | int quality = 100; 306 | 307 | // 判断是否是Jpg,png是无损压缩,所以不用进行质量压缩 308 | if (bitmap != null && isJpg) { 309 | 310 | ByteArrayOutputStream saveBaos = new ByteArrayOutputStream(); 311 | 312 | bitmap.compress(Bitmap.CompressFormat.JPEG, quality, saveBaos); 313 | 314 | // 循环判断如果压缩后图片是否大于100kb,大于继续压缩 315 | while (saveBaos.toByteArray().length / 1024 > 100) { 316 | 317 | // 重置saveBaos即清空saveBaos 318 | saveBaos.reset(); 319 | 320 | // 每次都减少10 321 | quality -= 10; 322 | 323 | // 这里压缩optionsNum%,把压缩后的数据存放到saveBaos中 324 | bitmap.compress(Bitmap.CompressFormat.JPEG, quality, 325 | saveBaos); 326 | 327 | } 328 | // 把压缩后的数据ByteArrayOutputStream存放到ByteArrayInputStream中 329 | ByteArrayInputStream saveBais = new ByteArrayInputStream( 330 | saveBaos.toByteArray()); 331 | 332 | bitmap = BitmapFactory.decodeStream(saveBais, null, null); 333 | 334 | } 335 | 336 | // 保存到SDCard 337 | ImageSDCacher.getImageSDCacher().saveBitmapToSDCard(bitmap, url, 338 | cachePath, isJpg, quality); 339 | 340 | } catch (Exception e) { 341 | Log.e("saveZoomBitmapToSDCard", "" + e); 342 | } 343 | 344 | return bitmap; 345 | } 346 | 347 | /** 348 | * 图片缩放处理,并保存到SDCard 349 | * 350 | * @param screen 351 | * 屏幕宽高 352 | * @param bitmap 353 | * 图片bitmap 354 | * @param cachePath 355 | * 本地缓存父路径
PathCommonDefines.PHOTOCACHE_FOLDER 程序缓存图片路径;
356 | * PathCommonDefines.MY_FAVOURITE_FOLDER 我的收藏图片路径 357 | * @param isJpg 358 | * 是否是Jpg 359 | * @return 缩放后的图片bitmap 360 | */ 361 | public static Bitmap saveZoomBitmapToSDCard(Bitmap bitmap, Screen screen, 362 | String url, String cachePath, boolean isJpg) { 363 | Bitmap tempBitmap = null; 364 | byte[] byteArray = bitmap2Bytes(bitmap); 365 | try { 366 | 367 | BitmapFactory.Options options = new BitmapFactory.Options(); 368 | 369 | // 获取屏幕的宽和高 370 | int screenWidth = screen.widthPixels; 371 | int screenHeight = screen.heightPixels; 372 | 373 | // 屏幕最大像素个数 374 | int maxNumOfPixels = screenWidth * screenHeight; 375 | 376 | // 计算采样率 377 | int sampleSize = computeSampleSize(options, -1, maxNumOfPixels); 378 | 379 | options.inSampleSize = sampleSize; 380 | 381 | options.inJustDecodeBounds = false; 382 | 383 | // 重新读入图片,此时为缩放后的图片 384 | tempBitmap = BitmapFactory.decodeByteArray(byteArray, 0, 385 | byteArray.length, options); 386 | 387 | // 压缩比例 388 | int quality = 100; 389 | 390 | // 判断是否是Jpg,png是无损压缩,所以不用进行质量压缩 391 | if (bitmap != null && isJpg) { 392 | 393 | ByteArrayOutputStream saveBaos = new ByteArrayOutputStream(); 394 | 395 | tempBitmap.compress(Bitmap.CompressFormat.JPEG, quality, 396 | saveBaos); 397 | 398 | // 循环判断如果压缩后图片是否大于100kb,大于继续压缩 399 | while (saveBaos.toByteArray().length / 1024 > 100) { 400 | 401 | // 重置saveBaos即清空saveBaos 402 | saveBaos.reset(); 403 | 404 | // 每次都减少10 405 | quality -= 10; 406 | 407 | // 这里压缩optionsNum%,把压缩后的数据存放到saveBaos中 408 | tempBitmap.compress(Bitmap.CompressFormat.JPEG, quality, 409 | saveBaos); 410 | 411 | } 412 | // 把压缩后的数据ByteArrayOutputStream存放到ByteArrayInputStream中 413 | ByteArrayInputStream saveBais = new ByteArrayInputStream( 414 | saveBaos.toByteArray()); 415 | 416 | tempBitmap = BitmapFactory.decodeStream(saveBais, null, null); 417 | 418 | } 419 | 420 | // 保存到SDCard 421 | ImageSDCacher.getImageSDCacher().saveBitmapToSDCard(tempBitmap, 422 | url, cachePath, isJpg, quality); 423 | 424 | } catch (Exception e) { 425 | Log.e("", e.getMessage()); 426 | } 427 | 428 | return tempBitmap; 429 | } 430 | 431 | public static byte[] bitmap2Bytes(Bitmap bitmap) { 432 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 433 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); 434 | return baos.toByteArray(); 435 | } 436 | 437 | // Recycle the resource of the Image 438 | public void recycleImage(Bitmap bitmap) { 439 | try { 440 | if (bitmap != null && !bitmap.isMutable() && !bitmap.isRecycled()) { 441 | bitmap.recycle(); 442 | System.gc(); 443 | } 444 | } catch (Exception e) { 445 | e.printStackTrace(); 446 | LogUtils.e("bitmap recycle excpetion", e); 447 | } 448 | } 449 | 450 | /** 451 | * 替换特殊字符 452 | * 453 | * @param fileName 454 | * 图片的处理前的名字 455 | * @return 图片处理后的名字 456 | */ 457 | public static String renameUploadFile(String fileName) { 458 | String result = "yepcolor"; 459 | if (fileName != null && !"".equals(fileName)) { 460 | result = fileName.hashCode() + "";// 获得文件名称的hashcode值 461 | } 462 | return result; 463 | // 只允许字母和数字 464 | // String regEx = "[^a-zA-Z0-9]"; 465 | // 清除掉所有特殊字符 466 | // String regEx = 467 | // "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]"; 468 | // Pattern p = Pattern.compile(regEx); 469 | // Matcher m = p.matcher(fileName); 470 | // result = m.replaceAll("").trim(); 471 | } 472 | 473 | /** 474 | * 计算采样率 475 | * 476 | * @param options 477 | * @param minSideLength 478 | * @param maxNumOfPixels 479 | * @return 480 | */ 481 | public static int computeSampleSize(BitmapFactory.Options options, 482 | int minSideLength, int maxNumOfPixels) { 483 | 484 | int initialSize = computeInitialSampleSize(options, minSideLength, 485 | 486 | maxNumOfPixels); 487 | 488 | int roundedSize; 489 | 490 | if (initialSize <= 8) { 491 | 492 | roundedSize = 1; 493 | 494 | while (roundedSize < initialSize) { 495 | 496 | roundedSize <<= 1; 497 | 498 | } 499 | 500 | } else { 501 | 502 | roundedSize = (initialSize + 7) / 8 * 8; 503 | 504 | } 505 | 506 | return roundedSize; 507 | 508 | } 509 | 510 | /** 511 | * 计算初始采样率 512 | * 513 | * @param options 514 | * @param minSideLength 515 | * @param maxNumOfPixels 516 | * @return 517 | */ 518 | private static int computeInitialSampleSize(BitmapFactory.Options options, 519 | int minSideLength, int maxNumOfPixels) { 520 | 521 | double w = options.outWidth; 522 | 523 | double h = options.outHeight; 524 | 525 | int lowerBound = (maxNumOfPixels == -1) ? 1 : 526 | 527 | (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); 528 | 529 | int upperBound = (minSideLength == -1) ? 128 : 530 | 531 | (int) Math.min(Math.floor(w / minSideLength), 532 | 533 | Math.floor(h / minSideLength)); 534 | 535 | if (upperBound < lowerBound) { 536 | 537 | // return the larger one when there is no overlapping zone. 538 | 539 | return lowerBound; 540 | 541 | } 542 | 543 | if ((maxNumOfPixels == -1) && 544 | 545 | (minSideLength == -1)) { 546 | 547 | return 1; 548 | 549 | } else if (minSideLength == -1) { 550 | 551 | return lowerBound; 552 | 553 | } else { 554 | 555 | return upperBound; 556 | 557 | } 558 | 559 | } 560 | /** 561 | * 根据图片的路径获取图片的大小 562 | * 563 | * @param item 564 | */ 565 | // public static void getBitmapSize(Items item) { 566 | // URL url; 567 | // try { 568 | // url = new URL(item.getPicUrl()); 569 | // URLConnection conn = url.openConnection(); 570 | // conn.connect(); 571 | // InputStream is = conn.getInputStream(); 572 | // BitmapFactory.Options options = new BitmapFactory.Options(); 573 | // BitmapFactory.decodeStream(is, null, options); 574 | // options.inJustDecodeBounds = true; 575 | // int height = options.outHeight; 576 | // int width = options.outWidth; 577 | // item.setImageWidth(width); 578 | // item.setImageHeight(height); 579 | // } catch (MalformedURLException e) { 580 | // e.printStackTrace(); 581 | // } catch (IOException e) { 582 | // e.printStackTrace(); 583 | // } 584 | // 585 | // } 586 | } -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/image/GuideImage.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.image; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 5 | import android.util.DisplayMetrics; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.ViewParent; 9 | import android.widget.FrameLayout; 10 | import android.widget.ImageView; 11 | import android.widget.ImageView.ScaleType; 12 | import android.widget.RelativeLayout; 13 | 14 | import com.ihgoo.allinone.support.SharePreferenceUtil; 15 | 16 | /** 17 | * 引导图层 18 | * 19 | * @author Kelvin 20 | * 21 | */ 22 | public class GuideImage { 23 | 24 | private int mTemp; 25 | 26 | private GuideImage() { 27 | } 28 | 29 | public static GuideImage getInstance() { 30 | return GuidImageHolder.INSTANCE; 31 | } 32 | 33 | private static class GuidImageHolder { 34 | public static final GuideImage INSTANCE = new GuideImage(); 35 | } 36 | 37 | private OnGuidImageClickListener mOnClickListener; 38 | 39 | /** 40 | * 回调点击,点击覆盖的图层之后要做的事情 41 | */ 42 | public interface OnGuidImageClickListener { 43 | void onClick(); 44 | } 45 | 46 | public void setOnClickListener(OnGuidImageClickListener onClickListener) { 47 | this.mOnClickListener = onClickListener; 48 | } 49 | 50 | /** 51 | * 在acitivity依次覆盖图层显示 52 | * 53 | * @param act 54 | * @param viewId 55 | * @param imageIds 56 | * @param preferenceName 57 | */ 58 | public void setGuidImages(final Activity act, final int viewId, final int[] imageIds, final String preferenceName) { 59 | if (preferenceName != null) { 60 | if (SharePreferenceUtil.getBoolean(act, preferenceName)) { 61 | return; 62 | } 63 | } 64 | 65 | int imageNumber = imageIds.length; 66 | if (imageNumber == 0) { 67 | throw new IllegalArgumentException("Image RESIds may be null,Please check it"); 68 | } 69 | mTemp++; 70 | if (imageIds.length < mTemp) { 71 | mTemp = 0; 72 | 73 | SharePreferenceUtil.setValue(act, preferenceName, true); 74 | return; 75 | } 76 | 77 | View view = act.getWindow().getDecorView().findViewById(viewId); 78 | ViewParent viewParent = view.getParent(); 79 | if (viewParent instanceof FrameLayout) { 80 | final FrameLayout frameLayout = (FrameLayout) viewParent; 81 | final ImageView guideImage = new ImageView(act.getApplication()); 82 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 83 | guideImage.setLayoutParams(params); 84 | guideImage.setScaleType(ScaleType.FIT_XY); 85 | 86 | DisplayMetrics localDisplayMetrics = new DisplayMetrics(); 87 | act.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics); 88 | int x = localDisplayMetrics.heightPixels; 89 | int y = localDisplayMetrics.widthPixels; 90 | 91 | final Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromResource(act.getResources(), imageIds[mTemp - 1], x, y); 92 | guideImage.setImageBitmap(bitmap); 93 | guideImage.setOnClickListener(new View.OnClickListener() { 94 | 95 | @Override 96 | public void onClick(View v) { 97 | BitmapUtils.releaseImageViewResouce(guideImage); 98 | frameLayout.removeView(guideImage); 99 | bitmap.recycle(); 100 | if (mOnClickListener != null) { 101 | mOnClickListener.onClick(); 102 | } 103 | setGuidImages(act, viewId, imageIds, preferenceName); 104 | } 105 | 106 | }); 107 | frameLayout.addView(guideImage); 108 | } 109 | 110 | } 111 | 112 | /** 113 | * 在activity覆盖一层引导图层,无论何时都会显示 114 | * 115 | * @param act 116 | * @param viewId 117 | * @param imageId 118 | */ 119 | public void setGuidImage(Activity act, int viewId, int imageId) { 120 | setGuidImage(act, viewId, imageId, null); 121 | } 122 | 123 | /** 124 | * 在activity覆盖一层引导图层,初次进入activity时候显示 125 | * 126 | * @param act 127 | * @param viewId 128 | * @param imageId 129 | * @param preferenceName 130 | */ 131 | public void setGuidImage(Activity act, int viewId, int imageId, String preferenceName) { 132 | if (preferenceName != null) { 133 | if (SharePreferenceUtil.getBoolean(act, preferenceName)) { 134 | return; 135 | } 136 | SharePreferenceUtil.setValue(act, preferenceName, true); 137 | } 138 | 139 | View view = act.getWindow().getDecorView().findViewById(viewId); // 将要添加引导图片 140 | ViewParent viewParent = view.getParent(); 141 | if (viewParent instanceof FrameLayout) { 142 | final FrameLayout frameLayout = (FrameLayout) viewParent; 143 | final ImageView guideImage = new ImageView(act.getApplication()); 144 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 145 | guideImage.setLayoutParams(params); 146 | guideImage.setScaleType(ScaleType.FIT_XY); 147 | 148 | DisplayMetrics localDisplayMetrics = new DisplayMetrics(); 149 | act.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics); 150 | int x = localDisplayMetrics.heightPixels; 151 | int y = localDisplayMetrics.widthPixels; 152 | 153 | final Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromResource(act.getResources(), imageId, x, y); 154 | 155 | guideImage.setImageBitmap(bitmap); 156 | guideImage.setOnClickListener(new View.OnClickListener() { 157 | 158 | @Override 159 | public void onClick(View v) { 160 | frameLayout.removeView(guideImage); 161 | BitmapUtils.releaseImageViewResouce(guideImage); 162 | if (mOnClickListener != null) { // 点击图层后将要做什么 163 | mOnClickListener.onClick(); 164 | mOnClickListener = null; 165 | } 166 | } 167 | 168 | }); 169 | frameLayout.addView(guideImage); 170 | } 171 | 172 | } 173 | 174 | /** 175 | * 在activity覆盖一层引导图层,无论何时都会显示 176 | * 177 | * @param act 178 | * @param view 179 | * @param imageId 180 | */ 181 | public void setGuidImage(Activity act, View view, int imageId) { 182 | setGuidImage(act, view, imageId, null); 183 | } 184 | 185 | /** 186 | * 在activity覆盖一层引导图层,初次进入activity时候显示 187 | * 188 | * @param act 189 | * @param view 190 | * @param imageId 191 | * @param preferenceName 192 | */ 193 | public void setGuidImage(Activity act, View view, int imageId, String preferenceName) { 194 | if (preferenceName != null) { 195 | if (SharePreferenceUtil.getBoolean(act, preferenceName)) { 196 | return; 197 | } 198 | SharePreferenceUtil.setValue(act, preferenceName, true); 199 | } 200 | 201 | ViewParent viewParent = view.getParent(); 202 | if (viewParent instanceof RelativeLayout) { 203 | final RelativeLayout frameLayout = (RelativeLayout) viewParent; 204 | final ImageView guideImage = new ImageView(act.getApplication()); 205 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 206 | guideImage.setLayoutParams(params); 207 | guideImage.setScaleType(ScaleType.FIT_XY); 208 | 209 | DisplayMetrics localDisplayMetrics = new DisplayMetrics(); 210 | act.getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics); 211 | int x = localDisplayMetrics.heightPixels; 212 | int y = localDisplayMetrics.widthPixels; 213 | 214 | final Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromResource(act.getResources(), imageId, x, y); 215 | guideImage.setImageBitmap(bitmap); 216 | guideImage.setOnClickListener(new View.OnClickListener() { 217 | 218 | @Override 219 | public void onClick(View v) { 220 | frameLayout.removeView(guideImage); 221 | BitmapUtils.releaseImageViewResouce(guideImage); 222 | if (mOnClickListener != null) { // 点击图层后将要做什么 223 | mOnClickListener.onClick(); 224 | mOnClickListener = null; 225 | } 226 | } 227 | 228 | }); 229 | frameLayout.addView(guideImage); 230 | } else { 231 | } 232 | } 233 | } -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/image/ImageUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.image; 2 | 3 | import java.io.BufferedOutputStream; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.OutputStream; 8 | 9 | import com.ihgoo.allinone.support.Check; 10 | import com.ihgoo.allinone.support.Persistence; 11 | import com.ihgoo.allinone.support.ResourceUtil; 12 | import com.ihgoo.allinone.support.ScreenUtil; 13 | 14 | import android.content.Context; 15 | import android.graphics.Bitmap; 16 | import android.graphics.BitmapFactory; 17 | import android.graphics.Canvas; 18 | import android.graphics.Color; 19 | import android.graphics.Matrix; 20 | import android.graphics.Paint; 21 | import android.graphics.drawable.BitmapDrawable; 22 | import android.graphics.drawable.Drawable; 23 | import android.text.TextPaint; 24 | import android.view.View; 25 | import android.widget.ImageView; 26 | 27 | /** 28 | * Created by ihgoo on 2015/6/16. 29 | */ 30 | public class ImageUtil { 31 | /** 32 | * @param v 33 | * @param width 34 | * @param height 35 | * @return 获取view固定宽高的图像 36 | */ 37 | public static Bitmap getViewCache(View v, int width, int height) { 38 | Bitmap b = null; 39 | if (v != null) { 40 | try { 41 | v.setDrawingCacheEnabled(true); 42 | v.measure(width == 0 ? View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) : width, height == 0 ? View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) : height); 43 | v.layout(0, 0, width == 0 ? v.getMeasuredWidth() : width, height == 0 ? v.getMeasuredHeight() : height); 44 | v.buildDrawingCache(true); 45 | if (v.getDrawingCache() != null) { 46 | b = Bitmap.createBitmap(v.getDrawingCache()); 47 | } 48 | v.setDrawingCacheEnabled(false); // clear drawing cache 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | } 53 | return b; 54 | } 55 | 56 | public static String getDarenShareImagePath(Context context,View view, String type) { 57 | String darenShareImagePath = ""; 58 | Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight() + 50, Bitmap.Config.ARGB_8888); 59 | Canvas canvas = new Canvas(bitmap); 60 | // 绘制背景 61 | canvas.drawColor(Color.WHITE); 62 | // 绘制元素 63 | view.draw(canvas); 64 | // 绘制logo 65 | drawLogo(context,canvas, type); 66 | // 保存文件,并返回文件路径 67 | darenShareImagePath = saveImageToCache(bitmap); 68 | return darenShareImagePath; 69 | } 70 | 71 | /** 72 | * 在左下角绘制logo 73 | * 74 | * @param canvas 75 | */ 76 | public static void drawLogo(Context context,Canvas canvas, String type) { 77 | float heightParent = canvas.getHeight(); 78 | 79 | float heightWrap = ScreenUtil.dip2px(context,40); 80 | float heightLogo = ScreenUtil.dip2px(context,20); 81 | float heightText = ScreenUtil.dip2px(context,12); 82 | float leftMargin = ScreenUtil.dip2px(context,10); 83 | 84 | canvas.save(); 85 | canvas.translate(leftMargin, 0); 86 | // 绘制logo 87 | Bitmap logoBitmap = BitmapFactory.decodeResource(context.getResources(), android.R.layout.select_dialog_item); 88 | Matrix logoMatrix = new Matrix(); 89 | Paint logoPaint = new Paint(); 90 | logoPaint.setAntiAlias(true); 91 | float scale = heightLogo / (float) logoBitmap.getHeight(); 92 | logoMatrix.postScale(scale, scale, 0, 0); 93 | logoMatrix.postTranslate(0, heightParent - heightWrap + (heightWrap - heightLogo) / 2); 94 | 95 | canvas.drawBitmap(logoBitmap, logoMatrix, logoPaint); 96 | 97 | // 绘制文字 98 | TextPaint textPaint = new TextPaint(); 99 | textPaint.setAntiAlias(true); 100 | textPaint.setTextSize(heightText); 101 | String text = " " + type + " by 微兼职"; 102 | 103 | // 垂直居中高度修正 104 | // float fix = Ihgoo.dip2px(2); 105 | /* 106 | * canvas.drawText(text, heightLogo, heightParent - heightWrap + 107 | * heightText - fix + (heightWrap - heightText) / 2, textPaint); 108 | */ 109 | 110 | canvas.drawText(text, heightLogo, heightParent - heightText, textPaint); 111 | 112 | canvas.restore(); 113 | } 114 | 115 | /** 116 | * 临时保存图片 117 | * 118 | * @param bitmap 119 | * @return 图片路径 120 | */ 121 | public static String saveImageToCache(Bitmap bitmap) { 122 | String result = null; 123 | try { 124 | if (Check.checkSDCard()) { 125 | String cacheDir = Persistence.getCacheDir(); 126 | if (cacheDir != null) { 127 | File cacheFile = new File(Persistence.getCacheDir(), "com.guangzhi.weijianzhi.imageShare.png"); 128 | cacheFile.deleteOnExit(); 129 | OutputStream out = new BufferedOutputStream(new FileOutputStream(cacheFile)); 130 | bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); 131 | result = cacheFile.getPath(); 132 | // 文件关闭 133 | out.flush(); 134 | out.close(); 135 | } 136 | } 137 | } catch (Exception e) { 138 | e.printStackTrace(); 139 | } 140 | return result; 141 | } 142 | 143 | public static Drawable getDrawable(Context context,int id) { 144 | return ResourceUtil.getResources(context).getDrawable(id); 145 | } 146 | 147 | /** 148 | * 临时保存图片 149 | * 150 | * @param bitmap 151 | * @return 图片路径 152 | */ 153 | public static String saveImageToAPP(Context context,Bitmap bitmap) { 154 | String result = ""; 155 | OutputStream out = null; 156 | try { 157 | if (bitmap != null) { 158 | String path = context.getApplicationContext().getFilesDir().getAbsolutePath(); 159 | path = path + "/../.cache/"; 160 | File file = new File(path); 161 | if (!file.exists()) { 162 | file.mkdir(); 163 | } 164 | File cacheFile = new File(file, "imageShare.jpeg"); 165 | cacheFile.deleteOnExit(); 166 | out = new BufferedOutputStream(new FileOutputStream(cacheFile)); 167 | bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); 168 | result = cacheFile.getPath(); 169 | // 文件关闭 170 | out.flush(); 171 | out.close(); 172 | } 173 | } catch (Exception e) { 174 | e.printStackTrace(); 175 | if (out != null) { 176 | try { 177 | out.flush(); 178 | out.close(); 179 | } catch (IOException e1) { 180 | e1.printStackTrace(); 181 | } 182 | } 183 | } 184 | return result; 185 | } 186 | 187 | public static Drawable getDrawable(Context context,String id) { 188 | int resourceId = -1; 189 | try { 190 | resourceId = ResourceUtil.getResourceId(context, id, "drawable"); 191 | } catch (Exception e) { 192 | e.printStackTrace(); 193 | } 194 | return context.getResources().getDrawable(resourceId); 195 | } 196 | 197 | /** 198 | * 手动回收imageView图片资源 199 | * 200 | * @param imageView 201 | */ 202 | public static void releaseImageViewResouce(ImageView imageView) { 203 | if (imageView == null) 204 | return; 205 | Drawable drawable = imageView.getDrawable(); 206 | if (drawable != null && drawable instanceof BitmapDrawable) { 207 | BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; 208 | Bitmap bitmap = bitmapDrawable.getBitmap(); 209 | if (bitmap != null && !bitmap.isRecycled()) { 210 | bitmap.recycle(); 211 | } 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/AppUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.util.List; 4 | 5 | import android.app.ActivityManager; 6 | import android.app.ActivityManager.RunningAppProcessInfo; 7 | import android.app.ActivityManager.RunningServiceInfo; 8 | import android.content.ComponentName; 9 | import android.content.Context; 10 | import android.content.pm.PackageInfo; 11 | import android.content.pm.PackageManager; 12 | import android.content.pm.PackageManager.NameNotFoundException; 13 | 14 | /** 15 | * Created by ihgoo on 2015/6/16. 16 | */ 17 | public class AppUtil { 18 | 19 | public static int getVersion(Context context) { 20 | int result = 0; 21 | try { 22 | PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 23 | result = info.versionCode; 24 | } catch (PackageManager.NameNotFoundException e) { 25 | e.printStackTrace(); 26 | } 27 | return result; 28 | } 29 | 30 | public static String getVersionName(Context context) { 31 | String result = ""; 32 | try { 33 | PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 34 | result = info.versionName; 35 | } catch (PackageManager.NameNotFoundException e) { 36 | e.printStackTrace(); 37 | } 38 | return result; 39 | } 40 | 41 | 42 | public static boolean isAppInstalled(final Context context, final String packageName) { 43 | try { 44 | final PackageManager pm = context.getPackageManager(); 45 | final PackageInfo info = pm.getPackageInfo(packageName, 0); 46 | return info != null; 47 | } catch (NameNotFoundException e) { 48 | return false; 49 | } 50 | } 51 | 52 | public static boolean isMainProcess(final Context context) { 53 | ActivityManager am = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)); 54 | List processes = am.getRunningAppProcesses(); 55 | String mainProcessName = context.getPackageName(); 56 | int myPid = android.os.Process.myPid(); 57 | for (RunningAppProcessInfo info : processes) { 58 | if (info.pid == myPid && mainProcessName.equals(info.processName)) { 59 | return true; 60 | } 61 | } 62 | return false; 63 | } 64 | 65 | public static boolean isServiceRunning(Context context, Class cls) { 66 | final ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 67 | final List services = am.getRunningServices(Integer.MAX_VALUE); 68 | final String className = cls.getName(); 69 | for (RunningServiceInfo service : services) { 70 | if (className.equals(service.service.getClassName())) { 71 | return true; 72 | } 73 | } 74 | return false; 75 | } 76 | 77 | public static boolean isAppRunning(final Context context, final String packageName) { 78 | final ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 79 | final List apps = am.getRunningAppProcesses(); 80 | if (apps == null || apps.isEmpty()) { 81 | return false; 82 | } 83 | for (RunningAppProcessInfo app : apps) { 84 | if (packageName.equals(app.processName)) { 85 | return true; 86 | } 87 | } 88 | return false; 89 | } 90 | 91 | public static PackageInfo getCurrentPackageInfo(final Context context) { 92 | final PackageManager pm = context.getPackageManager(); 93 | try { 94 | return pm.getPackageInfo(context.getPackageName(), PackageManager.GET_META_DATA); 95 | } catch (NameNotFoundException e) { 96 | return null; 97 | } 98 | } 99 | 100 | public static PackageInfo getPackageInfo(final Context context, final String packageName) { 101 | final PackageManager pm = context.getPackageManager(); 102 | try { 103 | return pm.getPackageInfo(packageName, PackageManager.GET_META_DATA); 104 | } catch (NameNotFoundException e) { 105 | return null; 106 | } 107 | } 108 | 109 | public static boolean isDisabled(Context context, Class clazz) { 110 | ComponentName componentName = new ComponentName(context, clazz); 111 | PackageManager pm = context.getPackageManager(); 112 | return pm.getComponentEnabledSetting(componentName) 113 | == PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 114 | } 115 | 116 | public static boolean isEnabled(Context context, Class clazz) { 117 | ComponentName componentName = new ComponentName(context, clazz); 118 | PackageManager pm = context.getPackageManager(); 119 | return pm.getComponentEnabledSetting(componentName) 120 | != PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 121 | } 122 | 123 | public static void enableComponent(Context context, Class clazz) { 124 | setComponentState(context, clazz, true); 125 | } 126 | 127 | public static void disableComponent(Context context, Class clazz) { 128 | setComponentState(context, clazz, false); 129 | } 130 | 131 | public static void setComponentState(Context context, Class clazz, boolean enable) { 132 | ComponentName componentName = new ComponentName(context, clazz); 133 | PackageManager pm = context.getPackageManager(); 134 | final int oldState = pm.getComponentEnabledSetting(componentName); 135 | final int newState = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 136 | : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 137 | if (newState != oldState) { 138 | final int flags = PackageManager.DONT_KILL_APP; 139 | pm.setComponentEnabledSetting(componentName, newState, flags); 140 | } 141 | } 142 | 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/AsyncRun.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | /** 7 | * Created by bailong on 14/10/22. 8 | */ 9 | public class AsyncRun { 10 | public static void run(Runnable r) { 11 | Handler h = new Handler(Looper.getMainLooper()); 12 | h.post(r); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/CharsetUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package com.ihgoo.allinone.support; 17 | 18 | import org.apache.http.protocol.HTTP; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * Created by wyouflf on 13-8-30. 25 | */ 26 | public class CharsetUtils { 27 | 28 | private CharsetUtils() { 29 | } 30 | 31 | public static String toCharset(final String str, final String charset, int judgeCharsetLength) { 32 | try { 33 | String oldCharset = getEncoding(str, judgeCharsetLength); 34 | return new String(str.getBytes(oldCharset), charset); 35 | } catch (Throwable ex) { 36 | LogUtils.w(ex); 37 | return str; 38 | } 39 | } 40 | 41 | public static String getEncoding(final String str, int judgeCharsetLength) { 42 | String encode = CharsetUtils.DEFAULT_ENCODING_CHARSET; 43 | for (String charset : SUPPORT_CHARSET) { 44 | if (isCharset(str, charset, judgeCharsetLength)) { 45 | encode = charset; 46 | break; 47 | } 48 | } 49 | return encode; 50 | } 51 | 52 | public static boolean isCharset(final String str, final String charset, int judgeCharsetLength) { 53 | try { 54 | String temp = str.length() > judgeCharsetLength ? str.substring(0, judgeCharsetLength) : str; 55 | return temp.equals(new String(temp.getBytes(charset), charset)); 56 | } catch (Throwable e) { 57 | return false; 58 | } 59 | } 60 | 61 | public static final String DEFAULT_ENCODING_CHARSET = HTTP.DEFAULT_CONTENT_CHARSET; 62 | 63 | public static final List SUPPORT_CHARSET = new ArrayList(); 64 | 65 | static { 66 | SUPPORT_CHARSET.add("ISO-8859-1"); 67 | 68 | SUPPORT_CHARSET.add("GB2312"); 69 | SUPPORT_CHARSET.add("GBK"); 70 | SUPPORT_CHARSET.add("GB18030"); 71 | 72 | SUPPORT_CHARSET.add("US-ASCII"); 73 | SUPPORT_CHARSET.add("ASCII"); 74 | 75 | SUPPORT_CHARSET.add("ISO-2022-KR"); 76 | 77 | SUPPORT_CHARSET.add("ISO-8859-2"); 78 | 79 | SUPPORT_CHARSET.add("ISO-2022-JP"); 80 | SUPPORT_CHARSET.add("ISO-2022-JP-2"); 81 | 82 | SUPPORT_CHARSET.add("UTF-8"); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/Check.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.util.List; 4 | 5 | import android.app.ActivityManager; 6 | import android.app.KeyguardManager; 7 | import android.content.Context; 8 | import android.net.ConnectivityManager; 9 | import android.net.NetworkInfo; 10 | import android.os.Environment; 11 | 12 | /** 13 | * Created by ihgoo on 2015/6/16. 14 | */ 15 | public class Check { 16 | 17 | /** 18 | * 检测是否有sd卡 19 | * 20 | * @return 21 | */ 22 | public static boolean checkSDCard() { 23 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 24 | return true; 25 | } else { 26 | return false; 27 | } 28 | } 29 | 30 | 31 | /** 32 | * 检测App是否在前台 33 | * 34 | * @param context 35 | * @param processName 36 | * @return APP在后台或者锁屏了返回TRUE,如果在前台返回false 37 | */ 38 | public static boolean isBackgroundRunning(Context context, String processName) { 39 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 40 | KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); 41 | if (activityManager == null) 42 | return false; 43 | // get running application processes 44 | List processList = activityManager 45 | .getRunningAppProcesses(); 46 | for (ActivityManager.RunningAppProcessInfo process : processList) { 47 | if (process.processName.startsWith(processName)) { 48 | boolean isBackground = process.importance != android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND 49 | && process.importance != android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; 50 | boolean isLockedState = keyguardManager.inKeyguardRestrictedInputMode(); 51 | if (isBackground || isLockedState) 52 | return true; 53 | else 54 | return false; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | private static long lastClickTime; 61 | 62 | /** 63 | * 是否快速点击 64 | * 65 | * @return 66 | */ 67 | public static boolean isFastDoubleClick() { 68 | long time = System.currentTimeMillis(); 69 | if (time - lastClickTime < 1000) { 70 | return true; 71 | } 72 | lastClickTime = time; 73 | return false; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/IOUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.BufferedReader; 6 | import java.io.Closeable; 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.FileNotFoundException; 10 | import java.io.FileOutputStream; 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | import java.io.InputStreamReader; 14 | 15 | import android.content.Context; 16 | import android.database.Cursor; 17 | 18 | /** 19 | * Created by ihgoo on 2015/6/16. 20 | */ 21 | public class IOUtil { 22 | 23 | 24 | private IOUtil() { 25 | } 26 | 27 | public static void closeQuietly(Closeable closeable) { 28 | if (closeable != null) { 29 | try { 30 | closeable.close(); 31 | } catch (Throwable e) { 32 | } 33 | } 34 | } 35 | 36 | public static void closeQuietly(Cursor cursor) { 37 | if (cursor != null) { 38 | try { 39 | cursor.close(); 40 | } catch (Throwable e) { 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * @return 导出数据流 47 | */ 48 | public static BufferedInputStream exportData(Context context,String dbName) { 49 | try { 50 | // 当前程序路径 51 | String path = context.getFilesDir().getAbsolutePath(); 52 | path = path + "/../databases/" + dbName; 53 | File file = new File(path); 54 | FileInputStream inStream = new FileInputStream(file); 55 | BufferedInputStream in = new BufferedInputStream(inStream); 56 | return in; 57 | } catch (FileNotFoundException e) { 58 | return null; 59 | } 60 | } 61 | 62 | /** 63 | * @param in 导入数据流 64 | */ 65 | public static void importData(Context context,BufferedInputStream in, String dbName) { 66 | try { 67 | // 当前程序路径 68 | String path = context.getFilesDir().getAbsolutePath(); 69 | path = path + "/../databases/"; 70 | File file = new File(path); 71 | file.mkdirs(); 72 | path += dbName; 73 | file = new File(path); 74 | file.createNewFile(); 75 | FileOutputStream outStream = new FileOutputStream(file); 76 | BufferedOutputStream out = new BufferedOutputStream(outStream); 77 | int c; 78 | while ((c = in.read()) >= 0) { 79 | out.write(c); 80 | } 81 | out.flush(); 82 | out.close(); 83 | } catch (IOException e) { 84 | e.printStackTrace(); 85 | } 86 | } 87 | public static String toString(InputStream inputStream) { 88 | BufferedReader r = new BufferedReader(new InputStreamReader(inputStream)); 89 | StringBuilder total = new StringBuilder(); 90 | try { 91 | String line; 92 | while ((line = r.readLine()) != null) { 93 | total.append(line); 94 | } 95 | } catch (IOException e) { 96 | e.printStackTrace(); 97 | } 98 | return total.toString(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | /** 9 | * Created by ihgoo on 2015/6/16. 10 | */ 11 | public class JsonUtil { 12 | public static final T J2O(JSONObject object, Class clazz) { 13 | T result = null; 14 | try { 15 | result = clazz.newInstance(); 16 | 17 | } catch (IllegalAccessException e) { 18 | e.printStackTrace(); 19 | return null; 20 | } catch (InstantiationException e) { 21 | e.printStackTrace(); 22 | return null; 23 | } 24 | 25 | Field[] fields = clazz.getDeclaredFields(); 26 | for (Field field : fields) { 27 | final String name = field.getName(); 28 | field.setAccessible(true); 29 | if (object.has(name)) { 30 | try { 31 | field.set(result, object.getString(name)); 32 | } catch (IllegalArgumentException e) { 33 | e.printStackTrace(); 34 | return null; 35 | } catch (IllegalAccessException e) { 36 | e.printStackTrace(); 37 | return null; 38 | } catch (JSONException e) { 39 | e.printStackTrace(); 40 | return null; 41 | } 42 | } 43 | } 44 | 45 | return result; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/LogUtils.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.text.TextUtils; 4 | import android.util.Log; 5 | 6 | public class LogUtils { 7 | 8 | private static String customTagPrefix = ""; 9 | 10 | private LogUtils() { 11 | } 12 | 13 | private static boolean allowD = true; 14 | private static boolean allowE = true; 15 | private static boolean allowI = true; 16 | private static boolean allowV = true; 17 | private static boolean allowW = true; 18 | private static boolean allowWtf = true; 19 | 20 | private static String generateTag(StackTraceElement caller) { 21 | String tag = "%s.%s(L:%d)"; 22 | String callerClazzName = caller.getClassName(); 23 | callerClazzName = callerClazzName.substring(callerClazzName 24 | .lastIndexOf(".") + 1); 25 | tag = String.format(tag, callerClazzName, caller.getMethodName(), 26 | caller.getLineNumber()); 27 | tag = TextUtils.isEmpty(customTagPrefix) ? tag : customTagPrefix + ":" 28 | + tag; 29 | return tag; 30 | } 31 | 32 | public static void setTagPrefix(String tag) { 33 | customTagPrefix = tag; 34 | } 35 | 36 | private static CustomLogger customLogger; 37 | 38 | public interface CustomLogger { 39 | void d(String tag, String content); 40 | 41 | void d(String tag, String content, Throwable tr); 42 | 43 | void e(String tag, String content); 44 | 45 | void e(String tag, String content, Throwable tr); 46 | 47 | void i(String tag, String content); 48 | 49 | void i(String tag, String content, Throwable tr); 50 | 51 | void v(String tag, String content); 52 | 53 | void v(String tag, String content, Throwable tr); 54 | 55 | void w(String tag, String content); 56 | 57 | void w(String tag, String content, Throwable tr); 58 | 59 | void w(String tag, Throwable tr); 60 | 61 | void wtf(String tag, String content); 62 | 63 | void wtf(String tag, String content, Throwable tr); 64 | 65 | void wtf(String tag, Throwable tr); 66 | } 67 | 68 | public static void d(String content) { 69 | if (!allowD) { 70 | return; 71 | } 72 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 73 | String tag = generateTag(caller); 74 | 75 | if (customLogger != null) { 76 | customLogger.d(tag, content); 77 | } else { 78 | Log.d(tag, content); 79 | } 80 | } 81 | 82 | public static void d(String content, Throwable tr) { 83 | if (!allowD) { 84 | return; 85 | } 86 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 87 | String tag = generateTag(caller); 88 | 89 | if (customLogger != null) { 90 | customLogger.d(tag, content, tr); 91 | } else { 92 | Log.d(tag, content, tr); 93 | } 94 | } 95 | 96 | public static void e(String content) { 97 | if (!allowE) { 98 | return; 99 | } 100 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 101 | String tag = generateTag(caller); 102 | 103 | if (customLogger != null) { 104 | customLogger.e(tag, content); 105 | } else { 106 | Log.e(tag, content); 107 | } 108 | } 109 | 110 | public static void e(String content, Throwable tr) { 111 | if (!allowE) { 112 | return; 113 | } 114 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 115 | String tag = generateTag(caller); 116 | 117 | if (customLogger != null) { 118 | customLogger.e(tag, content, tr); 119 | } else { 120 | Log.e(tag, content, tr); 121 | } 122 | } 123 | 124 | public static void i(String content) { 125 | if (!allowI) { 126 | return; 127 | } 128 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 129 | String tag = generateTag(caller); 130 | 131 | if (customLogger != null) { 132 | customLogger.i(tag, content); 133 | } else { 134 | Log.i(tag, content); 135 | } 136 | } 137 | 138 | public static void i(String content, Throwable tr) { 139 | if (!allowI) { 140 | return; 141 | } 142 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 143 | String tag = generateTag(caller); 144 | 145 | if (customLogger != null) { 146 | customLogger.i(tag, content, tr); 147 | } else { 148 | Log.i(tag, content, tr); 149 | } 150 | } 151 | 152 | public static void v(String content) { 153 | if (!allowV) { 154 | return; 155 | } 156 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 157 | String tag = generateTag(caller); 158 | 159 | if (customLogger != null) { 160 | customLogger.v(tag, content); 161 | } else { 162 | Log.v(tag, content); 163 | } 164 | } 165 | 166 | public static void v(String content, Throwable tr) { 167 | if (!allowV) { 168 | return; 169 | } 170 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 171 | String tag = generateTag(caller); 172 | 173 | if (customLogger != null) { 174 | customLogger.v(tag, content, tr); 175 | } else { 176 | Log.v(tag, content, tr); 177 | } 178 | } 179 | 180 | public static void w(String content) { 181 | if (!allowW) { 182 | return; 183 | } 184 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 185 | String tag = generateTag(caller); 186 | 187 | if (customLogger != null) { 188 | customLogger.w(tag, content); 189 | } else { 190 | Log.w(tag, content); 191 | } 192 | } 193 | 194 | public static void w(String content, Throwable tr) { 195 | if (!allowW) { 196 | return; 197 | } 198 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 199 | String tag = generateTag(caller); 200 | 201 | if (customLogger != null) { 202 | customLogger.w(tag, content, tr); 203 | } else { 204 | Log.w(tag, content, tr); 205 | } 206 | } 207 | 208 | public static void w(Throwable tr) { 209 | if (!allowW) { 210 | return; 211 | } 212 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 213 | String tag = generateTag(caller); 214 | 215 | if (customLogger != null) { 216 | customLogger.w(tag, tr); 217 | } else { 218 | Log.w(tag, tr); 219 | } 220 | } 221 | 222 | public static void wtf(String content) { 223 | if (!allowWtf) { 224 | return; 225 | } 226 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 227 | String tag = generateTag(caller); 228 | 229 | if (customLogger != null) { 230 | customLogger.wtf(tag, content); 231 | } else { 232 | Log.wtf(tag, content); 233 | } 234 | } 235 | 236 | public static void wtf(String content, Throwable tr) { 237 | if (!allowWtf) { 238 | return; 239 | } 240 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 241 | String tag = generateTag(caller); 242 | 243 | if (customLogger != null) { 244 | customLogger.wtf(tag, content, tr); 245 | } else { 246 | Log.wtf(tag, content, tr); 247 | } 248 | } 249 | 250 | public static void wtf(Throwable tr) { 251 | if (!allowWtf) { 252 | return; 253 | } 254 | StackTraceElement caller = OtherUtils.getCallerStackTraceElement(); 255 | String tag = generateTag(caller); 256 | 257 | if (customLogger != null) { 258 | customLogger.wtf(tag, tr); 259 | } else { 260 | Log.wtf(tag, tr); 261 | } 262 | } 263 | 264 | } 265 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/MathUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.text.TextUtils; 4 | 5 | import org.json.JSONObject; 6 | 7 | import com.ihgoo.allinone.exception.MathException; 8 | 9 | import java.lang.reflect.Field; 10 | import java.math.BigDecimal; 11 | import java.text.DecimalFormat; 12 | import java.util.ArrayList; 13 | import java.util.Calendar; 14 | import java.util.List; 15 | import java.util.Random; 16 | import java.util.Set; 17 | 18 | /** 19 | * Created by ihgoo on 2015/6/16. 20 | */ 21 | public class MathUtil { 22 | /** 23 | * DecimalFormat("0.00")会四舍五入 24 | * 该方法是截取小数点后两位 25 | * @param number 数据 26 | */ 27 | public static String dotSubTwo(double number) { 28 | DecimalFormat df = new DecimalFormat("0.000"); 29 | if (Double.isNaN(number)) { 30 | throw new MathException("The parameter is not a number,plese check it."); 31 | } 32 | String str = df.format(number); 33 | if (str.contains(".")) { 34 | return str.substring(0, str.length()-1); 35 | } 36 | return null; 37 | } 38 | 39 | 40 | /** 41 | * 提供精确的小数位四舍五入处理。 42 | * 43 | * @param v 44 | * 需要四舍五入的数字 45 | * @param scale 46 | * 小数点后保留几位 47 | * @return 四舍五入后的结果 48 | */ 49 | public static double round(double v, int scale) { 50 | if (scale < 0) { 51 | throw new IllegalArgumentException( 52 | "The scale must be a positive integer or zero"); 53 | } 54 | BigDecimal b = new BigDecimal(Double.toString(v)); 55 | BigDecimal one = new BigDecimal("1"); 56 | return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); 57 | } 58 | 59 | /** 60 | * 检查一个字符串是否是整数。该函数将避免NumberFormat异常。 61 | * 62 | * @param num 需要检查的字符串 63 | * @return 返回true表示是一个整数;如果字符串为为空,或者不符合规则返回false. 64 | * @see {@link NumberFormatException} 65 | */ 66 | public static final boolean checkNumberFormat(String num) { 67 | if (TextUtils.isEmpty(num)) 68 | return false; 69 | return num.matches("-[0-9]+|[0-9]+"); 70 | } 71 | 72 | /** 73 | * 求一个数的模数,该函数通常用来循环获得0-length的索引. 74 | *

75 | * for example:
76 | *

 77 |      * final int divisor = 4;
 78 |      * for(int dividend = -9; dividend < 10; dividend ++)
 79 |      * {
 80 |      *     System.out.println(computeRemainder(dividend, divisor));
 81 |      * }
 82 |      * 
83 | * 84 | * 你将只能获得0-3的数。 85 | * 86 | * @param dividend 被除数 87 | * @param divisor 除数 88 | * @return 模数 89 | */ 90 | public static final int computeRemainder(int dividend, int divisor) { 91 | final int modulus = dividend % divisor; 92 | if (modulus < 0) 93 | return modulus + divisor; 94 | else 95 | return modulus; 96 | } 97 | 98 | /** 99 | * 计算方差 100 | * 101 | * @param nums 102 | * @return 103 | */ 104 | public static double calD(ArrayList nums) { 105 | double sum = 0; 106 | double n = nums.size(); 107 | double d = 0; 108 | if (n > 0) { 109 | // 求和 110 | for (double num : nums) { 111 | sum += num; 112 | } 113 | double u = (double) sum / (double) nums.size(); 114 | 115 | double temp = 0; 116 | for (double num : nums) { 117 | temp += (num - u) * (num - u); 118 | } 119 | 120 | d = Math.sqrt((double) temp / (double) n) / u; 121 | 122 | } 123 | 124 | return d; 125 | } 126 | 127 | public static boolean isInt(Field field) { 128 | return field.getType().getSimpleName().equals("int"); 129 | } 130 | 131 | public static int getInt(Object object, int defaultValue) { 132 | 133 | String str = ""; 134 | if (object != null) { 135 | str = object.toString(); 136 | 137 | } 138 | return parseInt(str, defaultValue); 139 | } 140 | 141 | public static long getLong(Object object, long defaultValue) { 142 | String str = ""; 143 | if (object != null) { 144 | str = object.toString(); 145 | 146 | } 147 | return parseLong(str, defaultValue); 148 | } 149 | 150 | public static long getLong(JSONObject jsonObject, String name, long defaultValue) { 151 | long result = defaultValue; 152 | try { 153 | if (jsonObject != null && jsonObject.has(name)) { 154 | result = jsonObject.getLong(name); 155 | } 156 | } catch (Exception e) { 157 | e.printStackTrace(); 158 | } 159 | return result; 160 | } 161 | 162 | public static int parseInt(String object, int defalult) { 163 | return (int) parseDouble(object, defalult); 164 | } 165 | 166 | public static float parseFloat(String object, float defalult) { 167 | return (float) parseDouble(object, defalult); 168 | } 169 | 170 | public static long parseLong(String object, long defalult) { 171 | return (long) parseDouble(object, defalult); 172 | } 173 | 174 | public static double parseDouble(String object, double defalult) { 175 | double result = defalult; 176 | if (object != null && object.length() > 0) { 177 | try { 178 | result = Double.parseDouble(object); 179 | } catch (Exception e) { 180 | 181 | } 182 | } 183 | return result; 184 | } 185 | 186 | public static int getInt(JSONObject jsonObject, String name, int defaultValue) { 187 | int result = defaultValue; 188 | try { 189 | if (jsonObject != null && jsonObject.has(name)) { 190 | result = jsonObject.getInt(name); 191 | } 192 | } catch (Exception e) { 193 | e.printStackTrace(); 194 | } 195 | return result; 196 | 197 | } 198 | 199 | /** 200 | * @param week calendar.day 201 | * @return 星期几 202 | */ 203 | public static String getFriendlyWeekStr(int week) { 204 | String result = ""; 205 | switch (week) { 206 | case Calendar.MONDAY: 207 | result = "一"; 208 | break; 209 | case Calendar.TUESDAY: 210 | result = "二"; 211 | break; 212 | case Calendar.WEDNESDAY: 213 | result = "三"; 214 | break; 215 | case Calendar.THURSDAY: 216 | result = "四"; 217 | break; 218 | case Calendar.FRIDAY: 219 | result = "五"; 220 | break; 221 | case Calendar.SATURDAY: 222 | result = "六"; 223 | break; 224 | case Calendar.SUNDAY: 225 | result = "日"; 226 | break; 227 | 228 | } 229 | 230 | return result; 231 | 232 | } 233 | 234 | /** 235 | * 从数组里随机的获取一个 236 | * 237 | * @param 238 | * @param list 239 | * @return 240 | */ 241 | public static T getRandOne(T[] list) { 242 | T result = null; 243 | if (list != null && list.length > 0) { 244 | int count = list.length; 245 | // int index = count - 1; 246 | int index = (int) (Math.random() * count); 247 | result = list[index]; 248 | } 249 | return result; 250 | } 251 | 252 | public static T getRandOne(List arrayList) { 253 | T result = null; 254 | if (arrayList != null && arrayList.size() > 0) { 255 | int count = arrayList.size(); 256 | int index = count - 1; 257 | index = (int) (Math.random() * index); 258 | result = arrayList.get(index); 259 | } 260 | return result; 261 | } 262 | 263 | public static T getRandOne(Set sets) { 264 | T result = null; 265 | if (sets != null) { 266 | int size = sets.size(); 267 | int random = new Random().nextInt(size); 268 | int i = 0; 269 | for (T item : sets) { 270 | if (i == random) { 271 | result = item; 272 | break; 273 | } 274 | i = i + 1; 275 | } 276 | } 277 | return result; 278 | } 279 | 280 | @SuppressWarnings("unchecked") 281 | public static ArrayList getRands(ArrayList arrayList, int num) { 282 | ArrayList result = new ArrayList(); 283 | if (arrayList != null && arrayList.size() > 0) { 284 | num = Math.min(num, arrayList.size()); 285 | arrayList = (ArrayList) arrayList.clone(); 286 | 287 | for (int i = 0; i < num; i++) { 288 | int randIndex = (int) (Math.random() * (arrayList.size() - 1)); 289 | result.add(arrayList.get(randIndex)); 290 | arrayList.remove(randIndex); 291 | } 292 | } 293 | return result; 294 | } 295 | 296 | public static String getSign(int num) { 297 | String result = ""; 298 | if (num > 0) { 299 | result = "+"; 300 | } else if (num == 0) { 301 | result = ""; 302 | } else { 303 | result = ""; 304 | } 305 | return result; 306 | } 307 | 308 | 309 | /** 310 | * 返回下一个元素,如果是最后一个,返回最后一个 311 | * 312 | * @param 313 | * @param lists 314 | * @param cur 315 | * @return 316 | */ 317 | public static T getNextCycle(List lists, int cur) { 318 | int count = lists.size(); 319 | T result; 320 | 321 | int next = cur + 1; 322 | 323 | if (next == count) { 324 | next = 0; 325 | } 326 | 327 | result = lists.get(next); 328 | 329 | return result; 330 | 331 | } 332 | 333 | public static Float max(Float... nums) { 334 | 335 | Float result = null; 336 | if (nums.length > 0) { 337 | result = nums[0]; 338 | for (Float num : nums) { 339 | if (num > result) { 340 | result = num; 341 | } 342 | } 343 | } 344 | return result; 345 | } 346 | 347 | public static Float min(Float... nums) { 348 | 349 | Float result = null; 350 | if (nums.length > 0) { 351 | result = nums[0]; 352 | for (Float num : nums) { 353 | if (num < result) { 354 | result = num; 355 | } 356 | } 357 | } 358 | return result; 359 | } 360 | 361 | public static Float sum(Float... nums) { 362 | 363 | Float result = 0f; 364 | for (Float num : nums) { 365 | result += num; 366 | } 367 | return result; 368 | } 369 | 370 | 371 | public static ArrayList toArrayList(T[] objects) { 372 | ArrayList result = new ArrayList(); 373 | if (objects != null) { 374 | for (T object : objects) { 375 | result.add(object); 376 | } 377 | } 378 | return result; 379 | } 380 | 381 | } 382 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/MediaUtils.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.io.File; 4 | 5 | import android.content.ContentResolver; 6 | import android.content.ContentValues; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.database.Cursor; 10 | import android.media.MediaScannerConnection; 11 | import android.net.Uri; 12 | import android.os.Environment; 13 | import android.provider.MediaStore; 14 | 15 | public class MediaUtils { 16 | 17 | /** 18 | * 向多媒体数据库手动添加(Android4.4中拒绝发送Intent.ACTION_MEDIA_MOUNTED扫描SD卡的广播) 19 | * 20 | * @param mContext 21 | * @param filePath 22 | */ 23 | public static void insertMediaFile(final Context mContext, String filePath) { 24 | if (filePath == null) { 25 | return; 26 | } 27 | // broadcast to scan file 28 | boolean bmnt = Environment.getExternalStorageDirectory().getPath() 29 | .startsWith("/mnt"); 30 | 31 | File file = new File(bmnt ? ("/mnt" + filePath) : filePath); 32 | 33 | MediaScannerConnection.scanFile(mContext, 34 | new String[] { file.toString() }, null, 35 | new MediaScannerConnection.OnScanCompletedListener() { 36 | @Override 37 | public void onScanCompleted(String path, Uri uri) { 38 | 39 | ContentResolver cr = mContext.getContentResolver(); 40 | long datemodified = 0; 41 | long dateadded = 0; 42 | Cursor cursor = cr.query(uri, null, null, null, null); 43 | if (cursor != null && cursor.moveToFirst()) { 44 | datemodified = cursor.getLong(cursor 45 | .getColumnIndex(MediaStore.MediaColumns.DATE_MODIFIED)); 46 | dateadded = cursor.getLong(cursor 47 | .getColumnIndex(MediaStore.MediaColumns.DATE_ADDED)); 48 | cursor.close(); 49 | } 50 | 51 | ContentValues values = new ContentValues(); 52 | if (datemodified > 0 53 | && String.valueOf(datemodified).length() > 10) { 54 | values.put(MediaStore.MediaColumns.DATE_MODIFIED, 55 | datemodified / 1000); 56 | } 57 | if (dateadded > 0 58 | && String.valueOf(dateadded).length() > 13) { 59 | values.put(MediaStore.MediaColumns.DATE_ADDED, 60 | dateadded / 1000); 61 | } 62 | 63 | if (values.size() > 0) { 64 | cr.update(uri, values, null, null); 65 | } 66 | 67 | } 68 | }); 69 | } 70 | 71 | /** 72 | * 手动单独扫描相册文件 73 | * 74 | * @param context 75 | * 上下文 76 | * @param filename 77 | * 文件完整路径 78 | */ 79 | public static void updateGallery(final Context context, String filename) { 80 | MediaScannerConnection.scanFile(context, new String[] { filename }, 81 | null, new MediaScannerConnection.OnScanCompletedListener() { 82 | public void onScanCompleted(String path, Uri uri) { 83 | context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri)); 84 | LogUtils.i("Scanned " + path + ":"); 85 | LogUtils.i("-> uri=" + uri); 86 | } 87 | }); 88 | } 89 | 90 | 91 | public static void fileScan(final Context context, String file){ 92 | Uri data = Uri.parse("file://"+file); 93 | LogUtils.i("file:"+file); 94 | context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, data)); 95 | } 96 | 97 | public static void folderScan(final Context context, String path){ 98 | File file = new File(path); 99 | 100 | if(file.isDirectory()){ 101 | File[] array = file.listFiles(); 102 | 103 | for(int i=0;i 0) { 72 | buffer.append(version); 73 | } else { 74 | // default to "1.0" 75 | buffer.append("1.0"); 76 | } 77 | buffer.append("; "); 78 | final String language = locale.getLanguage(); 79 | if (language != null) { 80 | buffer.append(language.toLowerCase()); 81 | final String country = locale.getCountry(); 82 | if (country != null) { 83 | buffer.append("-"); 84 | buffer.append(country.toLowerCase()); 85 | } 86 | } else { 87 | // default to "en" 88 | buffer.append("en"); 89 | } 90 | // add the model for the release build 91 | if ("REL".equals(Build.VERSION.CODENAME)) { 92 | final String model = Build.MODEL; 93 | if (model.length() > 0) { 94 | buffer.append("; "); 95 | buffer.append(model); 96 | } 97 | } 98 | final String id = Build.ID; 99 | if (id.length() > 0) { 100 | buffer.append(" Build/"); 101 | buffer.append(id); 102 | } 103 | return String.format(webUserAgent, buffer, "Mobile "); 104 | } 105 | 106 | 107 | 108 | public static boolean isSupportRange(final HttpResponse response) { 109 | if (response == null) 110 | return false; 111 | Header header = response.getFirstHeader("Accept-Ranges"); 112 | if (header != null) { 113 | return "bytes".equals(header.getValue()); 114 | } 115 | header = response.getFirstHeader("Content-Range"); 116 | if (header != null) { 117 | String value = header.getValue(); 118 | return value != null && value.startsWith("bytes"); 119 | } 120 | return false; 121 | } 122 | 123 | public static String getFileNameFromHttpResponse(final HttpResponse response) { 124 | if (response == null) 125 | return null; 126 | String result = null; 127 | Header header = response.getFirstHeader("Content-Disposition"); 128 | if (header != null) { 129 | for (HeaderElement element : header.getElements()) { 130 | NameValuePair fileNamePair = element 131 | .getParameterByName("filename"); 132 | if (fileNamePair != null) { 133 | result = fileNamePair.getValue(); 134 | // try to get correct encoding str 135 | result = CharsetUtils.toCharset(result, HTTP.UTF_8, 136 | result.length()); 137 | break; 138 | } 139 | } 140 | } 141 | return result; 142 | } 143 | 144 | public static Charset getCharsetFromHttpRequest( 145 | final HttpRequestBase request) { 146 | if (request == null) 147 | return null; 148 | String charsetName = null; 149 | Header header = request.getFirstHeader("Content-Type"); 150 | if (header != null) { 151 | for (HeaderElement element : header.getElements()) { 152 | NameValuePair charsetPair = element 153 | .getParameterByName("charset"); 154 | if (charsetPair != null) { 155 | charsetName = charsetPair.getValue(); 156 | break; 157 | } 158 | } 159 | } 160 | 161 | boolean isSupportedCharset = false; 162 | if (!TextUtils.isEmpty(charsetName)) { 163 | try { 164 | isSupportedCharset = Charset.isSupported(charsetName); 165 | } catch (Throwable e) { 166 | } 167 | } 168 | 169 | return isSupportedCharset ? Charset.forName(charsetName) : null; 170 | } 171 | 172 | private static final int STRING_BUFFER_LENGTH = 100; 173 | 174 | public static long sizeOfString(final String str, String charset) 175 | throws UnsupportedEncodingException { 176 | if (TextUtils.isEmpty(str)) { 177 | return 0; 178 | } 179 | int len = str.length(); 180 | if (len < STRING_BUFFER_LENGTH) { 181 | return str.getBytes(charset).length; 182 | } 183 | long size = 0; 184 | for (int i = 0; i < len; i += STRING_BUFFER_LENGTH) { 185 | int end = i + STRING_BUFFER_LENGTH; 186 | end = end < len ? end : len; 187 | String temp = getSubString(str, i, end); 188 | size += temp.getBytes(charset).length; 189 | } 190 | return size; 191 | } 192 | 193 | /** 194 | * Get the sub string for large string 195 | * 196 | * @param str 197 | * @param start 198 | * @param end 199 | * @return 200 | */ 201 | public static String getSubString(final String str, int start, int end) { 202 | return new String(str.substring(start, end)); 203 | } 204 | 205 | public static StackTraceElement getCurrentStackTraceElement() { 206 | return Thread.currentThread().getStackTrace()[3]; 207 | } 208 | 209 | public static StackTraceElement getCallerStackTraceElement() { 210 | return Thread.currentThread().getStackTrace()[4]; 211 | } 212 | 213 | public static void updateFileTime(String dir, String fileName) { 214 | File file = new File(dir, fileName); 215 | long newModifiedTime = System.currentTimeMillis(); 216 | file.setLastModified(newModifiedTime); 217 | } 218 | 219 | 220 | private static SSLSocketFactory sslSocketFactory; 221 | 222 | public static void trustAllHttpsURLConnection() { 223 | // Create a trust manager that does not validate certificate chains 224 | if (sslSocketFactory == null) { 225 | TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { 226 | @Override 227 | public java.security.cert.X509Certificate[] getAcceptedIssuers() { 228 | return null; 229 | } 230 | 231 | @Override 232 | public void checkClientTrusted(X509Certificate[] certs, 233 | String authType) { 234 | } 235 | 236 | @Override 237 | public void checkServerTrusted(X509Certificate[] certs, 238 | String authType) { 239 | } 240 | } }; 241 | try { 242 | SSLContext sslContext = SSLContext.getInstance("TLS"); 243 | sslContext.init(null, trustAllCerts, null); 244 | sslSocketFactory = sslContext.getSocketFactory(); 245 | } catch (Throwable e) { 246 | LogUtils.e(e.getMessage(), e); 247 | } 248 | } 249 | 250 | if (sslSocketFactory != null) { 251 | HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory); 252 | HttpsURLConnection 253 | .setDefaultHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 254 | } 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/ParseUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import org.json.JSONObject; 6 | 7 | public class ParseUtil { 8 | public static boolean isInt(Field field) { 9 | return field.getType().getSimpleName().equals("int"); 10 | } 11 | 12 | public static int getInt(Object object, int defaultValue) { 13 | 14 | String str = ""; 15 | if (object != null) { 16 | str = object.toString(); 17 | 18 | } 19 | return parseInt(str, defaultValue); 20 | } 21 | 22 | public static long getLong(Object object, long defaultValue) { 23 | String str = ""; 24 | if (object != null) { 25 | str = object.toString(); 26 | 27 | } 28 | return parseLong(str, defaultValue); 29 | } 30 | 31 | public static long getLong(JSONObject jsonObject, String name, long defaultValue) { 32 | long result = defaultValue; 33 | try { 34 | if (jsonObject != null && jsonObject.has(name)) { 35 | result = jsonObject.getLong(name); 36 | } 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } 40 | return result; 41 | } 42 | 43 | public static int parseInt(String object, int defalult) { 44 | return (int) parseDouble(object, defalult); 45 | } 46 | 47 | public static float parseFloat(String object, float defalult) { 48 | return (float) parseDouble(object, defalult); 49 | } 50 | 51 | public static long parseLong(String object, long defalult) { 52 | return (long) parseDouble(object, defalult); 53 | } 54 | 55 | public static double parseDouble(String object, double defalult) { 56 | double result = defalult; 57 | if (object != null && object.length() > 0) { 58 | try { 59 | result = Double.parseDouble(object); 60 | } catch (Exception e) { 61 | 62 | } 63 | } 64 | return result; 65 | } 66 | 67 | public static int getInt(JSONObject jsonObject, String name, int defaultValue) { 68 | int result = defaultValue; 69 | try { 70 | if (jsonObject != null && jsonObject.has(name)) { 71 | result = jsonObject.getInt(name); 72 | } 73 | } catch (Exception e) { 74 | e.printStackTrace(); 75 | } 76 | return result; 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/Persistence.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.os.Environment; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * Created by ihgoo on 2015/6/16. 9 | */ 10 | public class Persistence { 11 | 12 | public static final String APP_FOLDER_ON_SD = Environment 13 | .getExternalStorageDirectory().getAbsolutePath() 14 | + "/AllInOne/AllInOne"; 15 | 16 | public static final String PHOTOCACHE_FOLDER = APP_FOLDER_ON_SD 17 | + "/photo_cache"; 18 | public static final String MY_FAVOURITE_FOLDER = APP_FOLDER_ON_SD 19 | + "/my_favourite"; 20 | /** 21 | * 创建用户时的头像缓存 22 | */ 23 | public static final String USER_AVATAR_FOLDER = APP_FOLDER_ON_SD 24 | + "/avatar"; 25 | 26 | /** 27 | * @return 精简版缓存路径 28 | */ 29 | public static String getCacheDir() { 30 | File cacheDir = new File(StringUtil.concat(getSDcardRootPath(), "/", ".cache/dayima/concept/")); 31 | if (!cacheDir.exists()) { 32 | cacheDir.mkdirs(); 33 | } 34 | return cacheDir.getAbsolutePath(); 35 | } 36 | 37 | /** 38 | * @return 精简版crash路径 39 | */ 40 | public static String getCrashReportDir() { 41 | File cacheDir = new File(StringUtil.concat(getSDcardRootPath(), "/", ".cache/dayima/concept/crash/")); 42 | if (!cacheDir.exists()) { 43 | cacheDir.mkdirs(); 44 | } 45 | return cacheDir.getAbsolutePath(); 46 | } 47 | 48 | public static String getSDcardRootPath() { 49 | return Environment.getExternalStorageDirectory().getAbsolutePath(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/PhoneUtils.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.lang.reflect.Method; 6 | import java.util.Locale; 7 | 8 | import android.app.Activity; 9 | import android.content.Context; 10 | import android.content.pm.ApplicationInfo; 11 | import android.content.pm.PackageInfo; 12 | import android.content.pm.PackageManager; 13 | import android.content.pm.PackageManager.NameNotFoundException; 14 | import android.os.Build; 15 | import android.os.Bundle; 16 | import android.os.Environment; 17 | import android.os.StatFs; 18 | import android.telephony.TelephonyManager; 19 | import android.text.TextUtils; 20 | import android.util.DisplayMetrics; 21 | 22 | public class PhoneUtils { 23 | private PhoneUtils() { 24 | } 25 | 26 | /** 27 | * @param context 28 | * @param dirName 29 | * Only the folder name, not full path. 30 | * @return app_cache_path/dirName 31 | */ 32 | public static String getDiskCacheDir(Context context, String dirName) { 33 | String cachePath = null; 34 | if (Environment.MEDIA_MOUNTED.equals(Environment 35 | .getExternalStorageState())) { 36 | File externalCacheDir = context.getExternalCacheDir(); 37 | if (externalCacheDir != null) { 38 | cachePath = externalCacheDir.getPath(); 39 | } 40 | } 41 | if (cachePath == null) { 42 | File cacheDir = context.getCacheDir(); 43 | if (cacheDir != null && cacheDir.exists()) { 44 | cachePath = cacheDir.getPath(); 45 | } 46 | } 47 | 48 | return cachePath + File.separator + dirName; 49 | } 50 | 51 | public static long getAvailableSpace(File dir) { 52 | try { 53 | final StatFs stats = new StatFs(dir.getPath()); 54 | return (long) stats.getBlockSize() 55 | * (long) stats.getAvailableBlocks(); 56 | } catch (Throwable e) { 57 | LogUtils.e(e.getMessage(), e); 58 | return -1; 59 | } 60 | 61 | } 62 | 63 | /** 64 | * The end-user-visible name for the end product. 65 | * 66 | * @param context 67 | * @return 68 | */ 69 | public static String getModel(Context context) { 70 | return Build.MODEL; 71 | } 72 | 73 | // 74 | // public static String getHardware(Context context) { 75 | // if (getPhoneSDK(context) < 8) { 76 | // return "undefined"; 77 | // } else { 78 | // Logger.d(TAG, "hardware:" + Build.HARDWARE); 79 | // } 80 | // return Build.HARDWARE; 81 | // } 82 | 83 | public static String getManufacturer(Context context) { 84 | return Build.MANUFACTURER; 85 | } 86 | 87 | /** 88 | * 获取发行版版本 89 | * 90 | * @param context 91 | * @return 92 | */ 93 | public static String getFirmware(Context context) { 94 | return Build.VERSION.RELEASE; 95 | } 96 | 97 | public static String getSDKVer() { 98 | return Integer.valueOf(Build.VERSION.SDK_INT).toString(); 99 | } 100 | 101 | /** 102 | * 获取本机语言 103 | * 104 | * @return 105 | */ 106 | public static String getLanguage() { 107 | Locale locale = Locale.getDefault(); 108 | String languageCode = locale.getLanguage(); 109 | if (TextUtils.isEmpty(languageCode)) { 110 | languageCode = ""; 111 | } 112 | return languageCode; 113 | } 114 | 115 | /** 116 | * 获取城市编号 117 | * 118 | * @return 119 | */ 120 | public static String getCountry() { 121 | Locale locale = Locale.getDefault(); 122 | String countryCode = locale.getCountry(); 123 | if (TextUtils.isEmpty(countryCode)) { 124 | countryCode = ""; 125 | } 126 | return countryCode; 127 | } 128 | 129 | /** 130 | * 获取IMEI(移动设备国际身份码) 131 | * 132 | * @param context 133 | * @return 134 | */ 135 | public static String getIMEI(Context context) { 136 | TelephonyManager mTelephonyMgr = (TelephonyManager) context 137 | .getSystemService(Context.TELEPHONY_SERVICE); 138 | String imei = mTelephonyMgr.getDeviceId(); 139 | if (TextUtils.isEmpty(imei) || imei.equals("000000000000000")) { 140 | imei = "0"; 141 | } 142 | 143 | return imei; 144 | } 145 | 146 | /** 147 | * 获取国际移动用户识别码(IMSI) 148 | * 149 | * @param context 150 | * @return 151 | */ 152 | public static String getIMSI(Context context) { 153 | TelephonyManager mTelephonyMgr = (TelephonyManager) context 154 | .getSystemService(Context.TELEPHONY_SERVICE); 155 | String imsi = mTelephonyMgr.getSubscriberId(); 156 | if (TextUtils.isEmpty(imsi)) { 157 | return "0"; 158 | } else { 159 | return imsi; 160 | } 161 | } 162 | 163 | // public static String getLac(Context context) { 164 | // CellIdInfo cell = new CellIdInfo(); 165 | // CellIDData cData = cell.getCellId(context); 166 | // return (cData != null ? cData.getLac() : "1"); 167 | // } 168 | // 169 | // public static String getCellid(Context context) { 170 | // CellIdInfo cell = new CellIdInfo(); 171 | // CellIDData cData = cell.getCellId(context); 172 | // return (cData != null ? cData.getCellid() : "1"); 173 | // } 174 | 175 | public static String getMcnc(Context context) { 176 | 177 | TelephonyManager tm = (TelephonyManager) context 178 | .getSystemService(Context.TELEPHONY_SERVICE); 179 | String mcnc = tm.getNetworkOperator(); 180 | if (TextUtils.isEmpty(mcnc)) { 181 | return "0"; 182 | } else { 183 | return mcnc; 184 | } 185 | } 186 | 187 | /** 188 | * Get phone SDK version 189 | * 190 | * @return 191 | */ 192 | public static int getPhoneSDK(Context mContext) { 193 | TelephonyManager phoneMgr = (TelephonyManager) mContext 194 | .getSystemService(Context.TELEPHONY_SERVICE); 195 | LogUtils.i("Bild model:" + Build.MODEL); 196 | LogUtils.i("Bild model:" + phoneMgr.getLine1Number()); 197 | LogUtils.i("Bild model:" + Build.VERSION.SDK); 198 | LogUtils.i("Bild model:" + Build.VERSION.RELEASE); 199 | int sdk = 7; 200 | try { 201 | sdk = Integer.parseInt(Build.VERSION.SDK); 202 | } catch (Exception e) { 203 | e.printStackTrace(); 204 | } 205 | return sdk; 206 | } 207 | 208 | public static Object getMetaData(Context context, String keyName) { 209 | try { 210 | ApplicationInfo info = context.getPackageManager() 211 | .getApplicationInfo(context.getPackageName(), 212 | PackageManager.GET_META_DATA); 213 | 214 | Bundle bundle = info.metaData; 215 | Object value = bundle.get(keyName); 216 | return value; 217 | } catch (NameNotFoundException e) { 218 | e.printStackTrace(); 219 | } 220 | return ""; 221 | } 222 | 223 | /** 224 | * 获取该app的版本 225 | * 226 | * @param context 227 | * @return 228 | */ 229 | public static String getAppVersion(Context context) { 230 | PackageManager pm = context.getPackageManager(); 231 | PackageInfo pi; 232 | try { 233 | pi = pm.getPackageInfo(context.getPackageName(), 0); 234 | String versionName = pi.versionName; 235 | return versionName; 236 | } catch (NameNotFoundException e) { 237 | e.printStackTrace(); 238 | } 239 | return ""; 240 | } 241 | 242 | /** 243 | * 返回十进制序列号,用于唯一标识一个磁盘卷 244 | * 245 | * @param context 246 | * @return 247 | */ 248 | public static String getSerialNumber(Context context) { 249 | String serial = null; 250 | try { 251 | Class c = Class.forName("android.os.SystemProperties"); 252 | Method get = c.getMethod("get", String.class); 253 | serial = (String) get.invoke(c, "ro.serialno"); 254 | if (serial == null || serial.trim().length() <= 0) { 255 | TelephonyManager tManager = (TelephonyManager) context 256 | .getSystemService(Context.TELEPHONY_SERVICE); 257 | serial = tManager.getDeviceId(); 258 | } 259 | LogUtils.d("Serial:" + serial); 260 | } catch (Exception ignored) { 261 | ignored.printStackTrace(); 262 | } 263 | return serial; 264 | } 265 | 266 | /** 267 | * 判断SDCard是否已满 268 | * 269 | * @return 270 | */ 271 | public boolean isSDCardSizeOverflow() { 272 | boolean result = false; 273 | // 取得SDCard当前的状态 274 | String sDcString = android.os.Environment.getExternalStorageState(); 275 | 276 | if (sDcString.equals(android.os.Environment.MEDIA_MOUNTED)) { 277 | 278 | // 取得sdcard文件路径 279 | File pathFile = android.os.Environment 280 | .getExternalStorageDirectory(); 281 | android.os.StatFs statfs = new android.os.StatFs(pathFile.getPath()); 282 | 283 | // 获取SDCard上BLOCK总数 284 | long nTotalBlocks = statfs.getBlockCount(); 285 | 286 | // 获取SDCard上每个block的SIZE 287 | long nBlocSize = statfs.getBlockSize(); 288 | 289 | // 获取可供程序使用的Block的数量 290 | long nAvailaBlock = statfs.getAvailableBlocks(); 291 | 292 | // 获取剩下的所有Block的数量(包括预留的一般程序无法使用的块) 293 | long nFreeBlock = statfs.getFreeBlocks(); 294 | 295 | // 计算SDCard 总容量大小MB 296 | long nSDTotalSize = nTotalBlocks * nBlocSize / 1024 / 1024; 297 | 298 | // 计算 SDCard 剩余大小MB 299 | long nSDFreeSize = nAvailaBlock * nBlocSize / 1024 / 1024; 300 | if (nSDFreeSize <= 1) { 301 | result = true; 302 | } 303 | }// end of if 304 | // end of func 305 | return result; 306 | } 307 | 308 | /** 309 | * 获取手机屏幕DisplayMetrics属性 310 | * 311 | * @param activity 312 | * @return 313 | */ 314 | public static DisplayMetrics getDisplayMetrics(Activity activity) { 315 | if (activity == null) { 316 | return null; 317 | } 318 | DisplayMetrics metrics = new DisplayMetrics(); 319 | activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); 320 | return metrics; 321 | } 322 | 323 | /** 324 | * 获取当前宽和高 325 | * 326 | * @param activity 327 | * @return 328 | */ 329 | public static String getWidthAndHeight(Activity activity) { 330 | DisplayMetrics displayMetrics = getDisplayMetrics(activity); 331 | if (displayMetrics == null) { 332 | return ""; 333 | } 334 | int heightPixels = displayMetrics.heightPixels; 335 | int widthPixels = displayMetrics.widthPixels; 336 | String retString = heightPixels + "*" + widthPixels; 337 | return retString; 338 | } 339 | 340 | public static boolean checkFsWritable() { 341 | // Create a temporary file to see whether a volume is really writeable. 342 | // It's important not to put it in the root directory which may have a 343 | // limit on the number of files. 344 | 345 | // Logger.d(TAG, "checkFsWritable directoryName == " 346 | // + PathCommonDefines.APP_FOLDER_ON_SD); 347 | File directory = new File(Persistence.APP_FOLDER_ON_SD); 348 | if (!directory.isDirectory()) { 349 | if (!directory.mkdirs()) { 350 | LogUtils.e("checkFsWritable directoryName 000 "); 351 | return false; 352 | } 353 | } 354 | File f = new File(Persistence.APP_FOLDER_ON_SD, ".probe"); 355 | try { 356 | // Remove stale file if any 357 | if (f.exists()) { 358 | f.delete(); 359 | } 360 | if (!f.createNewFile()) { 361 | return false; 362 | } 363 | f.delete(); 364 | return true; 365 | } catch (IOException ex) { 366 | return false; 367 | } 368 | } 369 | 370 | public static boolean hasStorage() { 371 | boolean hasStorage = false; 372 | String str = Environment.getExternalStorageState(); 373 | 374 | if (str.equalsIgnoreCase(Environment.MEDIA_MOUNTED)) { 375 | hasStorage = checkFsWritable(); 376 | } 377 | 378 | return hasStorage; 379 | } 380 | 381 | 382 | public static int freeSpaceOnSd() { 383 | int freeSize = 0; 384 | 385 | if (hasStorage()) { 386 | StatFs statFs = new StatFs(Persistence.APP_FOLDER_ON_SD); 387 | 388 | try { 389 | long nBlocSize = statFs.getBlockSize(); 390 | long nAvailaBlock = statFs.getAvailableBlocks(); 391 | freeSize = (int) (nBlocSize * nAvailaBlock / 1024 / 1024); 392 | 393 | } catch (Exception e) { 394 | e.printStackTrace(); 395 | } 396 | } 397 | return freeSize; 398 | } 399 | } 400 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/PreferencesCookieStore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013. wyouflf (wyouflf@gmail.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package com.ihgoo.allinone.support; 17 | 18 | import android.content.Context; 19 | import android.content.SharedPreferences; 20 | import android.text.TextUtils; 21 | import org.apache.http.client.CookieStore; 22 | import org.apache.http.cookie.Cookie; 23 | import org.apache.http.impl.cookie.BasicClientCookie; 24 | 25 | import java.io.*; 26 | import java.util.ArrayList; 27 | import java.util.Date; 28 | import java.util.List; 29 | import java.util.concurrent.ConcurrentHashMap; 30 | 31 | /** 32 | * A CookieStore impl, it's save cookie to SharedPreferences. 33 | * 34 | * @author michael yang 35 | */ 36 | public class PreferencesCookieStore implements CookieStore { 37 | 38 | private static final String COOKIE_PREFS = "CookiePrefsFile"; 39 | private static final String COOKIE_NAME_STORE = "names"; 40 | private static final String COOKIE_NAME_PREFIX = "cookie_"; 41 | 42 | private final ConcurrentHashMap cookies; 43 | private final SharedPreferences cookiePrefs; 44 | 45 | /** 46 | * Construct a persistent cookie store. 47 | */ 48 | public PreferencesCookieStore(Context context) { 49 | cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, Context.MODE_PRIVATE); 50 | cookies = new ConcurrentHashMap(); 51 | 52 | // Load any previously stored cookies into the store 53 | String storedCookieNames = cookiePrefs.getString(COOKIE_NAME_STORE, null); 54 | if (storedCookieNames != null) { 55 | String[] cookieNames = TextUtils.split(storedCookieNames, ","); 56 | for (String name : cookieNames) { 57 | String encodedCookie = cookiePrefs.getString(COOKIE_NAME_PREFIX + name, null); 58 | if (encodedCookie != null) { 59 | Cookie decodedCookie = decodeCookie(encodedCookie); 60 | if (decodedCookie != null) { 61 | cookies.put(name, decodedCookie); 62 | } 63 | } 64 | } 65 | 66 | // Clear out expired cookies 67 | clearExpired(new Date()); 68 | } 69 | } 70 | 71 | @Override 72 | public void addCookie(Cookie cookie) { 73 | String name = cookie.getName(); 74 | 75 | // Save cookie into local store, or remove if expired 76 | if (!cookie.isExpired(new Date())) { 77 | cookies.put(name, cookie); 78 | } else { 79 | cookies.remove(name); 80 | } 81 | 82 | // Save cookie into persistent store 83 | SharedPreferences.Editor editor = cookiePrefs.edit(); 84 | editor.putString(COOKIE_NAME_STORE, TextUtils.join(",", cookies.keySet())); 85 | editor.putString(COOKIE_NAME_PREFIX + name, encodeCookie(new SerializableCookie(cookie))); 86 | editor.commit(); 87 | } 88 | 89 | @Override 90 | public void clear() { 91 | // Clear cookies from persistent store 92 | SharedPreferences.Editor editor = cookiePrefs.edit(); 93 | for (String name : cookies.keySet()) { 94 | editor.remove(COOKIE_NAME_PREFIX + name); 95 | } 96 | editor.remove(COOKIE_NAME_STORE); 97 | editor.commit(); 98 | 99 | // Clear cookies from local store 100 | cookies.clear(); 101 | } 102 | 103 | @Override 104 | public boolean clearExpired(Date date) { 105 | boolean clearedAny = false; 106 | SharedPreferences.Editor editor = cookiePrefs.edit(); 107 | 108 | for (ConcurrentHashMap.Entry entry : cookies.entrySet()) { 109 | String name = entry.getKey(); 110 | Cookie cookie = entry.getValue(); 111 | if (cookie.getExpiryDate() == null || cookie.isExpired(date)) { 112 | // Remove the cookie by name 113 | cookies.remove(name); 114 | 115 | // Clear cookies from persistent store 116 | editor.remove(COOKIE_NAME_PREFIX + name); 117 | 118 | // We've cleared at least one 119 | clearedAny = true; 120 | } 121 | } 122 | 123 | // Update names in persistent store 124 | if (clearedAny) { 125 | editor.putString(COOKIE_NAME_STORE, TextUtils.join(",", cookies.keySet())); 126 | } 127 | editor.commit(); 128 | 129 | return clearedAny; 130 | } 131 | 132 | @Override 133 | public List getCookies() { 134 | return new ArrayList(cookies.values()); 135 | } 136 | 137 | public Cookie getCookie(String name) { 138 | return cookies.get(name); 139 | } 140 | 141 | 142 | protected String encodeCookie(SerializableCookie cookie) { 143 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 144 | try { 145 | ObjectOutputStream outputStream = new ObjectOutputStream(os); 146 | outputStream.writeObject(cookie); 147 | } catch (Throwable e) { 148 | return null; 149 | } 150 | 151 | return byteArrayToHexString(os.toByteArray()); 152 | } 153 | 154 | protected Cookie decodeCookie(String cookieStr) { 155 | byte[] bytes = hexStringToByteArray(cookieStr); 156 | ByteArrayInputStream is = new ByteArrayInputStream(bytes); 157 | Cookie cookie = null; 158 | try { 159 | ObjectInputStream ois = new ObjectInputStream(is); 160 | cookie = ((SerializableCookie) ois.readObject()).getCookie(); 161 | } catch (Throwable e) { 162 | LogUtils.e(e.getMessage(), e); 163 | } 164 | 165 | return cookie; 166 | } 167 | 168 | // Using some super basic byte array <-> hex conversions so we don't have 169 | // to rely on any large Base64 libraries. Can be overridden if you like! 170 | protected String byteArrayToHexString(byte[] b) { 171 | StringBuffer sb = new StringBuffer(b.length * 2); 172 | for (byte element : b) { 173 | int v = element & 0xff; 174 | if (v < 16) { 175 | sb.append('0'); 176 | } 177 | sb.append(Integer.toHexString(v)); 178 | } 179 | return sb.toString().toUpperCase(); 180 | } 181 | 182 | protected byte[] hexStringToByteArray(String s) { 183 | int len = s.length(); 184 | byte[] data = new byte[len / 2]; 185 | for (int i = 0; i < len; i += 2) { 186 | data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); 187 | } 188 | return data; 189 | } 190 | 191 | 192 | public class SerializableCookie implements Serializable { 193 | private static final long serialVersionUID = 6374381828722046732L; 194 | 195 | private transient final Cookie cookie; 196 | private transient BasicClientCookie clientCookie; 197 | 198 | public SerializableCookie(Cookie cookie) { 199 | this.cookie = cookie; 200 | } 201 | 202 | public Cookie getCookie() { 203 | Cookie bestCookie = cookie; 204 | if (clientCookie != null) { 205 | bestCookie = clientCookie; 206 | } 207 | return bestCookie; 208 | } 209 | 210 | private void writeObject(ObjectOutputStream out) throws IOException { 211 | out.writeObject(cookie.getName()); 212 | out.writeObject(cookie.getValue()); 213 | out.writeObject(cookie.getComment()); 214 | out.writeObject(cookie.getDomain()); 215 | out.writeObject(cookie.getExpiryDate()); 216 | out.writeObject(cookie.getPath()); 217 | out.writeInt(cookie.getVersion()); 218 | out.writeBoolean(cookie.isSecure()); 219 | } 220 | 221 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 222 | String name = (String) in.readObject(); 223 | String value = (String) in.readObject(); 224 | clientCookie = new BasicClientCookie(name, value); 225 | clientCookie.setComment((String) in.readObject()); 226 | clientCookie.setDomain((String) in.readObject()); 227 | clientCookie.setExpiryDate((Date) in.readObject()); 228 | clientCookie.setPath((String) in.readObject()); 229 | clientCookie.setVersion(in.readInt()); 230 | clientCookie.setSecure(in.readBoolean()); 231 | } 232 | } 233 | } -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/ResourceUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | 6 | /** 7 | * Created by ihgoo on 2015/6/16. 8 | */ 9 | public class ResourceUtil { 10 | 11 | /** 12 | * 根据名称返回字符资源的id 13 | * 14 | * @return 正确返回id值,异常返回-1 15 | */ 16 | public static int getStringId(Context context,String fieldName) { 17 | try { 18 | return getResourceId(context, fieldName, "string"); 19 | } catch (Exception e) { 20 | e.printStackTrace(); 21 | return -1; 22 | } 23 | } 24 | 25 | public static int getResourceId(Context context, String fieldName, String type) { 26 | try { 27 | return getResources(context).getIdentifier(fieldName, type, "com.guangzhi.weijianzhi"); 28 | } catch (Exception e) { 29 | e.printStackTrace(); 30 | return -1; 31 | } 32 | } 33 | 34 | private static Resources resources; 35 | /** 36 | * 获取resource 37 | * 38 | * @return 39 | */ 40 | public static synchronized Resources getResources(Context context) { 41 | if (resources == null) { 42 | resources = context.getResources(); 43 | } 44 | return resources; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/ScreenUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.graphics.Rect; 6 | import android.util.DisplayMetrics; 7 | import android.view.Display; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.view.WindowManager; 11 | 12 | /** 13 | * 屏幕大小有关 14 | * 15 | * @author Kelvin 16 | * 17 | */ 18 | public class ScreenUtil { 19 | /** 20 | * 获取屏幕的大小 21 | * 22 | * @param context 23 | * @return 24 | */ 25 | public static Screen getScreenPix(Context context) { 26 | DisplayMetrics dm = new DisplayMetrics(); 27 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 28 | windowManager.getDefaultDisplay().getMetrics(dm); 29 | return new Screen(dm.widthPixels, dm.heightPixels); 30 | } 31 | 32 | /** 33 | * 获取屏幕的宽 34 | * 35 | * @param context 36 | * @return 37 | */ 38 | public static int getScreenWidthPix(Context context) { 39 | DisplayMetrics dm = new DisplayMetrics(); 40 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 41 | windowManager.getDefaultDisplay().getMetrics(dm); 42 | return new Screen(dm.widthPixels, dm.heightPixels).widthPixels; 43 | } 44 | 45 | /** 46 | * 获取屏幕的高 47 | * 48 | * @param context 49 | * @return 50 | */ 51 | public static int getScreenHeightPix(Context context) { 52 | DisplayMetrics dm = new DisplayMetrics(); 53 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 54 | windowManager.getDefaultDisplay().getMetrics(dm); 55 | return new Screen(dm.widthPixels, dm.heightPixels).heightPixels; 56 | } 57 | 58 | public static class Screen { 59 | public int widthPixels; 60 | public int heightPixels; 61 | 62 | public Screen() { 63 | } 64 | 65 | public Screen(int widthPixels, int heightPixels) { 66 | this.widthPixels = widthPixels; 67 | this.heightPixels = heightPixels; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return "(" + widthPixels + "," + heightPixels + ")"; 73 | } 74 | } 75 | 76 | /** 77 | * get fit width for different resolution,input param is width for 720 78 | * 79 | * @param context 80 | * @param inwidth 81 | */ 82 | public static int getFitWidth(Context context, int inwidth) { 83 | if (context == null) 84 | return inwidth; 85 | int screenwidth = getResolution(context)[0]; 86 | return (inwidth * screenwidth) / 720; 87 | } 88 | 89 | /** 90 | * get fit width for different resolution,input param is width for 1180 91 | * 92 | * @param context 93 | * @param inheight 94 | */ 95 | public static int getFitHeight(Context context, int inheight) { 96 | if (context == null) 97 | return inheight; 98 | int screenheight = getResolution(context)[1]; 99 | return (inheight * screenheight) / 1280; 100 | } 101 | 102 | /** 103 | * get resolution 104 | * 105 | * @param context 106 | * @return 107 | */ 108 | public static int[] getResolution(Context context) { 109 | int resolution[] = new int[2]; 110 | // DisplayMetrics dm = new DisplayMetrics(); 111 | // getWindowManger(context).getDefaultDisplay().getMetrics(dm); 112 | Display display = getWindowManger(context).getDefaultDisplay(); 113 | resolution[0] = display.getWidth(); 114 | resolution[1] = display.getHeight(); 115 | return resolution; 116 | } 117 | 118 | /** 119 | * get WindowManager 120 | */ 121 | public static WindowManager getWindowManger(Context context) { 122 | if (context == null) 123 | return null; 124 | WindowManager windowManager = null; 125 | windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 126 | return windowManager; 127 | } 128 | 129 | public static float getDenisty(Context context) { 130 | DisplayMetrics screenDpi = new DisplayMetrics(); 131 | ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(screenDpi); 132 | return screenDpi.density; 133 | } 134 | 135 | /** 136 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 137 | */ 138 | public static int dip2px(Context context,float dpValue) { 139 | final float scale = context.getResources().getDisplayMetrics().density; 140 | return (int) (dpValue * scale + 0.5f); 141 | } 142 | 143 | /** 144 | * double 145 | * 146 | * @return 147 | */ 148 | public static int dip2px(Context context,Double dpValue) { 149 | final float scale = context.getResources().getDisplayMetrics().density; 150 | return (int) (dpValue * scale + 0.5f); 151 | } 152 | 153 | /** 154 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp 155 | */ 156 | public static int px2dip(Context context,float pxValue) { 157 | final float scale = context.getResources().getDisplayMetrics().density; 158 | return (int) (pxValue / scale + 0.5f); 159 | } 160 | 161 | /** 162 | * 获取手机状态栏高度 163 | * 164 | * @return 165 | */ 166 | public static int getStatusBarHeight(Context context) { 167 | Class c = null; 168 | Object obj = null; 169 | java.lang.reflect.Field field = null; 170 | int x = 0; 171 | int statusBarHeight = 0; 172 | try { 173 | c = Class.forName("com.android.internal.R$dimen"); 174 | obj = c.newInstance(); 175 | field = c.getField("status_bar_height"); 176 | x = Integer.parseInt(field.get(obj).toString()); 177 | statusBarHeight = ResourceUtil.getResources(context).getDimensionPixelSize(x); 178 | return statusBarHeight; 179 | } catch (Exception e) { 180 | e.printStackTrace(); 181 | } 182 | return statusBarHeight; 183 | } 184 | 185 | /** 186 | * 获得可视高度 187 | * 188 | * @param parent 189 | * @param son 190 | * @return 191 | */ 192 | public static int getVisiableHeight(ViewGroup parent, View son) { 193 | // parent 的可视区域 194 | /* 195 | * parent.invalidate(); son.invalidate(); 196 | */ 197 | Rect rect = new Rect(); 198 | parent.getHitRect(rect); 199 | int offset = parent.getScrollY(); 200 | int result = rect.height() - (son.getTop() - offset); 201 | return result; 202 | } 203 | 204 | public static Display display = null; 205 | 206 | public static Display getDisplay(Context context) { 207 | if (display == null) { 208 | WindowManager wm = ((Activity) context).getWindowManager(); 209 | display = wm.getDefaultDisplay(); 210 | } 211 | return display; 212 | } 213 | 214 | public static int getScreenWidth(Context context) { 215 | return getDisplay(context).getWidth(); 216 | } 217 | 218 | public static int getScreenHeight(Context context) { 219 | return getDisplay(context).getHeight(); 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/SharePreferenceUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.util.Set; 4 | 5 | import android.R.integer; 6 | import android.R.string; 7 | import android.annotation.TargetApi; 8 | import android.content.Context; 9 | import android.content.SharedPreferences; 10 | import android.content.SharedPreferences.Editor; 11 | import android.os.Build; 12 | 13 | /** 14 | * 15 | * @author Kelvin 16 | * 17 | */ 18 | public class SharePreferenceUtil { 19 | 20 | private static SharedPreferences sp; 21 | private final static String SharePreferncesName = "SP_SETTING"; 22 | 23 | /** 24 | * 25 | * @param context 26 | * @param key 27 | * @param value 28 | * @return 是否保存成功 29 | */ 30 | public static boolean setValue(Context context, String key, Object value) { 31 | if (sp == null) { 32 | sp = context.getSharedPreferences(SharePreferncesName, Context.MODE_PRIVATE); 33 | } 34 | Editor edit = sp.edit(); 35 | if (value instanceof String) { 36 | return edit.putString(key, (String) value).commit(); 37 | } else if (value instanceof Boolean) { 38 | return edit.putBoolean(key, (Boolean) value).commit(); 39 | } else if (value instanceof Float) { 40 | return edit.putFloat(key, (Float) value).commit(); 41 | } else if (value instanceof Integer) { 42 | return edit.putInt(key, (Integer) value).commit(); 43 | } else if (value instanceof Long) { 44 | return edit.putLong(key, (Long) value).commit(); 45 | } else if (value instanceof Set) { 46 | new IllegalArgumentException("Value can not be Set object!"); 47 | return false; 48 | } 49 | return false; 50 | } 51 | 52 | public static boolean getBoolean(Context context, String key) { 53 | if (sp == null) { 54 | sp = context.getSharedPreferences(SharePreferncesName, Context.MODE_PRIVATE); 55 | } 56 | return sp.getBoolean(key, false); 57 | } 58 | 59 | public static String getString(Context context ,String key){ 60 | if (sp == null) { 61 | sp = context.getSharedPreferences(SharePreferncesName, Context.MODE_PRIVATE); 62 | } 63 | return sp.getString(key, ""); 64 | } 65 | 66 | public static Float getFloat(Context context,String key){ 67 | if (sp == null) { 68 | sp = context.getSharedPreferences(SharePreferncesName, Context.MODE_PRIVATE); 69 | } 70 | return sp.getFloat(key, 0f); 71 | } 72 | 73 | public static int getInt(Context context,String key){ 74 | if (sp == null) { 75 | sp = context.getSharedPreferences(SharePreferncesName, Context.MODE_PRIVATE); 76 | } 77 | return sp.getInt(key, 0); 78 | } 79 | 80 | public static long getLong(Context context,String key){ 81 | if (sp == null) { 82 | sp = context.getSharedPreferences(SharePreferncesName, Context.MODE_PRIVATE); 83 | } 84 | return sp.getLong(key, 0); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/ShareUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | 7 | /** 8 | * Created by ihgoo on 2015/6/16. 9 | */ 10 | public class ShareUtil { 11 | /** 12 | * 分享文本信息 13 | * 14 | * @param title 15 | * 分享标题 16 | * @param content 17 | * 分享内容 18 | */ 19 | public static void share(Context context, String content) { 20 | Intent intent = new Intent("android.intent.action.SEND"); 21 | intent.setType("text/plain"); 22 | // intent.putExtra(Intent.EXTRA_SUBJECT, title); 23 | intent.putExtra(Intent.EXTRA_TEXT, content); 24 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 25 | context.startActivity(Intent.createChooser(intent, "分享到")); 26 | } 27 | 28 | /** 29 | * 分享带图片的信息 30 | * 31 | * @param content 32 | * 分享内容 33 | * @param imgPath 34 | * 图片路径,如"file:////sdcard//8.png",注意分享结束后该文件可能被删除,所以请使用临时文件, 35 | * 并分享结束后判断并删除该临时文件 36 | */ 37 | public static void share(Context context, String content, String imgPath) { 38 | Intent intent = new Intent("android.intent.action.SEND"); 39 | 40 | intent.setType("image/*"); 41 | // intent.setType("image/png"); 42 | // intent.putExtra(Intent.EXTRA_SUBJECT, title); 43 | intent.putExtra(Intent.EXTRA_TEXT, content); 44 | intent.putExtra("sms_body", content); 45 | intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(imgPath)); 46 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 47 | context.startActivity(Intent.createChooser(intent, "分享到")); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/ShellUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | import java.io.BufferedReader; 3 | import java.io.DataOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.List; 7 | 8 | /** 9 | * modify form Trinea 10 | * @author trinea 11 | * @date 2014-12-10 12 | */ 13 | public class ShellUtil { 14 | 15 | /** 16 | * check whether has root permission 17 | */ 18 | public static boolean hasRootPermission() { 19 | return execCommand("echo root", true, false).result == 0; 20 | } 21 | 22 | public static CommandResult execCommand(String command, boolean isRoot) { 23 | return execCommand(new String[] {command}, isRoot, true); 24 | } 25 | 26 | public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) { 27 | return execCommand(new String[]{command}, isRoot, isNeedResultMsg); 28 | } 29 | 30 | public static CommandResult execCommand(List commands, boolean isRoot, boolean isNeedResultMsg) { 31 | return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg); 32 | } 33 | 34 | /** 35 | * execute shell commands 36 | * {@link CommandResult#result} is -1, there maybe some excepiton. 37 | * 38 | * @param commands command array 39 | * @param isRoot whether need to run with root 40 | * @param needResponse whether need result msg 41 | */ 42 | public static CommandResult execCommand(String[] commands, boolean isRoot, boolean needResponse) { 43 | int result = -1; 44 | if (commands == null || commands.length == 0) { 45 | return new CommandResult(result, null, "空命令"); 46 | } 47 | 48 | Process process = null; 49 | BufferedReader successResult = null; 50 | BufferedReader errorResult = null; 51 | StringBuilder successMsg = null; 52 | StringBuilder errorMsg = null; 53 | 54 | DataOutputStream os = null; 55 | try { 56 | process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); 57 | os = new DataOutputStream(process.getOutputStream()); 58 | for (String command : commands) { 59 | if (command == null) { 60 | continue; 61 | } 62 | 63 | // donnot use os.writeBytes(commmand), avoid chinese charset error 64 | os.write(command.getBytes()); 65 | os.writeBytes(COMMAND_LINE_END); 66 | os.flush(); 67 | } 68 | os.writeBytes(COMMAND_EXIT); 69 | os.flush(); 70 | 71 | result = process.waitFor(); 72 | if (needResponse) { 73 | successMsg = new StringBuilder(); 74 | errorMsg = new StringBuilder(); 75 | successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); 76 | errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); 77 | String s; 78 | while ((s = successResult.readLine()) != null) { 79 | successMsg.append(s); 80 | } 81 | while ((s = errorResult.readLine()) != null) { 82 | errorMsg.append(s); 83 | } 84 | } 85 | } catch (IOException e) { 86 | e.printStackTrace(); 87 | } catch (Exception e) { 88 | e.printStackTrace(); 89 | } finally { 90 | try { 91 | if (errorResult != null) { 92 | errorResult.close(); 93 | } 94 | if (successResult != null) { 95 | successResult.close(); 96 | } 97 | if (os != null) { 98 | os.close(); 99 | } 100 | } catch (IOException e) { 101 | e.printStackTrace(); 102 | } finally { 103 | if (process != null) { 104 | process.destroy(); 105 | } 106 | } 107 | 108 | } 109 | return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null 110 | : errorMsg.toString()); 111 | } 112 | 113 | public static class CommandResult { 114 | 115 | public int result; 116 | public String responseMsg; 117 | public String errorMsg; 118 | 119 | public CommandResult(int result) { 120 | this.result = result; 121 | } 122 | 123 | public CommandResult(int result, String responseMsg, String errorMsg) { 124 | this.result = result; 125 | this.responseMsg = responseMsg; 126 | this.errorMsg = errorMsg; 127 | } 128 | } 129 | 130 | public static final String COMMAND_SU = "su"; 131 | public static final String COMMAND_SH = "sh"; 132 | public static final String COMMAND_EXIT = "exit\n"; 133 | public static final String COMMAND_LINE_END = "\n"; 134 | 135 | 136 | } -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/SilentInstaller.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | import android.content.Context; 3 | import android.content.pm.ApplicationInfo; 4 | import android.content.pm.PackageManager; 5 | import android.util.Log; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * modify form Trinea 11 | * 12 | * @author trinea 13 | * @date 2014-12-10 14 | */ 15 | public class SilentInstaller { 16 | /** 17 | * Installation return code
18 | * install success. 19 | */ 20 | public static final int INSTALL_SUCCEEDED = 1; 21 | /** 22 | * Installation return code
23 | * the package is already installed. 24 | */ 25 | public static final int INSTALL_FAILED_ALREADY_EXISTS = -1; 26 | 27 | /** 28 | * Installation return code
29 | * the package archive file is invalid. 30 | */ 31 | public static final int INSTALL_FAILED_INVALID_APK = -2; 32 | 33 | /** 34 | * Installation return code
35 | * the URI passed in is invalid. 36 | */ 37 | public static final int INSTALL_FAILED_INVALID_URI = -3; 38 | 39 | /** 40 | * Installation return code
41 | * the package manager service found that the device didn't have enough storage space to install the app. 42 | */ 43 | public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4; 44 | 45 | /** 46 | * Installation return code
47 | * a package is already installed with the same name. 48 | */ 49 | public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5; 50 | 51 | /** 52 | * Installation return code
53 | * the requested shared user does not exist. 54 | */ 55 | public static final int INSTALL_FAILED_NO_SHARED_USER = -6; 56 | 57 | /** 58 | * Installation return code
59 | * a previously installed package of the same name has a different signature than the new package (and the old 60 | * package's data was not removed). 61 | */ 62 | public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7; 63 | 64 | /** 65 | * Installation return code
66 | * the new package is requested a shared user which is already installed on the device and does not have matching 67 | * signature. 68 | */ 69 | public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8; 70 | 71 | /** 72 | * Installation return code
73 | * the new package uses a shared library that is not available. 74 | */ 75 | public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9; 76 | 77 | /** 78 | * Installation return code
79 | * the new package uses a shared library that is not available. 80 | */ 81 | public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10; 82 | 83 | /** 84 | * Installation return code
85 | * the new package failed while optimizing and validating its dex files, either because there was not enough storage 86 | * or the validation failed. 87 | */ 88 | public static final int INSTALL_FAILED_DEXOPT = -11; 89 | 90 | /** 91 | * Installation return code
92 | * the new package failed because the current SDK version is older than that required by the package. 93 | */ 94 | public static final int INSTALL_FAILED_OLDER_SDK = -12; 95 | 96 | /** 97 | * Installation return code
98 | * the new package failed because it contains a content provider with the same authority as a provider already 99 | * installed in the system. 100 | */ 101 | public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13; 102 | 103 | /** 104 | * Installation return code
105 | * the new package failed because the current SDK version is newer than that required by the package. 106 | */ 107 | public static final int INSTALL_FAILED_NEWER_SDK = -14; 108 | 109 | /** 110 | * Installation return code
111 | * the new package failed because it has specified that it is a test-only package and the caller has not supplied 112 | * the {@link #INSTALL_ALLOW_TEST} flag. 113 | */ 114 | public static final int INSTALL_FAILED_TEST_ONLY = -15; 115 | 116 | /** 117 | * Installation return code
118 | * the package being installed contains native code, but none that is compatible with the the device's CPU_ABI. 119 | */ 120 | public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16; 121 | 122 | /** 123 | * Installation return code
124 | * the new package uses a feature that is not available. 125 | */ 126 | public static final int INSTALL_FAILED_MISSING_FEATURE = -17; 127 | 128 | /** 129 | * Installation return code
130 | * a secure container mount point couldn't be accessed on external media. 131 | */ 132 | public static final int INSTALL_FAILED_CONTAINER_ERROR = -18; 133 | 134 | /** 135 | * Installation return code
136 | * the new package couldn't be installed in the specified install location. 137 | */ 138 | public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19; 139 | 140 | /** 141 | * Installation return code
142 | * the new package couldn't be installed in the specified install location because the media is not available. 143 | */ 144 | public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20; 145 | 146 | /** 147 | * Installation return code
148 | * the new package couldn't be installed because the verification timed out. 149 | */ 150 | public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21; 151 | 152 | /** 153 | * Installation return code
154 | * the new package couldn't be installed because the verification did not succeed. 155 | */ 156 | public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22; 157 | 158 | /** 159 | * Installation return code
160 | * the package changed from what the calling program expected. 161 | */ 162 | public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23; 163 | 164 | /** 165 | * Installation return code
166 | * the new package is assigned a different UID than it previously held. 167 | */ 168 | public static final int INSTALL_FAILED_UID_CHANGED = -24; 169 | 170 | /** 171 | * Installation return code
172 | * if the parser was given a path that is not a file, or does not end with the expected '.apk' extension. 173 | */ 174 | public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; 175 | 176 | /** 177 | * Installation return code
178 | * if the parser was unable to retrieve the AndroidManifest.xml file. 179 | */ 180 | public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101; 181 | 182 | /** 183 | * Installation return code
184 | * if the parser encountered an unexpected exception. 185 | */ 186 | public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; 187 | 188 | /** 189 | * Installation return code
190 | * if the parser did not find any certificates in the .apk. 191 | */ 192 | public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; 193 | 194 | /** 195 | * Installation return code
196 | * if the parser found inconsistent certificates on the files in the .apk. 197 | */ 198 | public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104; 199 | 200 | /** 201 | * Installation return code
202 | * if the parser encountered a CertificateEncodingException in one of the files in the .apk. 203 | */ 204 | public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105; 205 | 206 | /** 207 | * Installation return code
208 | * if the parser encountered a bad or missing package name in the manifest. 209 | */ 210 | public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106; 211 | 212 | /** 213 | * Installation return code
214 | * if the parser encountered a bad shared user id name in the manifest. 215 | */ 216 | public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107; 217 | 218 | /** 219 | * Installation return code
220 | * if the parser encountered some structural problem in the manifest. 221 | */ 222 | public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108; 223 | 224 | /** 225 | * Installation return code
226 | * if the parser did not find any actionable tags (instrumentation or application) in the manifest. 227 | */ 228 | public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109; 229 | 230 | /** 231 | * Installation return code
232 | * if the system failed to install the package because of system issues. 233 | */ 234 | public static final int INSTALL_FAILED_INTERNAL_ERROR = -110; 235 | /** 236 | * Installation return code
237 | * other reason 238 | */ 239 | public static final int INSTALL_FAILED_OTHER = -1000000; 240 | 241 | /** 242 | * Uninstall return code
243 | * uninstall success. 244 | */ 245 | public static final int DELETE_SUCCEEDED = 1; 246 | 247 | /** 248 | * Uninstall return code
249 | * uninstall fail if the system failed to delete the package for an unspecified reason. 250 | */ 251 | public static final int DELETE_FAILED_INTERNAL_ERROR = -1; 252 | 253 | /** 254 | * Uninstall return code
255 | * uninstall fail if the system failed to delete the package because it is the active DevicePolicy manager. 256 | */ 257 | public static final int DELETE_FAILED_DEVICE_POLICY_MANAGER = -2; 258 | 259 | /** 260 | * Uninstall return code
261 | * uninstall fail if pcakge name is invalid 262 | */ 263 | public static final int DELETE_FAILED_INVALID_PACKAGE = -3; 264 | 265 | /** 266 | * Uninstall return code
267 | * uninstall fail if permission denied 268 | */ 269 | public static final int DELETE_FAILED_PERMISSION_DENIED = -4; 270 | 271 | private static final String TAG = SilentInstaller.class.getSimpleName(); 272 | 273 | /** 274 | * App installation location flags of android system 275 | */ 276 | public static final int APP_INSTALL_AUTO = 0; 277 | public static final int APP_INSTALL_INTERNAL = 1; 278 | public static final int APP_INSTALL_EXTERNAL = 2; 279 | 280 | /** 281 | * uninstall package and clear data of app silent by root 282 | * 283 | * @param context 284 | * @param packageName package name of app 285 | * @return 286 | * @see #uninstallSilent(Context, String, boolean) 287 | */ 288 | public int uninstallSilent(Context context, String packageName) { 289 | return uninstallSilent(context, packageName, false); 290 | } 291 | 292 | /** 293 | * uninstall package silent by root 294 | *
    295 | * Attentions: 296 | *
  • Don't call this on the ui thread, it may costs some times.
  • 297 | *
  • You should add android.permission.DELETE_PACKAGES in manifest, so no need to request root 298 | * permission, if you are system app.
  • 299 | *
300 | * 301 | * @param context file path of package 302 | * @param packageName package name of app 303 | * @param isKeepData whether keep the data and cache directories around after package removal 304 | * @return
    305 | *
  • {@link #DELETE_SUCCEEDED} means uninstall success
  • 306 | *
  • {@link #DELETE_FAILED_INTERNAL_ERROR} means internal error
  • 307 | *
  • {@link #DELETE_FAILED_INVALID_PACKAGE} means package name error
  • 308 | *
  • {@link #DELETE_FAILED_PERMISSION_DENIED} means permission denied
  • 309 | */ 310 | public int uninstallSilent(Context context, String packageName, boolean isKeepData) { 311 | if (packageName == null || packageName.length() == 0) { 312 | return DELETE_FAILED_INVALID_PACKAGE; 313 | } 314 | 315 | /** 316 | * if context is system app, don't need root permission, but should add in mainfest 318 | **/ 319 | StringBuilder command = new StringBuilder().append("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm uninstall") 320 | .append(isKeepData ? " -k " : " ").append(packageName.replace(" ", "\\ ")); 321 | ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command.toString(), !isSystemApplication(context), true); 322 | if (commandResult.responseMsg != null 323 | && (commandResult.responseMsg.contains("Success") || commandResult.responseMsg.contains("success"))) { 324 | return DELETE_SUCCEEDED; 325 | } 326 | Log.e(TAG, 327 | new StringBuilder().append("uninstallSilent successMsg:").append(commandResult.responseMsg) 328 | .append(", ErrorMsg:").append(commandResult.errorMsg).toString()); 329 | if (commandResult.errorMsg == null) { 330 | return DELETE_FAILED_INTERNAL_ERROR; 331 | } 332 | if (commandResult.errorMsg.contains("Permission denied")) { 333 | return DELETE_FAILED_PERMISSION_DENIED; 334 | } 335 | return DELETE_FAILED_INTERNAL_ERROR; 336 | } 337 | 338 | /** 339 | * install package silent by root 340 | *
      341 | * Attentions: 342 | *
    • Don't call this on the ui thread, it may costs some times.
    • 343 | *
    • You should add android.permission.INSTALL_PACKAGES in manifest, so no need to request root 344 | * permission, if you are system app.
    • 345 | *
    • Default pm install params is "-r".
    • 346 | *
    347 | * 348 | * @param context 349 | * @param filePath file path of package 350 | * @see #installSilent(Context, String, String) 351 | */ 352 | public int installSilent(Context context, String filePath) { 353 | return installSilent(context, filePath, " -r " + getInstallLocationParams()); 354 | } 355 | 356 | /** 357 | * * install package silent by root 358 | *
      359 | * Attentions: 360 | *
    • Don't call this on the ui thread, it may costs some times.
    • 361 | *
    • You should add android.permission.INSTALL_PACKAGES in manifest, so no need to request root 362 | * permission, if you are system app.
    • 363 | *
    364 | */ 365 | public int installSilent(Context context, String filePath, String pmParams) { 366 | if (filePath == null || filePath.length() == 0) { 367 | return INSTALL_FAILED_INVALID_URI; 368 | } 369 | 370 | File file = new File(filePath); 371 | if (file == null || file.length() <= 0 || !file.exists() || !file.isFile()) { 372 | return INSTALL_FAILED_INVALID_URI; 373 | } 374 | 375 | /** 376 | * if context is system app, don't need root permission, but should add in mainfest 378 | **/ 379 | StringBuilder command = new StringBuilder().append("LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install ") 380 | .append(pmParams == null ? "" : pmParams).append(" ").append(filePath.replace(" ", "\\ ")); 381 | ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command.toString(), 382 | !isSystemApplication(context), true); 383 | if (commandResult.responseMsg != null 384 | && (commandResult.responseMsg.contains("Success") || commandResult.responseMsg.contains("success"))) { 385 | return INSTALL_SUCCEEDED; 386 | } 387 | 388 | Log.e(TAG, 389 | new StringBuilder().append("installSilent successMsg:").append(commandResult.responseMsg) 390 | .append(", ErrorMsg:").append(commandResult.errorMsg).toString()); 391 | if (commandResult.errorMsg == null) { 392 | return INSTALL_FAILED_OTHER; 393 | } 394 | if (commandResult.errorMsg.contains("INSTALL_FAILED_ALREADY_EXISTS")) { 395 | return INSTALL_FAILED_ALREADY_EXISTS; 396 | } 397 | if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_APK")) { 398 | return INSTALL_FAILED_INVALID_APK; 399 | } 400 | if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_URI")) { 401 | return INSTALL_FAILED_INVALID_URI; 402 | } 403 | if (commandResult.errorMsg.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE")) { 404 | return INSTALL_FAILED_INSUFFICIENT_STORAGE; 405 | } 406 | if (commandResult.errorMsg.contains("INSTALL_FAILED_DUPLICATE_PACKAGE")) { 407 | return INSTALL_FAILED_DUPLICATE_PACKAGE; 408 | } 409 | if (commandResult.errorMsg.contains("INSTALL_FAILED_NO_SHARED_USER")) { 410 | return INSTALL_FAILED_NO_SHARED_USER; 411 | } 412 | if (commandResult.errorMsg.contains("INSTALL_FAILED_UPDATE_INCOMPATIBLE")) { 413 | return INSTALL_FAILED_UPDATE_INCOMPATIBLE; 414 | } 415 | if (commandResult.errorMsg.contains("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE")) { 416 | return INSTALL_FAILED_SHARED_USER_INCOMPATIBLE; 417 | } 418 | if (commandResult.errorMsg.contains("INSTALL_FAILED_MISSING_SHARED_LIBRARY")) { 419 | return INSTALL_FAILED_MISSING_SHARED_LIBRARY; 420 | } 421 | if (commandResult.errorMsg.contains("INSTALL_FAILED_REPLACE_COULDNT_DELETE")) { 422 | return INSTALL_FAILED_REPLACE_COULDNT_DELETE; 423 | } 424 | if (commandResult.errorMsg.contains("INSTALL_FAILED_DEXOPT")) { 425 | return INSTALL_FAILED_DEXOPT; 426 | } 427 | if (commandResult.errorMsg.contains("INSTALL_FAILED_OLDER_SDK")) { 428 | return INSTALL_FAILED_OLDER_SDK; 429 | } 430 | if (commandResult.errorMsg.contains("INSTALL_FAILED_CONFLICTING_PROVIDER")) { 431 | return INSTALL_FAILED_CONFLICTING_PROVIDER; 432 | } 433 | if (commandResult.errorMsg.contains("INSTALL_FAILED_NEWER_SDK")) { 434 | return INSTALL_FAILED_NEWER_SDK; 435 | } 436 | if (commandResult.errorMsg.contains("INSTALL_FAILED_TEST_ONLY")) { 437 | return INSTALL_FAILED_TEST_ONLY; 438 | } 439 | if (commandResult.errorMsg.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE")) { 440 | return INSTALL_FAILED_CPU_ABI_INCOMPATIBLE; 441 | } 442 | if (commandResult.errorMsg.contains("INSTALL_FAILED_MISSING_FEATURE")) { 443 | return INSTALL_FAILED_MISSING_FEATURE; 444 | } 445 | if (commandResult.errorMsg.contains("INSTALL_FAILED_CONTAINER_ERROR")) { 446 | return INSTALL_FAILED_CONTAINER_ERROR; 447 | } 448 | if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_INSTALL_LOCATION")) { 449 | return INSTALL_FAILED_INVALID_INSTALL_LOCATION; 450 | } 451 | if (commandResult.errorMsg.contains("INSTALL_FAILED_MEDIA_UNAVAILABLE")) { 452 | return INSTALL_FAILED_MEDIA_UNAVAILABLE; 453 | } 454 | if (commandResult.errorMsg.contains("INSTALL_FAILED_VERIFICATION_TIMEOUT")) { 455 | return INSTALL_FAILED_VERIFICATION_TIMEOUT; 456 | } 457 | if (commandResult.errorMsg.contains("INSTALL_FAILED_VERIFICATION_FAILURE")) { 458 | return INSTALL_FAILED_VERIFICATION_FAILURE; 459 | } 460 | if (commandResult.errorMsg.contains("INSTALL_FAILED_PACKAGE_CHANGED")) { 461 | return INSTALL_FAILED_PACKAGE_CHANGED; 462 | } 463 | if (commandResult.errorMsg.contains("INSTALL_FAILED_UID_CHANGED")) { 464 | return INSTALL_FAILED_UID_CHANGED; 465 | } 466 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_NOT_APK")) { 467 | return INSTALL_PARSE_FAILED_NOT_APK; 468 | } 469 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_MANIFEST")) { 470 | return INSTALL_PARSE_FAILED_BAD_MANIFEST; 471 | } 472 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION")) { 473 | return INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; 474 | } 475 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES")) { 476 | return INSTALL_PARSE_FAILED_NO_CERTIFICATES; 477 | } 478 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES")) { 479 | return INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; 480 | } 481 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING")) { 482 | return INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING; 483 | } 484 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME")) { 485 | return INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 486 | } 487 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID")) { 488 | return INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; 489 | } 490 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_MANIFEST_MALFORMED")) { 491 | return INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 492 | } 493 | if (commandResult.errorMsg.contains("INSTALL_PARSE_FAILED_MANIFEST_EMPTY")) { 494 | return INSTALL_PARSE_FAILED_MANIFEST_EMPTY; 495 | } 496 | if (commandResult.errorMsg.contains("INSTALL_FAILED_INTERNAL_ERROR")) { 497 | return INSTALL_FAILED_INTERNAL_ERROR; 498 | } 499 | return INSTALL_FAILED_OTHER; 500 | } 501 | 502 | 503 | /** 504 | * 获取当前系统安装应用的默认位置 505 | * 506 | * @return APP_INSTALL_AUTO or APP_INSTALL_INTERNAL or APP_INSTALL_EXTERNAL. 507 | */ 508 | public int getInstallLocation() { 509 | ShellUtil.CommandResult commandResult = ShellUtil.execCommand( 510 | "LD_LIBRARY_PATH=/vendor/lib:/system/lib pm get-install-location", false, true); 511 | if (commandResult.result == 0 && commandResult.responseMsg != null && commandResult.responseMsg.length() > 0) { 512 | try { 513 | return Integer.parseInt(commandResult.responseMsg.substring(0, 1)); 514 | } catch (NumberFormatException e) { 515 | e.printStackTrace(); 516 | } 517 | } 518 | return APP_INSTALL_AUTO; 519 | } 520 | 521 | /** 522 | * get params for pm install location 523 | * 524 | * @return 525 | */ 526 | private String getInstallLocationParams() { 527 | int location = getInstallLocation(); 528 | switch (location) { 529 | case APP_INSTALL_INTERNAL: 530 | return "-f"; 531 | case APP_INSTALL_EXTERNAL: 532 | return "-s"; 533 | } 534 | return ""; 535 | } 536 | 537 | /** 538 | * /** 539 | * whether packageName is system application 540 | */ 541 | public boolean isSystemApplication(Context context) { 542 | PackageManager packageManager = context.getPackageManager(); 543 | String packageName = context.getPackageName(); 544 | if (packageManager == null || packageName == null || packageName.length() == 0) { 545 | return false; 546 | } 547 | try { 548 | ApplicationInfo app = packageManager.getApplicationInfo(packageName, 0); 549 | return (app != null && (app.flags & ApplicationInfo.FLAG_SYSTEM) > 0); 550 | } catch (Exception e) { 551 | e.printStackTrace(); 552 | } 553 | return false; 554 | } 555 | 556 | } -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/SpanFormatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Twidere - Twitter client for Android 3 | * 4 | * Copyright (C) 2012-2015 Mariotaku Lee 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | package com.ihgoo.allinone.support; 21 | 22 | import android.text.Spannable; 23 | import android.text.SpannableStringBuilder; 24 | import android.text.Spanned; 25 | import android.text.SpannedString; 26 | 27 | import java.util.Locale; 28 | import java.util.regex.Matcher; 29 | import java.util.regex.Pattern; 30 | 31 | /** 32 | * Provides {@link String#format} style functions that work with {@link Spanned} strings and preserve formatting. 33 | * 34 | * @author George T. Steel 35 | */ 36 | public class SpanFormatter { 37 | public static final Pattern FORMAT_SEQUENCE = Pattern.compile("%([0-9]+\\$|once in the result. 46 | * Any duplicates will appear as text only. 47 | * 48 | * @param format the format string (see {@link java.util.Formatter#format}) 49 | * @param args the list of arguments passed to the formatter. If there are 50 | * more arguments than required by {@code format}, 51 | * additional arguments are ignored. 52 | * @return the formatted string (with spans). 53 | */ 54 | public static SpannedString format(CharSequence format, Object... args) { 55 | return format(Locale.getDefault(), format, args); 56 | } 57 | 58 | /** 59 | * Version of {@link String#format(Locale, String, Object...)} that works on {@link Spanned} strings to preserve rich text formatting. 60 | * Both the {@code format} as well as any {@code %s args} can be Spanned and will have their formatting preserved. 61 | * Due to the way {@link Spannable}s work, any argument's spans will can only be included once in the result. 62 | * Any duplicates will appear as text only. 63 | * 64 | * @param locale the locale to apply; {@code null} value means no localization. 65 | * @param format the format string (see {@link java.util.Formatter#format}) 66 | * @param args the list of arguments passed to the formatter. 67 | * @return the formatted string (with spans). 68 | * @see String#format(Locale, String, Object...) 69 | */ 70 | public static SpannedString format(Locale locale, CharSequence format, Object... args) { 71 | SpannableStringBuilder out = new SpannableStringBuilder(format); 72 | 73 | int i = 0; 74 | int argAt = -1; 75 | 76 | while (i < out.length()) { 77 | Matcher m = FORMAT_SEQUENCE.matcher(out); 78 | if (!m.find(i)) break; 79 | i = m.start(); 80 | int exprEnd = m.end(); 81 | 82 | String argTerm = m.group(1); 83 | String modTerm = m.group(2); 84 | String typeTerm = m.group(3); 85 | 86 | CharSequence cookedArg; 87 | 88 | if (typeTerm.equals("%")) { 89 | cookedArg = "%"; 90 | } else if (typeTerm.equals("%")) { 91 | cookedArg = "\n"; 92 | } else { 93 | int argIdx = 0; 94 | if (argTerm.equals("")) argIdx = ++argAt; 95 | else if (argTerm.equals("<")) argIdx = argAt; 96 | else argIdx = Integer.parseInt(argTerm.substring(0, argTerm.length() - 1)) - 1; 97 | 98 | Object argItem = args[argIdx]; 99 | 100 | if (typeTerm.equals("s") && argItem instanceof Spanned) { 101 | cookedArg = (Spanned) argItem; 102 | } else { 103 | cookedArg = String.format(locale, "%" + modTerm + typeTerm, argItem); 104 | } 105 | } 106 | 107 | out.replace(i, exprEnd, cookedArg); 108 | i += cookedArg.length(); 109 | } 110 | 111 | return new SpannedString(out); 112 | } 113 | } -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import org.json.JSONObject; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * Created by ihgoo on 2015/6/16. 10 | */ 11 | public class StringUtil { 12 | 13 | public static String quoteString(Object object, String left, String right) { 14 | return left.concat(object.toString()).concat(right); 15 | } 16 | 17 | public static String concat(Object... objects) { 18 | 19 | String str = new String(); 20 | if (objects != null) { 21 | for (Object object : objects) { 22 | if (object != null) { 23 | try { 24 | str = str.concat(object.toString()); 25 | } catch (Exception e) { 26 | } 27 | } 28 | } 29 | } 30 | return str; 31 | } 32 | 33 | public static String join(Set list) { 34 | return join(list.toArray(), ","); 35 | } 36 | 37 | public static String join(Object[] objects) { 38 | return join(objects, ","); 39 | } 40 | 41 | public static String join(Object[] objects, String glue) { 42 | int k = objects.length; 43 | if (k == 0) 44 | return ""; 45 | StringBuilder out = new StringBuilder(); 46 | out.append(objects[0]); 47 | for (int x = 1; x < k; ++x) 48 | out.append(glue).append(objects[x]); 49 | return out.toString(); 50 | } 51 | public static String toString(Object object) { 52 | String result = "错误:null"; 53 | if (object != null) { 54 | result = object.toString(); 55 | } 56 | return result; 57 | } 58 | /** 59 | * @param string string以逗号分隔返回string的hashset 60 | * @return 61 | */ 62 | public static HashSet parseKeys(String string) { 63 | HashSet keywords = new HashSet(); 64 | if (string != null) { 65 | for (String key : string.split(",")) { 66 | keywords.add(key); 67 | } 68 | } 69 | return keywords; 70 | } 71 | 72 | /** 73 | * @param objects 74 | * @param glue 75 | * @param left 76 | * @param right 77 | * @return 78 | */ 79 | public static String joinWithQuote(Object[] objects, String glue, String left, String right) { 80 | int k = objects.length; 81 | if (k == 0) 82 | return null; 83 | StringBuilder out = new StringBuilder(); 84 | out.append(quoteString(objects[0], left, right)); 85 | for (int x = 1; x < k; ++x) 86 | out.append(glue).append(quoteString(objects[x], left, right)); 87 | return out.toString(); 88 | } 89 | public static String getStr(JSONObject jsonObject, String name) { 90 | String result = ""; 91 | try { 92 | if (jsonObject != null && jsonObject.has(name)) { 93 | result = jsonObject.getString(name); 94 | } 95 | } catch (Exception e) { 96 | e.printStackTrace(); 97 | } 98 | return result; 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | import android.annotation.SuppressLint; 7 | import android.text.TextUtils; 8 | 9 | public final class StringUtils { 10 | 11 | /** 12 | * 判断字符串是否为null或"" 13 | * 14 | * @param string 15 | * @return 为空或null返回false,否则返回true 16 | */ 17 | @SuppressLint("NewApi") 18 | public static boolean isNull(String string) { 19 | if (string == null && "".equals(string)) { 20 | return false; 21 | } 22 | return true; 23 | } 24 | 25 | public static String join(String[] array, String sep) { 26 | if (array == null) { 27 | return null; 28 | } 29 | 30 | int arraySize = array.length; 31 | int sepSize = 0; 32 | if (sep != null && !sep.equals("")) { 33 | sepSize = sep.length(); 34 | } 35 | 36 | int bufSize = (arraySize == 0 ? 0 : ((array[0] == null ? 16 : array[0] 37 | .length()) + sepSize) * arraySize); 38 | StringBuilder buf = new StringBuilder(bufSize); 39 | 40 | for (int i = 0; i < arraySize; i++) { 41 | if (i > 0) { 42 | buf.append(sep); 43 | } 44 | if (array[i] != null) { 45 | buf.append(array[i]); 46 | } 47 | } 48 | return buf.toString(); 49 | } 50 | 51 | // no null in array 52 | public static String jsonJoin(String[] array) { 53 | int arraySize = array.length; 54 | int bufSize = arraySize * (array[0].length() + 3); 55 | StringBuilder buf = new StringBuilder(bufSize); 56 | for (int i = 0; i < arraySize; i++) { 57 | if (i > 0) { 58 | buf.append(','); 59 | } 60 | 61 | buf.append('"'); 62 | buf.append(array[i]); 63 | buf.append('"'); 64 | } 65 | return buf.toString(); 66 | } 67 | 68 | /** 69 | * 将长字符从截取剩下的用...代替 70 | * 71 | * @param input 72 | * @param count 73 | * @return 74 | */ 75 | public static String cutString(String input, int count) { 76 | return cutString(input, count, null); 77 | } 78 | 79 | /** 80 | * 将长字符从截取剩下的用more代替,more为空则用省略号代替 81 | * 82 | * @param input 83 | * @param count 84 | * @param more 85 | * @return 86 | */ 87 | public static String cutString(String input, int count, String more) { 88 | String resultString = ""; 89 | if (input != null) { 90 | if (more == null) { 91 | more = "..."; 92 | } 93 | if (input.length() > count) { 94 | resultString = input.substring(0, count) + more; 95 | } else { 96 | resultString = input; 97 | } 98 | } 99 | return resultString; 100 | } 101 | 102 | /** 103 | * 获得指定中文长度对应的字符串长度,用于截取显示文字,一个中文等于两个英文 104 | * 105 | * @param chineseLengthForDisplay 106 | * @param content 107 | * @return 108 | */ 109 | public static int chineseWidth2StringLenth(int chineseLengthForDisplay, String string) { 110 | int result = 0; 111 | int displayWidth = chineseLengthForDisplay * 2; 112 | if (string != null) { 113 | for (char chr : string.toCharArray()) { 114 | // 中文 115 | if (chr >= 0x4e00 && chr <= 0x9fbb) { 116 | displayWidth -= 2; 117 | } else { 118 | // 英文 119 | displayWidth -= 1; 120 | } 121 | if (displayWidth <= 0) { 122 | break; 123 | } 124 | result++; 125 | } 126 | } 127 | return result; 128 | } 129 | 130 | /** 131 | * 将长时间格式字符串转换为字符串,默认为yyyy-MM-dd HH:mm:ss 132 | * 133 | * @param time 134 | * long型时间,支持毫秒和秒 135 | * 136 | * @param dataFormat 137 | * 需要返回的时间格式,例如: yyyy-MM-dd, yyyy-MM-dd HH:mm:ss 138 | * 139 | * @return dataFormat格式的时间结果字符串 140 | */ 141 | public static String dateFormat(long milliseconds, String dataFormat) { 142 | long tempTimestamp = milliseconds > 9999999999L ? milliseconds : milliseconds *1000; 143 | if (TextUtils.isEmpty(dataFormat)) { 144 | dataFormat = "yyyy-MM-dd HH:mm:ss"; 145 | } 146 | Date date = new Date(tempTimestamp * 1l); 147 | SimpleDateFormat formatter = new SimpleDateFormat(dataFormat); 148 | return formatter.format(date); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/TimeUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import java.util.Date; 7 | import java.util.Formatter; 8 | import java.util.Locale; 9 | 10 | import android.util.TimeUtils; 11 | 12 | /** 13 | * Created by ihgoo on 2015/6/16. 14 | */ 15 | public class TimeUtil { 16 | /** 17 | * 时间转换 输入一个string 输出 yyyy/MM/dd HH:mm 18 | */ 19 | public static String getDateFromStr(String strTime) { 20 | String date; 21 | if (strTime != null && !"".equals(strTime)) { 22 | 23 | long updateTime = Long.parseLong(strTime); 24 | SimpleDateFormat dateformat1 = new SimpleDateFormat("yyyy/MM/dd HH:mm"); 25 | date = dateformat1.format(new Date(updateTime * 1000)); 26 | return date; 27 | } else { 28 | return ""; 29 | } 30 | } 31 | 32 | /** 33 | * 不乘1000 34 | * 时间转换 输入一个string 输出 yyyy-MM-dd 35 | */ 36 | public static String getDateFromStr2(String strTime) { 37 | String date; 38 | if (strTime != null && !"".equals(strTime)) { 39 | 40 | long updateTime = Long.parseLong(strTime); 41 | SimpleDateFormat dateformat1 = new SimpleDateFormat("yyyy-MM-dd"); 42 | date = dateformat1.format(new Date(updateTime)); 43 | return date; 44 | } else { 45 | return ""; 46 | } 47 | } 48 | 49 | public static String timeFormat(long date) { 50 | long ssaa = new Date().getTime(); 51 | long delta = ssaa - date; 52 | final String ONE_SECOND_AGO = "秒前"; 53 | final String ONE_MINUTE_AGO = "分钟前"; 54 | final String ONE_HOUR_AGO = "小时前"; 55 | final String ONE_DAY_AGO = "天前"; 56 | final long ONE_MINUTE = 60000L; 57 | final long ONE_HOUR = 3600000L; 58 | final long ONE_DAY = 86400000L; 59 | if (delta < 1L * ONE_MINUTE) { 60 | long seconds = toSeconds(delta); 61 | return (seconds <= 0 ? 1 : seconds) + ONE_SECOND_AGO; 62 | } 63 | if (delta < 45L * ONE_MINUTE) { 64 | long minutes = toMinutes(delta); 65 | return (minutes <= 0 ? 1 : minutes) + ONE_MINUTE_AGO; 66 | } 67 | if (delta < 24L * ONE_HOUR) { 68 | long hours = toHours(delta); 69 | return (hours <= 0 ? 1 : hours) + ONE_HOUR_AGO; 70 | } 71 | if (delta < 48L * ONE_HOUR) { 72 | return "昨天"; 73 | } 74 | if (delta < 30L * ONE_DAY) { 75 | long days = toDays(delta); 76 | return (days <= 0 ? 1 : days) + ONE_DAY_AGO; 77 | } else { 78 | String time111 = getDateStr(date); 79 | return time111; 80 | } 81 | } 82 | 83 | private static long toSeconds(long date) { 84 | return date / 1000L; 85 | } 86 | 87 | private static long toMinutes(long date) { 88 | return toSeconds(date) / 60L; 89 | } 90 | 91 | private static long toHours(long date) { 92 | return toMinutes(date) / 60L; 93 | } 94 | 95 | private static long toDays(long date) { 96 | return toHours(date) / 24L; 97 | } 98 | 99 | private static long toMonths(long date) { 100 | return toDays(date) / 30L; 101 | } 102 | 103 | private static String getDateStr(long millis) { 104 | Calendar cal = Calendar.getInstance(); 105 | cal.setTimeInMillis(millis); 106 | Formatter ft = new Formatter(Locale.CHINA); 107 | return ft.format("%1$tY年%1$tm月%1$td日", cal).toString(); 108 | } 109 | 110 | 111 | /** 112 | * 将yyyy-MM-dd HH:mm:ss格式的时间字符串格式化成yyyy年MM月dd日格式的字符串 113 | * 114 | * @param dataString 115 | * @return 116 | */ 117 | public static String paserData2Data(String dataString) { 118 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 119 | long l = 0; 120 | try { 121 | Date d = sdf.parse(dataString); 122 | l = d.getTime(); 123 | } catch (ParseException e) { 124 | e.printStackTrace(); 125 | } 126 | SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日"); 127 | long lcc_time = Long.valueOf(l + ""); 128 | return sdf1.format(new Date(lcc_time)); 129 | } 130 | 131 | 132 | public static String paserDataNB(String timeStmp) { 133 | long i = ParseUtil.parseLong(timeStmp, 0); 134 | SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 135 | long lcc_time = Long.valueOf(i + ""); 136 | return sdf1.format(new Date(lcc_time)); 137 | } 138 | 139 | public static String parserData2ymd(String timeStmp) { 140 | long i = ParseUtil.parseLong(timeStmp, 0); 141 | SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd"); 142 | long lcc_time = Long.valueOf(i + ""); 143 | return sdf1.format(new Date(lcc_time)); 144 | } 145 | 146 | /** 147 | * 根据日期字符串判断当月第几周 148 | * 149 | * @param str 150 | * @return 151 | * @throws Exception 152 | */ 153 | public static int getWeek(String str) { 154 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 155 | Date date = null; 156 | try { 157 | date = sdf.parse(str); 158 | } catch (ParseException e) { 159 | e.printStackTrace(); 160 | } 161 | Calendar calendar = Calendar.getInstance(); 162 | calendar.setTime(date); 163 | //第几周 164 | int week = calendar.get(Calendar.WEEK_OF_MONTH); 165 | //第几天,从周日开始 166 | int day = calendar.get(Calendar.DAY_OF_WEEK); 167 | return day - 1; 168 | } 169 | 170 | /** 171 | * 得到指定月的天数 172 | */ 173 | public static int getMonthLastDay(int year, int month) { 174 | Calendar a = Calendar.getInstance(); 175 | a.set(Calendar.YEAR, year); 176 | a.set(Calendar.MONTH, month - 1); 177 | a.set(Calendar.DATE, 1);//把日期设置为当月第一天 178 | a.roll(Calendar.DATE, -1);//日期回滚一天,也就是最后一天 179 | int maxDate = a.get(Calendar.DATE); 180 | return maxDate; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/TrafficUtils.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import android.content.Context; 7 | import android.content.pm.ApplicationInfo; 8 | import android.content.pm.PackageManager; 9 | import android.content.pm.PackageManager.NameNotFoundException; 10 | import android.net.TrafficStats; 11 | 12 | import com.ihgoo.allinone.BuildConfig; 13 | 14 | /** 15 | * User: mcxiaoke 16 | * Date: 14-6-3 17 | * Time: 16:17 18 | */ 19 | public abstract class TrafficUtils { 20 | private static final String TAG = TrafficUtils.class.getSimpleName(); 21 | private static final boolean DEBUG = BuildConfig.DEBUG; 22 | 23 | public static final String TAG_SESSION = "session_traffic_info"; 24 | 25 | private static Map sReceivedBytes = new HashMap(); 26 | private static Map sSendBytes = new HashMap(); 27 | 28 | private TrafficUtils() { 29 | } 30 | 31 | /** 32 | * 开始流量统计 33 | * 34 | * @param context Context 35 | * @param tag traffic tag 36 | * @return received bytes 37 | */ 38 | public static long start(Context context, String tag) { 39 | final int uid = getUid(context); 40 | if (uid > 0) { 41 | long appRxValue = TrafficStats.getUidRxBytes(uid); 42 | long appTxValue = TrafficStats.getUidTxBytes(uid); 43 | sReceivedBytes.put(tag, appRxValue); 44 | sSendBytes.put(tag, appTxValue); 45 | if (DEBUG) { 46 | LogUtils.v("start() rxValue=" + appRxValue / 1000 + " txValue=" + appTxValue / 1000 + " uid=" + uid); 47 | } 48 | return appRxValue; 49 | } 50 | return 0; 51 | } 52 | 53 | /** 54 | * 计算当前流量 55 | * 56 | * @param context Context 57 | * @param tag traffic tag 58 | * @return received bytes 59 | */ 60 | public static long current(Context context, String tag) { 61 | Long appRxValue = sReceivedBytes.get(tag); 62 | Long appTxValue = sSendBytes.get(tag); 63 | if (appRxValue == null || appRxValue == null) { 64 | if (DEBUG) { 65 | LogUtils.w("current() appRxValue or appTxValue is null."); 66 | } 67 | return 0; 68 | } 69 | final int uid = getUid(context); 70 | long appRxValue2 = TrafficStats.getUidRxBytes(uid); 71 | long appTxValue2 = TrafficStats.getUidTxBytes(uid); 72 | long rxValue = appRxValue2 - appRxValue; 73 | long txValue = appTxValue2 - appTxValue; 74 | if (DEBUG) { 75 | LogUtils.v("current() rxValue=" + rxValue / 1000 + " txValue=" + txValue / 1000 + " uid=" + uid); 76 | } 77 | return rxValue; 78 | 79 | } 80 | 81 | /** 82 | * 统计TAG流量 83 | * 84 | * @param context Context 85 | * @param tag traffic tag 86 | * @return received bytes 87 | */ 88 | public static long stop(Context context, String tag) { 89 | Long appRxValue = sReceivedBytes.remove(tag); 90 | Long appTxValue = sSendBytes.remove(tag); 91 | if (appRxValue == null || appRxValue == null) { 92 | if (DEBUG) { 93 | LogUtils.w("stop() appRxValue or appTxValue is null."); 94 | } 95 | return 0; 96 | } 97 | final int uid = getUid(context); 98 | long appRxValue2 = TrafficStats.getUidRxBytes(uid); 99 | long appTxValue2 = TrafficStats.getUidTxBytes(uid); 100 | long rxValue = appRxValue2 - appRxValue; 101 | long txValue = appTxValue2 - appTxValue; 102 | if (DEBUG) { 103 | LogUtils.v("stop() rxValue=" + rxValue / 1000 + " txValue=" + txValue / 1000 + " uid=" + uid); 104 | } 105 | return rxValue; 106 | 107 | } 108 | 109 | public static int getUid(Context context) { 110 | try { 111 | final PackageManager pm = context.getPackageManager(); 112 | final String pn = context.getPackageName(); 113 | ApplicationInfo ai = pm.getApplicationInfo(pn, 0); 114 | return ai.uid; 115 | } catch (NameNotFoundException e) { 116 | if (DEBUG) { 117 | LogUtils.e("getUid() ex=" + e); 118 | } 119 | 120 | return -1; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/com/ihgoo/allinone/support/ViewUtil.java: -------------------------------------------------------------------------------- 1 | package com.ihgoo.allinone.support; 2 | 3 | import android.content.Context; 4 | import android.text.Html; 5 | import android.text.SpannableStringBuilder; 6 | import android.text.Spanned; 7 | import android.text.style.ForegroundColorSpan; 8 | import android.text.style.RelativeSizeSpan; 9 | import android.text.style.StyleSpan; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.ListAdapter; 14 | import android.widget.ListView; 15 | import android.widget.TextView; 16 | 17 | /** 18 | * Created by ihgoo on 2015/6/16. 19 | */ 20 | public class ViewUtil { 21 | 22 | public static void setUnderLine(TextView textView, String text1, String text2) { 23 | textView.setText(Html.fromHtml(text1 + "" + text2 + "")); 24 | } 25 | 26 | /** 27 | * @param color 28 | * @param relative 29 | * @param str 30 | * @return 31 | */ 32 | public static CharSequence getSpan(int color, float relative, CharSequence str) { 33 | SpannableStringBuilder sb = new SpannableStringBuilder(str); 34 | sb.setSpan(new ForegroundColorSpan(color), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 35 | if (relative != 1f) { 36 | sb.setSpan(new RelativeSizeSpan(relative), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 37 | } 38 | return sb; 39 | } 40 | 41 | /** 42 | * @param color 43 | * @param relative 44 | * @param typeFace 45 | * @param str 46 | * @return 47 | */ 48 | public static CharSequence getSpan(int color, float relative, int typeFace, CharSequence str) { 49 | SpannableStringBuilder sb = new SpannableStringBuilder(str); 50 | sb.setSpan(new ForegroundColorSpan(color), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 51 | if (relative != 1f) { 52 | sb.setSpan(new RelativeSizeSpan(relative), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 53 | } 54 | sb.setSpan(new StyleSpan(typeFace), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 55 | return sb; 56 | } 57 | 58 | public static View getSpaceViewForListView(Context context,int width, int height) { 59 | View view = new TextView(context); 60 | view.setLayoutParams(new ListView.LayoutParams(width, height)); 61 | return view; 62 | } 63 | 64 | public static View inflate(Context context,int id) { 65 | return LayoutInflater.from(context).inflate(id, null); 66 | } 67 | 68 | /** 69 | * 计算listview的高度,但子ListView每个Item必须是LinearLayout 70 | * 71 | * @param listView 72 | */ 73 | public static void setListViewHeightBasedOnChildren(ListView listView) { 74 | ListAdapter listAdapter = listView.getAdapter(); 75 | if (listAdapter == null) { 76 | // pre-condition 77 | return; 78 | } 79 | 80 | int totalHeight = 0; 81 | for (int i = 0; i < listAdapter.getCount(); i++) { 82 | View listItem = listAdapter.getView(i, null, listView); 83 | listItem.measure(0, 0); 84 | totalHeight += listItem.getMeasuredHeight() + 5; 85 | } 86 | 87 | ViewGroup.LayoutParams params = listView.getLayoutParams(); 88 | params.height = totalHeight 89 | + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); 90 | listView.setLayoutParams(params); 91 | } 92 | 93 | } 94 | --------------------------------------------------------------------------------