Repository: wzgiceman/ALibrary Branch: master Commit: aab1c1e48c67 Files: 21 Total size: 162.7 KB Directory structure: gitextract_6vu0r5a9/ ├── README.md ├── abLibraryUtils.iml ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties └── src/ └── main/ ├── AndroidManifest.xml └── java/ └── com/ └── ab/ ├── global/ │ └── AbAppConfig.java └── util/ ├── AbAppUtil.java ├── AbDateUtil.java ├── AbFileUtil.java ├── AbGraphicUtil.java ├── AbImageUtil.java ├── AbLogUtil.java ├── AbMathUtil.java ├── AbMd5.java ├── AbSharedUtil.java ├── AbStrUtil.java └── AbViewUtil.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # Android常用开发工具类 ## 应用工具类 [ **`AbAppUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbAppUtil.java) * 读取application 节点 meta-data 信息`readMetaDataFromApplication` * 打开并安装文件 `installApk` * 卸载程序 `uninstallApk` * 用来判断服务是否运行 `isServiceRunning` * 停止服务 `stopRunningService` * 判断网络是否有效 `isNetworkAvailable` * Gps是否打开 `isGpsEnabled` * 判断当前网络是否是移动数据网络 `isMobile` * 导入数据库 `importDatabase` * 获取屏幕尺寸与密度 `getDisplayMetrics` * 打开键盘 `showSoftInput` * 关闭键盘事件 `closeSoftInput` * 获取包信息 `getPackageInfo` * 获取当前版本号 `getVersionName` * 获取开发版本号 `getVersionCode` * 是否存在该包名的应用 `exitAppBy` ## 日期处理类 [**`AbDateUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbDateUtil.java) * String类型的日期时间转化为Date类型 `getDateByFormat` * 获取偏移之后的Date `getDateByOffset` * 获取指定日期时间的字符串(可偏移) `getStringByOffset` * Date类型转化为String类型(可偏移) `getStringByOffset` * Date类型转化为String类型 `getStringByFormat` * 获取指定日期时间的字符串,用于导出想要的格式 `getStringByFormat` * 获取milliseconds表示的日期时间的字符串 `getStringByFormat` * 获取表示当前日期时间的字符串 `getCurrentDate` * 获取表示当前日期时间的字符串(可偏移) `getCurrentDateByOffset` * 计算两个日期所差的天数 `getOffectDay` * 计算两个日期所差的小时数 `getOffectHour` * 计算两个日期所差的分钟数 `getOffectMinutes` * 获取本周一 `getFirstDayOfWeek` * 获取本周日 `getLastDayOfWeek` * 获取本周的某一天 `getDayOfWeek` * 获取本月第一天 `getFirstDayOfMonth` * 获取本月最后一天 `getLastDayOfMonth` * 获取表示当前日期的0点时间毫秒数 `getFirstTimeOfDay` * 获取表示当前日期24点时间毫秒数 `getLastTimeOfDay` * 判断是否是闰年 `isLeapYear` * 根据时间返回格式化后的时间的描述. 小于1小时显示多少分钟前 大于1小时显示今天+实际日期,大于今天全部显示实际时间`formatDateStr2Desc` * 取指定日期为星期几 `getWeekNumber` * 根据给定的日期判断是否为上下午 `getTimeQuantum` * 根据给定的毫秒数算得时间的描述 `getTimeDescription` * 解析时间按照小时:分:秒格式输出 `getTime` ## 文件操作类 [**`AbFileUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbFileUtil.java) * 通过文件的网络地址从SD卡中读取图片,如果SD中没有则自动下载并保存 `getBitmapFromSD` * 通过文件的本地地址从SD卡读取图片 `getBitmapFromSD` * 通过文件的本地地址从SD卡读取图片 `getBitmapFromSD` * 将图片的byte[]写入本地文件 `getBitmapFromByte` * 根据URL从互连网获取图片 `getBitmapFromURL` * 获取src中的图片资源 `getBitmapFromSrc` * 获取Asset中的图片资源 `getBitmapFromAsset` `getDrawableFromAsset` * 下载网络文件到SD卡中.如果SD中存在同名文件将不再下载 `downloadFile` * 获取网络文件的大小 `getContentLengthFromUrl` * 获取文件名,通过网络获取 `getRealFileNameFromUrl` * 获取真实文件名(xx.后缀),通过网络获取 `getRealFileName` * 获取文件名(不含后缀) `getCacheFileNameFromUrl` * 获取文件名(.后缀),外链模式和通过网络获取 `getCacheFileNameFromUrl` * 获取文件后缀,本地 `getMIMEFromUrl` * 从sd卡中的文件读取到byte `getByteArrayFromSD` * 将byte数组写入文件 `writeByteArrayToSD` * SD卡是否能用 `isCanUseSD` * 计算sdcard上的剩余空间 `freeSpaceOnSD` * 根据文件的最后修改时间进行排序 `FileLastModifSort` * 删除所有缓存文件 `clearDownloadFile` * 读取Assets目录的文件内容 `readAssetsByName` * 读取Raw目录的文件内容 `readRawByName` * 解压缩功能. 将zipFile文件解压到folderPath目录下 `upZipFile` * 给定根目录,返回一个相对路径所对应的实际文件名.(压缩文件) `getRealFileName` * 打开pdf文件 `openPdfFile` * 删除文件,可以是单个文件或文件夹 `delete` * 删除单个文件 `deleteFile` * 删除目录(文件夹)以及目录下的文件 `deleteDirectory` * 获取下载根目录 `getDownloadRootDir` * 获取图片下载根目录 `getImageDownloadDir` * 获取文件下载根目录`getFileDownloadDir` * 本地缓存的目录 `getCacheDownloadDir` * 本地数据库目录 `getDbDownloadDir` * 缓存中可用的大小 `getFreeSdSpaceNeededToCache` ## 图形处理类 [**`AbGraphicUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbGraphicUtil.java) * 获取字符的所在位置(按像素获取最大能容纳的)`subStringLength` * 获取文字的像素宽 `getStringWidth` * 获得文字的宽度 `getDesiredWidth` * 获取文字的高度 `getDesiredHeight` * 字符解析成行 `getDrawRowStr` * 获取这段文本多少行 `getDrawRowCount` * 绘制文本,支持换行 `drawText` ## 图片处理类 [**`AbImageUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbImageUtil.java) * 解析bitmap `getBitmapByte` * 直接获取互联网上的图片 `getBitmap` * 获取原图 `getBitmap` * 缩放图片.压缩 `scaleImg` * 缩放图片,不压缩的缩放 * 裁剪图片 `cutImg` * Drawable转Bitmap `drawableToBitmap` * Bitmap对象转换Drawable对象. `bitmapToDrawable` * Bitmap对象转换TransitionDrawable对象 `bitmapToTransitionDrawable` * Drawable对象转换TransitionDrawable对象 `drawableToTransitionDrawable` * 将Bitmap转换为byte[] `bitmap2Bytes` * 获取Bitmap大小 `getByteCount` * 将byte[]转换为Bitmap `bytes2Bimap` * 将View转换为Drawable.需要最上层布局为Linearlayout `view2Drawable` * 将View转换为Bitmap.需要最上层布局为Linearlayout `view2Bitmap` * 将View转换为byte[] `view2Bytes` * 旋转Bitmap为一定的角度 `rotateBitmap` * 旋转Bitmap为一定的角度并四周暗化处理 `rotateBitmapTranslate` * 转换图片转换成圆形 `toRoundBitmap` * 转换图片转换成圆形通过指定的弧度 `toRoundBitmap` * 转换图片转换成镜面效果的图片 `toReflectionBitmap` * 释放Bitmap对象 `releaseBitmap` * 释放Bitmap数组 `releaseBitmapArray` * 简单的图像的特征值,用于缩略图找原图比较好 `getHashCode` * 图像的特征值颜色分布 将颜色分4个区,0,1,2,3 区组合共64组,计算每个像素点属于哪个区 `getColorHistogram` * 计算"汉明距离"(Hamming distance)`hammingDistance` * 灰度值计算 `rgbToGray` * 压缩图片 `compressBitmap` * 根据URI获取图片物理路径 `getAbsoluteImagePath` ## 日志工具类 [**`AbLogUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbLogUtil.java) ## 数学处理类 [**`AbMathUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbMathUtil.java) * 四舍五入 `round` * 字节数组转换成16进制串 `byte2HexStr` * 二进制转为十六进制 `binaryToHex` * 一维数组转为二维数组 `arrayToMatrix` * 二维数组转为一维数组 `matrixToArray` * int数组转换为double数组 `intToDoubleArray` * int二维数组转换为double二维数组. `intToDoubleMatrix` * 计算数组的平均值 `average` * 点在直线上 `pointAtSLine` * 点在线段上 `pointAtELine` * 两条直线相交 `LineAtLine` * 线段与线段相交 `eLineAtELine` * 点在矩形内 `pointAtRect` * 矩形在矩形内 `rectAtRect` * 圆心在矩形内 `circleAtRect` * 获取两点间的距离 `getDistance` * 矩形碰撞检测 参数为x,y,width,height `isRectCollision` ## MD5加密 [**`AbMd5`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbMd5.java) * MD5加密 `MD5` ## 保存到 SharedPreferences 的数据 [**`AbSharedUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbSharedUtil.java) ## 字符串处理类 [**`AbStrUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbStrUtil.java) * 给填写搜索单词的关键词显示 特殊颜色 `changeTextColor` * 将null转化为“” `parseEmpty` * 判断一个字符串是否为null或空值 `isEmpty` * 集合是否为空 `isEmpty` * 获取字符串中文字符的长度(每个中文算2个字符) `chineseLength` * 获取字符串的长度 `strLength` * 获取指定长度的字符所在位置 `subStringLength` * 手机号格式验证 `isMobileNo` * 是否只是字母和数字 `isNumberLetter` * 是否只是数字 `isNumber` * 是否是邮箱 `isEmail` * 是否是中文 `isChinese` * 是否包含中文 `isContainChinese` * 是否包含中文数字字母的用户名 `isConintChinseUser` * 从输入流中获得String `convertStreamToString` * 标准化日期时间类型的数据,不足两位的补0 `dateTimeFormat` * 不足2个字符的在前面补“0” `strFormat2` * 截取字符串到指定字节长度 `cutString` * 截取字符串从第一个指定字符 `cutStringFromChar` * 获取字节长度 `strlen` * 获取大小的描述 `getSizeDesc` * ip地址转换为10进制数 `ip2int` ## View工具类 [**`AbViewUtil`**](https://github.com/wzgiceman/ALibrary/blob/master/src/main/java/com/ab/util/AbViewUtil.java) * 测量这个view `measureView` * 获得这个View的宽度 `getViewWidth` * 获得这个View的高度 `getViewHeight` * 从父亲布局中移除自己 `removeSelfFromParent` * dip转换为px `dip2px` * px转换为dip `px2dip` * sp转换为px `sp2px` * px转换为sp `px2sp` * 根据屏幕大小缩放 `scale` * 根据屏幕大小缩放 `scale` * TypedValue官方源码中的算法,任意单位转换为PX单位 `applyDimension` * View树递归调用做适配 `scaleContentView` * 按比例缩放View,以布局中的尺寸为基准 `scaleView` * 缩放文字大小 `setSPTextSize` * 缩放文字大小,这样设置的好处是文字的大小不和密度有关 `setTextSize` * 缩放文字大小 `setTextSize` * 设置View的PX尺寸 `setViewSize` * 设置PX padding. `setPadding` * 设置 PX margin `setMargin` ================================================ FILE: abLibraryUtils.iml ================================================ ================================================ FILE: build.gradle ================================================ apply plugin: 'com.android.library' android { compileSdkVersion 23 buildToolsVersion "23.0.3" defaultConfig { minSdkVersion 16 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Mon Dec 28 10:00:20 PST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip ================================================ FILE: gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: local.properties ================================================ ## This file is automatically generated by Android Studio. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # # This file must *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. #Tue Mar 01 14:22:54 CST 2016 sdk.dir=E\:\\Android+tool\\sdk\\sdk ================================================ FILE: src/main/AndroidManifest.xml ================================================ ================================================ FILE: src/main/java/com/ab/global/AbAppConfig.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.global; import java.io.File; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn 名称:AbAppConfig.java 描述:初始设置类. * * @author 还如一梦中 * @version v1.0 @date:2014-07-03 下午1:33:39 */ public class AbAppConfig { /** UI设计的基准宽度. */ public static int UI_WIDTH = 720; /** UI设计的基准高度. */ public static int UI_HEIGHT = 1080; /** 默认 SharePreferences文件名. */ public static String SHARED_PATH = "app_share"; /** 默认下载文件地址. */ public static String DOWNLOAD_ROOT_DIR = "Android" + File.separator + "data"; /** 默认下载图片文件地址. */ public static String DOWNLOAD_IMAGE_DIR = "images"; /** 默认下载文件地址. */ public static String DOWNLOAD_FILE_DIR = "files"; /** APP缓存目录. */ public static String CACHE_DIR = "caches"; /** DB目录. */ public static String DB_DIR = "db"; } ================================================ FILE: src/main/java/com/ab/util/AbAppUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.util.DisplayMetrics; import android.view.inputmethod.InputMethodManager; import java.io.File; import java.io.FileFilter; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; /** * 描述:应用工具类. */ public class AbAppUtil { /** * 读取application 节点 meta-data 信息 */ public static String readMetaDataFromApplication(Context context, String key) { try { ApplicationInfo appInfo = context.getPackageManager() .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); return appInfo.metaData.getString(key); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return null; } } /** * 描述:打开并安装文件. * * @param context the context * @param file apk文件路径 */ public static void installApk(Context context, File file) { Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); context.startActivity(intent); } /** * 描述:卸载程序. * * @param context the context * @param packageName 包名 */ public static void uninstallApk(Context context, String packageName) { Intent intent = new Intent(Intent.ACTION_DELETE); Uri packageURI = Uri.parse("package:" + packageName); intent.setData(packageURI); context.startActivity(intent); } /** * 用来判断服务是否运行. * * @param ctx the ctx * @param className 判断的服务名字 "com.xxx.xx..XXXService" * @return true 在运行 false 不在运行 */ public static boolean isServiceRunning(Context ctx, String className) { boolean isRunning = false; ActivityManager activityManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE); List servicesList = activityManager.getRunningServices(Integer.MAX_VALUE); Iterator l = servicesList.iterator(); while (l.hasNext()) { RunningServiceInfo si = (RunningServiceInfo) l.next(); if (className.equals(si.service.getClassName())) { isRunning = true; } } return isRunning; } /** * 停止服务. * * @param ctx the ctx * @param className the class name * @return true, if successful */ public static boolean stopRunningService(Context ctx, String className) { Intent intent_service = null; boolean ret = false; try { intent_service = new Intent(ctx, Class.forName(className)); } catch (Exception e) { e.printStackTrace(); } if (intent_service != null) { ret = ctx.stopService(intent_service); } return ret; } /** * Gets the number of cores available in this device, across all processors. * Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu" * * @return The number of cores, or 1 if failed to get result */ public static int getNumCores() { try { //Get directory containing CPU info File dir = new File("/sys/devices/system/cpu/"); //Filter to only list the devices we care about File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { //Check if filename is "cpu", followed by a single digit number if (Pattern.matches("cpu[0-9]", pathname.getName())) { return true; } return false; } }); //Return the number of cores (virtual CPU devices) return files.length; } catch (Exception e) { //Default to return 1 core return 1; } } /** * 描述:判断网络是否有效. * * @param context the context * @return true, if is network available */ public static boolean isNetworkAvailable(Context context) { try { ConnectivityManager connectivity = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivity != null) { NetworkInfo info = connectivity.getActiveNetworkInfo(); if (info != null && info.isConnected()) { if (info.getState() == NetworkInfo.State.CONNECTED) { return true; } } } } catch (Exception e) { e.printStackTrace(); return false; } return false; } /** * Gps是否打开 * 需要权限 * * @param context the context * @return true, if is gps enabled */ public static boolean isGpsEnabled(Context context) { LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); return lm.isProviderEnabled(LocationManager.GPS_PROVIDER); } /** * 判断当前网络是否是移动数据网络. * * @param context the context * @return boolean */ public static boolean isMobile(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); if (activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) { return true; } return false; } /** * 导入数据库. * * @param context the context * @param dbName the db name * @param rawRes the raw res * @return true, if successful */ public static boolean importDatabase(Context context, String dbName, int rawRes) { int buffer_size = 1024; InputStream is = null; FileOutputStream fos = null; boolean flag = false; try { String dbPath = "/data/data/" + context.getPackageName() + "/databases/" + dbName; File dbfile = new File(dbPath); //判断数据库文件是否存在,若不存在则执行导入,否则直接打开数据库 if (!dbfile.exists()) { //欲导入的数据库 if (!dbfile.getParentFile().exists()) { dbfile.getParentFile().mkdirs(); } dbfile.createNewFile(); is = context.getResources().openRawResource(rawRes); fos = new FileOutputStream(dbfile); byte[] buffer = new byte[buffer_size]; int count = 0; while ((count = is.read(buffer)) > 0) { fos.write(buffer, 0, count); } fos.flush(); } flag = true; } catch (Exception e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (Exception e) { } } if (is != null) { try { is.close(); } catch (Exception e) { } } } return flag; } /** * 获取屏幕尺寸与密度. * * @param context the context * @return mDisplayMetrics */ public static DisplayMetrics getDisplayMetrics(Context context) { Resources mResources; if (context == null) { mResources = Resources.getSystem(); } else { mResources = context.getResources(); } //DisplayMetrics{density=1.5, width=480, height=854, scaledDensity=1.5, xdpi=160.421, ydpi=159.497} //DisplayMetrics{density=2.0, width=720, height=1280, scaledDensity=2.0, xdpi=160.42105, ydpi=160.15764} DisplayMetrics mDisplayMetrics = mResources.getDisplayMetrics(); return mDisplayMetrics; } /** * 打开键盘. * * @param context the context */ public static void showSoftInput(Context context) { InputMethodManager inputMethodManager = (InputMethodManager) context .getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); } /** * 关闭键盘事件. * * @param context the context */ public static void closeSoftInput(Context context) { InputMethodManager inputMethodManager = (InputMethodManager) context .getSystemService(Context.INPUT_METHOD_SERVICE); if (inputMethodManager != null && ((Activity) context).getCurrentFocus() != null) { inputMethodManager.hideSoftInputFromWindow(((Activity) context).getCurrentFocus() .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } /** * 获取包信息. * * @param context the context */ public static PackageInfo getPackageInfo(Context context) { PackageInfo info = null; try { String packageName = context.getPackageName(); info = context.getPackageManager().getPackageInfo(packageName, 0); } catch (Exception e) { e.printStackTrace(); } return info; } /** * 获取当前版本号 * * @return * @throws Exception */ public static String getVersionName(Context context) { StringBuilder builder = new StringBuilder("v"); try { PackageInfo packInfo = getPackageInfo(context); builder.append(packInfo.versionName); } catch (Exception e) { e.printStackTrace(); } return builder.toString(); } /** * 获取开发版本号 * * @param context * @return */ public static String getVersionCode(Context context) { StringBuilder builder = new StringBuilder(); try { PackageInfo packInfo = getPackageInfo(context); builder.append(packInfo.versionCode); } catch (Exception e) { e.printStackTrace(); } return builder.toString(); } /** * 是否存在该包名的应用 * * @param context * @return */ public static boolean exitAppBy(Context context, String packageName) { final PackageManager packageManager = context.getPackageManager();// 获取packagemanager List pinfo = packageManager.getInstalledPackages(0);// 获取所有已安装程序的包信息 if (pinfo != null) { for (int i = 0; i < pinfo.size(); i++) { String pn = pinfo.get(i).packageName; if (pn.equals(packageName)) { return true; } } } return false; } } ================================================ FILE: src/main/java/com/ab/util/AbDateUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn 名称:AbDateUtil.java 描述:日期处理类. * */ public class AbDateUtil { /** 时间日期格式化到年月日时分秒. */ public static final String dateFormatYMDHMS = "yyyy-MM-dd HH:mm:ss"; /** 时间日期格式化到年月日. */ public static final String dateFormatYMD = "yyyy-MM-dd"; /** 时间日期格式化到年月. */ public static final String dateFormatYM = "yyyy-MM"; /** 时间日期格式化到年月日时分. */ public static final String dateFormatYMDHM = "yyyy-MM-dd HH:mm"; /** 时间日期格式化到月日. */ public static final String dateFormatMD = "MM/dd"; /** 时分秒. */ public static final String dateFormatHMS = "HH:mm:ss"; /** 时分. */ public static final String dateFormatHM = "HH:mm"; /** 上午. */ public static final String AM = "AM"; /** 下午. */ public static final String PM = "PM"; /** * 描述:String类型的日期时间转化为Date类型. * * @param strDate * String形式的日期时间 * @param format * 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return Date Date类型日期时间 */ public static Date getDateByFormat(String strDate, String format) { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); Date date = null; try { date = mSimpleDateFormat.parse(strDate); } catch (ParseException e) { e.printStackTrace(); } return date; } /** * 描述:获取偏移之后的Date. * * @param date * 日期时间 * @param calendarField * Calendar属性,对应offset的值, * 如(Calendar.DATE,表示+offset天,Calendar.HOUR_OF_DAY,表示+offset小时) * @param offset * 偏移(值大于0,表示+,值小于0,表示-) * @return Date 偏移之后的日期时间 */ public Date getDateByOffset(Date date, int calendarField, int offset) { Calendar c = new GregorianCalendar(); try { c.setTime(date); c.add(calendarField, offset); } catch (Exception e) { e.printStackTrace(); } return c.getTime(); } /** * 描述:获取指定日期时间的字符串(可偏移). * * @param strDate * String形式的日期时间 * @param format * 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @param calendarField * Calendar属性,对应offset的值, * 如(Calendar.DATE,表示+offset天,Calendar.HOUR_OF_DAY,表示+offset小时) * @param offset * 偏移(值大于0,表示+,值小于0,表示-) * @return String String类型的日期时间 */ public static String getStringByOffset(String strDate, String format, int calendarField, int offset) { String mDateTime = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); c.setTime(mSimpleDateFormat.parse(strDate)); c.add(calendarField, offset); mDateTime = mSimpleDateFormat.format(c.getTime()); } catch (ParseException e) { e.printStackTrace(); } return mDateTime; } /** * 描述:Date类型转化为String类型(可偏移). * * @param date * the date * @param format * the format * @param calendarField * the calendar field * @param offset * the offset * @return String String类型日期时间 */ public static String getStringByOffset(Date date, String format, int calendarField, int offset) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); c.setTime(date); c.add(calendarField, offset); strDate = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:Date类型转化为String类型. * * @param date * the date * @param format * the format * @return String String类型日期时间 */ public static String getStringByFormat(Date date, String format) { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); String strDate = null; try { strDate = mSimpleDateFormat.format(date); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取指定日期时间的字符串,用于导出想要的格式. * * @param strDate * String形式的日期时间,必须为yyyy-MM-dd HH:mm:ss格式 * @param format * 输出格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return String 转换后的String类型的日期时间 */ public static String getStringByFormat(String strDate, String format) { String mDateTime = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(dateFormatYMDHMS); c.setTime(mSimpleDateFormat.parse(strDate)); SimpleDateFormat mSimpleDateFormat2 = new SimpleDateFormat(format); mDateTime = mSimpleDateFormat2.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return mDateTime; } /** * 描述:获取milliseconds表示的日期时间的字符串. * * @param milliseconds * the milliseconds * @param format * 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return String 日期时间字符串 */ public static String getStringByFormat(long milliseconds, String format) { String thisDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); thisDateTime = mSimpleDateFormat.format(milliseconds); } catch (Exception e) { e.printStackTrace(); } return thisDateTime; } /** * 描述:获取表示当前日期时间的字符串. * * @param format * 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @return String String类型的当前日期时间 */ public static String getCurrentDate(String format) { AbLogUtil.d(AbDateUtil.class, "getCurrentDate:" + format); String curDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); Calendar c = new GregorianCalendar(); curDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return curDateTime; } /** * 描述:获取表示当前日期时间的字符串(可偏移). * * @param format * 格式化字符串,如:"yyyy-MM-dd HH:mm:ss" * @param calendarField * Calendar属性,对应offset的值, * 如(Calendar.DATE,表示+offset天,Calendar.HOUR_OF_DAY,表示+offset小时) * @param offset * 偏移(值大于0,表示+,值小于0,表示-) * @return String String类型的日期时间 */ public static String getCurrentDateByOffset(String format, int calendarField, int offset) { String mDateTime = null; try { SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); Calendar c = new GregorianCalendar(); c.add(calendarField, offset); mDateTime = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return mDateTime; } /** * 描述:计算两个日期所差的天数. * * @param milliseconds1 * the milliseconds1 * @param milliseconds2 * the milliseconds2 * @return int 所差的天数 */ public static int getOffectDay(long milliseconds1, long milliseconds2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTimeInMillis(milliseconds1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTimeInMillis(milliseconds2); // 先判断是否同年 int y1 = calendar1.get(Calendar.YEAR); int y2 = calendar2.get(Calendar.YEAR); int d1 = calendar1.get(Calendar.DAY_OF_YEAR); int d2 = calendar2.get(Calendar.DAY_OF_YEAR); int maxDays = 0; int day = 0; if (y1 - y2 > 0) { maxDays = calendar2.getActualMaximum(Calendar.DAY_OF_YEAR); day = d1 - d2 + maxDays; } else if (y1 - y2 < 0) { maxDays = calendar1.getActualMaximum(Calendar.DAY_OF_YEAR); day = d1 - d2 - maxDays; } else { day = d1 - d2; } return day; } /** * 描述:计算两个日期所差的小时数. * * @param date1 * 第一个时间的毫秒表示 * @param date2 * 第二个时间的毫秒表示 * @return int 所差的小时数 */ public static int getOffectHour(long date1, long date2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTimeInMillis(date1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTimeInMillis(date2); int h1 = calendar1.get(Calendar.HOUR_OF_DAY); int h2 = calendar2.get(Calendar.HOUR_OF_DAY); int h = 0; int day = getOffectDay(date1, date2); h = h1 - h2 + day * 24; return h; } /** * 描述:计算两个日期所差的分钟数. * * @param date1 * 第一个时间的毫秒表示 * @param date2 * 第二个时间的毫秒表示 * @return int 所差的分钟数 */ public static int getOffectMinutes(long date1, long date2) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTimeInMillis(date1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTimeInMillis(date2); int m1 = calendar1.get(Calendar.MINUTE); int m2 = calendar2.get(Calendar.MINUTE); int h = getOffectHour(date1, date2); int m = 0; m = m1 - m2 + h * 60; return m; } /** * 描述:获取本周一. * * @param format * the format * @return String String类型日期时间 */ public static String getFirstDayOfWeek(String format) { return getDayOfWeek(format, Calendar.MONDAY); } /** * 描述:获取本周日. * * @param format * the format * @return String String类型日期时间 */ public static String getLastDayOfWeek(String format) { return getDayOfWeek(format, Calendar.SUNDAY); } /** * 描述:获取本周的某一天. * * @param format * the format * @param calendarField * the calendar field * @return String String类型日期时间 */ private static String getDayOfWeek(String format, int calendarField) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); int week = c.get(Calendar.DAY_OF_WEEK); if (week == calendarField) { strDate = mSimpleDateFormat.format(c.getTime()); } else { int offectDay = calendarField - week; if (calendarField == Calendar.SUNDAY) { offectDay = 7 - Math.abs(offectDay); } c.add(Calendar.DATE, offectDay); strDate = mSimpleDateFormat.format(c.getTime()); } } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取本月第一天. * * @param format * the format * @return String String类型日期时间 */ public static String getFirstDayOfMonth(String format) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); // 当前月的第一天 c.set(GregorianCalendar.DAY_OF_MONTH, 1); strDate = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取本月最后一天. * * @param format * the format * @return String String类型日期时间 */ public static String getLastDayOfMonth(String format) { String strDate = null; try { Calendar c = new GregorianCalendar(); SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format); // 当前月的最后一天 c.set(Calendar.DATE, 1); c.roll(Calendar.DATE, -1); strDate = mSimpleDateFormat.format(c.getTime()); } catch (Exception e) { e.printStackTrace(); } return strDate; } /** * 描述:获取表示当前日期的0点时间毫秒数. * * @return the first time of day */ public static long getFirstTimeOfDay() { Date date = null; try { String currentDate = getCurrentDate(dateFormatYMD); date = getDateByFormat(currentDate + " 00:00:00", dateFormatYMDHMS); return date.getTime(); } catch (Exception e) { } return -1; } /** * 描述:获取表示当前日期24点时间毫秒数. * * @return the last time of day */ public static long getLastTimeOfDay() { Date date = null; try { String currentDate = getCurrentDate(dateFormatYMD); date = getDateByFormat(currentDate + " 24:00:00", dateFormatYMDHMS); return date.getTime(); } catch (Exception e) { } return -1; } /** * 描述:判断是否是闰年() *

