package net.coding.program.common; import android.app.Activity; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.Color; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; import android.text.Editable; import android.text.Html; import android.text.Spannable; import android.text.style.ImageSpan; import android.text.style.QuoteSpan; import android.text.style.URLSpan; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.WebView; import android.widget.EditText; import android.widget.ImageView; import com.loopj.android.http.PersistentCookieStore; import com.readystatesoftware.viewbadger.BadgeView; import net.coding.program.MyApp; import net.coding.program.WebActivity; import net.coding.program.common.enter.DrawableTool; import net.coding.program.common.enter.GifImageSpan; import net.coding.program.common.htmltext.GrayQuoteSpan; import net.coding.program.common.htmltext.URLSpanNoUnderline; import net.coding.program.login.auth.AuthListActivity; import net.coding.program.login.auth.Login2FATipActivity; import net.coding.program.maopao.MaopaoDetailActivity; import net.coding.program.model.AccountInfo; import net.coding.program.model.GitFileObject; import org.apache.http.cookie.Cookie; import org.json.JSONObject; import org.xml.sax.XMLReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import java.net.URLEncoder; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import pl.droidsonroids.gif.GifDrawable; /** * Created by cc191954 on 14-8-23. * 放一些公共的全局方法 */ public class Global { public static final String DEFAULT_HOST = "https://coding.net"; public static final SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd EEE"); public static final SimpleDateFormat mDateYMDHH = new SimpleDateFormat("yyyy-MM-dd HH:mm"); private static final String IMAGE_URL_SCAL = "%s?imageMogr2/thumbnail/!%s"; private static final SimpleDateFormat sFormatToday = new SimpleDateFormat("今天 HH:mm"); private static final SimpleDateFormat sFormatThisYear = new SimpleDateFormat("MM/dd HH:mm"); private static final SimpleDateFormat sFormatOtherYear = new SimpleDateFormat("yy/MM/dd HH:mm"); private static final SimpleDateFormat sFormatMessageToday = new SimpleDateFormat("今天"); private static final SimpleDateFormat sFormatMessageThisYear = new SimpleDateFormat("MM/dd"); private static final SimpleDateFormat sFormatMessageOtherYear = new SimpleDateFormat("yy/MM/dd"); public static String HOST = DEFAULT_HOST; public static String HOST_MOBILE = "https://m.coding.net"; public static String HOST_API = HOST + "/api"; /** * 语音文件存放目录 */ public static String sVoiceDir; public static SimpleDateFormat DateFormatTime = new SimpleDateFormat("HH:mm"); public static SimpleDateFormat MonthDayFormatTime = new SimpleDateFormat("MMMdd日"); public static SimpleDateFormat WeekFormatTime = new SimpleDateFormat("EEE"); public static SimpleDateFormat NextWeekFormatTime = new SimpleDateFormat("下EEE"); public static SimpleDateFormat LastWeekFormatTime = new SimpleDateFormat("上EEE"); public static Html.TagHandler tagHandler = new Html.TagHandler() { @Override public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { if (tag.toLowerCase().equals("code") && !opening) { output.append("\n\n"); } } }; public static DecimalFormat df = new DecimalFormat("#.00"); private static SimpleDateFormat DayFormatTime = new SimpleDateFormat("yyyy-MM-dd"); public static String dayFromTime(long time) { return DayFormatTime.format(time); } public static long longFromDay(String day) throws ParseException { final String format = "yyyy-MM-dd"; final SimpleDateFormat sd = new SimpleDateFormat(format); return sd.parse(day).getTime(); } public static boolean isEmptyContainSpace(EditText edit) { return edit.getText().toString().replace(" ", "").replace(" ", "").isEmpty(); } public static String dayCount(long time) { return DayFormatTime.format(time); } public static void errorLog(Exception e) { if (e == null) { return; } e.printStackTrace(); Log.e("", "" + e); } public static String encodeInput(String at, String input) { if (at == null || at.isEmpty()) { return input; } return String.format("@%s %s", at, input); } public static String encodeUtf8(String s) { try { return URLEncoder.encode(s, "utf-8"); } catch (Exception e) { return ""; } } public static String decodeUtf8(String s) { try { return URLDecoder.decode(s, "utf-8"); } catch (Exception e) { return ""; } } public static boolean isImageUri(String s1) { s1 = s1.toLowerCase(); return s1.endsWith(".png") || s1.endsWith(".jpg") || s1.endsWith(".jpeg") || s1.endsWith(".bmp") || s1.endsWith(".gif"); } public static void syncCookie(Context context) { PersistentCookieStore cookieStore = new PersistentCookieStore(context); List<Cookie> cookies = cookieStore.getCookies(); CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); for (int i = 0; i < cookies.size(); i++) { Cookie eachCookie = cookies.get(i); cookieManager.setCookie(Global.HOST, String.format("%s=%s; Domain=%s; Path=%s; Secure; HttpOnly", eachCookie.getName(), eachCookie.getValue(), eachCookie.getDomain(), eachCookie.getPath())); } CookieSyncManager.getInstance().sync(); } public static void copy(Context context, String content) { ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); String url = HtmlContent.parseReplaceHtml(content); cmb.setText(url); } public static String replaceAvatar(JSONObject json) { return replaceHeadUrl(json, "avatar"); } public static String getErrorMsg(JSONObject jsonObject) { String s = ""; try { JSONObject jsonData = jsonObject.getJSONObject("msg"); String key = jsonData.keys().next(); s = jsonData.getString(key); } catch (Exception e) { Global.errorLog(e); } return s; } // 用于头像,有些头像是 “/static/fruit_avatar/Fruit-12.png” public static String replaceHeadUrl(JSONObject json, String name) { String s = json.optString(name); return translateStaticIcon(s); } private static String translateStaticIcon(String s) { if (s.indexOf("/static/") == 0) { return Global.HOST + s; } return s; } public static void popSoftkeyboard(Context ctx, View view, boolean wantPop) { InputMethodManager imm = (InputMethodManager) ctx.getSystemService(Context.INPUT_METHOD_SERVICE); if (wantPop) { view.requestFocus(); imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); } else { imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } public static void hideSoftKeyboard(Activity activity) { View view = activity.getCurrentFocus(); if (view != null) { InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } public static String makeSmallUrl(ImageView view, String url) { ViewGroup.LayoutParams lp = view.getLayoutParams(); int max = Math.max(lp.height, lp.width); if (max > 0) { return makeSmallUrlSquare(url, max); } return url; } public static boolean canCrop(String url) { return url.startsWith("http") && (!url.contains("/thumbnail/")); } public static String makeSmallUrlSquare(String url, int widthPix) { if (canCrop(url)) { String parma = ""; if (!url.contains("?imageMogr2/")) { parma = "?imageMogr2/"; } return String.format("%s%s/!%dx%d", url, parma, widthPix, widthPix); } else { return url; } } public static String makeLargeUrl(String url) { final int MAX = 4096; // ImageView显示的图片不能大于这个数 return String.format(IMAGE_URL_SCAL, url, MAX); } private static String intToString(int length) { String width; if (length > 0) { width = String.valueOf(length); } else { width = ""; } return width; } public static int dpToPx(int dpValue) { return (int) (dpValue * MyApp.sScale + 0.5f); } public static int dpToPx(double dpValue) { return (int) (dpValue * MyApp.sScale + 0.5f); } public static int pxToDp(float pxValue) { return (int) (pxValue / MyApp.sScale + 0.5f); } public static Spannable changeHyperlinkColor(String content) { return Global.changeHyperlinkColor(content, null, null); } public static Spannable changeHyperlinkColor(String content, MyImageGetter imageGetter) { return Global.changeHyperlinkColor(content, imageGetter, null); } public static Spannable changeHyperlinkColor(String content, int linkColor) { return changeHyperlinkColor(content, null, tagHandler, linkColor); } public static Spannable changeHyperlinkColor(String content, int color, MyImageGetter imageGetter) { return Global.changeHyperlinkColor(content, imageGetter, null); } public static Spannable changeHyperlinkColor(String content, Html.ImageGetter imageGetter, Html.TagHandler tagHandler) { return changeHyperlinkColor(content, imageGetter, tagHandler, 0xFF3BBD79); } public static Spannable changeHyperlinkColorMaopao(String content, Html.ImageGetter imageGetter, Html.TagHandler tagHandler, AssetManager assetManager) { Spannable s = changeHyperlinkColor(content, imageGetter, tagHandler, 0xFF3BBD79); return spannToGif(s, assetManager); } public static Spannable changeHyperlinkColor(String content, Html.ImageGetter imageGetter, Html.TagHandler tagHandler, int color) { Spannable s = (Spannable) Html.fromHtml(content, imageGetter, tagHandler); return getCustomSpannable(color, s); } public static Spannable recentMessage(String content, Html.ImageGetter imageGetter, Html.TagHandler tagHandler) { String parse = HtmlContent.parseToText(content); Spannable s = (Spannable) Html.fromHtml(parse, imageGetter, null); return getCustomSpannable(0xff999999, s); } static public void cropImageUri(StartActivity activity, Uri uri, Uri outputUri, int outputX, int outputY, int requestCode) { try { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", outputX); intent.putExtra("outputY", outputY); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri); intent.putExtra("return-data", false); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); activity.startActivityForResult(intent, requestCode); } catch (Exception e) { Global.errorLog(e); } } private static Spannable getCustomSpannable(int color, Spannable s) { URLSpan[] urlSpan = s.getSpans(0, s.length(), URLSpan.class); for (URLSpan span : urlSpan) { int start = s.getSpanStart(span); int end = s.getSpanEnd(span); s.removeSpan(span); span = new URLSpanNoUnderline(span.getURL(), color); s.setSpan(span, start, end, 0); } QuoteSpan quoteSpans[] = s.getSpans(0, s.length(), QuoteSpan.class); for (QuoteSpan span : quoteSpans) { int start = s.getSpanStart(span); int end = s.getSpanEnd(span); s.removeSpan(span); GrayQuoteSpan grayQuoteSpan = new GrayQuoteSpan(); s.setSpan(grayQuoteSpan, start, end, 0); } return s; } private static Spannable spannToGif(Spannable s, AssetManager assetManager) { ImageSpan[] imageSpans = s.getSpans(0, s.length(), ImageSpan.class); final String[] gifEmojiName = new String[]{ "festival-emoji-01.gif", "festival-emoji-02.gif", "festival-emoji-03.gif", "festival-emoji-04.gif", "festival-emoji-05.gif", "festival-emoji-06.gif", "festival-emoji-07.gif", "festival-emoji-08.gif", }; for (ImageSpan imageSpan : imageSpans) { int start = s.getSpanStart(imageSpan); int end = s.getSpanEnd(imageSpan); String imageSource = imageSpan.getSource(); for (String endString : gifEmojiName) { if (imageSource.endsWith(endString)) { try { GifDrawable gifDrawable = new GifDrawable(assetManager, endString); DrawableTool.zoomDrwable(gifDrawable, true); gifDrawable.setLoopCount(100); GifImageSpan gifImageSpan = new GifImageSpan(gifDrawable); s.removeSpan(imageSpan); s.setSpan(gifImageSpan, start, end, 0); } catch (Exception e) { Global.errorLog(e); } } } } return s; } static public String readTextFile(Context context, String assetFile) throws IOException { InputStream inputStream = context.getAssets().open(assetFile); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte buf[] = new byte[1024]; int len; while ((len = inputStream.read(buf)) != -1) { outputStream.write(buf, 0, len); } outputStream.close(); inputStream.close(); return outputStream.toString(); } static public String readTextFile(File file) { try { FileInputStream is = new FileInputStream(file); return readTextFile(is); } catch (Exception e) { Global.errorLog(e); } return ""; } static public String readTextFile(InputStream inputStream) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte buf[] = new byte[1024]; int len; try { while ((len = inputStream.read(buf)) != -1) { outputStream.write(buf, 0, len); } outputStream.close(); inputStream.close(); } catch (IOException e) { Global.errorLog(e); } return outputStream.toString(); } public static void initWebView(WebView webView) { webView.getSettings().setJavaScriptEnabled(true); // 防止webview滚动时背景变成黑色 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { webView.setBackgroundColor(0x00000000); } else { webView.setBackgroundColor(Color.argb(1, 0, 0, 0)); } webView.getSettings().setDefaultTextEncodingName("UTF-8"); } static public void setWebViewContent(WebView webView, String tempate, String content) { Context context = webView.getContext(); Global.initWebView(webView); webView.setWebViewClient(new MaopaoDetailActivity.CustomWebViewClient(context, content)); try { syncCookie(webView.getContext()); String bubble = readTextFile(context.getAssets().open(tempate)); webView.loadDataWithBaseURL(Global.HOST, bubble.replace("${webview_content}", content), "text/html", "UTF-8", null); } catch (Exception e) { Global.errorLog(e); } } static public void setWebViewContent(WebView webview, GitFileObject gitFile) { Context context = webview.getContext(); if (gitFile.lang.equals("markdown")) { try { String template = readTextFile(context.getAssets().open("markdown.html")); webview.loadDataWithBaseURL(Global.HOST, template.replace("${webview_content}", gitFile.preview), "text/html", "UTF-8", null); } catch (Exception e) { Global.errorLog(e); } } else { try { String template = readTextFile(context.getAssets().open("code.html")); String replaceData = gitFile.data.replace("<", "<").replace(">", ">").replace("\u2028", "").replace("\u2029", ""); webview.loadDataWithBaseURL(Global.HOST, template.replace("${file_code}", replaceData).replace("${file_lang}", gitFile.lang), "text/html", "UTF-8", null); } catch (Exception e) { Global.errorLog(e); } } webview.setWebViewClient(new WebActivity.CustomWebViewClient(webview.getContext())); } static public void setWebViewContent(WebView webView, String tempate, String replaceString, String content, String replaceComment, String comment) { Context context = webView.getContext(); Global.initWebView(webView); webView.setWebViewClient(new MaopaoDetailActivity.CustomWebViewClient(context, content)); try { syncCookie(webView.getContext()); String bubble = readTextFile(context.getAssets().open(tempate)); webView.loadDataWithBaseURL(Global.HOST, bubble.replace(replaceString, content).replace(replaceComment, comment), "text/html", "UTF-8", null); } catch (Exception e) { Global.errorLog(e); } } public static boolean isGif(String uri) { return uri.toLowerCase().endsWith(".gif"); } // 通过文件头来判断是否gif public static boolean isGifByFile(File file) { try { int length = 10; InputStream is = new FileInputStream(file); byte[] data = new byte[length]; is.read(data); String type = getType(data); is.close(); if (type.equals("gif")) { return true; } } catch (Exception e) { Global.errorLog(e); } return false; } private static String getType(byte[] data) { String type = ""; if (data[1] == 'P' && data[2] == 'N' && data[3] == 'G') { type = "png"; } else if (data[0] == 'G' && data[1] == 'I' && data[2] == 'F') { type = "gif"; } else if (data[6] == 'J' && data[7] == 'F' && data[8] == 'I' && data[9] == 'F') { type = "jpg"; } return type; } private static String getDay(long time, boolean showToday) { Calendar calendarToday = Calendar.getInstance(); calendarToday.set(calendarToday.get(Calendar.YEAR), calendarToday.get(Calendar.MONTH), calendarToday.get(Calendar.DAY_OF_MONTH), 0, 0, 0); final long oneDay = 1000 * 3600 * 24; long today = calendarToday.getTimeInMillis(); long tomorrow = today + oneDay; long tomorrowNext = tomorrow + oneDay; long tomorrowNextNext = tomorrowNext + oneDay; long yesterday = today - oneDay; long lastYesterday = yesterday - oneDay; if (time >= today) { if (tomorrow > time) { if (showToday) { return "今天"; } else { return ""; } } else if (tomorrowNext > time) { return "明天"; } else if (tomorrowNextNext > time) { return "后天"; } } else { if (time > yesterday) { return "昨天"; } else if (time > lastYesterday) { return "前天"; } } return null; } private static String getWeek(long time) { Calendar today = Calendar.getInstance(); today.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); today.set(Calendar.HOUR, 0); today.set(Calendar.MINUTE, 0); today.set(Calendar.SECOND, 0); final long oneWeek = 1000 * 60 * 60 * 24 * 7; long weekBegin = today.getTimeInMillis(); long nextWeekBegin = weekBegin + oneWeek; long nextnextWeekBegin = nextWeekBegin + oneWeek; long lastWeekBegin = weekBegin - oneWeek; if (time >= weekBegin) { if (nextWeekBegin > time) { return WeekFormatTime.format(time); } else if (nextnextWeekBegin > time) { return NextWeekFormatTime.format(time); } } else { if (time > lastWeekBegin) { return LastWeekFormatTime.format(time); } } return null; } public static String getDataDetail(long timeInMillis) { String dataString = getDay(timeInMillis, true); if (dataString == null) { dataString = getWeek(timeInMillis); if (dataString == null) { dataString = MonthDayFormatTime.format(timeInMillis); } } return dataString; } public static String getTimeDetail(long timeInMillis) { // String dataString = getDay(timeInMillis, false); // if (dataString == null) { // dataString = getWeek(timeInMillis); // if (dataString == null) { // dataString = MonthDayFormatTime.format(timeInMillis); // } // } // // return String.format("%s %s", dataString, DateFormatTime.format(new Date(timeInMillis))); return dayToNow(timeInMillis, true); } public static String dayToNowCreate(long time) { return "创建于 " + Global.dayToNow(time); } public static String dayToNow(long time) { return dayToNow(time, true); } public static String dayToNow(long time, boolean displayHour) { long nowMill = System.currentTimeMillis(); long minute = (nowMill - time) / 60000; if (minute < 60) { if (minute <= 0) { return Math.max((nowMill - time) / 1000, 1) + "秒前"; // 由于手机时间的原因,有时候会为负,这时候显示1秒前 } else { return minute + "分钟前"; } } GregorianCalendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(time); int year = calendar.get(GregorianCalendar.YEAR); int month = calendar.get(GregorianCalendar.MONTH); int day = calendar.get(GregorianCalendar.DAY_OF_MONTH); calendar.setTimeInMillis(nowMill); Long timeObject = new Long(time); if (calendar.get(GregorianCalendar.YEAR) != year) { // 不是今年 SimpleDateFormat sFormatOtherYear = displayHour ? Global.sFormatOtherYear : Global.sFormatMessageOtherYear; return sFormatOtherYear.format(timeObject); } else if (calendar.get(GregorianCalendar.MONTH) != month || calendar.get(GregorianCalendar.DAY_OF_MONTH) != day) { // 今年 SimpleDateFormat sFormatThisYear = displayHour ? Global.sFormatThisYear : Global.sFormatMessageThisYear; return sFormatThisYear.format(timeObject); } else { // 今天 SimpleDateFormat sFormatToday = displayHour ? Global.sFormatToday : Global.sFormatMessageToday; return sFormatToday.format(timeObject); } } public static String dayToNow(long time, String template) { return String.format(template, dayToNow(time)); } public static boolean isWifiConnected(Context context) { if (context != null) { ConnectivityManager mConnectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activityNetwork = mConnectivityManager.getActiveNetworkInfo(); return activityNetwork != null && activityNetwork.getType() == ConnectivityManager.TYPE_WIFI; } return false; } public static boolean isConnected(Context context) { if (context != null) { ConnectivityManager mConnectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo(); if (mNetworkInfo != null) { return mNetworkInfo.isAvailable(); } } return false; } /** * 显示文件大小,保留两位 */ public static String HumanReadableFilesize(double size) { String[] units = new String[]{"B", "KB", "MB", "GB", "TB", "PB"}; double mod = 1024.0; int i = 0; while (size >= mod) { size /= mod; i++; } //return Math.round(size) + units[i]; return df.format(size) + " " + units[i]; } public static void setBadgeView(BadgeView badge, int count) { if (count > 0) { String countString = count > 99 ? "99+" : ("" + count); badge.setText(countString); badge.setVisibility(View.VISIBLE); } else { badge.setVisibility(View.INVISIBLE); } } public static void start2FAActivity(Activity activity) { Intent intent; if (AccountInfo.loadAuthDatas(activity).isEmpty()) { intent = new Intent(activity, Login2FATipActivity.class); } else { intent = new Intent(activity, AuthListActivity.class); } activity.startActivity(intent); } public static class MessageParse { public String text = ""; public ArrayList<String> uris = new ArrayList<>(); public boolean isVoice; public String voiceUrl; public int voiceDuration; public int played; public int id; public String toString() { String s = "text " + text + "\n"; for (int i = 0; i < uris.size(); ++i) { s += uris.get(i) + "\n"; } return s; } } }