package net.jejer.hipda.utils; import android.app.Activity; import android.app.DownloadManager; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.text.TextUtils; import android.util.TypedValue; import android.view.Display; import android.view.WindowManager; import com.bumptech.glide.Glide; import net.jejer.hipda.okhttp.OkHttpHelper; import net.jejer.hipda.ui.HiApplication; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.safety.Whitelist; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.regex.Pattern; import androidx.annotation.AttrRes; /** * Common utils * Created by GreenSkinMonster on 2015-03-23. */ public class Utils { private static Whitelist mWhitelist = null; private static int mScreenWidth = -1; private static int mScreenHeight = -1; private static String THIS_YEAR; private static String TODAY; private static String YESTERDAY; private static long UPDATE_TIME = 0; public final static String URL_REGEX = "[(http(s)?):\\/\\/(www\\.)[email protected]:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([[email protected]:%_\\+.~#?&//=]*)"; public final static Pattern URL_PATTERN = Pattern.compile(URL_REGEX); public final static String REPLACE_URL_REGEX = "(" + URL_REGEX + ")"; public static String nullToText(CharSequence text) { if (TextUtils.isEmpty(text)) { return ""; } return text.toString(); } public static String trim(String text) { return nullToText(text).replace(String.valueOf((char) 160), " ").trim(); } public static int getWordCount(String s) { s = s.replaceAll("[^\\x00-\\xff]", "**"); return s.length(); } public static String shortyTime(String time) { if (TextUtils.isEmpty(time)) return ""; if (System.currentTimeMillis() - UPDATE_TIME > 10 * 60 * 1000 || THIS_YEAR == null) { SimpleDateFormat dayFormatter = new SimpleDateFormat("yyyy-M-d", Locale.US); SimpleDateFormat yearFormatter = new SimpleDateFormat("yyyy", Locale.US); Date now = new Date(); THIS_YEAR = yearFormatter.format(now) + "-"; TODAY = dayFormatter.format(now); YESTERDAY = dayFormatter.format(new Date(now.getTime() - 24 * 60 * 60 * 1000)); UPDATE_TIME = System.currentTimeMillis(); } if (time.contains(TODAY)) { time = time.replace(TODAY, "今天"); } else if (time.contains(YESTERDAY)) { time = time.replace(YESTERDAY, "昨天"); } else if (time.contains(THIS_YEAR)) { time = time.replace(THIS_YEAR, ""); } return time; } public static String shortyTime(Date date) { if (date == null) return " - "; return Utils.shortyTime(Utils.formatDate(date, "yyyy-M-d HH:mm")); } /** * return parsable html for TextViewWithEmoticon */ public static String clean(String html) { if (mWhitelist == null) { mWhitelist = new Whitelist(); mWhitelist.addTags( "a", "br", "p", "b", "i", "strike", "strong", "u", "font") .addAttributes("a", "href") .addAttributes("font", "color") .addProtocols("a", "href", "http", "https"); } return Jsoup.clean(html, "", mWhitelist, new Document.OutputSettings().prettyPrint(false)); } public static CharSequence fromHtmlAndStrip(String s) { return HtmlCompat.fromHtml(s).toString().replace((char) 160, (char) 32).replace((char) 65532, (char) 32); } public static void copy(File src, File dst) throws IOException { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); } public static String getImageFileName(String prefix, String mime) { SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd_HHmmss", Locale.US); String filename = prefix + "_" + formatter.format(new Date()); String suffix = getImageFileSuffix(mime); return filename + "." + suffix; } public static String getImageFileSuffix(String mime) { String suffix = "jpg"; if (mime.toLowerCase().contains("gif")) { suffix = "gif"; } else if (mime.toLowerCase().contains("png")) { suffix = "png"; } else if (mime.toLowerCase().contains("bmp")) { suffix = "bmp"; } return suffix; } public static String formatDate(Date date) { return formatDate(date, "yyyy-MM-dd HH:mm:ss"); } public static String formatDate(Date date, String format) { SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.US); return formatter.format(date); } public static boolean isInTimeRange(String begin, String end) { try { //format hh:mm String[] bPieces = begin.split(":"); int bHour = Integer.parseInt(bPieces[0]); int bMinute = Integer.parseInt(bPieces[1]); String[] ePieces = end.split(":"); int eHour = Integer.parseInt(ePieces[0]); int eMinute = Integer.parseInt(ePieces[1]); Calendar now = Calendar.getInstance(); Calendar beginCal = Calendar.getInstance(); Calendar endCal = Calendar.getInstance(); beginCal.set(Calendar.HOUR_OF_DAY, bHour); beginCal.set(Calendar.MINUTE, bMinute); beginCal.set(Calendar.SECOND, 0); beginCal.set(Calendar.MILLISECOND, 0); endCal.set(Calendar.HOUR_OF_DAY, eHour); endCal.set(Calendar.MINUTE, eMinute); endCal.set(Calendar.SECOND, 59); endCal.set(Calendar.MILLISECOND, 999); if (endCal.before(beginCal)) { endCal.add(Calendar.DATE, 1); } if (beginCal.after(now)) { beginCal.add(Calendar.DATE, -1); endCal.add(Calendar.DATE, -1); } return now.getTimeInMillis() >= beginCal.getTimeInMillis() && now.getTimeInMillis() <= endCal.getTimeInMillis(); } catch (Exception e) { Logger.e(e); return false; } } public static String textToHtmlConvertingURLsToLinks(String text) { return nullToText(text).replaceAll("(\\A|\\s)((http|https):\\S+)(\\s|\\z)", "$1<a href=\"$2\">$2</a>$4"); } public static int dpToPx(int dp) { float density = HiApplication.getAppContext().getResources().getDisplayMetrics().density; return Math.round((float) dp * density); } public static Drawable getDrawableFromAttr(Context context, @AttrRes int attributeId) { TypedValue typedValue = new TypedValue(); context.getTheme().resolveAttribute(attributeId, typedValue, true); int drawableRes = typedValue.resourceId; return context.getResources().getDrawable(drawableRes); } public static int getScreenWidth() { if (mScreenWidth <= 0) { WindowManager wm = (WindowManager) HiApplication.getAppContext().getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Point size = new Point(); display.getSize(size); mScreenWidth = Math.min(size.x, size.y); mScreenHeight = Math.max(size.x, size.y); } return mScreenWidth; } public static int getScreenHeight() { if (mScreenHeight <= 0) { WindowManager wm = (WindowManager) HiApplication.getAppContext().getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); Point size = new Point(); display.getSize(size); mScreenWidth = Math.min(size.x, size.y); mScreenHeight = Math.max(size.x, size.y); } return mScreenHeight; } public static void restartActivity(Activity activity) { ColorHelper.clear(); activity.finish(); Intent intent = new Intent(activity.getApplicationContext(), activity.getClass()); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); activity.startActivity(intent); activity.overridePendingTransition(0, 0); System.exit(0); } public static void cleanShareTempFiles() { File destFile = HiApplication.getAppContext().getExternalCacheDir(); if (destFile != null && destFile.exists() && destFile.isDirectory() && destFile.canWrite()) { File[] files = destFile.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { return filename.startsWith(Constants.FILE_SHARE_PREFIX); } }); if (files != null) { for (File f : files) { f.delete(); } } } } public static void cleanPictures() { //defined in provider_paths.xml try { File destFile = HiApplication.getAppContext().getExternalFilesDir("Pictures"); if (destFile != null && destFile.exists() && destFile.isDirectory()) { for (File f : destFile.listFiles()) { f.delete(); } } } catch (Exception e) { Logger.e(e); } } public static boolean isMemoryUsageHigh() { Runtime runtime = Runtime.getRuntime(); return (runtime.totalMemory() - runtime.freeMemory()) > 0.6f * runtime.maxMemory(); } public static void printMemoryUsage() { Runtime runtime = Runtime.getRuntime(); DecimalFormat df = new DecimalFormat("#.##"); Logger.e("\nmax=" + df.format(runtime.maxMemory() * 1.0f / 1024 / 1024) + "M" + "\ntotal=" + df.format(runtime.totalMemory() * 1.0f / 1024 / 1024) + "M" + "\nfree=" + df.format(runtime.freeMemory() * 1.0f / 1024 / 1024) + "M" + "\nused=" + df.format((runtime.totalMemory() - runtime.freeMemory()) * 1.0f / 1024 / 1024) + "M" + "\nusage=" + df.format((runtime.totalMemory() - runtime.freeMemory()) * 100.0f / runtime.maxMemory()) + "%"); } private static boolean deleteDir(File file) { if (file != null) { if (file.isDirectory()) { String[] children = file.list(); for (String aChildren : children) { boolean success = deleteDir(new File(file, aChildren)); if (!success) { return false; } } } return file.delete(); } return false; } public static void clearInternalCache() { try { File cache = HiApplication.getAppContext().getCacheDir(); if (cache != null && cache.isDirectory()) { deleteDir(cache); } } catch (Exception ignored) { } } public static void clearOkhttpCache() { try { File cache = Glide.getPhotoCacheDir(HiApplication.getAppContext(), OkHttpHelper.CACHE_DIR_NAME); if (cache != null && cache.isDirectory()) { deleteDir(cache); } } catch (Exception ignored) { } } public static void clearExternalCache() { try { Glide.get(HiApplication.getAppContext()).clearDiskCache(); File cache = HiApplication.getAppContext().getExternalCacheDir(); if (cache != null && cache.isDirectory()) { deleteDir(cache); } } catch (Exception ignored) { } } public static boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { return true; } return false; } public static boolean isFromGooglePlay(Context context) { try { String installer = context.getPackageManager() .getInstallerPackageName(context.getPackageName()); return "com.android.vending".equals(installer); } catch (Throwable ignored) { } return false; } public static long parseSizeText(String sizeText) { //708 Bytes //100.1 KB //2.22 MB sizeText = Utils.nullToText(sizeText).trim().toUpperCase(); try { if (sizeText.endsWith("KB")) { return Math.round(Double.parseDouble(sizeText.replace("KB", "").trim()) * 1024); } else if (sizeText.endsWith("MB")) { return Math.round(Double.parseDouble(sizeText.replace("MB", "").trim()) * 1024 * 1024); } else if (sizeText.endsWith("BYTES")) { return Long.parseLong(sizeText.replace("BYTES", "").trim()); } } catch (Exception ignored) { } return -1; } public static String toSizeText(long fileSize) { DecimalFormat df = new DecimalFormat("#.#"); if (fileSize > 1024 * 1024) { return df.format(fileSize * 1.0 / 1024 / 1024) + " MB"; } return df.format(fileSize * 1.0 / 1024) + " KB"; } public static String toCountText(String countText) { if (countText.length() > 5 && TextUtils.isDigitsOnly(countText)) { long count = Long.parseLong(countText); if (count > 99999) { DecimalFormat df = new DecimalFormat("#.#"); return df.format(count * 1.0 / 10000) + "万"; } } return countText; } public static String removeLeadingBlank(String s) { int cutIndex = 0; boolean match = true; String[] blanks = {"<br>", (char) 160 + "", (char) 32 + ""}; while (match) { match = false; for (String blank : blanks) { if (s.length() > cutIndex + blank.length() && s.substring(cutIndex, cutIndex + blank.length()).equals(blank)) { cutIndex += blank.length(); match = true; break; } } } if (cutIndex > 0) s = s.substring(cutIndex); return s; } public static String replaceUrlWithTag(String content) { if (!TextUtils.isEmpty(content) && !content.contains("[/")) { return content.replaceAll(REPLACE_URL_REGEX, "[url]$1[/url]"); } return content; } public static String getMiddleString(String source, String start, String end) { int start_idx = source.indexOf(start); if (start_idx == -1) return ""; start_idx += start.length(); int end_idx; if (TextUtils.isEmpty(end)) { end_idx = source.length(); } else { end_idx = source.indexOf(end, start_idx); if (end_idx == -1) { end_idx = source.length(); } } if (end_idx == -1 || end_idx <= start_idx) { return ""; } return source.substring(start_idx, end_idx); } public static int getIntFromString(String s) { String tmp = s.replaceAll("[^\\d]", ""); if (!TextUtils.isEmpty(tmp) && TextUtils.isDigitsOnly(tmp)) { return parseInt(tmp); } else { return 0; } } public static int parseInt(String s) { try { return Integer.parseInt(s); } catch (NumberFormatException e) { return 0; } } public static void download(Context ctx, String url, String filename) { String authCookie = OkHttpHelper.getInstance().getAuthCookie(); if (TextUtils.isEmpty(url) || TextUtils.isEmpty(filename) || (url.contains(HiUtils.ForumUrlPattern) && TextUtils.isEmpty(authCookie))) { UIUtils.toast("下载信息不完整,无法进行下载"); return; } if (UIUtils.askForStoragePermission(ctx)) { return; } if (DownloadManagerResolver.resolve(ctx)) { DownloadManager dm = (DownloadManager) ctx.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request req = new DownloadManager.Request(Uri.parse(url)); req.addRequestHeader("User-agent", HiUtils.getUserAgent()); if (url.contains(HiUtils.ForumUrlPattern)) { req.addRequestHeader("Cookie", "cdb_auth=" + authCookie); } req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); req.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename); if (filename.toLowerCase().endsWith(".apk")) req.setMimeType("application/vnd.android.package-archive"); dm.enqueue(req); } } public static String readFromAssets(Context context, String filename) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open(filename))); StringBuilder sb = new StringBuilder(); String line = reader.readLine(); while (line != null) { sb.append(line).append("\n"); line = reader.readLine(); } reader.close(); return sb.toString(); } public static String getDeviceInfo() { StringBuilder sb = new StringBuilder(); sb.append("设备名称 : "); String manufacturer = Build.MANUFACTURER; String model = Build.MODEL; if (model.toLowerCase().startsWith(manufacturer.toLowerCase())) { sb.append(model); } else { sb.append(manufacturer).append(" ").append(model); } sb.append("\n"); sb.append("内存限制 : ").append(toSizeText(Runtime.getRuntime().maxMemory())).append("\n"); sb.append("系统版本 : ").append(Build.VERSION.RELEASE).append("\n"); sb.append("客户端版本 : ").append(HiApplication.getAppVersion()).append("\n"); return sb.toString(); } public static String getRingtoneTitle(Context context, Uri uri) { try { if (uri == null || TextUtils.isEmpty(uri.toString())) { return "无"; } Ringtone ringtone = RingtoneManager.getRingtone(context, uri); return ringtone.getTitle(context); } catch (Exception e) { return "-"; } } public static String md5(String content) throws UnsupportedEncodingException, NoSuchAlgorithmException { byte[] hash; hash = MessageDigest.getInstance("MD5").digest(content.getBytes("UTF-8")); StringBuilder hex = new StringBuilder(hash.length * 2); for (byte b : hash) { if ((b & 0xFF) < 0x10) { hex.append("0"); } hex.append(Integer.toHexString(b & 0xFF)); } return hex.toString(); } public static boolean isDestroyed(Activity activity) { if (activity == null) return true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { return activity.isDestroyed() || activity.isFinishing(); } else { return activity.isFinishing(); } } public static Bitmap getCircleBitmap(Bitmap bitmap) { Bitmap output; Rect srcRect, dstRect; float r; final int width = bitmap.getWidth(); final int height = bitmap.getHeight(); if (width > height) { output = Bitmap.createBitmap(height, height, Bitmap.Config.ARGB_8888); int left = (width - height) / 2; int right = left + height; srcRect = new Rect(left, 0, right, height); dstRect = new Rect(0, 0, height, height); r = height / 2; } else { output = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888); int top = (height - width) / 2; int bottom = top + width; srcRect = new Rect(0, top, width, bottom); dstRect = new Rect(0, 0, width, width); r = width / 2; } Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawCircle(r, r, r, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, srcRect, dstRect, paint); bitmap.recycle(); return output; } public static Bitmap.Config getBitmapConfig() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { return Bitmap.Config.ARGB_8888; } else { return Bitmap.Config.HARDWARE; } } }