* (year能被4整除 并且 不能被100整除) 或者 year能被400整除,则该年为闰年. * * @param year * 年代(如2012) * @return boolean 是否为闰年 */ public static boolean isLeapYear(int year) { if ((year % 4 == 0 && year % 400 != 0) || year % 400 == 0) { return true; } else { return false; } } /** * 描述:根据时间返回格式化后的时间的描述. 小于1小时显示多少分钟前 大于1小时显示今天+实际日期,大于今天全部显示实际时间 * * @param strDate * the str date * @param outFormat * the out format * @return the string */ public static String formatDateStr2Desc(String strDate, String outFormat) { DateFormat df = new SimpleDateFormat(dateFormatYMDHMS); Calendar c1 = Calendar.getInstance(); Calendar c2 = Calendar.getInstance(); try { c2.setTime(df.parse(strDate)); c1.setTime(new Date()); int d = getOffectDay(c1.getTimeInMillis(), c2.getTimeInMillis()); if (d == 0) { int h = getOffectHour(c1.getTimeInMillis(), c2.getTimeInMillis()); if (h > 0) { return "今天" + getStringByFormat(strDate, dateFormatHM); // return h + "小时前"; } else if (h < 0) { // return Math.abs(h) + "小时后"; } else if (h == 0) { int m = getOffectMinutes(c1.getTimeInMillis(), c2.getTimeInMillis()); if (m > 0) { return m + "分钟前"; } else if (m < 0) { // return Math.abs(m) + "分钟后"; } else { return "刚刚"; } } } else if (d > 0) { if (d == 1) { // return "昨天"+getStringByFormat(strDate,outFormat); } else if (d == 2) { // return "前天"+getStringByFormat(strDate,outFormat); } } else if (d < 0) { if (d == -1) { // return "明天"+getStringByFormat(strDate,outFormat); } else if (d == -2) { // return "后天"+getStringByFormat(strDate,outFormat); } else { // return Math.abs(d) + // "天后"+getStringByFormat(strDate,outFormat); } } String out = getStringByFormat(strDate, outFormat); if (!AbStrUtil.isEmpty(out)) { return out; } } catch (Exception e) { } return strDate; } /** * 取指定日期为星期几. * * @param strDate * 指定日期 * @param inFormat * 指定日期格式 * @return String 星期几 */ public static String getWeekNumber(String strDate, String inFormat) { String week = "星期日"; Calendar calendar = new GregorianCalendar(); DateFormat df = new SimpleDateFormat(inFormat); try { calendar.setTime(df.parse(strDate)); } catch (Exception e) { return "错误"; } int intTemp = calendar.get(Calendar.DAY_OF_WEEK) - 1; switch (intTemp) { case 0: week = "星期日"; break; case 1: week = "星期一"; break; case 2: week = "星期二"; break; case 3: week = "星期三"; break; case 4: week = "星期四"; break; case 5: week = "星期五"; break; case 6: week = "星期六"; break; } return week; } /** * 根据给定的日期判断是否为上下午. * * @param strDate * the str date * @param format * the format * @return the time quantum */ public static String getTimeQuantum(String strDate, String format) { Date mDate = getDateByFormat(strDate, format); int hour = mDate.getHours(); if (hour >= 12) return "PM"; else return "AM"; } /** * 根据给定的毫秒数算得时间的描述. * * @param milliseconds * the milliseconds * @return the time description */ public static String getTimeDescription(long milliseconds) { if (milliseconds > 1000) { // 大于一分 if (milliseconds / 1000 / 60 > 1) { long minute = milliseconds / 1000 / 60; long second = milliseconds / 1000 % 60; return minute + "分" + second + "秒"; } else { // 显示秒 return milliseconds / 1000 + "秒"; } } else { return milliseconds + "毫秒"; } } /** * 解析时间按照小时:分:秒格式输出 * * @param iTimeSeconds 秒 * @return */ public static String getTime(int iTimeSeconds) { String strUserTime = iTimeSeconds / 60 + " : " + ((iTimeSeconds % 60) < 10 ? ("0" + iTimeSeconds % 60) : iTimeSeconds % 60); return strUserTime; } } ================================================ FILE: src/main/java/com/ab/util/AbFileUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Environment; import android.os.StatFs; import android.util.Log; import com.ab.global.AbAppConfig; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.util.Comparator; import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn 名称:AbFileUtil.java 描述:文件操作类. */ public class AbFileUtil { /** 默认APP根目录. */ private static String downloadRootDir = null; /** 默认下载图片文件目录. */ private static String imageDownloadDir = null; /** 默认下载文件目录. */ private static String fileDownloadDir = null; /** 默认缓存目录. */ private static String cacheDownloadDir = null; /** 默认下载数据库文件的目录. */ private static String dbDownloadDir = null; /** 剩余空间大于200M才使用SD缓存. */ private static int freeSdSpaceNeededToCache = 200 * 1024 * 1024; /** * 描述:通过文件的网络地址从SD卡中读取图片,如果SD中没有则自动下载并保存. * * @param url * 文件的网络地址 * @param type * 图片的处理类型(剪切或者缩放到指定大小,参考AbImageUtil类) 如果设置为原图,则后边参数无效,得到原图 * @param desiredWidth * 新图片的宽 * @param desiredHeight * 新图片的高 * @return Bitmap 新图片 */ public static Bitmap getBitmapFromSD(String url, int type, int desiredWidth, int desiredHeight) { Bitmap bitmap = null; try { if (AbStrUtil.isEmpty(url)) { return null; } // SD卡不存在 或者剩余空间不足了就不缓存到SD卡了 if (!isCanUseSD() || freeSdSpaceNeededToCache < freeSpaceOnSD()) { bitmap = getBitmapFromURL(url, type, desiredWidth, desiredHeight); return bitmap; } // 下载文件,如果不存在就下载,存在直接返回地址 String downFilePath = downloadFile(url, imageDownloadDir); if (downFilePath != null) { // 获取图片 return getBitmapFromSD(new File(downFilePath), type, desiredWidth, desiredHeight); } else { return null; } } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** * 描述:通过文件的本地地址从SD卡读取图片. * * @param file * the file * @param type * 图片的处理类型(剪切或者缩放到指定大小,参考AbConstant类) 如果设置为原图,则后边参数无效,得到原图 * @param desiredWidth * 新图片的宽 * @param desiredHeight * 新图片的高 * @return Bitmap 新图片 */ public static Bitmap getBitmapFromSD(File file, int type, int desiredWidth, int desiredHeight) { Bitmap bitmap = null; try { // SD卡是否存在 if (!isCanUseSD()) { return null; } // 文件是否存在 if (!file.exists()) { return null; } // 文件存在 if (type == AbImageUtil.CUTIMG) { bitmap = AbImageUtil.cutImg(file, desiredWidth, desiredHeight); } else if (type == AbImageUtil.SCALEIMG) { bitmap = AbImageUtil.scaleImg(file, desiredWidth, desiredHeight); } else { bitmap = AbImageUtil.getBitmap(file); } } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** * 描述:通过文件的本地地址从SD卡读取图片. * * @param file * the file * @return Bitmap 图片 */ public static Bitmap getBitmapFromSD(File file) { Bitmap bitmap = null; try { // SD卡是否存在 if (!isCanUseSD()) { return null; } // 文件是否存在 if (!file.exists()) { return null; } // 文件存在 bitmap = AbImageUtil.getBitmap(file); } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** * 描述:将图片的byte[]写入本地文件. * * @param imgByte * 图片的byte[]形势 * @param fileName * 文件名称,需要包含后缀,如.jpg * @param type * 图片的处理类型(剪切或者缩放到指定大小,参考AbConstant类) * @param desiredWidth * 新图片的宽 * @param desiredHeight * 新图片的高 * @return Bitmap 新图片 */ public static Bitmap getBitmapFromByte(byte[] imgByte, String fileName, int type, int desiredWidth, int desiredHeight) { FileOutputStream fos = null; DataInputStream dis = null; ByteArrayInputStream bis = null; Bitmap bitmap = null; File file = null; try { if (imgByte != null) { file = new File(imageDownloadDir + fileName); if (!file.exists()) { file.createNewFile(); } fos = new FileOutputStream(file); int readLength = 0; bis = new ByteArrayInputStream(imgByte); dis = new DataInputStream(bis); byte[] buffer = new byte[1024]; while ((readLength = dis.read(buffer)) != -1) { fos.write(buffer, 0, readLength); try { Thread.sleep(500); } catch (Exception e) { } } fos.flush(); bitmap = getBitmapFromSD(file, type, desiredWidth, desiredHeight); } } catch (Exception e) { e.printStackTrace(); } finally { if (dis != null) { try { dis.close(); } catch (Exception e) { } } if (bis != null) { try { bis.close(); } catch (Exception e) { } } if (fos != null) { try { fos.close(); } catch (Exception e) { } } } return bitmap; } /** * 描述:根据URL从互连网获取图片. * * @param url * 要下载文件的网络地址 * @param type * 图片的处理类型(剪切或者缩放到指定大小,参考AbConstant类) * @param desiredWidth * 新图片的宽 * @param desiredHeight * 新图片的高 * @return Bitmap 新图片 */ public static Bitmap getBitmapFromURL(String url, int type, int desiredWidth, int desiredHeight) { Bitmap bit = null; try { bit = AbImageUtil.getBitmap(url, type, desiredWidth, desiredHeight); } catch (Exception e) { AbLogUtil.d(AbFileUtil.class, "下载图片异常:" + e.getMessage()); } return bit; } /** * 描述:获取src中的图片资源. * * @param src * 图片的src路径,如(“image/arrow.png”) * @return Bitmap 图片 */ public static Bitmap getBitmapFromSrc(String src) { Bitmap bit = null; try { bit = BitmapFactory.decodeStream(AbFileUtil.class.getResourceAsStream(src)); } catch (Exception e) { AbLogUtil.d(AbFileUtil.class, "获取图片异常:" + e.getMessage()); } return bit; } /** * 描述:获取Asset中的图片资源. * * @param context * the context * @param fileName * the file name * @return Bitmap 图片 */ public static Bitmap getBitmapFromAsset(Context context, String fileName) { Bitmap bit = null; try { AssetManager assetManager = context.getAssets(); InputStream is = assetManager.open(fileName); bit = BitmapFactory.decodeStream(is); } catch (Exception e) { AbLogUtil.d(AbFileUtil.class, "获取图片异常:" + e.getMessage()); } return bit; } /** * 描述:获取Asset中的图片资源. * * @param context * the context * @param fileName * the file name * @return Drawable 图片 */ public static Drawable getDrawableFromAsset(Context context, String fileName) { Drawable drawable = null; try { AssetManager assetManager = context.getAssets(); InputStream is = assetManager.open(fileName); drawable = Drawable.createFromStream(is, null); } catch (Exception e) { AbLogUtil.d(AbFileUtil.class, "获取图片异常:" + e.getMessage()); } return drawable; } /** * 下载网络文件到SD卡中.如果SD中存在同名文件将不再下载 * * @param url * 要下载文件的网络地址 * @param dirPath * the dir path * @return 下载好的本地文件地址 */ public static String downloadFile(String url, String dirPath) { InputStream in = null; FileOutputStream fileOutputStream = null; HttpURLConnection connection = null; String downFilePath = null; File file = null; try { if (!isCanUseSD()) { return null; } // 先判断SD卡中有没有这个文件,不比较后缀部分比较 String fileNameNoMIME = getCacheFileNameFromUrl(url); File parentFile = new File(imageDownloadDir); File[] files = parentFile.listFiles(); for (int i = 0; i < files.length; ++i) { String fileName = files[i].getName(); String name = fileName.substring(0, fileName.lastIndexOf(".")); if (name.equals(fileNameNoMIME)) { // 文件已存在 return files[i].getPath(); } } URL mUrl = new URL(url); connection = (HttpURLConnection) mUrl.openConnection(); connection.connect(); // 获取文件名,下载文件 String fileName = getCacheFileNameFromUrl(url, connection); file = new File(imageDownloadDir, fileName); downFilePath = file.getPath(); if (!file.exists()) { file.createNewFile(); } else { // 文件已存在 return file.getPath(); } in = connection.getInputStream(); fileOutputStream = new FileOutputStream(file); byte[] b = new byte[1024]; int temp = 0; while ((temp = in.read(b)) != -1) { fileOutputStream.write(b, 0, temp); } } catch (Exception e) { e.printStackTrace(); AbLogUtil.e(AbFileUtil.class, "有文件下载出错了,已删除"); // 检查文件大小,如果文件为0B说明网络不好没有下载成功,要将建立的空文件删除 if (file != null) { file.delete(); } file = null; downFilePath = null; } finally { try { if (in != null) { in.close(); } } catch (Exception e) { e.printStackTrace(); } try { if (fileOutputStream != null) { fileOutputStream.close(); } } catch (Exception e) { e.printStackTrace(); } try { if (connection != null) { connection.disconnect(); } } catch (Exception e) { e.printStackTrace(); } } return downFilePath; } /** * 描述:获取网络文件的大小. * * @param Url * 图片的网络路径 * @return int 网络文件的大小 */ public static int getContentLengthFromUrl(String Url) { int mContentLength = 0; try { URL url = new URL(Url); HttpURLConnection mHttpURLConnection = (HttpURLConnection) url.openConnection(); mHttpURLConnection.setConnectTimeout(5 * 1000); mHttpURLConnection.setRequestMethod("GET"); mHttpURLConnection.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); mHttpURLConnection.setRequestProperty("Accept-Language", "zh-CN"); mHttpURLConnection.setRequestProperty("Referer", Url); mHttpURLConnection.setRequestProperty("Charset", "UTF-8"); mHttpURLConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"); mHttpURLConnection.setRequestProperty("Connection", "Keep-Alive"); mHttpURLConnection.connect(); if (mHttpURLConnection.getResponseCode() == 200) { // 根据响应获取文件大小 mContentLength = mHttpURLConnection.getContentLength(); } } catch (Exception e) { e.printStackTrace(); AbLogUtil.d(AbFileUtil.class, "获取长度异常:" + e.getMessage()); } return mContentLength; } /** * 获取文件名,通过网络获取. * * @param url * 文件地址 * @return 文件名 */ public static String getRealFileNameFromUrl(String url) { String name = null; try { if (AbStrUtil.isEmpty(url)) { return name; } URL mUrl = new URL(url); HttpURLConnection mHttpURLConnection = (HttpURLConnection) mUrl.openConnection(); mHttpURLConnection.setConnectTimeout(5 * 1000); mHttpURLConnection.setRequestMethod("GET"); mHttpURLConnection.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); mHttpURLConnection.setRequestProperty("Accept-Language", "zh-CN"); mHttpURLConnection.setRequestProperty("Referer", url); mHttpURLConnection.setRequestProperty("Charset", "UTF-8"); mHttpURLConnection.setRequestProperty("User-Agent", ""); mHttpURLConnection.setRequestProperty("Connection", "Keep-Alive"); mHttpURLConnection.connect(); if (mHttpURLConnection.getResponseCode() == 200) { for (int i = 0;; i++) { String mine = mHttpURLConnection.getHeaderField(i); if (mine == null) { break; } if ("content-disposition".equals(mHttpURLConnection.getHeaderFieldKey(i).toLowerCase())) { Matcher m = Pattern.compile(".*filename=(.*)").matcher(mine.toLowerCase()); if (m.find()) return m.group(1).replace("\"", ""); } } } } catch (Exception e) { e.printStackTrace(); AbLogUtil.e(AbFileUtil.class, "网络上获取文件名失败"); } return name; } /** * 获取真实文件名(xx.后缀),通过网络获取. * * @param connection * 连接 * @return 文件名 */ public static String getRealFileName(HttpURLConnection connection) { String name = null; try { if (connection == null) { return name; } if (connection.getResponseCode() == 200) { for (int i = 0;; i++) { String mime = connection.getHeaderField(i); if (mime == null) { break; } // "Content-Disposition","attachment; filename=1.txt" // Content-Length if ("content-disposition".equals(connection.getHeaderFieldKey(i).toLowerCase())) { Matcher m = Pattern.compile(".*filename=(.*)").matcher(mime.toLowerCase()); if (m.find()) { return m.group(1).replace("\"", ""); } } } } } catch (Exception e) { e.printStackTrace(); AbLogUtil.e(AbFileUtil.class, "网络上获取文件名失败"); } return name; } /** * 获取文件名(不含后缀). * * @param url * 文件地址 * @return 文件名 */ public static String getCacheFileNameFromUrl(String url) { if (AbStrUtil.isEmpty(url)) { return null; } String name = null; try { name = AbMd5.MD5(url); } catch (Exception e) { e.printStackTrace(); } return name; } /** * 获取文件名(.后缀),外链模式和通过网络获取. * * @param url * 文件地址 * @param connection * the connection * @return 文件名 */ public static String getCacheFileNameFromUrl(String url, HttpURLConnection connection) { if (AbStrUtil.isEmpty(url)) { return null; } String name = null; try { // 获取后缀 String suffix = getMIMEFromUrl(url, connection); if (AbStrUtil.isEmpty(suffix)) { suffix = ".ab"; } name = AbMd5.MD5(url) + suffix; } catch (Exception e) { e.printStackTrace(); } return name; } /** * 获取文件后缀,本地. * * @param url * 文件地址 * @param connection * the connection * @return 文件后缀 */ public static String getMIMEFromUrl(String url, HttpURLConnection connection) { if (AbStrUtil.isEmpty(url)) { return null; } String suffix = null; try { // 获取后缀 if (url.lastIndexOf(".") != -1) { suffix = url.substring(url.lastIndexOf(".")); if (suffix.indexOf("/") != -1 || suffix.indexOf("?") != -1 || suffix.indexOf("&") != -1) { suffix = null; } } if (AbStrUtil.isEmpty(suffix)) { // 获取文件名 这个效率不高 String fileName = getRealFileName(connection); if (fileName != null && fileName.lastIndexOf(".") != -1) { suffix = fileName.substring(fileName.lastIndexOf(".")); } } } catch (Exception e) { e.printStackTrace(); } return suffix; } /** * 描述:从sd卡中的文件读取到byte[]. * * @param path * sd卡中文件路径 * @return byte[] */ public static byte[] getByteArrayFromSD(String path) { byte[] bytes = null; ByteArrayOutputStream out = null; try { File file = new File(path); // SD卡是否存在 if (!isCanUseSD()) { return null; } // 文件是否存在 if (!file.exists()) { return null; } long fileSize = file.length(); if (fileSize > Integer.MAX_VALUE) { return null; } FileInputStream in = new FileInputStream(path); out = new ByteArrayOutputStream(1024); byte[] buffer = new byte[1024]; int size = 0; while ((size = in.read(buffer)) != -1) { out.write(buffer, 0, size); } in.close(); bytes = out.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { try { out.close(); } catch (Exception e) { } } } return bytes; } /** * 描述:将byte数组写入文件. * * @param path * the path * @param content * the content * @param create * the create */ public static void writeByteArrayToSD(String path, byte[] content, boolean create) { FileOutputStream fos = null; try { File file = new File(path); // SD卡是否存在 if (!isCanUseSD()) { return; } // 文件是否存在 if (!file.exists()) { if (create) { File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); file.createNewFile(); } } else { return; } } fos = new FileOutputStream(path); fos.write(content); } catch (Exception e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (Exception e) { } } } } /** * 描述:SD卡是否能用. * * @return true 可用,false不可用 */ public static boolean isCanUseSD() { try { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } catch (Exception e) { e.printStackTrace(); } return false; } /** * 描述:初始化存储目录. * * @param context * the context */ public static void initFileDir(Context context) { PackageInfo info = AbAppUtil.getPackageInfo(context); // 默认下载文件根目录. String downloadRootPath = File.separator + AbAppConfig.DOWNLOAD_ROOT_DIR + File.separator + info.packageName + File.separator; // 默认下载图片文件目录. String imageDownloadPath = downloadRootPath + AbAppConfig.DOWNLOAD_IMAGE_DIR + File.separator; // 默认下载文件目录. String fileDownloadPath = downloadRootPath + AbAppConfig.DOWNLOAD_FILE_DIR + File.separator; // 默认缓存目录. String cacheDownloadPath = downloadRootPath + AbAppConfig.CACHE_DIR + File.separator; // 默认DB目录. String dbDownloadPath = downloadRootPath + AbAppConfig.DB_DIR + File.separator; try { if (!isCanUseSD()) { return; } else { File root = Environment.getExternalStorageDirectory(); File downloadDir = new File(root.getAbsolutePath() + downloadRootPath); if (!downloadDir.exists()) { downloadDir.mkdirs(); } downloadRootDir = downloadDir.getPath(); File cacheDownloadDirFile = new File(root.getAbsolutePath() + cacheDownloadPath); if (!cacheDownloadDirFile.exists()) { cacheDownloadDirFile.mkdirs(); } cacheDownloadDir = cacheDownloadDirFile.getPath(); File imageDownloadDirFile = new File(root.getAbsolutePath() + imageDownloadPath); if (!imageDownloadDirFile.exists()) { imageDownloadDirFile.mkdirs(); } imageDownloadDir = imageDownloadDirFile.getPath(); File fileDownloadDirFile = new File(root.getAbsolutePath() + fileDownloadPath); if (!fileDownloadDirFile.exists()) { fileDownloadDirFile.mkdirs(); } fileDownloadDir = fileDownloadDirFile.getPath(); File dbDownloadDirFile = new File(root.getAbsolutePath() + dbDownloadPath); if (!dbDownloadDirFile.exists()) { dbDownloadDirFile.mkdirs(); } dbDownloadDir = dbDownloadDirFile.getPath(); } } catch (Exception e) { e.printStackTrace(); } } /** * 计算sdcard上的剩余空间. * * @return the int */ public static int freeSpaceOnSD() { StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath()); double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat.getBlockSize()) / 1024 * 1024; return (int) sdFreeMB; } /** * 根据文件的最后修改时间进行排序. */ public static class FileLastModifSort implements Comparator { /* * (non-Javadoc) * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(File arg0, File arg1) { if (arg0.lastModified() > arg1.lastModified()) { return 1; } else if (arg0.lastModified() == arg1.lastModified()) { return 0; } else { return -1; } } } /** * 删除所有缓存文件. * * @return true, if successful */ public static boolean clearDownloadFile() { try { if (!isCanUseSD()) { return false; } File path = Environment.getExternalStorageDirectory(); File fileDirectory = new File(path.getAbsolutePath() + downloadRootDir); File[] files = fileDirectory.listFiles(); if (files == null) { return true; } for (int i = 0; i < files.length; i++) { files[i].delete(); } } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 描述:读取Assets目录的文件内容. * * @param context * the context * @param name * the name * @param encoding * the encoding * @return the string */ public static String readAssetsByName(Context context, String name, String encoding) { String text = null; InputStreamReader inputReader = null; BufferedReader bufReader = null; try { inputReader = new InputStreamReader(context.getAssets().open(name)); bufReader = new BufferedReader(inputReader); String line = null; StringBuffer buffer = new StringBuffer(); while ((line = bufReader.readLine()) != null) { buffer.append(line); } text = new String(buffer.toString().getBytes(), encoding); } catch (Exception e) { e.printStackTrace(); } finally { try { if (bufReader != null) { bufReader.close(); } if (inputReader != null) { inputReader.close(); } } catch (Exception e) { e.printStackTrace(); } } return text; } /** * 描述:读取Raw目录的文件内容. * * @param context * the context * @param id * the id * @param encoding * the encoding * @return the string */ public static String readRawByName(Context context, int id, String encoding) { String text = null; InputStreamReader inputReader = null; BufferedReader bufReader = null; try { inputReader = new InputStreamReader(context.getResources().openRawResource(id)); bufReader = new BufferedReader(inputReader); String line = null; StringBuffer buffer = new StringBuffer(); while ((line = bufReader.readLine()) != null) { buffer.append(line); } text = new String(buffer.toString().getBytes(), encoding); } catch (Exception e) { e.printStackTrace(); } finally { try { if (bufReader != null) { bufReader.close(); } if (inputReader != null) { inputReader.close(); } } catch (Exception e) { e.printStackTrace(); } } return text; } /** * 解压缩功能. 将zipFile文件解压到folderPath目录下. * * @param zipFile * zip文件地址 * @param folderPath * 解压目的文件 * @return */ public int upZipFile(File zipFile, String folderPath) { try { ZipFile zfile = new ZipFile(zipFile); Enumeration zList = zfile.entries(); ZipEntry ze = null; byte[] buf = new byte[1024]; while (zList.hasMoreElements()) { ze = (ZipEntry) zList.nextElement(); if (ze.isDirectory()) { Log.d("upZipFile", "ze.getName() = " + ze.getName()); String dirstr = folderPath + ze.getName(); // dirstr.trim(); dirstr = new String(dirstr.getBytes("8859_1"), "GB2312"); Log.d("upZipFile", "str = " + dirstr); File f = new File(dirstr); f.mkdir(); continue; } Log.d("upZipFile", "ze.getName() = " + ze.getName()); OutputStream os = new BufferedOutputStream( new FileOutputStream(getRealFileName(folderPath, ze.getName()))); InputStream is = new BufferedInputStream(zfile.getInputStream(ze)); int readLen = 0; while ((readLen = is.read(buf, 0, 1024)) != -1) { os.write(buf, 0, readLen); } is.close(); os.close(); } zfile.close(); } catch (IOException e) { Log.e("tag", "解压失败!"); } return 0; } /** * 给定根目录,返回一个相对路径所对应的实际文件名.(压缩文件) * * @param baseDir * 指定根目录 * @param absFileName * 相对路径名,来自于ZipEntry中的name * @return java.io.File 实际的文件 */ public static File getRealFileName(String baseDir, String absFileName) { String[] dirs = absFileName.split("/"); File ret = new File(baseDir); String substr = null; if (dirs.length > 1) { for (int i = 0; i < dirs.length - 1; i++) { substr = dirs[i]; try { substr = new String(substr.getBytes("8859_1"), "GB2312"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret = new File(ret, substr); } Log.d("upZipFile", "1ret = " + ret); if (!ret.exists()) ret.mkdirs(); substr = dirs[dirs.length - 1]; try { substr = new String(substr.getBytes("8859_1"), "GB2312"); Log.d("upZipFile", "substr = " + substr); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret = new File(ret, substr); Log.d("upZipFile", "2ret = " + ret); return ret; } return ret; } /** * 打开pdf文件 * * @param strPath * 文件的地址 * @param context * 对于的contenxt */ public String openPdfFile(String strPath, Context context) { File file = new File(strPath); if (file.exists()) { Uri path = Uri.fromFile(file); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(path, "application/pdf"); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); try { context.startActivity(intent); return "true"; } catch (ActivityNotFoundException e) { e.printStackTrace(); return "请安装wps"; } } else { return "文件地址不对、或者文件不存在"; } } /** * 删除文件,可以是单个文件或文件夹 * * @param fileName * 待删除的文件名 * @return 文件删除成功返回true,否则返回false */ public static boolean delete(String fileName) { File file = new File(fileName); if (!file.exists()) { System.out.println("删除文件失败:" + fileName + "文件不存在"); return false; } else { if (file.isFile()) { return deleteFile(fileName); } else { return deleteDirectory(fileName, false); } } } /** * 删除单个文件 * * @param fileName * 被删除文件的文件名 * @return 单个文件删除成功返回true,否则返回false */ public static boolean deleteFile(String fileName) { File file = new File(fileName); if (file.isFile() && file.exists()) { file.delete(); System.out.println("删除单个文件" + fileName + "成功!"); return true; } else { System.out.println("删除单个文件" + fileName + "失败!"); return false; } } /** * 删除目录(文件夹)以及目录下的文件 * * @param dir * 被删除目录的文件路径 * @param isSave * 是否保存文件 * @return 目录删除成功返回true,否则返回false */ public static boolean deleteDirectory(String dir, boolean isSave) { // 如果dir不以文件分隔符结尾,自动添加文件分隔符 if (!dir.endsWith(File.separator)) { dir = dir + File.separator; } File dirFile = new File(dir); // 如果dir对应的文件不存在,或者不是一个目录,则退出 if (!dirFile.exists() || !dirFile.isDirectory()) { System.out.println("删除目录失败" + dir + "目录不存在!"); return false; } boolean flag = true; // 删除文件夹下的所有文件(包括子目录) File[] files = dirFile.listFiles(); for (int i = 0; i < files.length; i++) { // 删除子文件 if (files[i].isFile()) { flag = deleteFile(files[i].getAbsolutePath()); if (!flag) { break; } } // 删除子目录 else { flag = deleteDirectory(files[i].getAbsolutePath(), false); if (!flag) { break; } } } if (!flag) { System.out.println("删除目录失败"); return false; } if (isSave) { return true; } else { // 删除当前目录 if (dirFile.delete()) { return true; } else { System.out.println("删除目录" + dir + "失败!"); return false; } } } /** * Gets the download root dir. * * @param context * the context * @return the download root dir */ public static String getDownloadRootDir(Context context) { if (downloadRootDir == null) { initFileDir(context); } return downloadRootDir; } /** * Gets the image download dir. * * @param context * the context * @return the image download dir */ public static String getImageDownloadDir(Context context) { if (downloadRootDir == null) { initFileDir(context); } return imageDownloadDir; } /** * Gets the file download dir. * * @param context * the context * @return the file download dir */ public static String getFileDownloadDir(Context context) { if (downloadRootDir == null) { initFileDir(context); } return fileDownloadDir; } /** * Gets the cache download dir. * * @param context * the context * @return the cache download dir */ public static String getCacheDownloadDir(Context context) { if (downloadRootDir == null) { initFileDir(context); } return cacheDownloadDir; } /** * Gets the db download dir. * * @param context * the context * @return the db download dir */ public static String getDbDownloadDir(Context context) { if (downloadRootDir == null) { initFileDir(context); } return dbDownloadDir; } /** * Gets the free sd space needed to cache. * * @return the free sd space needed to cache */ public static int getFreeSdSpaceNeededToCache() { return freeSdSpaceNeededToCache; } } ================================================ FILE: src/main/java/com/ab/util/AbGraphicUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import android.graphics.Canvas; import android.graphics.Paint.FontMetrics; import android.text.Layout; import android.text.TextPaint; import java.util.ArrayList; import java.util.List; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbGraphic.java * 描述:图形处理类. */ public final class AbGraphicUtil { /** * 描述:获取字符的所在位置(按像素获取最大能容纳的). * * @param str 指定的字符串 * @param maxPix 要取到的位置(像素) * @param paint the paint * @return 字符的所在位置 */ public static int subStringLength(String str,int maxPix,TextPaint paint) { if(AbStrUtil.isEmpty(str)){ return 0; } int currentIndex = 0; for (int i = 0; i < str.length(); i++) { //获取一个字符 String temp = str.substring(0, i + 1); float valueLength = paint.measureText(temp); if(valueLength > maxPix){ currentIndex = i-1; break; }else if(valueLength == maxPix){ currentIndex = i; break; } } //短于最大像素返回最后一个字符位置 if(currentIndex==0){ currentIndex = str.length()-1 ; } return currentIndex; } /** * 描述:获取文字的像素宽. * * @param str the str * @param paint the paint * @return the string width */ public static float getStringWidth(String str,TextPaint paint) { float strWidth = paint.measureText(str); return strWidth; } /** * 获得文字的宽度 * @param str the str * @param paint the paint * @return the string width */ public static float getDesiredWidth(String str,TextPaint paint) { float strWidth = Layout.getDesiredWidth(str, paint); return strWidth; } /** * 获取文字的高度 * @param paint the textPaint * @return the string height */ public static float getDesiredHeight(TextPaint paint) { FontMetrics fm = paint.getFontMetrics(); return (float)Math.ceil(fm.descent - fm.ascent); } /** * 解析成行. * @param text the text * @param maxWPix the max w pix * @param paint the paint * @return the draw row count */ public static List getDrawRowStr(String text,int maxWPix,TextPaint paint) { String [] texts = null; if(text.indexOf("\n")!=-1){ texts = text.split("\n"); }else{ texts = new String [1]; texts[0] = text; } //共多少行 List mStrList = new ArrayList(); for(int i=0;iendIndex+1){ //还有剩下的 textLine = textLine.substring(endIndex+1); }else{ break; } } } return mStrList; } /** * * 描述:获取这段文本多少行. * @param text * @param maxWPix * @return */ public static int getDrawRowCount(String text,int maxWPix,TextPaint paint) { String [] texts = null; if(text.indexOf("\n")!=-1){ texts = text.split("\n"); }else{ texts = new String [1]; texts[0] = text; } //共多少行 List mStrList = new ArrayList(); for(int i=0;iendIndex+1){ //还有剩下的 textLine = textLine.substring(endIndex+1); }else{ break; } } } return mStrList.size(); } /** * 描述:绘制文本,支持换行. * * @param canvas the canvas * @param text the text * @param maxWPix the max w pix * @param paint the paint * @param left the left * @param top the top * @return the int */ public static int drawText(Canvas canvas,String text,int maxWPix,TextPaint paint,int left,int top) { if(AbStrUtil.isEmpty(text)){ return 1; } //需要根据文字长度控制换行 //测量文字的长度 List mStrList = getDrawRowStr(text,maxWPix,paint); int hSize = (int)getDesiredHeight(paint); for(int i=0;i desiredWidth || resizeBmp.getHeight() > desiredHeight) { resizeBmp = cutImg(resizeBmp, desiredWidth, desiredHeight); } return resizeBmp; } /** * 描述:根据等比例缩放图片. * * @param bitmap * the bitmap * @param scale * 比例 * @return Bitmap 新图片 */ public static Bitmap scaleImg(Bitmap bitmap, float scale) { if (!checkBitmap(bitmap)) { return null; } if (scale == 1) { return bitmap; } Bitmap resizeBmp = null; try { // 获取Bitmap资源的宽和高 int bmpW = bitmap.getWidth(); int bmpH = bitmap.getHeight(); // 注意这个Matirx是android.graphics底下的那个 Matrix matrix = new Matrix(); // 设置缩放系数,分别为原来的0.8和0.8 matrix.postScale(scale, scale); resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bmpW, bmpH, matrix, true); } catch (Exception e) { e.printStackTrace(); } finally { if (resizeBmp != bitmap) { bitmap.recycle(); } } return resizeBmp; } /** * 描述:裁剪图片. * * @param file * File对象 * @param desiredWidth * 新图片的宽 * @param desiredHeight * 新图片的高 * @return Bitmap 新图片 */ public static Bitmap cutImg(File file, int desiredWidth, int desiredHeight) { Bitmap resizeBmp = null; BitmapFactory.Options opts = new BitmapFactory.Options(); // 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息 opts.inJustDecodeBounds = true; BitmapFactory.decodeFile(file.getPath(), opts); // 获取图片的原始宽度 int srcWidth = opts.outWidth; // 获取图片原始高度 int srcHeight = opts.outHeight; int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth, desiredHeight); desiredWidth = size[0]; desiredHeight = size[1]; // 缩放的比例 float scale = getMinScale(srcWidth, srcHeight, desiredWidth, desiredHeight); int destWidth = srcWidth; int destHeight = srcHeight; if (scale != 1) { destWidth = (int) (srcWidth * scale); destHeight = (int) (srcHeight * scale); } // 默认为ARGB_8888. opts.inPreferredConfig = Bitmap.Config.RGB_565; // 以下两个字段需一起使用: // 产生的位图将得到像素空间,如果系统gc,那么将被清空。当像素再次被访问,如果Bitmap已经decode,那么将被自动重新解码 opts.inPurgeable = true; // 位图可以共享一个参考输入数据(inputstream、阵列等) opts.inInputShareable = true; // 缩放的比例,缩放是很难按准备的比例进行缩放的,通过inSampleSize来进行缩放,其值表明缩放的倍数,SDK中建议其值是2的指数值 if (scale < 0.25) { // 缩小到4分之一 opts.inSampleSize = 2; } else if (scale < 0.125) { // 缩小 opts.inSampleSize = 4; } else { opts.inSampleSize = 1; } // 设置大小 opts.outHeight = destHeight; opts.outWidth = destWidth; // 创建内存 opts.inJustDecodeBounds = false; // 使图片不抖动 opts.inDither = false; Bitmap bitmap = BitmapFactory.decodeFile(file.getPath(), opts); if (bitmap != null) { resizeBmp = cutImg(bitmap, desiredWidth, desiredHeight); } return resizeBmp; } /** * 描述:裁剪图片. * * @param bitmap * the bitmap * @param desiredWidth * 新图片的宽 * @param desiredHeight * 新图片的高 * @return Bitmap 新图片 */ public static Bitmap cutImg(Bitmap bitmap, int desiredWidth, int desiredHeight) { if (!checkBitmap(bitmap)) { return null; } if (!checkSize(desiredWidth, desiredHeight)) { return null; } Bitmap resizeBmp = null; try { int width = bitmap.getWidth(); int height = bitmap.getHeight(); int offsetX = 0; int offsetY = 0; if (width > desiredWidth) { offsetX = (width - desiredWidth) / 2; } else { desiredWidth = width; } if (height > desiredHeight) { offsetY = (height - desiredHeight) / 2; } else { desiredHeight = height; } resizeBmp = Bitmap.createBitmap(bitmap, offsetX, offsetY, desiredWidth, desiredHeight); } catch (Exception e) { e.printStackTrace(); } finally { if (resizeBmp != bitmap) { bitmap.recycle(); } } return resizeBmp; } private static float getMinScale(int srcWidth, int srcHeight, int desiredWidth, int desiredHeight) { // 缩放的比例 float scale = 0; // 计算缩放比例,宽高的最小比例 float scaleWidth = (float) desiredWidth / srcWidth; float scaleHeight = (float) desiredHeight / srcHeight; if (scaleWidth > scaleHeight) { scale = scaleWidth; } else { scale = scaleHeight; } return scale; } private static int[] resizeToMaxSize(int srcWidth, int srcHeight, int desiredWidth, int desiredHeight) { int[] size = new int[2]; if (desiredWidth <= 0) { desiredWidth = srcWidth; } if (desiredHeight <= 0) { desiredHeight = srcHeight; } if (desiredWidth > MAX_WIDTH) { // 重新计算大小 desiredWidth = MAX_WIDTH; float scaleWidth = (float) desiredWidth / srcWidth; desiredHeight = (int) (desiredHeight * scaleWidth); } if (desiredHeight > MAX_HEIGHT) { // 重新计算大小 desiredHeight = MAX_HEIGHT; float scaleHeight = (float) desiredHeight / srcHeight; desiredWidth = (int) (desiredWidth * scaleHeight); } size[0] = desiredWidth; size[1] = desiredHeight; return size; } private static boolean checkBitmap(Bitmap bitmap) { if (bitmap == null) { AbLogUtil.e(AbImageUtil.class, "原图Bitmap为空了"); return false; } if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { AbLogUtil.e(AbImageUtil.class, "原图Bitmap大小为0"); return false; } return true; } private static boolean checkSize(int desiredWidth, int desiredHeight) { if (desiredWidth <= 0 || desiredHeight <= 0) { AbLogUtil.e(AbImageUtil.class, "请求Bitmap的宽高参数必须大于0"); return false; } return true; } /** * Drawable转Bitmap. * * @param drawable * 要转化的Drawable * @return Bitmap */ public static Bitmap drawableToBitmap(Drawable drawable) { Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); drawable.draw(canvas); return bitmap; } /** * Bitmap对象转换Drawable对象. * * @param bitmap * 要转化的Bitmap对象 * @return Drawable 转化完成的Drawable对象 */ public static Drawable bitmapToDrawable(Bitmap bitmap) { BitmapDrawable mBitmapDrawable = null; try { if (bitmap == null) { return null; } mBitmapDrawable = new BitmapDrawable(bitmap); } catch (Exception e) { e.printStackTrace(); } return mBitmapDrawable; } /** * Bitmap对象转换TransitionDrawable对象. * * @param bitmap * 要转化的Bitmap对象 imageView.setImageDrawable(td); * td.startTransition(200); * @return Drawable 转化完成的Drawable对象 */ public static TransitionDrawable bitmapToTransitionDrawable(Bitmap bitmap) { TransitionDrawable mBitmapDrawable = null; try { if (bitmap == null) { return null; } mBitmapDrawable = new TransitionDrawable( new Drawable[] { new ColorDrawable(android.R.color.transparent), new BitmapDrawable(bitmap) }); } catch (Exception e) { e.printStackTrace(); } return mBitmapDrawable; } /** * Drawable对象转换TransitionDrawable对象. * * @param drawable * 要转化的Drawable对象 imageView.setImageDrawable(td); * td.startTransition(200); * @return Drawable 转化完成的Drawable对象 */ public static TransitionDrawable drawableToTransitionDrawable(Drawable drawable) { TransitionDrawable mBitmapDrawable = null; try { if (drawable == null) { return null; } mBitmapDrawable = new TransitionDrawable( new Drawable[] { new ColorDrawable(android.R.color.transparent), drawable }); } catch (Exception e) { e.printStackTrace(); } return mBitmapDrawable; } /** * 将Bitmap转换为byte[]. * * @param bitmap * the bitmap * @param mCompressFormat * 图片格式 Bitmap.CompressFormat.JPEG,CompressFormat.PNG * @param needRecycle * 是否需要回收 * @return byte[] 图片的byte[] */ public static byte[] bitmap2Bytes(Bitmap bitmap, Bitmap.CompressFormat mCompressFormat, final boolean needRecycle) { byte[] result = null; ByteArrayOutputStream output = null; try { output = new ByteArrayOutputStream(); bitmap.compress(mCompressFormat, 100, output); result = output.toByteArray(); if (needRecycle) { bitmap.recycle(); } } catch (Exception e) { e.printStackTrace(); } finally { if (output != null) { try { output.close(); } catch (Exception e) { e.printStackTrace(); } } } return result; } /** * 获取Bitmap大小. * * @param bitmap * the bitmap * @param mCompressFormat * 图片格式 Bitmap.CompressFormat.JPEG,CompressFormat.PNG * @return 图片的大小 */ public static int getByteCount(Bitmap bitmap, Bitmap.CompressFormat mCompressFormat) { int size = 0; ByteArrayOutputStream output = null; try { output = new ByteArrayOutputStream(); bitmap.compress(mCompressFormat, 100, output); byte[] result = output.toByteArray(); size = result.length; result = null; } catch (Exception e) { e.printStackTrace(); } finally { if (output != null) { try { output.close(); } catch (Exception e) { e.printStackTrace(); } } } return size; } /** * 描述:将byte[]转换为Bitmap. * * @param b * 图片格式的byte[]数组 * @return bitmap 得到的Bitmap */ public static Bitmap bytes2Bimap(byte[] b) { Bitmap bitmap = null; try { if (b.length != 0) { bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); } } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** * 将ImageView转换为Bitmap. * * @param view * 要转换为bitmap的View * @return byte[] 图片的byte[] */ public static Bitmap imageView2Bitmap(ImageView view) { Bitmap bitmap = null; try { bitmap = Bitmap.createBitmap(view.getDrawingCache()); view.setDrawingCacheEnabled(false); } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** * 将View转换为Drawable.需要最上层布局为Linearlayout * * @param view * 要转换为Drawable的View * @return BitmapDrawable Drawable */ public static Drawable view2Drawable(View view) { BitmapDrawable mBitmapDrawable = null; try { Bitmap newbmp = view2Bitmap(view); if (newbmp != null) { mBitmapDrawable = new BitmapDrawable(newbmp); } } catch (Exception e) { e.printStackTrace(); } return mBitmapDrawable; } /** * 将View转换为Bitmap.需要最上层布局为Linearlayout * * @param view * 要转换为bitmap的View * @return byte[] 图片的byte[] */ public static Bitmap view2Bitmap(View view) { Bitmap bitmap = null; try { if (view != null) { view.setDrawingCacheEnabled(true); view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); view.buildDrawingCache(); bitmap = view.getDrawingCache(); } } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** * 将View转换为byte[]. * * @param view * 要转换为byte[]的View * @param compressFormat * the compress format * @return byte[] View图片的byte[] */ public static byte[] view2Bytes(View view, Bitmap.CompressFormat compressFormat) { byte[] b = null; try { Bitmap bitmap = AbImageUtil.view2Bitmap(view); b = AbImageUtil.bitmap2Bytes(bitmap, compressFormat, true); } catch (Exception e) { e.printStackTrace(); } return b; } /** * 描述:旋转Bitmap为一定的角度. * * @param bitmap * the bitmap * @param degrees * the degrees * @return the bitmap */ public static Bitmap rotateBitmap(Bitmap bitmap, float degrees) { Bitmap mBitmap = null; try { Matrix m = new Matrix(); m.setRotate(degrees % 360); mBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, false); } catch (Exception e) { e.printStackTrace(); } return mBitmap; } /** * 描述:旋转Bitmap为一定的角度并四周暗化处理. * * @param bitmap * the bitmap * @param degrees * the degrees * @return the bitmap */ public static Bitmap rotateBitmapTranslate(Bitmap bitmap, float degrees) { Bitmap mBitmap = null; int width; int height; try { Matrix matrix = new Matrix(); if ((degrees / 90) % 2 != 0) { width = bitmap.getWidth(); height = bitmap.getHeight(); } else { width = bitmap.getHeight(); height = bitmap.getWidth(); } int cx = width / 2; int cy = height / 2; matrix.preTranslate(-cx, -cy); matrix.postRotate(degrees); matrix.postTranslate(cx, cy); } catch (Exception e) { e.printStackTrace(); } return mBitmap; } /** * 转换图片转换成圆形. * * @param bitmap * 传入Bitmap对象 * @return the bitmap */ public static Bitmap toRoundBitmap(Bitmap bitmap) { if (bitmap == null) { return null; } int width = bitmap.getWidth(); int height = bitmap.getHeight(); float roundPx; float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom; if (width <= height) { roundPx = width / 2; top = 0; bottom = width; left = 0; right = width; height = width; dst_left = 0; dst_top = 0; dst_right = width; dst_bottom = width; } else { roundPx = height / 2; float clip = (width - height) / 2; left = clip; right = width - clip; top = 0; bottom = height; width = height; dst_left = 0; dst_top = 0; dst_right = height; dst_bottom = height; } Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom); final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom); final RectF rectF = new RectF(dst); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, src, dst, paint); return output; } /** * 转换图片转换成圆形通过指定的弧度 * * @param bitmap * @param roundPx * @return */ public static Bitmap toRoundBitmap(Bitmap bitmap, float roundPx) { if (bitmap == null) { return null; } int width = bitmap.getWidth(); int height = bitmap.getHeight(); float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom; if (width <= height) { top = 0; bottom = width; left = 0; right = width; height = width; dst_left = 0; dst_top = 0; dst_right = width; dst_bottom = width; } else { float clip = (width - height) / 2; left = clip; right = width - clip; top = 0; bottom = height; width = height; dst_left = 0; dst_top = 0; dst_right = height; dst_bottom = height; } Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom); final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom); final RectF rectF = new RectF(dst); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, src, dst, paint); return output; } /** * 转换图片转换成镜面效果的图片. * * @param bitmap * 传入Bitmap对象 * @return the bitmap */ public static Bitmap toReflectionBitmap(Bitmap bitmap) { if (bitmap == null) { return null; } try { int reflectionGap = 1; int width = bitmap.getWidth(); int height = bitmap.getHeight(); // This will not scale but will flip on the Y axis Matrix matrix = new Matrix(); matrix.preScale(1, -1); // Create a Bitmap with the flip matrix applied to it. // We only want the bottom half of the image Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2, width, height / 2, matrix, false); // Create a new bitmap with same width but taller to fit // reflection Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888); // Create a new Canvas with the bitmap that's big enough for // the image plus gap plus reflection Canvas canvas = new Canvas(bitmapWithReflection); // Draw in the original image canvas.drawBitmap(bitmap, 0, 0, null); // Draw in the gap Paint deafaultPaint = new Paint(); canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint); // Draw in the reflection canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null); // Create a shader that is a linear gradient that covers the // reflection Paint paint = new Paint(); LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP); // Set the paint to use this shader (linear gradient) paint.setShader(shader); // Set the Transfer mode to be porter duff and destination in paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN)); // Draw a rectangle using the paint with our linear gradient canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint); bitmap = bitmapWithReflection; } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** * 释放Bitmap对象. * * @param bitmap * 要释放的Bitmap */ public static void releaseBitmap(Bitmap bitmap) { if (bitmap != null) { try { if (!bitmap.isRecycled()) { AbLogUtil.d(AbImageUtil.class, "Bitmap释放" + bitmap.toString()); bitmap.recycle(); } } catch (Exception e) { } bitmap = null; } } /** * 释放Bitmap数组. * * @param bitmaps * 要释放的Bitmap数组 */ public static void releaseBitmapArray(Bitmap[] bitmaps) { if (bitmaps != null) { try { for (Bitmap bitmap : bitmaps) { if (bitmap != null && !bitmap.isRecycled()) { AbLogUtil.d(AbImageUtil.class, "Bitmap释放" + bitmap.toString()); bitmap.recycle(); } } } catch (Exception e) { } } } /** * 描述:简单的图像的特征值,用于缩略图找原图比较好. * * @param bitmap * the bitmap * @return the hash code */ public static String getHashCode(Bitmap bitmap) { // 第一步,缩小尺寸。 // 将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节, // 只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。 Bitmap temp = Bitmap.createScaledBitmap(bitmap, 8, 8, false); int width = temp.getWidth(); int height = temp.getHeight(); Log.i("th", "将图片缩小到8x8的尺寸:" + width + "*" + height); // 第二步,第二步,简化色彩。 // 将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。 int[] pixels = new int[width * height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { pixels[i * height + j] = rgbToGray(temp.getPixel(i, j)); } } releaseBitmap(temp); // 第三步,计算平均值。 // 计算所有64个像素的灰度平均值。 int avgPixel = AbMathUtil.average(pixels); // 第四步,比较像素的灰度。 // 将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。 int[] comps = new int[width * height]; for (int i = 0; i < comps.length; i++) { if (pixels[i] >= avgPixel) { comps[i] = 1; } else { comps[i] = 0; } } // 第五步,计算哈希值。 // 将上一步的比较结果,组合在一起,就构成了一个64位的整数, // 这就是这张图片的指纹。 StringBuffer hashCode = new StringBuffer(); for (int i = 0; i < comps.length; i += 4) { int result = comps[i] * (int) Math.pow(2, 3) + comps[i + 1] * (int) Math.pow(2, 2) + comps[i + 2] * (int) Math.pow(2, 1) + comps[i + 2]; hashCode.append(AbMathUtil.binaryToHex(result)); } String sourceHashCode = hashCode.toString(); // 得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。 // 在理论上,这等同于计算"汉明距离"(Hamming distance)。 // 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。 return sourceHashCode; } /** * 描述:图像的特征值颜色分布 将颜色分4个区,0,1,2,3 区组合共64组,计算每个像素点属于哪个区. * * @param bitmap * the bitmap * @return the color histogram */ public static int[] getColorHistogram(Bitmap bitmap) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); // 区颜色分布 int[] areaColor = new int[64]; // 获取色彩数组。 for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int pixels = bitmap.getPixel(i, j); int alpha = (pixels >> 24) & 0xFF; int red = (pixels >> 16) & 0xFF; int green = (pixels >> 8) & 0xFF; int blue = (pixels) & 0xFF; int redArea = 0; int greenArea = 0; int blueArea = 0; // 0-63 64-127 128-191 192-255 if (red >= 192) { redArea = 3; } else if (red >= 128) { redArea = 2; } else if (red >= 64) { redArea = 1; } else if (red >= 0) { redArea = 0; } if (green >= 192) { greenArea = 3; } else if (green >= 128) { greenArea = 2; } else if (green >= 64) { greenArea = 1; } else if (green >= 0) { greenArea = 0; } if (blue >= 192) { blueArea = 3; } else if (blue >= 128) { blueArea = 2; } else if (blue >= 64) { blueArea = 1; } else if (blue >= 0) { blueArea = 0; } int index = redArea * 16 + greenArea * 4 + blueArea; // 加入 areaColor[index] += 1; } } return areaColor; } /** * 计算"汉明距离"(Hamming distance)。 * 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。. * * @param sourceHashCode * 源hashCode * @param hashCode * 与之比较的hashCode * @return the int */ public static int hammingDistance(String sourceHashCode, String hashCode) { int difference = 0; int len = sourceHashCode.length(); for (int i = 0; i < len; i++) { if (sourceHashCode.charAt(i) != hashCode.charAt(i)) { difference++; } } return difference; } /** * 灰度值计算. * * @param pixels * 像素 * @return int 灰度值 */ private static int rgbToGray(int pixels) { // int _alpha = (pixels >> 24) & 0xFF; int _red = (pixels >> 16) & 0xFF; int _green = (pixels >> 8) & 0xFF; int _blue = (pixels) & 0xFF; return (int) (0.3 * _red + 0.59 * _green + 0.11 * _blue); } /** * 压缩图片 * * @param sourcePath * 目标路径 * @param targetPath * 压缩完图片路径 * @param maxSize * 压缩后大小 */ public static void compressBitmap(String sourcePath, String targetPath, float maxSize) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(sourcePath, options); final float originalWidth = options.outWidth; final float originalHeight = options.outHeight; float convertedWidth; float convertedHeight; if (originalWidth > originalHeight) { convertedWidth = maxSize; convertedHeight = maxSize / originalWidth * originalHeight; } else { convertedHeight = maxSize; convertedWidth = maxSize / originalHeight * originalWidth; } final float ratio = originalWidth / convertedWidth; options.inSampleSize = (int) ratio; options.inJustDecodeBounds = false; Bitmap convertedBitmap = BitmapFactory.decodeFile(sourcePath, options); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); convertedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); FileOutputStream fileOutputStream; try { File file = new File(targetPath); if (!file.exists()) { file.mkdirs(); } fileOutputStream = new FileOutputStream(new File(targetPath)); fileOutputStream.write(byteArrayOutputStream.toByteArray()); fileOutputStream.flush(); fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 根据URI获取图片物理路径 */ public static String getAbsoluteImagePath(Uri uri, Activity activity) { String[] proj = { MediaColumns.DATA }; Cursor cursor = activity.managedQuery(uri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } } ================================================ FILE: src/main/java/com/ab/util/AbLogUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import java.util.Calendar; import android.content.Context; import android.util.Log; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbLogUtil.java * 描述:日志工具类. */ public class AbLogUtil { /** debug开关. */ public static boolean D = true; /** info开关. */ public static boolean I = true; /** error开关. */ public static boolean E = true; /** 起始执行时间. */ public static long startLogTimeInMillis = 0; /** * debug日志 * @param tag * @param message */ public static void d(String tag,String message) { if(D) Log.d(tag, message); } /** * debug日志 * @param context * @param message */ public static void d(Context context,String message) { String tag = context.getClass().getSimpleName(); d(tag, message); } /** * debug日志 * @param clazz * @param message */ public static void d(Class clazz,String message) { String tag = clazz.getSimpleName(); d(tag, message); } /** * info日志 * @param tag * @param message */ public static void i(String tag,String message) { Log.i(tag, message); } /** * info日志 * @param context * @param message */ public static void i(Context context,String message) { String tag = context.getClass().getSimpleName(); i(tag, message); } /** * info日志 * @param clazz * @param message */ public static void i(Class clazz,String message) { String tag = clazz.getSimpleName(); i(tag, message); } /** * error日志 * @param tag * @param message */ public static void e(String tag,String message) { Log.e(tag, message); } /** * error日志 * @param context * @param message */ public static void e(Context context,String message) { String tag = context.getClass().getSimpleName(); e(tag, message); } /** * error日志 * @param clazz * @param message */ public static void e(Class clazz,String message) { String tag = clazz.getSimpleName(); e(tag, message); } /** * 描述:记录当前时间毫秒. * */ public static void prepareLog(String tag) { Calendar current = Calendar.getInstance(); startLogTimeInMillis = current.getTimeInMillis(); Log.d(tag,"日志计时开始:"+startLogTimeInMillis); } /** * 描述:记录当前时间毫秒. * */ public static void prepareLog(Context context) { String tag = context.getClass().getSimpleName(); prepareLog(tag); } /** * 描述:记录当前时间毫秒. * */ public static void prepareLog(Class clazz) { String tag = clazz.getSimpleName(); prepareLog(tag); } /** * 描述:打印这次的执行时间毫秒,需要首先调用prepareLog(). * * @param tag 标记 * @param message 描述 * @param printTime 是否打印时间 */ public static void d(String tag, String message,boolean printTime) { Calendar current = Calendar.getInstance(); long endLogTimeInMillis = current.getTimeInMillis(); Log.d(tag,message+":"+(endLogTimeInMillis-startLogTimeInMillis)+"ms"); } /** * 描述:打印这次的执行时间毫秒,需要首先调用prepareLog(). * * @param tag 标记 * @param message 描述 * @param printTime 是否打印时间 */ public static void d(Context context,String message,boolean printTime) { String tag = context.getClass().getSimpleName(); d(tag,message,printTime); } /** * 描述:打印这次的执行时间毫秒,需要首先调用prepareLog(). * * @param clazz 标记 * @param message 描述 * @param printTime 是否打印时间 */ public static void d(Class clazz,String message,boolean printTime) { String tag = clazz.getSimpleName(); d(tag,message,printTime); } /** * debug日志的开关 * @param d */ public static void debug(boolean d) { D = d; } /** * info日志的开关 * @param i */ public static void info(boolean i) { I = i; } /** * error日志的开关 * @param e */ public static void error(boolean e) { E = e; } /** * 设置日志的开关 * @param e */ public static void setVerbose(boolean d,boolean i,boolean e) { D = d; I = i; E = e; } /** * 打开所有日志,默认全打开 * @param d */ public static void openAll() { D = true; I = true; E = true; } /** * 关闭所有日志 * @param d */ public static void closeAll() { D = false; I = false; E = false; } } ================================================ FILE: src/main/java/com/ab/util/AbMathUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import java.math.BigDecimal; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbMathUtil.java * 描述:数学处理类. */ public class AbMathUtil{ /** * 四舍五入. * * @param number 原数 * @param decimal 保留几位小数 * @return 四舍五入后的值 */ public static BigDecimal round(double number, int decimal){ return new BigDecimal(number).setScale(decimal, BigDecimal.ROUND_HALF_UP); } /** * 描述:字节数组转换成16进制串. * * @param b the b * @param length the length * @return the string */ public static String byte2HexStr(byte[] b, int length){ String hs = ""; String stmp = ""; for (int n = 0; n < length; ++n) { stmp = Integer.toHexString(b[n] & 0xFF); if (stmp.length() == 1) hs = hs + "0" + stmp; else { hs = hs + stmp; } hs = hs + ","; } return hs.toUpperCase(); } /** * 二进制转为十六进制. * * @param binary the binary * @return char hex */ public static char binaryToHex(int binary) { char ch = ' '; switch (binary){ case 0: ch = '0'; break; case 1: ch = '1'; break; case 2: ch = '2'; break; case 3: ch = '3'; break; case 4: ch = '4'; break; case 5: ch = '5'; break; case 6: ch = '6'; break; case 7: ch = '7'; break; case 8: ch = '8'; break; case 9: ch = '9'; break; case 10: ch = 'a'; break; case 11: ch = 'b'; break; case 12: ch = 'c'; break; case 13: ch = 'd'; break; case 14: ch = 'e'; break; case 15: ch = 'f'; break; default: ch = ' '; } return ch; } /** * * 一维数组转为二维数组 * * * @param m the m * @param width the width * @param height the height * @return the int[][] */ public static int[][] arrayToMatrix(int[] m, int width, int height) { int[][] result = new int[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int p = j * height + i; result[i][j] = m[p]; } } return result; } /** * * 二维数组转为一维数组 * * * @param m the m * @return the double[] */ public static double[] matrixToArray(double[][] m) { int p = m.length * m[0].length; double[] result = new double[p]; for (int i = 0; i < m.length; i++) { for (int j = 0; j < m[i].length; j++) { int q = j * m.length + i; result[q] = m[i][j]; } } return result; } /** * 描述:int数组转换为double数组. * * @param input the input * @return the double[] */ public static double[] intToDoubleArray(int[] input) { int length = input.length; double[] output = new double[length]; for (int i = 0; i < length; i++){ output[i] = Double.valueOf(String.valueOf(input[i])); } return output; } /** * 描述:int二维数组转换为double二维数组. * * @param input the input * @return the double[][] */ public static double[][] intToDoubleMatrix(int[][] input) { int height = input.length; int width = input[0].length; double[][] output = new double[height][width]; for (int i = 0; i < height; i++) { // 列 for (int j = 0; j < width; j++) { // 行 output[i][j] = Double.valueOf(String.valueOf(input[i][j])); } } return output; } /** * 计算数组的平均值. * * @param pixels 数组 * @return int 平均值 */ public static int average(int[] pixels) { float m = 0; for (int i = 0; i < pixels.length; ++i) { m += pixels[i]; } m = m / pixels.length; return (int) m; } /** * 计算数组的平均值. * * @param pixels 数组 * @return int 平均值 */ public static int average(double[] pixels) { float m = 0; for (int i = 0; i < pixels.length; ++i) { m += pixels[i]; } m = m / pixels.length; return (int) m; } /** * * 描述:点在直线上. * 点A(x,y),B(x1,y1),C(x2,y2) 点A在直线BC上吗? * @param x * @param y * @param x1 * @param y1 * @param x2 * @param y2 * @return */ public boolean pointAtSLine(double x,double y,double x1,double y1,double x2,double y2){ double result = ( x - x1 ) * ( y2 - y1 ) - ( y - y1 ) * ( x2 - x1 ); if(result==0){ return true; }else{ return false; } } /** * * 描述:点在线段上. * 点A(x,y),B(x1,y1),C(x2,y2) 点A在线段BC上吗? * @param x * @param y * @param x1 * @param y1 * @param x2 * @param y2 * @return */ public static boolean pointAtELine(double x,double y,double x1,double y1,double x2,double y2){ double result = ( x - x1 ) * ( y2 - y1 ) - ( y - y1 ) * ( x2 - x1 ); if(result==0){ if(x >= Math.min(x1, x2) && x <= Math.max(x1,x2) && y >= Math.min(y1, y2) && y <= Math.max(y1,y2)){ return true; }else{ return false; } }else{ return false; } } /** * * 描述:两条直线相交. * 点A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4) 直线AB与直线CD相交吗? * @param x1 * @param y1 * @param x2 * @param y2 * @param x3 * @param y3 * @param x4 * @param y4 * @return */ public static boolean LineAtLine(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){ double k1 = ( y2-y1 )/(x2-x1); double k2 = ( y4-y3 )/(x4-x3); if(k1==k2){ //System.out.println("平行线"); return false; }else{ double x = ((x1*y2-y1*x2)*(x3-x4)-(x3*y4-y3*x4)*(x1-x2))/((y2-y1)*(x3-x4)-(y4-y3)*(x1-x2)); double y = ( x1*y2-y1*x2 - x*(y2-y1) ) / (x1-x2); //System.out.println("直线的交点("+x+","+y+")"); return true; } } /** * * 描述:线段与线段相交. * 点A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4) * 线段AB与线段CD相交吗? * @param x1 * @param y1 * @param x2 * @param y2 * @param x3 * @param y3 * @param x4 * @param y4 * @return */ public static boolean eLineAtELine(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){ double k1 = ( y2-y1 )/(x2-x1); double k2 = ( y4-y3 )/(x4-x3); if(k1==k2){ //System.out.println("平行线"); return false; }else{ double x = ((x1*y2-y1*x2)*(x3-x4)-(x3*y4-y3*x4)*(x1-x2))/((y2-y1)*(x3-x4)-(y4-y3)*(x1-x2)); double y = ( x1*y2-y1*x2 - x*(y2-y1) ) / (x1-x2); //System.out.println("直线的交点("+x+","+y+")"); if(x >= Math.min(x1, x2) && x <= Math.max(x1,x2) && y >= Math.min(y1, y2) && y <= Math.max(y1,y2) && x >= Math.min(x3, x4) && x <= Math.max(x3,x4) && y >= Math.min(y3, y4) && y <= Math.max(y3,y4) ){ //System.out.println("交点("+x+","+y+")在线段上"); return true; }else{ //System.out.println("交点("+x+","+y+")不在线段上"); return false; } } } /** * * 描述:线段直线相交. * 点A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4) * 线段AB与直线CD相交吗? * @param x1 * @param y1 * @param x2 * @param y2 * @param x3 * @param y3 * @param x4 * @param y4 * @return */ public static boolean eLineAtLine(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){ double k1 = ( y2-y1 )/(x2-x1); double k2 = ( y4-y3 )/(x4-x3); if(k1==k2){ //System.out.println("平行线"); return false; }else{ double x = ((x1*y2-y1*x2)*(x3-x4)-(x3*y4-y3*x4)*(x1-x2))/((y2-y1)*(x3-x4)-(y4-y3)*(x1-x2)); double y = ( x1*y2-y1*x2 - x*(y2-y1) ) / (x1-x2); //System.out.println("交点("+x+","+y+")"); if(x >= Math.min(x1, x2) && x <= Math.max(x1,x2) && y >= Math.min(y1, y2) && y <= Math.max(y1,y2)){ //System.out.println("交点("+x+","+y+")在线段上"); return true; }else{ //System.out.println("交点("+x+","+y+")不在线段上"); return false; } } } /** * * 描述:点在矩形内. * 矩形的边都是与坐标系平行或垂直的。 * 只要判断该点的横坐标和纵坐标是否夹在矩形的左右边和上下边之间。 * 点A(x,y),B(x1,y1),C(x2,y2) 点A在以直线BC为对角线的矩形中吗? * @param x * @param y * @param x1 * @param y1 * @param x2 * @param y2 * @return */ public static boolean pointAtRect(double x,double y,double x1,double y1,double x2,double y2){ if(x >= Math.min(x1, x2) && x <= Math.max(x1,x2) && y >= Math.min(y1, y2) && y <= Math.max(y1,y2)){ //System.out.println("点("+x+","+y+")在矩形内上"); return true; }else{ //System.out.println("点("+x+","+y+")不在矩形内上"); return false; } } /** * * 描述:矩形在矩形内. * 只要对角线的两点都在另一个矩形中就可以了. * 点A(x1,y1),B(x2,y2),C(x1,y1),D(x2,y2) 以直线AB为对角线的矩形在以直线BC为对角线的矩形中吗? * @param x1 * @param y1 * @param x2 * @param y2 * @param x3 * @param y3 * @param x4 * @param y4 * @return */ public static boolean rectAtRect(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){ if(x1 >= Math.min(x3, x4) && x1 <= Math.max(x3,x4) && y1 >= Math.min(y3, y4) && y1 <= Math.max(y3,y4) && x2 >= Math.min(x3, x4) && x2 <= Math.max(x3,x4) && y2 >= Math.min(y3, y4) && y2 <= Math.max(y3,y4)){ //System.out.println("矩形在矩形内"); return true; }else{ //System.out.println("矩形不在矩形内"); return false; } } /** * * 描述:圆心在矩形内 . * 圆心在矩形中且圆的半径小于等于圆心到矩形四边的距离的最小值。 * 圆心(x,y) 半径r 矩形对角点A(x1,y1),B(x2,y2) * @param x * @param y * @param r * @param x1 * @param y1 * @param x2 * @param y2 * @return */ public static boolean circleAtRect(double x,double y,double r,double x1,double y1,double x2,double y2){ //圆心在矩形内 if(x >= Math.min(x1, x2) && x <= Math.max(x1,x2) && y >= Math.min(y1, y2) && y <= Math.max(y1,y2)){ //圆心到4条边的距离 double l1= Math.abs(x-x1); double l2= Math.abs(y-y2); double l3= Math.abs(x-x2); double l4= Math.abs(y-y2); if(r<=l1 && r<=l2 && r<=l3 && r<=l4){ //System.out.println("圆在矩形内"); return true; }else{ //System.out.println("圆不在矩形内"); return false; } }else{ //System.out.println("圆不在矩形内"); return false; } } /** * * 描述:获取两点间的距离. * @param x1 * @param y1 * @param x2 * @param y2 * @return */ public static double getDistance(double x1,double y1,double x2,double y2) { double x = x1 - x2; double y = y1 - y2; return Math.sqrt(x * x + y * y); } /** * 矩形碰撞检测 参数为x,y,width,height * @param x1 第一个矩形的x * @param y1 第一个矩形的y * @param w1 第一个矩形的w * @param h1 第一个矩形的h * @param x2 第二个矩形的x * @param y2 第二个矩形的y * @param w2 第二个矩形的w * @param h2 第二个矩形的h * @return 是否碰撞 */ public static boolean isRectCollision(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) { if (x2 > x1 && x2 > x1 + w1) { return false; } else if (x2 < x1 && x2 < x1 - w2) { return false; } else if (y2 > y1 && y2 > y1 + h1) { return false; } else if (y2 < y1 && y2 < y1 - h2) { return false; } else { return true; } } } ================================================ FILE: src/main/java/com/ab/util/AbMd5.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import java.security.MessageDigest; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn 名称:AbMd5.java 描述:MD5加密. * */ public class AbMd5 { /** * 描述:MD5加密. * * @param str * 要加密的字符串 * @return String 加密的字符串 */ public final static String MD5(String str) { char hexDigits[] = { // 用来将字节转换成 16 进制表示的字符 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { byte[] strTemp = str.getBytes(); MessageDigest mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(strTemp); byte tmp[] = mdTemp.digest(); // MD5 的计算结果是一个 128 位的长整数, // 用字节表示就是 16 个字节 char strs[] = new char[16 * 2]; // 每个字节用 16 进制表示的话,使用两个字符, // 所以表示成 16 进制需要 32 个字符 int k = 0; // 表示转换结果中对应的字符位置 for (int i = 0; i < 16; i++) { // 从第一个字节开始,对 MD5 的每一个字节 // 转换成 16 进制字符的转换 byte byte0 = tmp[i]; // 取第 i 个字节 strs[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换, // >>> 为逻辑右移,将符号位一起右移 strs[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换 } // return new String(strs).toUpperCase(); // 换后的结果转换为字符串 return new String(strs).toLowerCase(); // 换后的结果转换为字符串 } catch (Exception e) { return null; } } } ================================================ FILE: src/main/java/com/ab/util/AbSharedUtil.java ================================================ package com.ab.util; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import com.ab.global.AbAppConfig; //TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbSharedUtil.java * 描述:保存到 SharedPreferences 的数据. * */ public class AbSharedUtil { private static final String SHARED_PATH = AbAppConfig.SHARED_PATH; public static SharedPreferences getDefaultSharedPreferences(Context context) { return context.getSharedPreferences(SHARED_PATH, Context.MODE_PRIVATE); } public static void putInt(Context context,String key, int value) { SharedPreferences sharedPreferences = getDefaultSharedPreferences(context); Editor edit = sharedPreferences.edit(); edit.putInt(key, value); edit.commit(); } public static int getInt(Context context,String key) { SharedPreferences sharedPreferences = getDefaultSharedPreferences(context); return sharedPreferences.getInt(key, 0); } public static void putString(Context context,String key, String value) { SharedPreferences sharedPreferences = getDefaultSharedPreferences(context); Editor edit = sharedPreferences.edit(); edit.putString(key, value); edit.commit(); } public static String getString(Context context,String key) { SharedPreferences sharedPreferences = getDefaultSharedPreferences(context); return sharedPreferences.getString(key,null); } public static void putBoolean(Context context,String key, boolean value) { SharedPreferences sharedPreferences = getDefaultSharedPreferences(context); Editor edit = sharedPreferences.edit(); edit.putBoolean(key, value); edit.commit(); } public static boolean getBoolean(Context context,String key,boolean defValue) { SharedPreferences sharedPreferences = getDefaultSharedPreferences(context); return sharedPreferences.getBoolean(key,defValue); } } ================================================ FILE: src/main/java/com/ab/util/AbStrUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import android.content.Context; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbStrUtil.java * 描述:字符串处理类. */ public class AbStrUtil { /** * 给填写搜索单词的关键词显示 特殊颜色 * * @param word * @return */ public static SpannableStringBuilder changeTextColor(String word, String input, int color, Context context) { int len = input.length(); int start = 0; int end = 0; int position = 0; SpannableStringBuilder style = new SpannableStringBuilder(word); while (true) { position = word.indexOf(input, end); if (-1 == position) { break; } start = position; end = start + len; style.setSpan(new ForegroundColorSpan(context.getResources().getColor(color)), start, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); } return style; } /** * 描述:将null转化为“”. * * @param str 指定的字符串 * @return 字符串的String类型 */ public static String parseEmpty(String str) { if (str == null || "null".equals(str.trim())) { str = ""; } return str.trim(); } /** * 描述:判断一个字符串是否为null或空值. * * @param str 指定的字符串 * @return true or false */ public static boolean isEmpty(String str) { return str == null || str.trim().length() == 0 || str.equals("null"); } /** * 集合是否为空 * * @param list * @return */ public static boolean isEmpty(List list) { if (list != null && list.size() > 0) { return false; } return true; } /** * 获取字符串中文字符的长度(每个中文算2个字符). * * @param str 指定的字符串 * @return 中文字符的长度 */ public static int chineseLength(String str) { int valueLength = 0; String chinese = "[\u0391-\uFFE5]"; /* 获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1 */ if (!isEmpty(str)) { for (int i = 0; i < str.length(); i++) { /* 获取一个字符 */ String temp = str.substring(i, i + 1); /* 判断是否为中文字符 */ if (temp.matches(chinese)) { valueLength += 2; } } } return valueLength; } /** * 描述:获取字符串的长度. * * @param str 指定的字符串 * @return 字符串的长度(中文字符计2个) */ public static int strLength(String str) { int valueLength = 0; String chinese = "[\u0391-\uFFE5]"; if (!isEmpty(str)) { //获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1 for (int i = 0; i < str.length(); i++) { //获取一个字符 String temp = str.substring(i, i + 1); //判断是否为中文字符 if (temp.matches(chinese)) { //中文字符长度为2 valueLength += 2; } else { //其他字符长度为1 valueLength += 1; } } } return valueLength; } /** * 描述:获取指定长度的字符所在位置. * * @param str 指定的字符串 * @param maxL 要取到的长度(字符长度,中文字符计2个) * @return 字符的所在位置 */ public static int subStringLength(String str, int maxL) { int currentIndex = 0; int valueLength = 0; String chinese = "[\u0391-\uFFE5]"; //获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1 for (int i = 0; i < str.length(); i++) { //获取一个字符 String temp = str.substring(i, i + 1); //判断是否为中文字符 if (temp.matches(chinese)) { //中文字符长度为2 valueLength += 2; } else { //其他字符长度为1 valueLength += 1; } if (valueLength >= maxL) { currentIndex = i; break; } } return currentIndex; } /** * 描述:手机号格式验证. * * @param str 指定的手机号码字符串 * @return 是否为手机号码格式:是为true,否则false */ public static Boolean isMobileNo(String str) { Boolean isMobileNo = false; try { Pattern p = Pattern.compile("^((13[0-9])|(15[0-9])|(18[0-9])|(14[0-9])|(17[0-9]))\\d{8}$"); Matcher m = p.matcher(str); isMobileNo = m.matches(); } catch (Exception e) { e.printStackTrace(); } return isMobileNo; } /** * 描述:是否只是字母和数字. * * @param str 指定的字符串 * @return 是否只是字母和数字:是为true,否则false */ public static Boolean isNumberLetter(String str) { Boolean isNoLetter = false; String expr = "^[A-Za-z0-9]+$"; if (str.matches(expr)) { isNoLetter = true; } return isNoLetter; } /** * 描述:是否只是数字. * * @param str 指定的字符串 * @return 是否只是数字:是为true,否则false */ public static Boolean isNumber(String str) { Boolean isNumber = false; String expr = "^[0-9]+$"; if (str.matches(expr)) { isNumber = true; } return isNumber; } /** * 描述:是否是邮箱. * * @param str 指定的字符串 * @return 是否是邮箱:是为true,否则false */ public static Boolean isEmail(String str) { Boolean isEmail = false; String expr = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; if (str.matches(expr)) { isEmail = true; } return isEmail; } /** * 描述:是否是中文. * * @param str 指定的字符串 * @return 是否是中文:是为true,否则false */ public static Boolean isChinese(String str) { Boolean isChinese = true; String chinese = "[\u0391-\uFFE5]"; if (!isEmpty(str)) { //获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1 for (int i = 0; i < str.length(); i++) { //获取一个字符 String temp = str.substring(i, i + 1); //判断是否为中文字符 if (temp.matches(chinese)) { } else { isChinese = false; } } } return isChinese; } /** * 描述:是否包含中文. * * @param str 指定的字符串 * @return 是否包含中文:是为true,否则false */ public static Boolean isContainChinese(String str) { Boolean isChinese = false; String chinese = "[\u0391-\uFFE5]"; if (!isEmpty(str)) { //获取字段值的长度,如果含中文字符,则每个中文字符长度为2,否则为1 for (int i = 0; i < str.length(); i++) { //获取一个字符 String temp = str.substring(i, i + 1); //判断是否为中文字符 if (temp.matches(chinese)) { isChinese = true; } else { } } } return isChinese; } /** * 是否包含中文数字字母的用户名 * 长度1-20 * * @param str * @return */ public static boolean isConintChinseUser(String str) { /**此正则表达式将上面二者结合起来进行判断,中文、大小写字母和数字**/ String all = "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D\\w]{2,10}$"; Pattern pattern = Pattern.compile(all); return pattern.matcher(str).matches(); } /** * 描述:从输入流中获得String. * * @param is 输入流 * @return 获得的String */ public static String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } //最后一个\n删除 if (sb.indexOf("\n") != -1 && sb.lastIndexOf("\n") == sb.length() - 1) { sb.delete(sb.lastIndexOf("\n"), sb.lastIndexOf("\n") + 1); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } /** * 描述:标准化日期时间类型的数据,不足两位的补0. * * @param dateTime 预格式的时间字符串,如:2012-3-2 12:2:20 * @return String 格式化好的时间字符串,如:2012-03-20 12:02:20 */ public static String dateTimeFormat(String dateTime) { StringBuilder sb = new StringBuilder(); try { if (isEmpty(dateTime)) { return null; } String[] dateAndTime = dateTime.split(" "); if (dateAndTime.length > 0) { for (String str : dateAndTime) { if (str.indexOf("-") != -1) { String[] date = str.split("-"); for (int i = 0; i < date.length; i++) { String str1 = date[i]; sb.append(strFormat2(str1)); if (i < date.length - 1) { sb.append("-"); } } } else if (str.indexOf(":") != -1) { sb.append(" "); String[] date = str.split(":"); for (int i = 0; i < date.length; i++) { String str1 = date[i]; sb.append(strFormat2(str1)); if (i < date.length - 1) { sb.append(":"); } } } } } } catch (Exception e) { e.printStackTrace(); return null; } return sb.toString(); } /** * 描述:不足2个字符的在前面补“0”. * * @param str 指定的字符串 * @return 至少2个字符的字符串 */ public static String strFormat2(String str) { try { if (str.length() <= 1) { str = "0" + str; } } catch (Exception e) { e.printStackTrace(); } return str; } /** * 描述:截取字符串到指定字节长度. * * @param str the str * @param length 指定字节长度 * @return 截取后的字符串 */ public static String cutString(String str, int length) { return cutString(str, length, ""); } /** * 描述:截取字符串到指定字节长度. * * @param str 文本 * @param length 字节长度 * @param dot 省略符号 * @return 截取后的字符串 */ public static String cutString(String str, int length, String dot) { int strBLen = strlen(str, "GBK"); if (strBLen <= length) { return str; } int temp = 0; StringBuffer sb = new StringBuffer(length); char[] ch = str.toCharArray(); for (char c : ch) { sb.append(c); if (c > 256) { temp += 2; } else { temp += 1; } if (temp >= length) { if (dot != null) { sb.append(dot); } break; } } return sb.toString(); } /** * 描述:截取字符串从第一个指定字符. * * @param str1 原文本 * @param str2 指定字符 * @param offset 偏移的索引 * @return 截取后的字符串 */ public static String cutStringFromChar(String str1, String str2, int offset) { if (isEmpty(str1)) { return ""; } int start = str1.indexOf(str2); if (start != -1) { if (str1.length() > start + offset) { return str1.substring(start + offset); } } return ""; } /** * 描述:获取字节长度. * * @param str 文本 * @param charset 字符集(GBK) * @return the int */ public static int strlen(String str, String charset) { if (str == null || str.length() == 0) { return 0; } int length = 0; try { length = str.getBytes(charset).length; } catch (Exception e) { e.printStackTrace(); } return length; } /** * 获取大小的描述. * * @param size 字节个数 * @return 大小的描述 */ public static String getSizeDesc(long size) { String suffix = "B"; if (size >= 1024) { suffix = "K"; size = size >> 10; if (size >= 1024) { suffix = "M"; //size /= 1024; size = size >> 10; if (size >= 1024) { suffix = "G"; size = size >> 10; //size /= 1024; } } } return size + suffix; } /** * 描述:ip地址转换为10进制数. * * @param ip the ip * @return the long */ public static long ip2int(String ip) { ip = ip.replace(".", ","); String[] items = ip.split(","); return Long.valueOf(items[0]) << 24 | Long.valueOf(items[1]) << 16 | Long.valueOf(items[2]) << 8 | Long.valueOf(items[3]); } } ================================================ FILE: src/main/java/com/ab/util/AbViewUtil.java ================================================ /* * Copyright (C) 2012 www.amsoft.cn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ab.util; import android.content.Context; import android.graphics.Paint; import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; import android.view.ViewParent; import android.widget.AbsListView; import android.widget.GridView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import com.ab.global.AbAppConfig; // TODO: Auto-generated Javadoc /** * © 2012 amsoft.cn * 名称:AbViewUtil.java * 描述:View工具类. */ public class AbViewUtil { /** * 无效值 */ public static final int INVALID = Integer.MIN_VALUE; /** * 测量这个view * 最后通过getMeasuredWidth()获取宽度和高度. * @param view 要测量的view * @return 测量过的view */ public static void measureView(View view) { ViewGroup.LayoutParams p = view.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width); int lpHeight = p.height; int childHeightSpec; if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } view.measure(childWidthSpec, childHeightSpec); } /** * 获得这个View的宽度 * 测量这个view,最后通过getMeasuredWidth()获取宽度. * @param view 要测量的view * @return 测量过的view的宽度 */ public static int getViewWidth(View view) { measureView(view); return view.getMeasuredWidth(); } /** * 获得这个View的高度 * 测量这个view,最后通过getMeasuredHeight()获取高度. * @param view 要测量的view * @return 测量过的view的高度 */ public static int getViewHeight(View view) { measureView(view); return view.getMeasuredHeight(); } /** * 从父亲布局中移除自己 * @param v */ public static void removeSelfFromParent(View v) { ViewParent parent = v.getParent(); if(parent != null){ if(parent instanceof ViewGroup){ ((ViewGroup)parent).removeView(v); } } } /** * 描述:dip转换为px. * * @param context the context * @param dipValue the dip value * @return px值 */ public static float dip2px(Context context, float dipValue) { DisplayMetrics mDisplayMetrics = AbAppUtil.getDisplayMetrics(context); return applyDimension(TypedValue.COMPLEX_UNIT_DIP,dipValue,mDisplayMetrics); } /** * 描述:px转换为dip. * * @param context the context * @param pxValue the px value * @return dip值 */ public static float px2dip(Context context, float pxValue) { DisplayMetrics mDisplayMetrics = AbAppUtil.getDisplayMetrics(context); return pxValue / mDisplayMetrics.density; } /** * 描述:sp转换为px. * * @param context the context * @param spValue the sp value * @return sp值 */ public static float sp2px(Context context, float spValue) { DisplayMetrics mDisplayMetrics = AbAppUtil.getDisplayMetrics(context); return applyDimension(TypedValue.COMPLEX_UNIT_SP,spValue,mDisplayMetrics); } /** * 描述:px转换为sp. * * @param context the context * @param spValue the sp value * @return sp值 */ public static float px2sp(Context context, float pxValue) { DisplayMetrics mDisplayMetrics = AbAppUtil.getDisplayMetrics(context); return pxValue / mDisplayMetrics.scaledDensity; } /** * 描述:根据屏幕大小缩放. * * @param context the context * @param pxValue the px value * @return the int */ public static int scale(Context context, float value) { DisplayMetrics mDisplayMetrics = AbAppUtil.getDisplayMetrics(context); return scale(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, value); } /** * 描述:根据屏幕大小缩放. * * @param displayWidth the display width * @param displayHeight the display height * @param pxValue the px value * @return the int */ public static int scale(int displayWidth, int displayHeight, float pxValue) { if(pxValue == 0 ){ return 0; } float scale = 1; try { float scaleWidth = (float) displayWidth / AbAppConfig.UI_WIDTH; float scaleHeight = (float) displayHeight / AbAppConfig.UI_HEIGHT; scale = Math.min(scaleWidth, scaleHeight); } catch (Exception e) { } return Math.round(pxValue * scale + 0.5f); } /** * TypedValue官方源码中的算法,任意单位转换为PX单位 * @param unit TypedValue.COMPLEX_UNIT_DIP * @param value 对应单位的值 * @param metrics 密度 * @return px值 */ public static float applyDimension(int unit, float value, DisplayMetrics metrics){ switch (unit) { case TypedValue.COMPLEX_UNIT_PX: return value; case TypedValue.COMPLEX_UNIT_DIP: return value * metrics.density; case TypedValue.COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case TypedValue.COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case TypedValue.COMPLEX_UNIT_IN: return value * metrics.xdpi; case TypedValue.COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; } /** * * 描述:View树递归调用做适配. * AbAppConfig.uiWidth = 1080; * AbAppConfig.uiHeight = 700; * scaleContentView((RelativeLayout)findViewById(R.id.rootLayout)); * 要求布局中的单位都用px并且和美工的设计图尺寸一致,包括所有宽高,Padding,Margin,文字大小 * @param contentView */ public static void scaleContentView(ViewGroup contentView){ AbViewUtil.scaleView(contentView); if(contentView.getChildCount()>0){ for(int i=0;i