diff --git a/md/about_app.md b/md/about_app.md index 3b634a1a6ed61df57635e7d58e4b8a24fa874ab6..1a5c570ed0e0e776ef82d6a6dd66040912f92793 100644 --- a/md/about_app.md +++ b/md/about_app.md @@ -1,138 +1,159 @@ # App相关 -### 安装指定路径下的Apk ``` java +import android.app.ActivityManager; +import android.content.ComponentName; +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.graphics.drawable.Drawable; +import android.net.Uri; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + /** - * 安装指定路径下的Apk - *
根据路径名是否符合和文件是否存在判断是否安装成功 - *
更好的做法应该是startActivityForResult回调判断是否安装成功比较妥当 - *
这里做不了回调,后续自己做处理 + *
+ * author: Blankj + * blog : http://blankj.com + * time : 2016/8/2 + * desc : App相关的工具类 + **/ -public static boolean installApp(Context context, String filePath) { - if (filePath != null && filePath.length() > 4 - && filePath.toLowerCase().substring(filePath.length() - 4).equals(".apk")) { +public class AppUtils { + + private AppUtils() { + throw new UnsupportedOperationException("u can't fuck me..."); + } + + /** + * 安装App + *
根据路径安装App
+ * + * @param context 上下文 + * @param filePath 文件路径 + */ + public static void installApp(Context context, String filePath) { + installApp(context, new File(filePath)); + } + + /** + * 安装App + *根据文件安装App
+ * + * @param context 上下文 + * @param file 文件 + */ + public static void installApp(Context context, File file) { Intent intent = new Intent(Intent.ACTION_VIEW); - File file = new File(filePath); - if (file.exists() && file.isFile() && file.length() > 0) { - intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - return true; - } + intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); } - return false; -} -``` -### 卸载指定包名的App -``` java -/** - * 卸载指定包名的App - *这里卸载成不成功只判断了packageName是否为空 - *
如果要根据是否卸载成功应该用startActivityForResult回调判断是否还存在比较妥当 - *
这里做不了回调,后续自己做处理 - */ -public boolean uninstallApp(Context context, String packageName) { - if (!TextUtils.isEmpty(packageName)) { + /** + * 卸载指定包名的App + * + * @param context 上下文 + * @param packageName 包名 + */ + public void uninstallApp(Context context, String packageName) { Intent intent = new Intent(Intent.ACTION_DELETE); intent.setData(Uri.parse("package:" + packageName)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); - return true; } - return false; -} -``` -### 获取当前App信息 -``` java -/** - * 封装App信息的Bean类 - */ -public static class AppInfo { - - private String name; - private Drawable icon; - private String packagName; - private String versionName; - private int versionCode; - private boolean isSD; - private boolean isUser; - - public Drawable getIcon() { - return icon; - } + /** + * 封装App信息的Bean类 + */ + public static class AppInfo { - public void setIcon(Drawable icon) { - this.icon = icon; - } + private String name; + private Drawable icon; + private String packageName; + private String versionName; + private int versionCode; + private boolean isSD; + private boolean isUser; - public boolean isSD() { - return isSD; - } + public Drawable getIcon() { + return icon; + } - public void setSD(boolean SD) { - isSD = SD; - } + public void setIcon(Drawable icon) { + this.icon = icon; + } - public boolean isUser() { - return isUser; - } + public boolean isSD() { + return isSD; + } - public void setUser(boolean user) { - isUser = user; - } + public void setSD(boolean SD) { + isSD = SD; + } - public String getName() { - return name; - } + public boolean isUser() { + return isUser; + } - public void setName(String name) { - this.name = name; - } + public void setUser(boolean user) { + isUser = user; + } - public String getPackagName() { - return packagName; - } + public String getName() { + return name; + } - public void setPackagName(String packagName) { - this.packagName = packagName; - } + public void setName(String name) { + this.name = name; + } - public int getVersionCode() { - return versionCode; - } + public String getPackageName() { + return packageName; + } - public void setVersionCode(int versionCode) { - this.versionCode = versionCode; - } + public void setPackageName(String packagName) { + this.packageName = packagName; + } - public String getVersionName() { - return versionName; - } + public int getVersionCode() { + return versionCode; + } - public void setVersionName(String versionName) { - this.versionName = versionName; - } + public void setVersionCode(int versionCode) { + this.versionCode = versionCode; + } - /** - * @param name 名称 - * @param icon 图标 - * @param packagName 包名 - * @param versionName 版本号 - * @param versionCode 版本Code - * @param isSD 是否安装在SD卡 - * @param isUser 是否是用户程序 - */ - public AppInfo(String name, Drawable icon, String packagName, - String versionName, int versionCode, boolean isSD, boolean isUser) { - this.setName(name); - this.setIcon(icon); - this.setPackagName(packagName); - this.setVersionName(versionName); - this.setVersionCode(versionCode); - this.setSD(isSD); - this.setUser(isUser); - } + public String getVersionName() { + return versionName; + } + + public void setVersionName(String versionName) { + this.versionName = versionName; + } + + /** + * @param name 名称 + * @param icon 图标 + * @param packageName 包名 + * @param versionName 版本号 + * @param versionCode 版本Code + * @param isSD 是否安装在SD卡 + * @param isUser 是否是用户程序 + */ + public AppInfo(String name, Drawable icon, String packageName, + String versionName, int versionCode, boolean isSD, boolean isUser) { + this.setName(name); + this.setIcon(icon); + this.setPackageName(packageName); + this.setVersionName(versionName); + this.setVersionCode(versionCode); + this.setSD(isSD); + this.setUser(isUser); + } /*@Override public String toString() { @@ -144,127 +165,149 @@ public static class AppInfo { + isSD() + "\n" + isUser() + "\n"; }*/ -} + } -/** - * 获取当前App信息 - *
AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序) - */ -public static AppInfo getAppInfo(Context context) { - PackageManager pm = context.getPackageManager(); - PackageInfo pi = null; - try { - pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); + /** + * 获取当前App信息 + *
AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序)
+ * + * @param context 上下文 + * @return 当前应用的AppInfo + */ + public static AppInfo getAppInfo(Context context) { + PackageManager pm = context.getPackageManager(); + PackageInfo pi = null; + try { + pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return pi != null ? getBean(pm, pi) : null; } - return pi != null ? getBean(pm, pi) : null; -} -/** - * 得到AppInfo的Bean - */ -private static AppInfo getBean(PackageManager pm, PackageInfo pi) { - ApplicationInfo ai = pi.applicationInfo; - String name = ai.loadLabel(pm).toString(); - Drawable icon = ai.loadIcon(pm); - String packageName = pi.packageName; - String versionName = pi.versionName; - int versionCode = pi.versionCode; - boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; - boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; - return new AppInfo(name, icon, packageName, versionName, versionCode, isSD, isUser); -} -``` + /** + * 得到AppInfo的Bean + * + * @param pm 包的管理 + * @param pi 包的信息 + * @return AppInfo类 + */ + private static AppInfo getBean(PackageManager pm, PackageInfo pi) { + ApplicationInfo ai = pi.applicationInfo; + String name = ai.loadLabel(pm).toString(); + Drawable icon = ai.loadIcon(pm); + String packageName = pi.packageName; + String versionName = pi.versionName; + int versionCode = pi.versionCode; + boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; + boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; + return new AppInfo(name, icon, packageName, versionName, versionCode, isSD, isUser); + } -### 获取所有已安装App信息 -``` -/** - * 获取所有已安装App信息 - *AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序) - *
依赖上面的getBean方法
- */
-public static List AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序) 依赖上面的getBean方法 需添加权限 android.permission.GET_TASKS
- * 并且必须是系统应用该方法才有效
- */
-public static boolean isAppBackground(Context context) {
- ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- @SuppressWarnings("deprecation")
- List 需添加权限 android.permission.GET_TASKS 并且必须是系统应用该方法才有效 需添加权限 android.permission.ACCESS_WIFI_STATE
+ * 需添加权限 android.permission.ACCESS_WIFI_STATE 需添加权限 android.permission.ACCESS_WIFI_STATE 一般是/storage/emulated/0/
- */
-public static String getSDCardPath() {
- return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;
+ /**
+ * 获取设备型号,如MI2SC
+ *
+ * @return 设备型号
+ */
+ public static String getModel() {
+ String model = Build.MODEL;
+ if (model != null) {
+ model = model.trim().replaceAll("\\s*", "");
+ } else {
+ model = "";
+ }
+ return model;
+ }
+
+ /**
+ * 获取设备SD卡是否可用
+ *
+ * @return true : 可用 一般是/storage/emulated/0/ 若想自己指定字符集,可以使用encode(String string, String charset)方法 若系统不支持指定的编码字符集,则直接将string原样返回 若想自己指定字符集,可以使用# {decode(String string, String charset)}方法 若系统不支持指定的解码字符集,则直接将string原样返回 在onTouch中处理,未获焦点则隐藏
- * 参照以下注释代码
- */
-public static void clickBlankArea2HideSoftInput0() {
- Log.i("tips", "U should copy the following code.");
- /*
- @Override
- public boolean onTouchEvent (MotionEvent event){
- if (null != this.getCurrentFocus()) {
- InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
- return mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
+ /**
+ * 动态隐藏软键盘
+ *
+ * @param activity activity
+ */
+ public static void hideSoftInput(Activity activity) {
+ View view = activity.getWindow().peekDecorView();
+ if (view != null) {
+ InputMethodManager inputmanger = (InputMethodManager) activity
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
- return super.onTouchEvent(event);
}
- */
-}
-/**
- * 点击屏幕空白区域隐藏软键盘(方法1)
- * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘
- * 需重写dispatchTouchEvent
- * 参照以下注释代码
- */
-public static void clickBlankArea2HideSoftInput1() {
- Log.i("tips", "U should copy the following code.");
- /*
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- View v = getCurrentFocus();
- if (isShouldHideKeyboard(v, ev)) {
- hideKeyboard(v.getWindowToken());
+ /**
+ * 动态隐藏软键盘
+ *
+ * @param context 上下文
+ * @param edit 输入框
+ */
+ public static void hideSoftInput(Context context, EditText edit) {
+ edit.clearFocus();
+ InputMethodManager inputmanger = (InputMethodManager) context
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0);
+ }
+
+ /**
+ * 点击屏幕空白区域隐藏软键盘(方法1)
+ * 在onTouch中处理,未获焦点则隐藏 参照以下注释代码 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 需重写dispatchTouchEvent 参照以下注释代码 3.0以下打开设置界面
+ * 需添加权限 android.permission.ACCESS_NETWORK_STATE
- */
-public static boolean isAvailable(Context context) {
- NetworkInfo info = getActiveNetworkInfo(context);
- return info != null && info.isAvailable();
-}
-```
+ private static final int NETWORK_TYPE_GSM = 16;
+ private static final int NETWORK_TYPE_TD_SCDMA = 17;
+ private static final int NETWORK_TYPE_IWLAN = 18;
-### 判断网络是否连接
-``` java
-/**
- * 判断网络是否连接
- * 需添加权限 android.permission.ACCESS_NETWORK_STATE
- */
-public static boolean isConnected(Context context) {
- NetworkInfo info = getActiveNetworkInfo(context);
- return info != null && info.isConnected();
-}
-```
+ /**
+ * 打开网络设置界面
+ * 3.0以下打开设置界面 需添加权限 android.permission.ACCESS_NETWORK_STATE
- */
-public static boolean is4G(Context context) {
- NetworkInfo info = getActiveNetworkInfo(context);
- return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE;
-}
-```
+ /**
+ * 获取活动网路信息
+ *
+ * @param context 上下文
+ * @return NetworkInfo
+ */
+ private static NetworkInfo getActiveNetworkInfo(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ return cm.getActiveNetworkInfo();
+ }
-### 判断wifi是否连接状态
-``` java
-/**
- * 判断wifi是否连接状态
- * 需添加权限 android.permission.ACCESS_NETWORK_STATE
- */
-public static boolean isWifiConnected(Context context) {
- ConnectivityManager cm = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
-}
-```
+ /**
+ * 判断网络是否可用
+ * 需添加权限 android.permission.ACCESS_NETWORK_STATE 如中国联通、中国移动、中国电信
- */
-public static String getNetworkOperatorName(Context context) {
- TelephonyManager tm = (TelephonyManager) context
- .getSystemService(Context.TELEPHONY_SERVICE);
- return tm != null ? tm.getNetworkOperatorName() : null;
-}
-```
+ /**
+ * 判断网络是否连接
+ * 需添加权限 android.permission.ACCESS_NETWORK_STATE 需添加权限 android.permission.ACCESS_NETWORK_STATE 需添加权限 android.permission.ACCESS_NETWORK_STATE
- *
- * @return 网络类型
- * 需添加权限 android.permission.ACCESS_NETWORK_STATE 如中国联通、中国移动、中国电信 需添加权限 android.permission.ACCESS_NETWORK_STATE 依赖上面的方法 需与上面的isPhone一起使用
- * 需添加权限 android.permission.READ_PHONE_STATE
+ * 需添加权限 android.permission.READ_PHONE_STATE
- * 返回如下
- * 需与上面的isPhone一起使用 需添加权限 android.permission.READ_PHONE_STATE 需添加权限 android.permission.READ_PHONE_STATE 需添加权限 android.permission.CALL_PHONE
- */
-public static void call(Context context, String phoneNumber) {
- context.startActivity(new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber)));
-}
-```
+ /**
+ * 跳至填充好phoneNumber的拨号界面
+ *
+ * @param context 上下文
+ * @param phoneNumber 电话号码
+ */
+ public static void dial(Context context, String phoneNumber) {
+ context.startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)));
+ }
-### 发送短信
-``` java
-/**
-* 发送短信
-*/
-public static void sendSms(Context context, String phoneNumber, String content) {
- Uri uri = Uri.parse("smsto:" + (TextUtils.isEmpty(phoneNumber) ? "" : phoneNumber));
- Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
- intent.putExtra("sms_body", TextUtils.isEmpty(content) ? "" : content);
- context.startActivity(intent);
-}
-```
+ /**
+ * 拨打phoneNumber
+ * 需添加权限 android.permission.CALL_PHONE 需添加权限 android.permission.READ_EXTERNAL_STORAGE
- * 需添加权限 android.permission.READ_CONTACTS
- */
-public static List 需添加权限 android.permission.READ_EXTERNAL_STORAGE 需添加权限 android.permission.READ_CONTACTS 参照以下注释代码
- */
-public static void getContantNum() {
- Log.i("tips", "U should copy the follow code.");
- /*
- Intent intent = new Intent();
- intent.setAction("android.intent.action.PICK");
- intent.setType("vnd.android.cursor.dir/phone_v2");
- startActivityForResult(intent, 0);
- @Override
- protected void onActivityResult ( int requestCode, int resultCode, Intent data){
- super.onActivityResult(requestCode, resultCode, data);
- if (data != null) {
- Uri uri = data.getData();
- String num = null;
- // 创建内容解析者
- ContentResolver contentResolver = getContentResolver();
- Cursor cursor = contentResolver.query(uri,
- null, null, null, null);
- while (cursor.moveToNext()) {
- num = cursor.getString(cursor.getColumnIndex("data1"));
+ /**
+ * 打开手机联系人界面点击联系人后便获取该号码
+ * 参照以下注释代码 需添加权限 android.permission.READ_SMS
- * 需添加权限 android.permission.WRITE_EXTERNAL_STORAGE
- */
-public static void getAllSMS(Context context) {
- //1.获取短信
- //1.1获取内容解析者
- ContentResolver resolver = context.getContentResolver();
- //1.2获取内容提供者地址 sms,sms表的地址:null 不写
- //1.3获取查询路径
- Uri uri = Uri.parse("content://sms");
- //1.4.查询操作
- //projection : 查询的字段
- //selection : 查询的条件
- //selectionArgs : 查询条件的参数
- //sortOrder : 排序
- Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null);
- //设置最大进度
- int count = cursor.getCount();//获取短信的个数
- //2.备份短信
- //2.1获取xml序列器
- XmlSerializer xmlSerializer = Xml.newSerializer();
- try {
- //2.2设置xml文件保存的路径
- //os : 保存的位置
- //encoding : 编码格式
- xmlSerializer.setOutput(new FileOutputStream(new File("/mnt/sdcard/backupsms.xml")), "utf-8");
- //2.3设置头信息
- //standalone : 是否独立保存
- xmlSerializer.startDocument("utf-8", true);
- //2.4设置根标签
- xmlSerializer.startTag(null, "smss");
- //1.5.解析cursor
- while (cursor.moveToNext()) {
- SystemClock.sleep(1000);
- //2.5设置短信的标签
- xmlSerializer.startTag(null, "sms");
- //2.6设置文本内容的标签
- xmlSerializer.startTag(null, "address");
- String address = cursor.getString(0);
- //2.7设置文本内容
- xmlSerializer.text(address);
- xmlSerializer.endTag(null, "address");
- xmlSerializer.startTag(null, "date");
- String date = cursor.getString(1);
- xmlSerializer.text(date);
- xmlSerializer.endTag(null, "date");
- xmlSerializer.startTag(null, "type");
- String type = cursor.getString(2);
- xmlSerializer.text(type);
- xmlSerializer.endTag(null, "type");
- xmlSerializer.startTag(null, "body");
- String body = cursor.getString(3);
- xmlSerializer.text(body);
- xmlSerializer.endTag(null, "body");
- xmlSerializer.endTag(null, "sms");
- System.out.println("address:" + address + " date:" + date + " type:" + type + " body:" + body);
+ /**
+ * 获取手机短信并保存到xml中
+ * 需添加权限 android.permission.READ_SMS 需添加权限 android.permission.WRITE_EXTERNAL_STORAGE
+ * 移动:134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188
* 联通:130、131、132、145、155、156、175、176、185、186
* 电信:133、153、173、177、180、181、189
diff --git a/md/about_screen.md b/md/about_screen.md
index 2b97a76ec78e7cbe0e229df6a2dacbfaceeec0ca..da88681fee985ee9419f836f98270733592ec166 100644
--- a/md/about_screen.md
+++ b/md/about_screen.md
@@ -1,217 +1,238 @@
# 屏幕相关
-### 获取手机分辨率
``` java
-/**
-* 获取屏幕的宽度px
-*/
-public static int getDeviceWidth(Context context) {
- WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸
- windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高
- return outMetrics.widthPixels;
-}
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.graphics.Bitmap;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
-/**
-* 获取屏幕的高度px
-*/
-public static int getDeviceHeight(Context context) {
- WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸
- windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高
- return outMetrics.heightPixels;
-}
-```
+import java.lang.reflect.Method;
-### 设置透明状态栏(api >= 19方可使用)
-``` java
/**
- * 设置透明状态栏(api >= 19方可使用)
- * 可在Activity的onCreat()中调用
- * 需在顶部控件布局中加入以下属性让内容出现在状态栏之下
- * android:clipToPadding="true"
- * android:fitsSystemWindows="true"
+ * 也就是设置全屏,一定要在setContentView之前调用,否则报错
- * 此方法Activity可以继承AppCompatActivity
- * 启动的时候状态栏会显示一下再隐藏,比如QQ的欢迎界面
- * 在配置文件中Activity加属性android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- * 如加了以上配置Activity不能继承AppCompatActivity,会报错
- */
-public static void hideStatusBar(Activity activity) {
- activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
- activity.getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN,
- LayoutParams.FLAG_FULLSCREEN);
-}
-```
+ /**
+ * 获取屏幕的宽度px
+ *
+ * @param context 上下文
+ * @return 屏幕宽px
+ */
+ public static int getScreenWidth(Context context) {
+ WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸
+ windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高
+ return outMetrics.widthPixels;
+ }
-### 获取状态栏高度
-``` java
-/**
- * 获取状态栏高度
- */
-public static int getStatusBarHeight(Context context) {
- int result = 0;
- int resourceId = context.getResources()
- .getIdentifier("status_bar_height", "dimen", "android");
- if (resourceId > 0) {
- result = context.getResources().getDimensionPixelSize(resourceId);
+ /**
+ * 获取屏幕的高度px
+ *
+ * @param context 上下文
+ * @return 屏幕高px
+ */
+ public static int getScreenHeight(Context context) {
+ WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸
+ windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高
+ return outMetrics.heightPixels;
}
- return result;
-}
-```
-### 判断状态栏是否存在
-``` java
-/**
-* 判断状态栏是否存在
-*
-* @param activity
-* @return 可在Activity的onCreat()中调用 需在顶部控件布局中加入以下属性让内容出现在状态栏之下 android:clipToPadding="true" android:fitsSystemWindows="true" 也就是设置全屏,一定要在setContentView之前调用,否则报错 此方法Activity可以继承AppCompatActivity 启动的时候状态栏会显示一下再隐藏,比如QQ的欢迎界面 在配置文件中Activity加属性android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 如加了以上配置Activity不能继承AppCompatActivity,会报错 还有一种就是在Activity中加属性android:screenOrientation="landscape"
- * 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
- * 设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
- * 设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时
- * 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
- */
-public static void setLandscape(Activity activity) {
- activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-}
-```
+ /**
+ * 获取ActionBar高度
+ *
+ * @param activity activity
+ * @return ActionBar高度
+ */
+ public static int getActionBarHeight(Activity activity) {
+ TypedValue tv = new TypedValue();
+ if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
+ return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics());
+ }
+ return 0;
+ }
-### 获取当前屏幕截图
-``` java
-/**
- * 获取当前屏幕截图,包含状态栏
- */
-public static Bitmap captureWithStatusBar(Activity activity) {
- View view = activity.getWindow().getDecorView();
- view.setDrawingCacheEnabled(true);
- view.buildDrawingCache();
- Bitmap bmp = view.getDrawingCache();
- int width = getScreenWidth(activity);
- int height = getScreenHeight(activity);
- Bitmap bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
- view.destroyDrawingCache();
- return bp;
-}
+ /**
+ * 显示通知栏
+ * 需添加权限 android.permission.EXPAND_STATUS_BAR 需要用到上面获取状态栏高度的方法
- */
-public static Bitmap captureWithoutStatusBar(Activity activity) {
- View view = activity.getWindow().getDecorView();
- view.setDrawingCacheEnabled(true);
- view.buildDrawingCache();
- Bitmap bmp = view.getDrawingCache();
- int statusBarHeight = getStatusBarHeight(activity);
- int width = getScreenWidth(activity);
- int height = getScreenHeight(activity);
- Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight);
- view.destroyDrawingCache();
- return bp;
-}
-```
+ /**
+ * 隐藏通知栏
+ * 需添加权限 android.permission.EXPAND_STATUS_BAR 还有一种就是在Activity中加属性android:screenOrientation="landscape" 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次 设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次 设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"(4.0以上必须带最后一个参数)时
+ * 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法 需要用到上面获取状态栏高度getStatusBarHeight的方法 该方法存在于TypedValue
- */
-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);
+ /**
+ * dp转px
+ *
+ * @param context 上下文
+ * @param dpValue dp值
+ * @return px值
+ */
+ public static int dp2px(Context context, float dpValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
}
- return 0;
-}
-```
-### 在onCreate()即可强行获取View的尺寸
-``` java
-/**
-* 在onCreate()即可强行获取View的尺寸
-* 需回调onGetSizeListener接口,在onGetSize中获取view宽高
-* 用法示例如下所示
-* SizeUtils.forceGetViewSize(view);
-* SizeUtils.setListener(new SizeUtils.onGetSizeListener() {
- * @Override
- * public void onGetSize(View view) {
- * Log.d("tag", view.getWidth() + " " + view.getHeight());
- * }
-* });
-*/
-public static void forceGetViewSize(final View view) {
- view.post(new Runnable() {
- @Override
- public void run() {
- if (mListener != null) {
- mListener.onGetSize(view);
- }
- }
- });
-}
+ /**
+ * px转dp
+ *
+ * @param context 上下文
+ * @param pxValue px值
+ * @return dp值
+ */
+ public static int px2dp(Context context, float pxValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (pxValue / scale + 0.5f);
+ }
-/**
-* 获取到View尺寸的监听
-*/
-public interface onGetSizeListener {
- void onGetSize(View view);
-}
+ /**
+ * sp转px
+ *
+ * @param context 上下文
+ * @param spValue sp值
+ * @return px值
+ */
+ public static int sp2px(Context context, float spValue) {
+ final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+ return (int) (spValue * fontScale + 0.5f);
+ }
-public static void setListener(onGetSizeListener listener) {
- mListener = listener;
-}
+ /**
+ * px转sp
+ *
+ * @param context 上下文
+ * @param pxValue px值
+ * @return sp值
+ */
+ public static int px2sp(Context context, float pxValue) {
+ final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+ return (int) (pxValue / fontScale + 0.5f);
+ }
-private static onGetSizeListener mListener;
-```
+ /**
+ * 各种单位转换
+ * 该方法存在于TypedValue 用的时候去掉注释拷贝到ListView中即可
- * 参照以下注释代码
- */
-public static void measureViewInLV(View view) {
- Log.i("tips", "U should copy the follow code.");
- /*
- ViewGroup.LayoutParams p = view.getLayoutParams();
- if (p == null) {
- p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
+ /**
+ * 在onCreate()即可强行获取View的尺寸
+ * 需回调onGetSizeListener接口,在onGetSize中获取view宽高 用法示例如下所示 用的时候去掉注释拷贝到ListView中即可 参照以下注释代码 可通过修改PREFERENCE_NAME变量修改SP的name值 格式为yyyy-MM-dd HH:mm:ss
- */
-public static String milliseconds2String(long milliseconds) {
- return milliseconds2String(milliseconds, DEFAULT_SDF);
-}
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
/**
- * 将时间戳转为时间字符串
- * 格式为用户自定义
- */
-public static String milliseconds2String(long milliseconds, SimpleDateFormat format) {
- return format.format(new Date(milliseconds));
-}
-```
-
-### 将时间字符串转为时间戳
-``` java
-/**
- * 将时间字符串转为时间戳
- * 格式为yyyy-MM-dd HH:mm:ss
+ * 格式为用户自定义
- */
-public static long string2Milliseconds(String time, SimpleDateFormat format) {
- try {
- return format.parse(time).getTime();
- } catch (ParseException e) {
- e.printStackTrace();
+ private TimeUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
}
- return -1;
-}
-```
-### 将时间字符串转为Date类型
-``` java
-/**
- * 将时间字符串转为Date类型
- * 格式为yyyy-MM-dd HH:mm:ss
- */
-public static Date string2Date(String formatDate) {
- return string2Date(formatDate, DEFAULT_SDF);
-}
+ /**
+ * 在工具类中经常使用到工具类的格式化描述,这个主要是一个日期的操作类,所以日志格式主要使用 SimpleDateFormat的定义格式. 日期和时间格式由日期和时间模式字符串指定。在日期和时间模式字符串中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z'
+ * 被解释为模式字母,用来表示日期或时间字符串元素。文本可以使用单引号 (') 引起来,以免进行解释。"''"
+ * 表示单引号。所有其他字符均不解释;只是在格式化时将它们简单复制到输出字符串,或者在分析时与输入字符串进行匹配。
+ * 格式为用户自定义
- */
-public static Date string2Date(String formatDate, SimpleDateFormat format) {
- return new Date(string2Milliseconds(formatDate, format));
-}
-```
+ /**
+ * 将时间戳转为时间字符串
+ * 格式为yyyy-MM-dd HH:mm:ss 格式为yyyy-MM-dd HH:mm:ss
- */
-public static String date2String(Date date) {
- return date2String(date, DEFAULT_SDF);
-}
+ /**
+ * 将时间戳转为时间字符串
+ * 格式为用户自定义 格式为用户自定义
- */
-public static String date2String(Date date, SimpleDateFormat format) {
- return format.format(date);
-}
-```
+ /**
+ * 将时间字符串转为时间戳
+ * 格式为yyyy-MM-dd HH:mm:ss 格式为用户自定义 格式为yyyy-MM-dd HH:mm:ss 格式为用户自定义 time1和time2格式都为yyyy-MM-dd HH:mm:ss
- */
-public static long getIntervalTime(String time1, String time2, int unit) {
- return getIntervalTime(time1, time2, unit, DEFAULT_SDF);
-}
+ /**
+ * 将Date类型转为时间字符串
+ * 格式为yyyy-MM-dd HH:mm:ss time1和time2格式都为format
- */
-public static long getIntervalTime(String time1, String time2, int unit, SimpleDateFormat for
- return milliseconds2Unit(string2Milliseconds(time1, format)
- - string2Milliseconds(time2, format), unit);
-}
+ /**
+ * 将Date类型转为时间字符串
+ * 格式为用户自定义 time1和time2都为Date
- */
-public static long getIntervalTime(Date time1, Date time2, int unit) {
- return milliseconds2Unit(date2Milliseconds(time2) - date2Milliseconds(time1), unit);
-}
-```
+ /**
+ * 将Date类型转为时间戳
+ *
+ * @param time Date类型时间
+ * @return 毫秒时间戳
+ */
+ public static long date2Milliseconds(Date time) {
+ return time.getTime();
+ }
-### 获取当前时间
-``` java
-/**
- * 获取当前时间
- * 单位(毫秒)
- */
-public static long getCurTimeMills() {
- return System.currentTimeMillis();
-}
+ /**
+ * 将时间戳转为Date类型
+ *
+ * @param milliseconds 毫秒时间戳
+ * @return Date类型时间
+ */
+ public static Date milliseconds2Date(long milliseconds) {
+ return new Date(milliseconds);
+ }
-/**
- * 获取当前时间
- * 格式为yyyy-MM-dd HH:mm:ss
- */
-public static String getCurTimeString() {
- return milliseconds2String(getCurTimeMills());
-}
+ /**
+ * 毫秒时间戳单位转换(单位:unit)
+ *
+ * @param milliseconds 毫秒时间戳
+ * @param unit 格式为用户自定义
- */
-public static String getCurTimeString(SimpleDateFormat format) {
- return milliseconds2String(getCurTimeMills(), format);
-}
+ /**
+ * 获取两个时间差(单位:unit)
+ * time1和time2格式都为yyyy-MM-dd HH:mm:ss Date类型
- */
-public static Date getCurTimeDate() {
- return new Date();
-}
-```
+ /**
+ * 获取两个时间差(单位:unit)
+ * time1和time2格式都为format time1和time2格式都为yyyy-MM-dd HH:mm:ss
- */
-public static long getIntervalByNow(String time, int unit) {
- return getIntervalByNow(time, unit, DEFAULT_SDF);
-}
+ /**
+ * 获取两个时间差(单位:unit)
+ * time1和time2都为Date类型 time1和time2格式都为format
- */
-public static long getIntervalByNow(String time, int unit, SimpleDateFormat format) {
- return getIntervalTime(getCurTimeString(), time, unit, format);
-}
+ /**
+ * 获取当前时间
+ *
+ * @return 毫秒时间戳
+ */
+ public static long getCurTimeMills() {
+ return System.currentTimeMillis();
+ }
-/**
- * 获取与当前时间的差(单位:unit)
- * time1和time2格式都为format
- */
-public static long getIntervalByNow(Date time, int unit) {
- return getIntervalTime(getCurTimeDate(), time, unit);
-}
-```
+ /**
+ * 获取当前时间
+ * 格式为yyyy-MM-dd HH:mm:ss 格式为用户自定义 Date类型 time格式为yyyy-MM-dd HH:mm:ss time格式为format time为Date类型 对输入参数中的敏感字符进行过滤替换,防止用户利用JavaScript等方式输入恶意代码
false: 未安装
+ */
+ public static boolean isInstallApp(Context context, String packageName) {
+ return getIntentByPackageName(context, packageName) != null;
+ }
+
+ /**
+ * 打开指定包名的App
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ * @return true: 打开成功
false: 打开失败
+ */
+ public static boolean openAppByPackageName(Context context, String packageName) {
+ Intent intent = getIntentByPackageName(context, packageName);
+ if (intent != null) {
+ context.startActivity(intent);
return true;
}
+ return false;
}
- return false;
-}
-```
-### 打开指定包名的App应用信息界面
-``` java
-/**
- * 打开指定包名的App应用信息界面
- */
-public static boolean openAppInfo(Context context, String packageName) {
- if (!TextUtils.isEmpty(packageName)) {
+ /**
+ * 打开指定包名的App应用信息界面
+ *
+ * @param context 上下文
+ * @param packageName 包名
+ */
+ public static void openAppInfo(Context context, String packageName) {
Intent intent = new Intent();
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.parse("package:" + packageName));
context.startActivity(intent);
- return true;
}
- return false;
-}
-```
-### 可用来做App信息分享
-``` java
-/**
- * 可用来做App信息分享
- */
-public static void shareAppInfo(Context context, String info) {
- if (!TextUtils.isEmpty(info)) {
+ /**
+ * 可用来做App信息分享
+ *
+ * @param context 上下文
+ * @param info 分享信息
+ */
+ public static void shareAppInfo(Context context, String info) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, info);
context.startActivity(intent);
}
-}
-```
-### 判断当前App处于前台还是后台
-``` java
-/**
- * 判断当前App处于前台还是后台
- *
false: 前台
+ */
+ public static boolean isAppBackground(Context context) {
+ ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ @SuppressWarnings("deprecation")
+ List
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/1
+ * desc : 设备相关的工具类
+ *
*/
-public static String getMacAddress(Context context) {
- String macAddress;
- WifiManager wifi = (WifiManager) context
- .getSystemService(Context.WIFI_SERVICE);
- WifiInfo info = wifi.getConnectionInfo();
- macAddress = info.getMacAddress();
- if (null == macAddress) {
- return "";
+public class DeviceUtils {
+
+ private DeviceUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
}
- macAddress = macAddress.replace(":", "");
- return macAddress;
-}
-```
-### 获取设备厂商,如Xiaomi
-``` java
-/**
-* 获取设备厂商,如Xiaomi
-*/
-public static String getManufacturer() {
- String MANUFACTURER = Build.MANUFACTURER;
- return MANUFACTURER;
-}
-```
+ /**
+ * 获取设备MAC地址
+ *
false : 不可用
+ */
+ public static boolean isSDCardEnable() {
+ return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
+ }
+
+ /**
+ * 获取设备SD卡路径
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/7
+ * desc : 编码解码相关工具类
+ *
*/
-public static String getMD5(String data, String salt) {
- return bytes2Hex(encryptMD5((data + salt).getBytes()));
-}
+public class EncodeUtils {
-/**
- * MD5加密
- *
- * @param data 明文字节数组
- * @return 密文
- */
-public static String getMD5(byte[] data) {
- return bytes2Hex(encryptMD5(data));
-}
-
-/**
- * MD5加密
- *
- * @param data 明文字节数组
- * @param salt 盐字节数组
- * @return 密文
- */
-public static String getMD5(byte[] data, byte[] salt) {
- byte[] dataSalt = new byte[data.length + salt.length];
- System.arraycopy(data, 0, dataSalt, 0, data.length);
- System.arraycopy(salt, 0, dataSalt, data.length, salt.length);
- return bytes2Hex(encryptMD5(dataSalt));
-}
+ private EncodeUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
+ }
-/**
- * MD5加密
- *
- * @param data 明文字节数组
- * @return 密文字节数组
- */
-public static byte[] encryptMD5(byte[] data) {
- try {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(data);
- return md.digest();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
+ /**
+ * 以UTF-8编码字符串
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 加密相关的工具类
+ *
*/
-public static String getMD5(String data, String salt) {
- return bytes2Hex(encryptMD5((data + salt).getBytes()));
-}
+public class EncryptUtils {
-/**
- * MD5加密
- *
- * @param data 明文字节数组
- * @return 密文
- */
-public static String getMD5(byte[] data) {
- return bytes2Hex(encryptMD5(data));
-}
+ private EncryptUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
+ }
-/**
- * MD5加密
- *
- * @param data 明文字节数组
- * @param salt 盐字节数组
- * @return 密文
- */
-public static String getMD5(byte[] data, byte[] salt) {
- byte[] dataSalt = new byte[data.length + salt.length];
- System.arraycopy(data, 0, dataSalt, 0, data.length);
- System.arraycopy(salt, 0, dataSalt, data.length, salt.length);
- return bytes2Hex(encryptMD5(dataSalt));
-}
+ /**
+ * MD5加密
+ *
+ * @param data 明文字符串
+ * @return 密文
+ */
+ public static String getMD5(String data) {
+ return getMD5(data.getBytes());
+ }
-/**
- * MD5加密
- *
- * @param data 明文字节数组
- * @return 密文字节数组
- */
-public static byte[] encryptMD5(byte[] data) {
- try {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(data);
- return md.digest();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
+ /**
+ * MD5加密
+ *
+ * @param data 明文字符串
+ * @param salt 盐
+ * @return 密文
+ */
+ public static String getMD5(String data, String salt) {
+ return bytes2Hex(encryptMD5((data + salt).getBytes()));
}
- return new byte[0];
-}
-/**
- * 获取文件的MD5校验码
- *
- * @param filePath 文件路径
- * @return 文件的MD5校验码
- */
-public static String getMD5File(String filePath) {
- FileInputStream in = null;
- try {
- MessageDigest md = MessageDigest.getInstance("MD5");
- in = new FileInputStream(filePath);
- int len;
- byte[] buffer = new byte[1024];
- while ((len = in.read(buffer)) != -1) {
- md.update(buffer, 0, len);
+ /**
+ * MD5加密
+ *
+ * @param data 明文字节数组
+ * @return 密文
+ */
+ public static String getMD5(byte[] data) {
+ return bytes2Hex(encryptMD5(data));
+ }
+
+ /**
+ * MD5加密
+ *
+ * @param data 明文字节数组
+ * @param salt 盐字节数组
+ * @return 密文
+ */
+ public static String getMD5(byte[] data, byte[] salt) {
+ byte[] dataSalt = new byte[data.length + salt.length];
+ System.arraycopy(data, 0, dataSalt, 0, data.length);
+ System.arraycopy(salt, 0, dataSalt, data.length, salt.length);
+ return bytes2Hex(encryptMD5(dataSalt));
+ }
+
+ /**
+ * MD5加密
+ *
+ * @param data 明文字节数组
+ * @return 密文字节数组
+ */
+ public static byte[] encryptMD5(byte[] data) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(data);
+ return md.digest();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
}
- return bytes2Hex(md.digest());
- } catch (NoSuchAlgorithmException | IOException e) {
- e.printStackTrace();
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException ignored) {
+ return new byte[0];
+ }
+
+ /**
+ * 获取文件的MD5校验码
+ *
+ * @param filePath 文件路径
+ * @return 文件的MD5校验码
+ */
+ public static String getMD5File(String filePath) {
+ return getMD5File(new File(filePath));
+ }
+
+ /**
+ * 获取文件的MD5校验码
+ *
+ * @param file 文件
+ * @return 文件的MD5校验码
+ */
+ public static String getMD5File(File file) {
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ FileChannel channel = in.getChannel();
+ MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(buffer);
+ return bytes2Hex(md.digest());
+ } catch (NoSuchAlgorithmException | IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ignored) {
+ }
}
}
+ return "";
}
- return "";
-}
-```
-### SHA加密
-```
-/**
- * SHA加密
- *
- * @param data 明文字符串
- * @return 密文
- */
-public static String getSHA(String data) {
- return getSHA(data.getBytes());
-}
+ /**
+ * SHA加密
+ *
+ * @param data 明文字符串
+ * @return 密文
+ */
+ public static String getSHA(String data) {
+ return getSHA(data.getBytes());
+ }
-/**
- * SHA加密
- *
- * @param data 明文字节数组
- * @return 密文
- */
-public static String getSHA(byte[] data) {
- return bytes2Hex(encryptSHA(data));
-}
+ /**
+ * SHA加密
+ *
+ * @param data 明文字节数组
+ * @return 密文
+ */
+ public static String getSHA(byte[] data) {
+ return bytes2Hex(encryptSHA(data));
+ }
-/**
- * SHA加密
- *
- * @param data 明文字节数组
- * @return 密文字节数组
- */
-public static byte[] encryptSHA(byte[] data) {
- try {
- MessageDigest md = MessageDigest.getInstance("SHA");
- md.update(data);
- return md.digest();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
+ /**
+ * SHA加密
+ *
+ * @param data 明文字节数组
+ * @return 密文字节数组
+ */
+ public static byte[] encryptSHA(byte[] data) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA");
+ md.update(data);
+ return md.digest();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return new byte[0];
}
- return new byte[0];
-}
-/**
- * 一个byte转为2个hex字符
- */
-public static String bytes2Hex(byte[] src) {
- char[] res = new char[src.length * 2];
- final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
- for (int i = 0, j = 0; i < src.length; i++) {
- res[j++] = hexDigits[src[i] >>> 4 & 0x0f];
- res[j++] = hexDigits[src[i] & 0x0f];
+ /**
+ * 一个byte转为2个hex字符
+ *
+ * @param src byte数组
+ * @return 16进制大写字符串
+ */
+ public static String bytes2Hex(byte[] src) {
+ char[] res = new char[src.length << 1];
+ final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ for (int i = 0, j = 0; i < src.length; i++) {
+ res[j++] = hexDigits[src[i] >>> 4 & 0x0f];
+ res[j++] = hexDigits[src[i] & 0x0f];
+ }
+ return new String(res);
}
- return new String(res);
}
```
diff --git a/md/about_keyboard.md b/md/about_keyboard.md
index 5cadb8fdd5dcf045f49b942e2886875587b51408..4f15fd9b0973d125fee550abc1bf5bbabb6702e9 100644
--- a/md/about_keyboard.md
+++ b/md/about_keyboard.md
@@ -1,126 +1,145 @@
# 键盘相关
-### 避免输入法面板遮挡
``` java
-// 在manifest.xml中activity中设置
-android:windowSoftInputMode="stateVisible|adjustResize"
-```
+import android.app.Activity;
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
-### 动态隐藏软键盘
-``` java
/**
-* 动态隐藏软键盘
-*/
-public static void hideSoftInput(Activity activity) {
- View view = activity.getWindow().peekDecorView();
- if (view != null) {
- InputMethodManager inputmanger = (InputMethodManager) activity
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0);
- }
-}
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 键盘相关的工具类
+ *
+ */
+public class KeyboardUtils {
-/**
-* 动态隐藏软键盘
-*/
-public static void hideSoftInput(Context context, EditText edit) {
- edit.clearFocus();
- InputMethodManager inputmanger = (InputMethodManager) context
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- inputmanger.hideSoftInputFromWindow(edit.getWindowToken(), 0);
-}
-```
+ private KeyboardUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
+ }
-### 点击屏幕空白区域隐藏软键盘
-``` java
-/**
- * 点击屏幕空白区域隐藏软键盘(方法0)
- *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 网络相关的工具类
+ *
*/
-public static void openWirelessSettings(Context context) {
- if (android.os.Build.VERSION.SDK_INT > 10) {
- context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
- } else {
- context.startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
+public class NetworkUtils {
+
+ private NetworkUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
}
-}
-```
-### 判断网络是否可用
-``` java
-/**
- * 获取活动网路信息
- */
-private static NetworkInfo getActiveNetworkInfo(Context context) {
- ConnectivityManager cm = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- return cm.getActiveNetworkInfo();
-}
+ public static final int NETWORK_WIFI = 1; // wifi network
+ public static final int NETWORK_4G = 4; // "4G" networks
+ public static final int NETWORK_3G = 3; // "3G" networks
+ public static final int NETWORK_2G = 2; // "2G" networks
+ public static final int NETWORK_UNKNOWN = 5; // unknown network
+ public static final int NETWORK_NO = -1; // no network
-/**
- * 判断网络是否可用
- *
false: 否
+ */
+ public static boolean isConnected(Context context) {
+ NetworkInfo info = getActiveNetworkInfo(context);
+ return info != null && info.isConnected();
+ }
-### 获取移动终端类型
-``` java
-/**
- * 获取移动终端类型
- *
- * @return 手机制式
- *
- *
- */
-public static int getPhoneType(Context context) {
- TelephonyManager tm = (TelephonyManager) context
- .getSystemService(Context.TELEPHONY_SERVICE);
- return tm != null ? tm.getPhoneType() : -1;
-}
-```
+ /**
+ * 判断网络是否是4G
+ *
false: 不是
+ */
+ public static boolean is4G(Context context) {
+ NetworkInfo info = getActiveNetworkInfo(context);
+ return info != null && info.isAvailable() && info.getSubtype() == TelephonyManager.NETWORK_TYPE_LTE;
+ }
-### 获取当前的网络类型(WIFI,2G,3G,4G)
-``` java
-/**
- * 获取当前的网络类型(WIFI,2G,3G,4G)
- *
- *
- */
-public static int getNetWorkType(Context context) {
- int netType = NETWORK_NO;
- NetworkInfo info = getActiveNetworkInfo(context);
- if (info != null && info.isAvailable()) {
-
- if (info.getType() == ConnectivityManager.TYPE_WIFI) {
- netType = NETWORK_WIFI;
- } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
- switch (info.getSubtype()) {
-
- case NETWORK_TYPE_GSM:
- case TelephonyManager.NETWORK_TYPE_GPRS:
- case TelephonyManager.NETWORK_TYPE_CDMA:
- case TelephonyManager.NETWORK_TYPE_EDGE:
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- case TelephonyManager.NETWORK_TYPE_IDEN:
- netType = NETWORK_2G;
- break;
-
- case NETWORK_TYPE_TD_SCDMA:
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- case TelephonyManager.NETWORK_TYPE_UMTS:
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- case TelephonyManager.NETWORK_TYPE_HSPA:
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- netType = NETWORK_3G;
- break;
-
- case NETWORK_TYPE_IWLAN:
- case TelephonyManager.NETWORK_TYPE_LTE:
- netType = NETWORK_4G;
- break;
- default:
-
- String subtypeName = info.getSubtypeName();
- if (subtypeName.equalsIgnoreCase("TD-SCDMA")
- || subtypeName.equalsIgnoreCase("WCDMA")
- || subtypeName.equalsIgnoreCase("CDMA2000")) {
+ /**
+ * 判断wifi是否连接状态
+ *
false: 未连接
+ */
+ public static boolean isWifiConnected(Context context) {
+ ConnectivityManager cm = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ return cm != null && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
+ }
+
+ /**
+ * 获取移动网络运营商名称
+ *
+ *
+ */
+ public static int getPhoneType(Context context) {
+ TelephonyManager tm = (TelephonyManager) context
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ return tm != null ? tm.getPhoneType() : -1;
+ }
+
+
+ /**
+ * 获取当前的网络类型(WIFI,2G,3G,4G)
+ *
+ *
+ */
+ public static int getNetWorkType(Context context) {
+ int netType = NETWORK_NO;
+ NetworkInfo info = getActiveNetworkInfo(context);
+ if (info != null && info.isAvailable()) {
+
+ if (info.getType() == ConnectivityManager.TYPE_WIFI) {
+ netType = NETWORK_WIFI;
+ } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
+ switch (info.getSubtype()) {
+
+ case NETWORK_TYPE_GSM:
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ netType = NETWORK_2G;
+ break;
+
+ case NETWORK_TYPE_TD_SCDMA:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
netType = NETWORK_3G;
- } else {
- netType = NETWORK_UNKNOWN;
- }
- break;
+ break;
+
+ case NETWORK_TYPE_IWLAN:
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ netType = NETWORK_4G;
+ break;
+ default:
+
+ String subtypeName = info.getSubtypeName();
+ if (subtypeName.equalsIgnoreCase("TD-SCDMA")
+ || subtypeName.equalsIgnoreCase("WCDMA")
+ || subtypeName.equalsIgnoreCase("CDMA2000")) {
+ netType = NETWORK_3G;
+ } else {
+ netType = NETWORK_UNKNOWN;
+ }
+ break;
+ }
+ } else {
+ netType = NETWORK_UNKNOWN;
}
- } else {
- netType = NETWORK_UNKNOWN;
}
+ return netType;
}
- return netType;
-}
-/**
- * 获取当前的网络类型(WIFI,2G,3G,4G)
- * 依赖上面的方法
- *
- * @param context
- * @return 网络类型名称
- *
- *
- */
-public static String getNetWorkTypeName(Context context) {
- switch (getNetWorkType(context)) {
- case NETWORK_WIFI:
- return "NETWORK_WIFI";
- case NETWORK_4G:
- return "NETWORK_4G";
- case NETWORK_3G:
- return "NETWORK_3G";
- case NETWORK_2G:
- return "NETWORK_2G";
- case NETWORK_NO:
- return "NETWORK_NO";
- default:
- return "NETWORK_UNKNOWN";
+ /**
+ * 获取当前的网络类型(WIFI,2G,3G,4G)
+ *
+ *
+ */
+ public static String getNetWorkTypeName(Context context) {
+ switch (getNetWorkType(context)) {
+ case NETWORK_WIFI:
+ return "NETWORK_WIFI";
+ case NETWORK_4G:
+ return "NETWORK_4G";
+ case NETWORK_3G:
+ return "NETWORK_3G";
+ case NETWORK_2G:
+ return "NETWORK_2G";
+ case NETWORK_NO:
+ return "NETWORK_NO";
+ default:
+ return "NETWORK_UNKNOWN";
+ }
}
}
```
diff --git a/md/about_phone.md b/md/about_phone.md
index 90f0de0b88e9f356146cc1d58652d887e37f4c88..e7bb09a00673e11ea4a54e6808f5124c7a2171da 100644
--- a/md/about_phone.md
+++ b/md/about_phone.md
@@ -1,282 +1,312 @@
# 手机相关
-### 判断设备是否是手机
``` java
-/**
- * 判断设备是否是手机
- */
-public static boolean isPhone(Context context) {
- TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
-}
-```
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
-### 获取手机的IMIE
-``` java
/**
- * 获取当前设备的IMIE
- *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 手机相关的工具类
+ *
*/
-public static String getPhoneIMEI(Context context) {
- String deviceId;
- if (isPhone(context)) {
+public class PhoneUtils {
+
+ private PhoneUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
+ }
+
+ /**
+ * 判断设备是否是手机
+ *
+ * @param context 上下文
+ * @return true: 是
false: 否
+ */
+ public static boolean isPhone(Context context) {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- deviceId = tm.getDeviceId();
- } else {
- deviceId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+ return tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
}
- return deviceId;
-}
-```
-### 获取手机状态信息
-``` java
-/**
- * 获取手机状态信息
- *
- * DeviceId(IMEI) = 99000311726612
- * DeviceSoftwareVersion = 00
- * Line1Number =
- * NetworkCountryIso = cn
- * NetworkOperator = 46003
- * NetworkOperatorName = 中国电信
- * NetworkType = 6
- * honeType = 2
- * SimCountryIso = cn
- * SimOperator = 46003
- * SimOperatorName = 中国电信
- * SimSerialNumber = 89860315045710604022
- * SimState = 5
- * SubscriberId(IMSI) = 460030419724900
- * VoiceMailNumber = *86
- *
- */
-public static String getPhoneStatus(Context context) {
- TelephonyManager tm = (TelephonyManager) context
- .getSystemService(Context.TELEPHONY_SERVICE);
- String str = "";
- str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n";
- str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
- str += "Line1Number = " + tm.getLine1Number() + "\n";
- str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
- str += "NetworkOperator = " + tm.getNetworkOperator() + "\n";
- str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n";
- str += "NetworkType = " + tm.getNetworkType() + "\n";
- str += "honeType = " + tm.getPhoneType() + "\n";
- str += "SimCountryIso = " + tm.getSimCountryIso() + "\n";
- str += "SimOperator = " + tm.getSimOperator() + "\n";
- str += "SimOperatorName = " + tm.getSimOperatorName() + "\n";
- str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n";
- str += "SimState = " + tm.getSimState() + "\n";
- str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n";
- str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n";
- return str;
-}
-```
+ /**
+ * 获取当前设备的IMIE
+ *
+ * DeviceSoftwareVersion = 00
+ * Line1Number =
+ * NetworkCountryIso = cn
+ * NetworkOperator = 46003
+ * NetworkOperatorName = 中国电信
+ * NetworkType = 6
+ * honeType = 2
+ * SimCountryIso = cn
+ * SimOperator = 46003
+ * SimOperatorName = 中国电信
+ * SimSerialNumber = 89860315045710604022
+ * SimState = 5
+ * SubscriberId(IMSI) = 460030419724900
+ * VoiceMailNumber = *86
+ */
+ public static String getPhoneStatus(Context context) {
+ TelephonyManager tm = (TelephonyManager) context
+ .getSystemService(Context.TELEPHONY_SERVICE);
+ String str = "";
+ str += "DeviceId(IMEI) = " + tm.getDeviceId() + "\n";
+ str += "DeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion() + "\n";
+ str += "Line1Number = " + tm.getLine1Number() + "\n";
+ str += "NetworkCountryIso = " + tm.getNetworkCountryIso() + "\n";
+ str += "NetworkOperator = " + tm.getNetworkOperator() + "\n";
+ str += "NetworkOperatorName = " + tm.getNetworkOperatorName() + "\n";
+ str += "NetworkType = " + tm.getNetworkType() + "\n";
+ str += "honeType = " + tm.getPhoneType() + "\n";
+ str += "SimCountryIso = " + tm.getSimCountryIso() + "\n";
+ str += "SimOperator = " + tm.getSimOperator() + "\n";
+ str += "SimOperatorName = " + tm.getSimOperatorName() + "\n";
+ str += "SimSerialNumber = " + tm.getSimSerialNumber() + "\n";
+ str += "SimState = " + tm.getSimState() + "\n";
+ str += "SubscriberId(IMSI) = " + tm.getSubscriberId() + "\n";
+ str += "VoiceMailNumber = " + tm.getVoiceMailNumber() + "\n";
+ return str;
+ }
-### 拨打phoneNumber
-``` java
-/**
- * 拨打phoneNumber
- *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 正则相关的工具类
+ *
+ */
public class RegularUtils {
private RegularUtils() {
@@ -22,7 +24,7 @@ public class RegularUtils {
private static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$";
/**
* 验证手机号(精确)
- *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 屏幕相关的工具类
+ *
*/
-public static void setTransparentStatusBar(Activity activity) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- //透明状态栏
- activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
- //透明导航栏
- activity.getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+public class ScreenUtils {
+
+ private ScreenUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
}
-}
-```
-### 隐藏状态栏
-``` java
-/**
- * 隐藏状态栏
- *
-*
-*/
-public static boolean isStatusBarExists(Activity activity) {
- WindowManager.LayoutParams params = activity.getWindow().getAttributes();
- return (params.flags & LayoutParams.FLAG_FULLSCREEN) != LayoutParams.FLAG_FULLSCREEN;
-}
-```
+ /**
+ * 设置透明状态栏(api大于19方可使用)
+ *
false: 不存在
+ */
+ public static boolean isStatusBarExists(Activity activity) {
+ LayoutParams params = activity.getWindow().getAttributes();
+ return (params.flags & LayoutParams.FLAG_FULLSCREEN) != LayoutParams.FLAG_FULLSCREEN;
+ }
-### 设置屏幕为横屏
-```
-/**
- * 设置屏幕为横屏
- *
false: 打开通知
+ */
+ public static void showNotificationBar(Context context, boolean isSettingPanel) {
+ String methodName = (Build.VERSION.SDK_INT <= 16) ? "expand"
+ : (isSettingPanel ? "expandSettingsPanel" : "expandNotificationsPanel");
+ invokePanels(context, methodName);
+ }
-/**
- * 获取当前屏幕截图,不包含状态栏
- *
false: 否
+ */
+ public static boolean isScreenLock(Context context) {
+ KeyguardManager km = (KeyguardManager) context
+ .getSystemService(Context.KEYGUARD_SERVICE);
+ return km.inKeyguardRestrictedInputMode();
+ }
}
-```
-
\ No newline at end of file
+```
\ No newline at end of file
diff --git a/md/about_shell.md b/md/about_shell.md
new file mode 100644
index 0000000000000000000000000000000000000000..c0e22cf2ac27f4edeaf24c98b725bb6245e69b26
--- /dev/null
+++ b/md/about_shell.md
@@ -0,0 +1,193 @@
+# Shell相关
+``` java
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+
+/**
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/7
+ * desc : Shell操作工具类
+ *
+ */
+public class ShellUtils {
+
+ private ShellUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
+ }
+
+ public static final String COMMAND_SU = "su";
+ public static final String COMMAND_SH = "sh";
+ public static final String COMMAND_EXIT = "exit\n";
+ public static final String COMMAND_LINE_END = "\n";
+
+ /**
+ * 判断设备是否root
+ */
+ public static boolean isRoot() {
+ return execCmd("echo root", true, false).result == 0;
+ }
+
+ /**
+ * 是否是在root下执行命令
+ *
+ * @param command 命令
+ * @param isRoot 是否root
+ * @return CommandResult
+ */
+ public static CommandResult execCmd(String command, boolean isRoot) {
+ return execCmd(new String[]{command}, isRoot, true);
+ }
+
+ /**
+ * 是否是在root下执行命令
+ *
+ * @param commands 多条命令链表
+ * @param isRoot 是否root
+ * @return CommandResult
+ */
+ public static CommandResult execCmd(List
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 尺寸相关的工具类
+ *
+ */
+public class SizeUtils {
-/**
-* px转sp
-*/
-public static int px2sp(Context context, float pxValue) {
- final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
- return (int) (pxValue / fontScale + 0.5f);
-}
-```
+ private SizeUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
+ }
-### 各种单位转换
-``` java
-/**
- * 各种单位转换
- *
+ * SizeUtils.forceGetViewSize(view);
+ * SizeUtils.setListener(new SizeUtils.onGetSizeListener() {
+ *
+ *
+ * @param view 视图
+ */
+ public static void forceGetViewSize(final View view) {
+ view.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mListener != null) {
+ mListener.onGetSize(view);
+ }
+ }
+ });
+ }
+
+ /**
+ * 获取到View尺寸的监听
+ */
+ public interface onGetSizeListener {
+ void onGetSize(View view);
+ }
+
+ public static void setListener(onGetSizeListener listener) {
+ mListener = listener;
}
- int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);
- int height;
- int tempHeight = p.height;
- if (tempHeight > 0) {
- height = MeasureSpec.makeMeasureSpec(tempHeight,
- MeasureSpec.EXACTLY);
- } else {
- height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+
+ private static onGetSizeListener mListener;
+
+ /**
+ * ListView中提前测量View尺寸,如headerView
+ *
@Override
+ * public void onGetSize(View view) {
+ * Log.d("tag", view.getWidth() + " " + view.getHeight());
+ * }
+ * });
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : SP读写工具类
+ *
+ */
+public class SPUtils {
+
+ private SPUtils() {
+ throw new UnsupportedOperationException("u can't fuck me...");
+ }
+
+ /**
+ * SP的name值
+ *
false: 写入失败
+ */
+ public static boolean putString(Context context, String key, String value) {
+ return getSP(context).edit().putString(key, value).commit();
+ }
+
+ /**
+ * SP中读取String
+ *
+ * @param context 上下文
+ * @param key 键
+ * @return 存在返回对应值,不存在返回默认值null
+ */
+ public static String getString(Context context, String key) {
+ return getString(context, key, null);
+ }
+
+ /**
+ * SP中读取String
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param defaultValue 默认值
+ * @return 存在返回对应值,不存在返回默认值defaultValue
+ */
+ public static String getString(Context context, String key, String defaultValue) {
+ return getSP(context).getString(key, defaultValue);
+ }
+
+ /**
+ * SP中写入int类型value
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param value 值
+ * @return true: 写入成功
false: 写入失败
+ */
+ public static boolean putInt(Context context, String key, int value) {
+ return getSP(context).edit().putInt(key, value).commit();
+ }
+
+ /**
+ * SP中读取int
+ *
+ * @param context 上下文
+ * @param key 键
+ * @return 存在返回对应值,不存在返回默认值-1
+ */
+ public static int getInt(Context context, String key) {
+ return getInt(context, key, -1);
+ }
+
+ /**
+ * SP中读取int
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param defaultValue 默认值
+ * @return 存在返回对应值,不存在返回默认值defaultValue
+ */
+ public static int getInt(Context context, String key, int defaultValue) {
+ return getSP(context).getInt(key, defaultValue);
+ }
+
+ /**
+ * SP中写入long类型value
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param value 值
+ * @return true: 写入成功
false: 写入失败
+ */
+ public static boolean putLong(Context context, String key, long value) {
+ return getSP(context).edit().putLong(key, value).commit();
+ }
+
+ /**
+ * SP中读取long
+ *
+ * @param context 上下文
+ * @param key 键
+ * @return 存在返回对应值,不存在返回默认值-1
+ */
+ public static long getLong(Context context, String key) {
+ return getLong(context, key, -1);
+ }
+
+ /**
+ * SP中读取long
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param defaultValue 默认值
+ * @return 存在返回对应值,不存在返回默认值defaultValue
+ */
+ public static long getLong(Context context, String key, long defaultValue) {
+ return getSP(context).getLong(key, defaultValue);
+ }
+
+ /**
+ * SP中写入float类型value
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param value 值
+ * @return true: 写入成功
false: 写入失败
+ */
+ public static boolean putFloat(Context context, String key, float value) {
+ return getSP(context).edit().putFloat(key, value).commit();
+ }
+
+ /**
+ * SP中读取float
+ *
+ * @param context 上下文
+ * @param key 键
+ * @return 存在返回对应值,不存在返回默认值-1
+ */
+ public static float getFloat(Context context, String key) {
+ return getFloat(context, key, -1);
+ }
+
+ /**
+ * SP中读取float
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param defaultValue 默认值
+ * @return 存在返回对应值,不存在返回默认值defaultValue
+ */
+ public static float getFloat(Context context, String key, float defaultValue) {
+ return getSP(context).getFloat(key, defaultValue);
+ }
+
+ /**
+ * SP中写入boolean类型value
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param value 值
+ * @return true: 写入成功
false: 写入失败
+ */
+ public static boolean putBoolean(Context context, String key, boolean value) {
+ return getSP(context).edit().putBoolean(key, value).commit();
+ }
+
+ /**
+ * SP中读取boolean
+ *
+ * @param context 上下文
+ * @param key 键
+ * @return 存在返回对应值,不存在返回默认值false
+ */
+ public static boolean getBoolean(Context context, String key) {
+ return getBoolean(context, key, false);
+ }
+
+ /**
+ * SP中读取boolean
+ *
+ * @param context 上下文
+ * @param key 键
+ * @param defaultValue 默认值
+ * @return 存在返回对应值,不存在返回默认值defaultValue
+ */
+ public static boolean getBoolean(Context context, String key, boolean defaultValue) {
+ return getSP(context).getBoolean(key, defaultValue);
+ }
+
+ /**
+ * 获取name为PREFERENCE_NAME的SP对象
+ *
+ * @param context 上下文
+ * @return SP
+ */
+ private static SharedPreferences getSP(Context context) {
+ return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
+ }
+}
+```
\ No newline at end of file
diff --git a/md/about_time.md b/md/about_time.md
index e1d7c95253414d007938d2459875b94bc1874467..ce287b35eacedbaec4351d5c65ff1ba3ca64e7d1 100644
--- a/md/about_time.md
+++ b/md/about_time.md
@@ -1,265 +1,481 @@
# 时间相关
-### 将时间戳转为时间字符串
``` java
-/**
- * 将时间戳转为时间字符串
- *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 时间相关的工具类
+ *
*/
-public static long string2Milliseconds(String time) {
- return string2Milliseconds(time, DEFAULT_SDF);
-}
+public class TimeUtils {
-/**
- * 将时间字符串转为时间戳
- *
+ *
+ *
+ *
+ *
+ *
+ * 字母
+ * 日期或时间元素
+ * 表示
+ * 示例
+ *
+ *
+ *
+ * G
Era 标志符
+ * Text
+ *
+ * AD
+ *
+ *
+ * y
年
+ * Year
+ *
+ * 1996
; 96
+ *
+ *
+ * M
年中的月份
+ * Month
+ *
+ * July
; Jul
; 07
+ *
+ *
+ * w
年中的周数
+ * Number
+ *
+ * 27
+ *
+ *
+ * W
月份中的周数
+ * Number
+ *
+ * 2
+ *
+ *
+ * D
年中的天数
+ * Number
+ *
+ * 189
+ *
+ *
+ * d
月份中的天数
+ * Number
+ *
+ * 10
+ *
+ *
+ * F
月份中的星期
+ * Number
+ *
+ * 2
+ *
+ *
+ * E
星期中的天数
+ * Text
+ *
+ * Tuesday
; Tue
+ *
+ *
+ * a
Am/pm 标记
+ * Text
+ *
+ * PM
+ *
+ *
+ * H
一天中的小时数(0-23)
+ * Number
+ *
+ * 0
+ *
+ *
+ * k
一天中的小时数(1-24)
+ * Number
+ *
+ * 24
+ *
+ *
+ * K
am/pm 中的小时数(0-11)
+ * Number
+ *
+ * 0
+ *
+ *
+ * h
am/pm 中的小时数(1-12)
+ * Number
+ *
+ * 12
+ *
+ *
+ * m
小时中的分钟数
+ * Number
+ *
+ * 30
+ *
+ *
+ * s
分钟中的秒数
+ * Number
+ *
+ * 55
+ *
+ *
+ * S
毫秒数
+ * Number
+ *
+ * 978
+ *
+ *
+ * z
时区
+ * General time zone
+ *
+ * Pacific Standard Time
; PST
; GMT-08:00
+ *
+ *
+ * Z
时区
+ * RFC 822 time zone
+ *
+ * -0800
+ * yyyy-MM-dd 1969-12-31
+ * yyyy-MM-dd 1970-01-01
+ * yyyy-MM-dd HH:mm 1969-12-31 16:00
+ * yyyy-MM-dd HH:mm 1970-01-01 00:00
+ * yyyy-MM-dd HH:mmZ 1969-12-31 16:00-0800
+ * yyyy-MM-dd HH:mmZ 1970-01-01 00:00+0000
+ * yyyy-MM-dd HH:mm:ss.SSSZ 1969-12-31 16:00:00.000-0800
+ * yyyy-MM-dd HH:mm:ss.SSSZ 1970-01-01 00:00:00.000+0000
+ * yyyy-MM-dd'T'HH:mm:ss.SSSZ 1969-12-31T16:00:00.000-0800
+ * yyyy-MM-dd'T'HH:mm:ss.SSSZ 1970-01-01T00:00:00.000+0000
+ *
+ */
+ public static final SimpleDateFormat DEFAULT_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ /**
+ * 各时间单位与毫秒的倍数
+ */
+ public static final int UNIT_MSEC = 1;
+ public static final int UNIT_SEC = 1000;
+ public static final int UNIT_MIN = 60000;
+ public static final int UNIT_HOUR = 3600000;
+ public static final int UNIT_DAY = 86400000;
-/**
- * 将时间字符串转为Date类型
- *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- *
- */
-private static long milliseconds2Unit(long milliseconds, int unit) {
- switch (unit) {
- case UNIT_MSEC:
- case UNIT_SEC:
- case UNIT_MIN:
- case UNIT_HOUR:
- case UNIT_DAY:
- return Math.abs(milliseconds) / unit;
+ /**
+ * 将时间字符串转为Date类型
+ *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- *
- *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- *
- *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- *
- *
+ *
+ * @return unit时间戳
+ */
+ private static long milliseconds2Unit(long milliseconds, int unit) {
+ switch (unit) {
+ case UNIT_MSEC:
+ case UNIT_SEC:
+ case UNIT_MIN:
+ case UNIT_HOUR:
+ case UNIT_DAY:
+ return Math.abs(milliseconds) / unit;
+ }
+ return -1;
+ }
-/**
- * 获取当前时间
- *
+ *
+ * @return unit时间戳
+ */
+ public static long getIntervalTime(String time1, String time2, int unit) {
+ return getIntervalTime(time1, time2, unit, DEFAULT_SDF);
+ }
-/**
- * 获取当前时间
- *
+ *
+ * @param format 时间格式
+ * @return unit时间戳
+ */
+ public static long getIntervalTime(String time1, String time2, int unit, SimpleDateFormat format) {
+ return milliseconds2Unit(string2Milliseconds(time1, format)
+ - string2Milliseconds(time2, format), unit);
+ }
-### 获取与当前时间的差(单位:unit)
-``` java
-/**
- * 获取与当前时间的差(单位:unit)
- *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- *
+ *
+ * @return unit时间戳
+ */
+ public static long getIntervalTime(Date time1, Date time2, int unit) {
+ return milliseconds2Unit(date2Milliseconds(time2) - date2Milliseconds(time1), unit);
+ }
-/**
- * 获取与当前时间的差(单位:unit)
- *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- *
- * UNIT_MSEC:毫秒
- * UNIT_SEC :秒
- * UNIT_MIN :分
- * UNIT_HOUR:小时
- * UNIT_DAY :天
- *
+ *
+ * @return unit时间戳
+ */
+ public static long getIntervalByNow(String time, int unit) {
+ return getIntervalByNow(time, unit, DEFAULT_SDF);
+ }
+
+ /**
+ * 获取与当前时间的差(单位:unit)
+ *
+ *
+ * @param format 时间格式
+ * @return unit时间戳
+ */
+ public static long getIntervalByNow(String time, int unit, SimpleDateFormat format) {
+ return getIntervalTime(getCurTimeString(), time, unit, format);
+ }
+
+ /**
+ * 获取与当前时间的差(单位:unit)
+ *
+ *
+ * @return unit时间戳
+ */
+ public static long getIntervalByNow(Date time, int unit) {
+ return getIntervalTime(getCurTimeDate(), time, unit);
+ }
+
+ /**
+ * 判断闰年
+ *
+ * @param year 年份
+ * @return true: 闰年
false: 平年
+ */
+ public static boolean isLeapYear(int year) {
+ return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
+ }
-### 判断闰年
-``` java
-/**
- * 判断闰年
- */
-public static boolean isLeapYear(int year) {
- return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}
-```
+```
\ No newline at end of file
diff --git a/md/about_unclassified.md b/md/about_unclassified.md
index 7aeb2377034259773b91a2bd53008a380e44a804..351337fa800b7d4445b818f482f08f872c194f85 100644
--- a/md/about_unclassified.md
+++ b/md/about_unclassified.md
@@ -1,23 +1,64 @@
# 未归类
-### 获取服务是否开启
-```
+``` java
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningServiceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+
+import java.util.List;
+
/**
- * 获取服务是否开启
- * @param className 完整包名的服务类名
+ *
+ * author: Blankj
+ * blog : http://blankj.com
+ * time : 2016/8/2
+ * desc : 未归类的工具类
+ *
*/
-public static boolean isRunningService(String className, Context context) {
- // 进程的管理者,活动的管理者
- ActivityManager activityManager = (ActivityManager)
- context.getSystemService(Context.ACTIVITY_SERVICE);
- // 获取正在运行的服务,最多获取1000个
- List
false: 否
+ */
+ public static boolean isRunningService(Context context, String className) {
+ // 进程的管理者,活动的管理者
+ ActivityManager activityManager = (ActivityManager)
+ context.getSystemService(Context.ACTIVITY_SERVICE);
+ // 获取正在运行的服务,最多获取1000个
+ List
");
}
- return false;
}
```