Java tutorial
/* Copyright 2013 Owen Shepherd. A part of Impeller. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package eu.e43.impeller; import android.accounts.Account; import android.accounts.AccountManager; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.util.Log; import android.view.View; import android.widget.TextView; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; import org.json.JSONException; import org.json.JSONObject; import eu.e43.impeller.activity.ActivityWithAccount; import eu.e43.impeller.api.Content; public class Utils { public static Uri getHostUri(Context ctx, Account user, String... components) { AccountManager am = AccountManager.get(ctx); String host = am.getUserData(user, "host"); Uri.Builder b = new Uri.Builder(); b.scheme("https"); b.authority(host); for (String s : components) { b.appendPath(s); } return b.build(); } public static Uri getUserUri(Context ctx, Account user, String... components) { AccountManager am = AccountManager.get(ctx); String username = am.getUserData(user, "username"); ArrayList<String> parts = new ArrayList<String>(); parts.add("api"); parts.add("user"); parts.add(username); for (String s : components) parts.add(s); return getHostUri(ctx, user, parts.toArray(components)); } static public String readAll(Reader r) throws IOException { int nRead; char[] buf = new char[16 * 1024]; StringBuilder bld = new StringBuilder(); while ((nRead = r.read(buf)) != -1) { bld.append(buf, 0, nRead); } return bld.toString(); } static public String readAll(InputStream s) throws IOException { return readAll(new InputStreamReader(s, "UTF-8")); } static public OutputStream copyBytes(OutputStream out, InputStream in) throws IOException { int nRead; byte[] buf = new byte[32 * 1024]; while ((nRead = in.read(buf)) != -1) { out.write(buf, 0, nRead); } return out; } static public byte[] readAllBytes(InputStream s) throws IOException { ByteArrayOutputStream aos = new ByteArrayOutputStream(); copyBytes(aos, s); return aos.toByteArray(); } static public String encode(Map<String, String> params) { try { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (sb.length() > 0) { sb.append('&'); } sb.append(URLEncoder.encode(entry.getKey(), "UTF-8")); sb.append('='); sb.append(URLEncoder.encode(entry.getValue(), "UTF-8")); } return sb.toString(); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } } public static Map<String, String> getQueryMap(String query) { try { String[] params = query.split("&"); Map<String, String> map = new HashMap<String, String>(); for (String param : params) { String[] parts = param.split("=", 2); String name; name = URLDecoder.decode(parts[0], "UTF-8"); String value = URLDecoder.decode(parts[1], "UTF-8"); map.put(name, value); } return map; } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public static byte[] sha1(String text) { try { MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(text.getBytes("utf-8"), 0, text.length()); return md.digest(); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } private static final char[] HEX_DIGITS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static String sha1Hex(String text) { byte[] sha = sha1(text); char[] hex = new char[sha.length * 2]; for (int i = 0; i < sha.length; i++) { hex[2 * i + 0] = HEX_DIGITS[sha[i] & 0x0F]; hex[2 * i + 1] = HEX_DIGITS[(sha[1] >> 4) & 0x0F]; } return new String(hex); } public static String getProxyUrl(Context ctx, Account acct, JSONObject obj) { if (obj.has("pump_io")) { JSONObject pump_io = obj.optJSONObject("pump_io"); String url = pump_io.optString("proxyURL", null); // If the hosts mismatch between the proxyURL and the Account ID, assume we have a // "leakage" issue Uri uri = Uri.parse(url); Uri userUri = Uri.parse(AccountManager.get(ctx).getUserData(acct, "id")); if (!uri.getHost().equalsIgnoreCase(userUri.getHost())) { Log.w("Utils.getProxyUrl", "Discarding proxyURL " + url + " due to host mismatch with user " + userUri.toString()); return null; } if (url == null || url.length() == 0) return null; return url; } else return null; } public static String getImageUrl(Context context, Account account, JSONObject img) { if (img == null) return null; String url = getProxyUrl(context, account, img); if (url == null) url = img.optString("url"); return url; } public static String getImageUrl(ActivityWithAccount awa, JSONObject img) { return getImageUrl(awa, awa.getAccount(), img); } public static int getCollectionItemCount(JSONObject obj, String collection) { JSONObject col = obj.optJSONObject("collection"); if (col != null) { return col.optInt("totalItems"); } else return 0; } public static void updateStatebar(View parent, JSONObject obj) { updateStatebar(parent, getCollectionItemCount(obj, "replies"), getCollectionItemCount(obj, "likes"), getCollectionItemCount(obj, "shares")); } public static void updateStatebar(View parent, int replies, int likes, int shares) { TextView commentsIcon = (TextView) parent.findViewById(R.id.commentsIcon); TextView sharesIcon = (TextView) parent.findViewById(R.id.sharesIcon); TextView likesIcon = (TextView) parent.findViewById(R.id.likesIcon); commentsIcon.setTypeface(ImpellerApplication.fontAwesome); sharesIcon.setTypeface(ImpellerApplication.fontAwesome); likesIcon.setTypeface(ImpellerApplication.fontAwesome); TextView commentCount = (TextView) parent.findViewById(R.id.commentsCount); TextView shareCount = (TextView) parent.findViewById(R.id.sharesCount); TextView likeCount = (TextView) parent.findViewById(R.id.likesCount); commentCount.setText(String.valueOf(replies)); shareCount.setText(String.valueOf(shares)); likeCount.setText(String.valueOf(likes)); } public static long parseDate(String date) { if (date == null) return new Date().getTime(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); df.setTimeZone(TimeZone.getTimeZone("Zulu")); try { return df.parse(date).getTime(); } catch (ParseException e) { return new Date().getTime(); } } public static String humanDate(long milis) { return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT).format(new Date(milis)) .replace(' ', '\u00A0'); } public static String humanDate(String isoDate) { return humanDate(parseDate(isoDate)); } public static int getScreenDensityDpi(Context ctx) { return ctx.getResources().getDisplayMetrics().densityDpi; } public static int pxFromDip(Context ctx, int dip) { final float density = ctx.getResources().getDisplayMetrics().density; return (int) (density * dip + 0.5f); } public static int dipFromPx(Context ctx, int px) { if (ctx == null) return px; final float density = ctx.getResources().getDisplayMetrics().density; return (int) (px / density + 0.5f); } public static String formatHtmlFragment(String fragment, Integer width) { final String base = "<html>" + "<head>" + "<meta name=\"viewport\" content=\"width=%s, user-scalable=no\">" + "<style>" + "body { margin: 0; }" + "img, video, object, iframe { max-width: 100%%; } " + "</style>" + "</head>" + "<body>%s</body>" + "</html>"; String strWidth = "device-width"; if (width != null) strWidth = width.toString(); return String.format(base, strWidth, fragment); } /** Builds a stub object, in the form * * { "objectType": (type), "id": (id) } */ public static JSONObject buildStubObject(JSONObject obj) throws JSONException { JSONObject stub = new JSONObject(); stub.put("id", obj.getString("id")); stub.putOpt("objectType", obj.optString("objectType", null)); return stub; } public static JSONObject findPost(Context ctx, Content.Uris uris, JSONObject object) throws JSONException { Cursor res = ctx.getContentResolver().query(uris.activitiesUri, new String[] { "_json" }, "actor=? AND verb='post' AND object.id=?", new String[] { object.getJSONObject("author").getString("id"), object.getString("id") }, null); try { if (res.getCount() > 0) { res.moveToFirst(); return new JSONObject(res.getString(0)); } else { return null; } } finally { res.close(); } } public static int mixColours(int first, int second, float mix) { float inverseMix = 1 - mix; int a = ((int) (((float) (first >> 24 & 0xff) * mix) + ((float) (second >> 24 & 0xff) * inverseMix))) & 0xff; int r = ((int) (((float) (first >> 16 & 0xff) * mix) + ((float) (second >> 16 & 0xff) * inverseMix))) & 0xff; int g = ((int) (((float) (first >> 8 & 0xff) * mix) + ((float) (second >> 8 & 0xff) * inverseMix))) & 0xff; int b = ((int) (((float) (first & 0xff) * mix) + ((float) (second & 0xff) * inverseMix))) & 0xff; return a << 24 | r << 16 | g << 8 | b; } }