验证、判断 Posted on 2021-06-10 | In Android代码片段 利用正则表达式校验邮箱、手机号等123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301/** * 校验器:利用正则表达式校验邮箱、手机号等 * Created by shenbinghong on 2018/1/6. */public class Validator { /** * 正则表达式:验证用户名 */ public static final String REGEX_USERNAME = "^[a-zA-Z]\\w{5,20}$"; /** * 正则表达式:验证密码 */ public static final String REGEX_PASSWORD = "^[a-zA-Z0-9]{6,20}$"; /** * 正则表达式:验证手机号 */ public static final String REGEX_MOBILE = "^((17[0-9])|(14[0-9])|(13[0-9])|(15[0-9])|(18[0-9]))\\d{8}$"; /** * 正则表达式:验证邮箱 */ public static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; /** * 正则表达式:验证汉字 */ public static final String REGEX_CHINESE = "^[\u4e00-\u9fa5],{0,}$"; /** * 正则表达式:验证身份证 */ public static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)"; /** * 正则表达式:验证URL */ public static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?"; /** * 正则表达式:验证IP地址 */ public static final String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)"; /** * 校验用户名 * * @param username * @return 校验通过返回true,否则返回false */ public static boolean isUsername(String username) { return Pattern.matches(REGEX_USERNAME, username); } /** * 校验密码 * * @param password * @return 校验通过返回true,否则返回false */ public static boolean isPassword(String password) { return Pattern.matches(REGEX_PASSWORD, password); } /** * 校验手机号 * * @param mobile * @return 校验通过返回true,否则返回false */ public static boolean isMobile(String mobile) { return Pattern.matches(REGEX_MOBILE, mobile); } /** * 校验邮箱 * * @param email * @return 校验通过返回true,否则返回false */ public static boolean isEmail(String email) { return Pattern.matches(REGEX_EMAIL, email); } /** * 校验汉字 * * @param chinese * @return 校验通过返回true,否则返回false */ public static boolean isChinese(String chinese) { return Pattern.matches(REGEX_CHINESE, chinese); } /** * 校验身份证 * * @param idCard * @return 校验通过返回true,否则返回false */ public static boolean isIDCard(String idCard) { return Pattern.matches(REGEX_ID_CARD, idCard); } /** * 校验URL * * @param url * @return 校验通过返回true,否则返回false */ public static boolean isUrl(String url) { return Pattern.matches(REGEX_URL, url); } /** * 校验IP地址 * * @param ipAddr * @return */ public static boolean isIPAddr(String ipAddr) { return Pattern.matches(REGEX_IP_ADDR, ipAddr); } /** * 校验是否是中国身份证号 * * @param sfzh * @return true验证通过 false不通过 */ public static boolean isChinaIDCard(String sfzh) { try { int flag = 1; // 如果长度不是15和18,则返回错误 if (sfzh.length() != 18 && sfzh.length() != 15) { flag = flag * 0; } if (sfzh.length() == 18) { String start = sfzh.substring(0, 6); int year = Integer.parseInt(sfzh.substring(6, 10)); int month = Integer.parseInt(sfzh.substring(10, 12)); int day = Integer.parseInt(sfzh.substring(12, 14)); int nowYear = (new Date()).getYear() + 1900; Log.v("sfzh year is ", year + ""); Log.v("sfzh month is ", month + ""); Log.v("sfzh day is ", day + ""); Log.v("now year is ", nowYear + ""); if (year < 1900 || year > nowYear) { flag = flag * 0; } if (month < 1 || month > 12) { flag = flag * 0; } if (day < 1 || day > 31) { flag = flag * 0; } // 判断验证位 String check = ""; int a = Integer.parseInt(sfzh.substring(0, 1)) * 7 + Integer.parseInt(sfzh.substring(1, 2)) * 9 + Integer.parseInt(sfzh.substring(2, 3)) * 10 + Integer.parseInt(sfzh.substring(3, 4)) * 5 + Integer.parseInt(sfzh.substring(4, 5)) * 8 + Integer.parseInt(sfzh.substring(5, 6)) * 4 + Integer.parseInt(sfzh.substring(6, 7)) * 2 + Integer.parseInt(sfzh.substring(7, 8)) * 1 + Integer.parseInt(sfzh.substring(8, 9)) * 6 + Integer.parseInt(sfzh.substring(9, 10)) * 3 + Integer.parseInt(sfzh.substring(10, 11)) * 7 + Integer.parseInt(sfzh.substring(11, 12)) * 9 + Integer.parseInt(sfzh.substring(12, 13)) * 10 + Integer.parseInt(sfzh.substring(13, 14)) * 5 + Integer.parseInt(sfzh.substring(14, 15)) * 8 + Integer.parseInt(sfzh.substring(15, 16)) * 4 + Integer.parseInt(sfzh.substring(16, 17)) * 2; int b = a % 11; switch (b) { case 0: check = "1"; break; case 1: check = "0"; break; case 2: check = "X"; break; case 3: check = "9"; break; case 4: check = "8"; break; case 5: check = "7"; break; case 6: check = "6"; break; case 7: check = "5"; break; case 8: check = "4"; break; case 9: check = "3"; break; case 10: check = "2"; break; default: break; } Log.v("check num is ", check); if (!check.equals(sfzh.subSequence(17, 18))) { flag = flag * 0; } } Log.v("flag", flag + ""); if (flag == 1) { return true; } else { return false; } } catch (Exception ex) { ex.printStackTrace(); return false; } } /** * 校验是否是身份证 */ public static boolean isPid(String str) { if (TextUtils.isEmpty(str)) { return false; } String[] arg = {str}; // 17位加权因子,与身份证号前17位依次相乘。 int w[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; int sum = 0;// 保存级数和 try { for (int i = 0; i < arg[0].length() - 1; i++) { sum += new Integer(arg[0].substring(i, i + 1)) * w[i]; } } catch (Exception e) { return false; } /** * 校验结果,上一步计算得出的结果与11取模,得到的结果相对应的字符就是身份证最后一位 ,也就是校验位。例如:0对应下面数组第一个元素, * 以此类推。 */ String sums[] = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}; if (sums[(sum % 11)].equals(arg[0].substring(arg[0].length() - 1, arg[0].length()))) {// 与身份证最后一位比较 return true; } else { return false; } } /** * 校验是否是银行卡卡号 * * @param cardId * @return */ public static boolean isBankCard(String cardId) { char bit = getBankCardCheckCode(cardId.substring(0, cardId.length() - 1)); if (bit == 'N') { return false; } return cardId.charAt(cardId.length() - 1) == bit; } /** * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位 * * @param nonCheckCodeCardId * @return */ public static char getBankCardCheckCode(String nonCheckCodeCardId) { if (nonCheckCodeCardId == null || nonCheckCodeCardId.trim().length() == 0 || !nonCheckCodeCardId.matches("\\d+")) { //如果传的不是数据返回N return 'N'; } char[] chs = nonCheckCodeCardId.trim().toCharArray(); int luhmSum = 0; for (int i = chs.length - 1, j = 0; i >= 0; i--, j++) { int k = chs[i] - '0'; if (j % 2 == 0) { k *= 2; k = k / 10 + k % 10; } luhmSum += k; } return (luhmSum % 10 == 0) ? '0' : (char) ((10 - luhmSum % 10) + '0'); }} 检测服务是否在运行 Read more »
后期-APP信息保护合规审核 Posted on 2021-05-27 | In Android 背景从2019年开始工信部发文强调个人隐私安全开始,网安部审核并通报了一批批的APP。 597直聘有被通报过,限期15个工作日内整改完毕。 Read more »
功能-权限管理 Posted on 2021-05-25 | In Android代码片段 获取权限app/build.gradle 12// 权限implementation 'com.yanzhenjie:permission:2.0.3' Read more »
UML相关 Posted on 2021-05-21 | In 其他IT 泛化各种关系的强弱顺序各种关系的强弱顺序: 1泛化(继承) = 实现(接口) > 组合() > 聚合() > 关联(拥有) > 依赖(使用) Read more »
工具-生命周期管理 Posted on 2021-05-10 | In Android代码片段 监听app切换前后台ActivityLifecycleCallbacks使用要求API 14+ (Android 4.0+)。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115public class ForegroundCallbacks implements Application.ActivityLifecycleCallbacks { public static final long CHECK_DELAY = 500; public static final String TAG = ForegroundCallbacks.class.getName(); public interface Listener { public void onBecameForeground(); public void onBecameBackground(); } private static ForegroundCallbacks instance; private boolean foreground = false, paused = true; private Handler handler = new Handler(); private List<Listener> listeners = new CopyOnWriteArrayList<Listener>(); private Runnable check; public static ForegroundCallbacks init(Application application){ if (instance == null) { instance = new ForegroundCallbacks(); application.registerActivityLifecycleCallbacks(instance); } return instance; } public static ForegroundCallbacks get(Application application){ if (instance == null) { init(application); } return instance; } public static ForegroundCallbacks get(Context ctx){ if (instance == null) { Context appCtx = ctx.getApplicationContext(); if (appCtx instanceof Application) { init((Application)appCtx); } throw new IllegalStateException( "Foreground is not initialised and " + "cannot obtain the Application object"); } return instance; } public static ForegroundCallbacks get(){ if (instance == null) { throw new IllegalStateException( "Foreground is not initialised - invoke " + "at least once with parameterised init/get"); } return instance; } public boolean isForeground(){ return foreground; } public boolean isBackground(){ return !foreground; } public void addListener(Listener listener){ listeners.add(listener); } public void removeListener(Listener listener){ listeners.remove(listener); } @Override public void onActivityResumed(Activity activity) { paused = false; boolean wasBackground = !foreground; foreground = true; if (check != null) handler.removeCallbacks(check); if (wasBackground){ L.d ("went foreground"); for (Listener l : listeners) { try { l.onBecameForeground(); } catch (Exception exc) { L.d ("Listener threw exception!:"+exc.toString()); } } } else { L.d ("still foreground"); } } @Override public void onActivityPaused(Activity activity) { paused = true; if (check != null) handler.removeCallbacks(check); handler.postDelayed(check = new Runnable(){ @Override public void run() { if (foreground && paused) { foreground = false; L.d ("went background"); for (Listener l : listeners) { try { l.onBecameBackground(); } catch (Exception exc) { L.d ("Listener threw exception!:"+exc.toString()); } } } else { L.d ("still foreground"); } } }, CHECK_DELAY); } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {} @Override public void onActivityStarted(Activity activity) {} @Override public void onActivityStopped(Activity activity) {} @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} @Override public void onActivityDestroyed(Activity activity) {}} Read more »
UI相关问题 Posted on 2021-04-30 | In Android ListView相关ListView的setOnItemClickListener无效问题:使用listview的时候遇到了设置item监听事件的时候在没有回调onItemClick 方法的问题 Read more »
Manifest Posted on 2021-04-30 | In Android AndroidManifest清单文件合并优先级(低的合并到高的)【库清单<主清单<flavor的清单】 Read more »
EventBus封装 Posted on 2021-04-28 | In Android代码片段 EventBus封装使用封装1implementation 'org.greenrobot:eventbus:3.2.0' Read more »
唯一设备码 Posted on 2021-02-23 | In Android Android10(api29)获取唯一设备码12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394public static String getDeviceId(Context context) { String deviceId = (String) SharedPreferencesUtil.getParam(SP_NAME_SYSTEM_INFO, SP_KEY_DEVICE_ID, ""); if (TextUtils.isEmpty(deviceId)) { deviceId = getMD5(getDeviceInfo(context)); SharedPreferencesUtil.setParam(SP_NAME_SYSTEM_INFO, SP_KEY_DEVICE_ID, deviceId); } return deviceId;}/** * deviceID的组成为:渠道标志+识别符来源标志+hash后的终端识别符 * 渠道标志为: * andriod(a_) * 识别符来源标志: * 1, wifi mac地址(wifi_); * 2, IMEI(imei_); * 3, 序列号(sn_); * 4, id:随机码。若前面的都取不到时,则随机生成一个随机码,需要缓存。 * * @param context * @return */private static String getDeviceInfo(Context context) { StringBuilder deviceId = new StringBuilder(); // 渠道标志 deviceId.append("a_"); try { //wifi mac地址 WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo info = wifi.getConnectionInfo(); String wifiMac = info.getMacAddress(); if (!TextUtils.isEmpty(wifiMac)) { deviceId.append("wifi"); deviceId.append(wifiMac); return deviceId.toString(); } //IMEI(imei) TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); String imei = tm.getDeviceId(); if (!TextUtils.isEmpty(imei)) { deviceId.append("imei_"); deviceId.append(imei); return deviceId.toString(); } //AndroidID if(!TextUtils.isEmpty(Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID))) { return Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); } //序列号(sn) String sn = tm.getSimSerialNumber(); if (!TextUtils.isEmpty(sn)) { deviceId.append("sn_"); deviceId.append(sn); return deviceId.toString(); } //如果上面都没有, 则生成一个id:随机码 String uuid = UUID.randomUUID().toString(); if (!TextUtils.isEmpty(uuid)) { deviceId.append("id_"); deviceId.append(uuid); return deviceId.toString(); } } catch (Exception e) { e.printStackTrace(); deviceId.append("id_").append(UUID.randomUUID().toString()); } return deviceId.toString();}/** * 获取String的MD5值 * * @param info 字符串 * @return 该字符串的MD5值 返回值为十六进制的32位长度的字符串 */private static String getMD5(String info) { try { //获取 MessageDigest 对象,参数为 MD5 字符串,表示这是一个 MD5 算法(其他还有 SHA1 算法等): MessageDigest md5 = MessageDigest.getInstance("MD5"); //update(byte[])方法,输入原数据 //类似StringBuilder对象的append()方法,追加模式,属于一个累计更改的过程 md5.update(info.getBytes("UTF-8")); //digest()被调用后,MessageDigest对象就被重置,即不能连续再次调用该方法计算原数据的MD5值。可以手动调用reset()方法重置输入源。 //digest()返回值16位长度的哈希值,由byte[]承接 byte[] md5Array = md5.digest(); //byte[]通常我们会转化为十六进制的32位长度的字符串来使用,本文会介绍三种常用的转换方法 return new BigInteger(1, md5Array).toString(16); } catch (NoSuchAlgorithmException e) { return ""; } catch (UnsupportedEncodingException e) { return ""; }} Read more »
版本相关-Android10 Posted on 2021-02-23 | In Android Android10Android 10版本特性Android 10适配要点,作用域存储 Read more »
版本相关-Android11 Posted on 2021-02-23 | In Android Android 11版本特性Android 11 新特性,Scoped Storage又有了新花样Android 11上强制启用了 Scoped Storage Read more »