Android Tutorial - Development : random
Random Alphabet Maker
//package com.ou.android.game.common; import java.util.ArrayList; class RandomAlphabetMaker { private ArrayList<String> mList; int mCount; public RandomAlphabetMaker(int count) { mCount = count; init(); } private void init() { mList = new ArrayList<String>(); char a = 'A'; for (int i = 0; i < mCount; i++) { char item = (char) (a + i); String s = Character.toString(item); mList.add(s); } } public ArrayList<String> getRandomList() { ArrayList<String> ret = new ArrayList<String>(); if (mList.size() == 0) { init(); } while (mList.size() > 0) { int index = (int) (Math.random() * 100) % mList.size(); ret.add(mList.get(index)); mList.remove(index); } return ret; } }
Next random Int
//package org.expressme.wireless.game; import java.util.Random; class Main { private static final Random RANDOM = new Random(); /** * Generate random integer between 0(include) and max(exclude). */ public static int nextRandomInt(int max) { int n = RANDOM.nextInt(); return (n < 0 ? -n : n) % max; } /** * Generate random integer between 0(include) and Integer.MAX_VALUE. */ public static int nextRandomInt() { int n = RANDOM.nextInt(); return n < 0 ? -n : n; } }
Random Xor Obfuscator
//package se.ramfelt.psnfriends.util; import java.util.Random; import java.util.StringTokenizer; public class RandomXorObfuscator { private final long seed; public RandomXorObfuscator(long seed) { this.seed = seed; } public String perform(String text) { if (text == null) { return null; } Random random = new Random(seed); StringBuilder builder = new StringBuilder(text.length()); char[] chars = text.toCharArray(); for (int i = 0; i < chars.length; i++) { builder.append((int)(chars[i] ^ random.nextInt())); builder.append(','); } return builder.toString(); } public String reverse(String text) { if (text == null) { return null; } StringTokenizer tokenizer = new StringTokenizer(text, ","); StringBuilder builder = new StringBuilder(); Random random = new Random(seed); while (tokenizer.hasMoreTokens()) { builder.append((char)(Integer.parseInt(tokenizer.nextToken()) ^ random.nextInt())); } return builder.toString(); } }
returns a random number among { 0 to count-1 }
import java.util.Calendar; import java.util.Random; class CommonUtil { private static Random random = new Random(Calendar.getInstance().getTimeInMillis()); /** * * @param count * @return returns a random number among { 0 to count-1 } */ public static short getRandomIndex(short count){ int randomIndex = random.nextInt(); short resultIndex = (short) (randomIndex % count); if(resultIndex < 0){ resultIndex += count; } return resultIndex; } }
Random Generator
//package br.com.tecnove.random.android.util; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Random; public class RandomGenerator { private static final Random r = new Random(); public static int generateFromRange(int min, int max) { // swap values if they come in the wrong order if (min > max) { int aux = min; min = max; max = aux; } int i = max - min; int x = r.nextInt(i + 1); return x + min; } public static String generateFromStringArray(String[] input) { int i = generateFromRange(0, input.length - 1); return input[i]; } public static String generateFromStringCollection(Collection<String> input) { return generateFromStringArray((String[]) input.toArray()); } public static char generateLetter() { return (char) generateFromRange((int) 'A', (int) 'Z'); } public static List<Integer> generateLottery(Integer maxRange, Integer numbersToGenerate) { List<Integer> numbersGenerated = new ArrayList<Integer>(); for (int c = 0; c < numbersToGenerate; c++) { int nGenerated = 0; do { nGenerated = r.nextInt(maxRange); // adding +1 to make the int start at 1 and the maxRange be included in the sorted values nGenerated++; // if the number is allready on the list, sort a new number } while (numbersGenerated.contains(nGenerated)); numbersGenerated.add(nGenerated); } return numbersGenerated; } public static String generateFromString(String valor) { // the input must be like: curitiba/fortaleza/google/facebook/android/motorola String[] vetor = valor.split("/"); String outValue = ""; if (vetor.length>0){ outValue = vetor[r.nextInt(vetor.length)]; } return outValue; } }
Get Random Index
import android.graphics.Paint; class Main { public static int GetRandomIndex(int min, int max) { return (int) (Math.random() * (max - min + 1)) + min; } }
Run System Command
//package com.googlecode.gogodroid; import java.io.IOException; import java.io.OutputStream; import android.util.Log; class Utils { private static final String LOG_TAG = "Gogoc"; public static void runCommand(String command) { try { Process process = Runtime.getRuntime().exec("sh"); //process = Runtime.getRuntime().exec("sh"); OutputStream os = process.getOutputStream(); Log.d(LOG_TAG, "runCommand() cmd=" + command ); writeLine( os, command ); os.flush(); } catch ( IOException e ) { e.printStackTrace(); } } public static void runSuCommand(String sucommand) { try { Process process = Runtime.getRuntime().exec("su -c sh"); //process = Runtime.getRuntime().exec("sh"); OutputStream os = process.getOutputStream(); Log.d(LOG_TAG, "runSuCommand() cmd=" + sucommand ); writeLine( os, sucommand ); os.flush(); } catch ( IOException e ) { e.printStackTrace(); } } private static void writeLine(OutputStream os, String value) throws IOException { String line = value + "\n"; os.write( line.getBytes() ); } }
Exec And Wait
//package org.zenthought.flashrec; import java.io.IOException; import android.util.Log; class Util { public static boolean execAndWait(String[] args) { try { Process p = Runtime.getRuntime().exec(args); while (true) try { int code = p.waitFor(); if (code != 0) { Log.d("FlashRec", String.format("%s exited with code %d", args[0], code)); return false; } return true; } catch (InterruptedException e) { e.printStackTrace(); continue; } } catch (IOException e) { e.printStackTrace(); return false; } } }
Get Api Level
//package com.alfray.brighteriffic; import android.os.Build; import android.os.Build.VERSION; class Utils { private static int sApiLevel = 0; /** * Return {@link VERSION#SDK} as an int. * Value is cached locally. */ public static int getApiLevel() { if (sApiLevel == 0) { try { // SDK_INT only exists since API 4 so let's use the string version. sApiLevel = Integer.parseInt(Build.VERSION.SDK); } catch (Exception e) { // This app doesn't run below 3 anyway sApiLevel = 3; } } return sApiLevel; } }
Check For Installed App
import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; class Main { public static boolean checkForInstalledApp(Context ctx, String pkgName) { try { PackageManager pm = ctx.getPackageManager(); pm.getPackageInfo(pkgName, 0); // Log.d(TAG, pkgString + " is installed"); return true; } catch (NameNotFoundException e) { // Log.d(TAG, pkgString + " is not installed"); } return false; } }
Get App Name
import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; class Main { public static String getAppName(Context ctx, String pkgName) { try { PackageManager pm = ctx.getPackageManager(); ApplicationInfo appInfo = pm.getApplicationInfo(pkgName, 0); String label = pm.getApplicationLabel(appInfo).toString(); return label; } catch (NameNotFoundException e) { return ""; } } }
Get Process ID with shell command and read by Java code
//package org.codeandroid.vpnc_frontend; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.StringTokenizer; import android.util.Log; class Util { private static final String LOG_TAG = "VPN_Connections"; public static final int DISCONNECT_NOTIFICATION = 1; private static final int pidColumn = getPidColumn(); public static int getPidColumn() { try { Process psProcess = Runtime.getRuntime().exec( "sh" ); OutputStream os = psProcess.getOutputStream(); InputStream is = psProcess.getInputStream(); writeLine( os, null, "ps | grep PID" ); writeLine( os, null, "exit" ); try { psProcess.waitFor(); } catch( InterruptedException interruptedException ) { Log.e( LOG_TAG, "While trying to read process id", interruptedException ); return -1; } String headerLine = readString( is, null, false ); Log.d( LOG_TAG, "Read PS header line as " + headerLine ); if( headerLine == null || headerLine.trim().length() == 0 ) { Log.e( LOG_TAG, "Attempt to do a PS did not return anything" ); return -1; } else { StringTokenizer tokenizer = new StringTokenizer( headerLine, " ", false ); int columnCount = tokenizer.countTokens(); for( int index = 0; index < columnCount; index++ ) { if( "PID".equals( tokenizer.nextToken() ) ) { Log.d( LOG_TAG, "PID is in column #" + index ); return index; } } return -1; } } catch( IOException e ) { Log.e( LOG_TAG, "While trying to read process id", e ); return -1; } } public static int getProcessId() { if( pidColumn == -1 ) { return -1; } try { Process psProcess = Runtime.getRuntime().exec( "sh" ); OutputStream os = psProcess.getOutputStream(); InputStream is = psProcess.getInputStream(); writeLine( os, null, "ps | grep 'vpnc$'" ); writeLine( os, null, "exit" ); try { psProcess.waitFor(); } catch( InterruptedException interruptedException ) { Log.e( LOG_TAG, "While trying to read process id", interruptedException ); return 0; } String pidStringLine = readString( is, null, false ); Log.d( LOG_TAG, "Read vpnc process line as " + pidStringLine ); if( pidStringLine == null || pidStringLine.trim().length() == 0 ) { Log.d( LOG_TAG, "Attempt to read vpnc process id did not return anything" ); return -1; } else { StringTokenizer tokenizer = new StringTokenizer( pidStringLine, " ", false ); String pidString = tokenizer.nextToken(); for( int index = 0; index < pidColumn; index++ ) { pidString = tokenizer.nextToken(); } Log.d( LOG_TAG, "Read vpnc process id as " + pidString ); try { return Integer.parseInt( pidString ); } catch( NumberFormatException e ) { Log.w( LOG_TAG, "Could not parse process id of " + pidString, e ); return 0; } } } catch( IOException e ) { Log.e( LOG_TAG, "While trying to read process id", e ); return 0; } } public static String readString(InputStream is, PrintWriter logWriter, boolean block) throws IOException { if( !block && is.available() == 0 ) { //Caller doesn't want to wait for data and there isn't any available right now return null; } byte firstByte = (byte)is.read(); //wait till something becomes available int available = is.available(); byte[] characters = new byte[available + 1]; characters[0] = firstByte; is.read( characters, 1, available ); String string = new String( characters ); if( logWriter != null ) { logWriter.println( string ); } return string; } public static void writeLine(OutputStream os, PrintWriter logWriter, String value) throws IOException { String line = value + "\n"; os.write( line.getBytes() ); if( logWriter != null ) { logWriter.println( value ); } } public static void debug(String msg) { Log.d( LOG_TAG, msg ); } public static void debug(String msg, Throwable throwable) { Log.d( LOG_TAG, msg, throwable ); } public static void info(String msg) { Log.i( LOG_TAG, msg ); } public static void info(String msg, Throwable throwable) { Log.i( LOG_TAG, msg, throwable ); } public static void warn(String msg) { Log.w( LOG_TAG, msg ); } public static void warn(String msg, Throwable throwable) { Log.w( LOG_TAG, msg, throwable ); } public static void error(String msg) { Log.e( LOG_TAG, msg ); } public static void error(String msg, Throwable throwable) { Log.e( LOG_TAG, msg, throwable ); } public static void printLog(int priority, String msg) { Log.println( priority, LOG_TAG, msg ); } }
decode UTF8 to char
class Main { public static final String HEX_DIGITS = "0123456789ABCDEF"; public static char decodeUTF8(String src) { if (src == null) { throw new IllegalArgumentException("Malformed \\uxxxx encoding."); } if (!(src.startsWith("\\u") && src.length() <= 6)) { throw new IllegalArgumentException("Malformed \\uxxxx encoding."); } char[] sources = src.substring(2).toCharArray(); char res = 0; for (char nextChar : sources) { int digit = HEX_DIGITS.indexOf(Character.toUpperCase(nextChar)); res = (char) (res * 16 + digit); } return res; } }
decode UTF8 to String
class Main { public static final String HEX_DIGITS = "0123456789ABCDEF"; public static char decodeUTF8(String src) { if (src == null) { throw new IllegalArgumentException("Malformed \\uxxxx encoding."); } if (!(src.startsWith("\\u") && src.length() <= 6)) { throw new IllegalArgumentException("Malformed \\uxxxx encoding."); } char[] sources = src.substring(2).toCharArray(); char res = 0; for (char nextChar : sources) { int digit = HEX_DIGITS.indexOf(Character.toUpperCase(nextChar)); res = (char) (res * 16 + digit); } return res; } public static String decodeUTF8String(String src) { StringBuilder sb = new StringBuilder(); char[] sources = src.toCharArray(); for (int i = 0; i < sources.length; i++) { if (sources[i] == '\\' && i < sources.length - 5 && sources[i + 1] == 'u') { String utf8 = "" + sources[i++] + sources[i++] + sources[i++] + sources[i++] + sources[i++] + sources[i]; sb.append(decodeUTF8(utf8)); i = i + 5; } else { sb.append(sources[i]); } } return sb.toString(); } }
implements InputFilter
//package divestoclimb.util; import android.text.InputFilter; import android.text.Spanned; class ValidFilenameFilter implements InputFilter { public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { String valid = ""; for(int i = start; i < end; i++) { char c = source.charAt(i); // These characters are the ones Windows doesn't // like, which appears to be the most restrictive // set. http://support.microsoft.com/kb/177506 switch(c) { case '/': case '\\': case ':': c = '-'; break; case '"': c = '\''; break; case '*': case '?': case '<': case '>': case '|': c = '_'; } valid = valid.concat(String.valueOf(c)); } return valid; } }
UTF 2 GBUtil
public abstract class UTF2GBUtil { public static String covert(String src) { StringBuffer sb = new StringBuffer(); char[] chars = src.toCharArray(); for (int i = 0; i < chars.length; i++) { if (chars[i] == '\\' && chars[i + 1] == 'u') { int one = h(chars[i + 2]) * 4096; if (-1 == one) { sb.append(chars[i]); continue; } int two = h(chars[i + 3]) * 256; if (-1 == two) { sb.append(chars[i]); continue; } int three = h(chars[i + 4]) * 16; if (-1 == three) { sb.append(chars[i]); continue; } int four = h(chars[i + 5]); if (-1 == four) { sb.append(chars[i]); continue; } int count = one + two + three + four; sb.append((char) count); i += 5; continue; } sb.append(chars[i]); } return sb.toString(); } private static int h(char c) { if (c > 47 && c < 58) { return c - 48; } else if (c > 64 && c < 71) { return c - 55; } else if (c > 96 && c < 103) { return c - 87; } return -1; } }
Load UTF8 encoded file to String
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; class Utils { public static String loadFile(String fileName) throws IOException { StringBuffer buffer = new StringBuffer(); FileInputStream fis = new FileInputStream(fileName); InputStreamReader isr = new InputStreamReader(fis, "UTF8"); Reader in = new BufferedReader(isr); int ch; while ((ch = in.read()) > -1) { buffer.append((char) ch); } in.close(); return buffer.toString(); } }
UTF8 to Byte Array
//package org.bouncycastle.util; import java.io.ByteArrayOutputStream; import java.util.Vector; public final class Strings { public static String fromUTF8ByteArray(byte[] bytes) { int i = 0; int length = 0; while (i < bytes.length) { length++; if ((bytes[i] & 0xf0) == 0xf0) { // surrogate pair length++; i += 4; } else if ((bytes[i] & 0xe0) == 0xe0) { i += 3; } else if ((bytes[i] & 0xc0) == 0xc0) { i += 2; } else { i += 1; } } char[] cs = new char[length]; i = 0; length = 0; while (i < bytes.length) { char ch; if ((bytes[i] & 0xf0) == 0xf0) { int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F); int U = codePoint - 0x10000; char W1 = (char)(0xD800 | (U >> 10)); char W2 = (char)(0xDC00 | (U & 0x3FF)); cs[length++] = W1; ch = W2; i += 4; } else if ((bytes[i] & 0xe0) == 0xe0) { ch = (char)(((bytes[i] & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)); i += 3; } else if ((bytes[i] & 0xd0) == 0xd0) { ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); i += 2; } else if ((bytes[i] & 0xc0) == 0xc0) { ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f)); i += 2; } else { ch = (char)(bytes[i] & 0xff); i += 1; } cs[length++] = ch; } return new String(cs); } public static byte[] toUTF8ByteArray(String string) { return toUTF8ByteArray(string.toCharArray()); } public static byte[] toUTF8ByteArray(char[] string) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); char[] c = string; int i = 0; while (i < c.length) { char ch = c[i]; if (ch < 0x0080) { bOut.write(ch); } else if (ch < 0x0800) { bOut.write(0xc0 | (ch >> 6)); bOut.write(0x80 | (ch & 0x3f)); } // surrogate pair else if (ch >= 0xD800 && ch <= 0xDFFF) { // in error - can only happen, if the Java String class has a // bug. if (i + 1 >= c.length) { throw new IllegalStateException("invalid UTF-16 codepoint"); } char W1 = ch; ch = c[++i]; char W2 = ch; // in error - can only happen, if the Java String class has a // bug. if (W1 > 0xDBFF) { throw new IllegalStateException("invalid UTF-16 codepoint"); } int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000; bOut.write(0xf0 | (codePoint >> 18)); bOut.write(0x80 | ((codePoint >> 12) & 0x3F)); bOut.write(0x80 | ((codePoint >> 6) & 0x3F)); bOut.write(0x80 | (codePoint & 0x3F)); } else { bOut.write(0xe0 | (ch >> 12)); bOut.write(0x80 | ((ch >> 6) & 0x3F)); bOut.write(0x80 | (ch & 0x3F)); } i++; } return bOut.toByteArray(); } /** * A locale independent version of toUpperCase. * * @param string input to be converted * @return a US Ascii uppercase version */ public static String toUpperCase(String string) { boolean changed = false; char[] chars = string.toCharArray(); for (int i = 0; i != chars.length; i++) { char ch = chars[i]; if ('a' <= ch && 'z' >= ch) { changed = true; chars[i] = (char)(ch - 'a' + 'A'); } } if (changed) { return new String(chars); } return string; } /** * A locale independent version of toLowerCase. * * @param string input to be converted * @return a US ASCII lowercase version */ public static String toLowerCase(String string) { boolean changed = false; char[] chars = string.toCharArray(); for (int i = 0; i != chars.length; i++) { char ch = chars[i]; if ('A' <= ch && 'Z' >= ch) { changed = true; chars[i] = (char)(ch - 'A' + 'a'); } } if (changed) { return new String(chars); } return string; } public static byte[] toByteArray(char[] chars) { byte[] bytes = new byte[chars.length]; for (int i = 0; i != bytes.length; i++) { bytes[i] = (byte)chars[i]; } return bytes; } public static byte[] toByteArray(String string) { byte[] bytes = new byte[string.length()]; for (int i = 0; i != bytes.length; i++) { char ch = string.charAt(i); bytes[i] = (byte)ch; } return bytes; } public static String[] split(String input, char delimiter) { Vector v = new Vector(); boolean moreTokens = true; String subString; while (moreTokens) { int tokenLocation = input.indexOf(delimiter); if (tokenLocation > 0) { subString = input.substring(0, tokenLocation); v.addElement(subString); input = input.substring(tokenLocation + 1); } else { moreTokens = false; v.addElement(input); } } String[] res = new String[v.size()]; for (int i = 0; i != res.length; i++) { res[i] = (String)v.elementAt(i); } return res; } }
Parse Json string
package app.test; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import org.json.JSONObject; import org.json.JSONException; public class Test extends Activity { private static final String JSON_STRING = "{\"person\":{\"name\":\"A\",\"age\":30,\"children\":[{\"name\":\"B\",\"age\":5}," + "\"name\":\"C\",\"age\":7},{\"name\":\"D\",\"age\":9}]}}"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView line1 = (TextView)findViewById(R.id.line1); TextView line2 = (TextView)findViewById(R.id.line2); TextView line3 = (TextView)findViewById(R.id.line3); try { JSONObject person = (new JSONObject(JSON_STRING)).getJSONObject("person"); String name = person.getString("name"); line1.setText("This person's name is " + name); line2.setText(name + " is " + person.getInt("age") + " years old."); line3.setText(name + " has " + person.getJSONArray("children").length() + " children."); } catch (JSONException e) { e.printStackTrace(); } } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/line1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/line2" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/line3" android:layout_width="fill_parent" android:layout_height="wrap_content"T /> </LinearLayout>
Upload Image to Flickr with JSON
package app.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONObject; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class Test extends Activity { String API_KEY = "YOUR_API_KEY"; FlickrPhoto[] photos; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet("http://api.flickr.com/services/rest/?method=flickr.photos.search&tags=yourTag&format=json&api_key="+ API_KEY + "&per_page=5&nojsoncallback=1"); HttpResponse response; try { response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inputstream = entity.getContent(); BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(inputstream)); StringBuilder stringbuilder = new StringBuilder(); String currentline = null; try { while ((currentline = bufferedreader.readLine()) != null) { stringbuilder.append(currentline + "\n"); } } catch (IOException e) { e.printStackTrace(); } String result = stringbuilder.toString(); JSONObject thedata = new JSONObject(result); JSONObject thephotosdata = thedata.getJSONObject("photos"); JSONArray thephotodata = thephotosdata.getJSONArray("photo"); photos = new FlickrPhoto[thephotodata.length()]; for (int i = 0; i < thephotodata.length(); i++) { JSONObject photodata = thephotodata.getJSONObject(i); photos[i] = new FlickrPhoto(photodata.getString("id"), photodata.getString("owner"), photodata .getString("secret"), photodata .getString("server"), photodata .getString("title"), photodata .getString("farm")); } inputstream.close(); } } catch (Exception e) { e.printStackTrace(); } ListView listView = (ListView) this.findViewById(R.id.ListView); listView.setAdapter(new FlickrGalleryAdapter(this, photos)); } } class FlickrGalleryAdapter extends BaseAdapter { private Context context; private FlickrPhoto[] photos; LayoutInflater inflater; public FlickrGalleryAdapter(Context _context, FlickrPhoto[] _items) { context = _context; photos = _items; inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public int getCount() { return photos.length; } public Object getItem(int position) { return photos[position]; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { View photoRow = inflater.inflate(R.layout.row, null); ImageView image = (ImageView) photoRow.findViewById(R.id.ImageView); image.setImageBitmap(imageFromUrl(photos[position].makeURL())); TextView imagevideoTitle = (TextView) photoRow .findViewById(R.id.TextView); imagevideoTitle.setText(photos[position].title); return photoRow; } public Bitmap imageFromUrl(String url) { Bitmap bitmapImage; URL imageUrl = null; try { imageUrl = new URL(url); } catch (MalformedURLException e) { e.printStackTrace(); } try { HttpURLConnection httpConnection = (HttpURLConnection) imageUrl .openConnection(); httpConnection.setDoInput(true); httpConnection.connect(); InputStream is = httpConnection.getInputStream(); bitmapImage = BitmapFactory.decodeStream(is); } catch (IOException e) { e.printStackTrace(); bitmapImage = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); } return bitmapImage; } } class FlickrPhoto { String id; String owner; String secret; String server; String title; String farm; public FlickrPhoto(String _id, String _owner, String _secret, String _server, String _title, String _farm) { id = _id; owner = _owner; secret = _secret; server = _server; title = _title; farm = _farm; } public String makeURL() { return "http://farm" + farm + ".static.flickr.com/" + server + "/"+ id + "_" + secret + "_m.jpg"; } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ListView"></ListView> </LinearLayout> //row.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/ImageView" android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageView> <TextView android:text="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/TextView"></TextView> </LinearLayout>
Flickr JSON Location
package app.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONObject; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class Test extends Activity implements LocationListener { public static final String API_KEY = "YOUR_API_KEY"; FlickrPhoto[] photos; TextView tv; LocationManager lm; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView) findViewById(R.id.TextView); tv.setText("Looking Up Location"); lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000l, 500.0f, this); } public void onPause() { super.onPause(); lm.removeUpdates(this); } public void onLocationChanged(Location location) { tv.setText(location.getLatitude() + " " + location.getLongitude()); Log.v("LOCATION", "onLocationChanged: lat=" + location.getLatitude() + ", lon=" + location.getLongitude()); HttpClient httpclient = new DefaultHttpClient(); String url = "http://api.flickr.com/services/rest/?method=flickr.photos.search&tags= dog,halloween&format=json&api_key=" + API_KEY + "&per_page=5&nojsoncallback=1&accuracy=6&lat=" + location.getLatitude() + "&lon=" + location.getLongitude(); HttpGet httpget = new HttpGet(url); HttpResponse response; try { response = httpclient.execute(httpget); HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inputstream = entity.getContent(); BufferedReader bufferedreader = new BufferedReader( new InputStreamReader(inputstream)); StringBuilder stringbuilder = new StringBuilder(); String currentline = null; try { while ((currentline = bufferedreader.readLine()) != null) { stringbuilder.append(currentline + "\n"); } } catch (IOException e) { e.printStackTrace(); } String result = stringbuilder.toString(); JSONObject thedata = new JSONObject(result); JSONObject thephotosdata = thedata.getJSONObject("photos"); JSONArray thephotodata = thephotosdata.getJSONArray("photo"); photos = new FlickrPhoto[thephotodata.length()]; for (int i = 0; i < thephotodata.length(); i++) { JSONObject photodata = thephotodata.getJSONObject(i); photos[i] = new FlickrPhoto(photodata.getString("id"), photodata.getString("owner"), photodata .getString("secret"), photodata .getString("server"), photodata .getString("title"), photodata .getString("farm")); Log.v("URL", photos[i].makeURL()); } inputstream.close(); } } catch (Exception e) { e.printStackTrace(); } ListView listView = (ListView) this.findViewById(R.id.ListView); listView.setAdapter(new FlickrGalleryAdapter(this, photos)); } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } } class FlickrGalleryAdapter extends BaseAdapter { private Context context; private FlickrPhoto[] photos; LayoutInflater inflater; public FlickrGalleryAdapter(Context _context, FlickrPhoto[] _items) { context = _context; photos = _items; inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public int getCount() { return photos.length; } public Object getItem(int position) { return photos[position]; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { View videoRow = inflater.inflate(R.layout.row, null); ImageView image = (ImageView) videoRow.findViewById(R.id.ImageView); image.setImageBitmap(imageFromUrl(photos[position].makeURL())); TextView videoTitle = (TextView) videoRow .findViewById(R.id.TextView); videoTitle.setText(photos[position].title); return videoRow; } public Bitmap imageFromUrl(String url) { Bitmap bitmapImage; URL imageUrl = null; try { imageUrl = new URL(url); } catch (MalformedURLException e) { e.printStackTrace(); } try { HttpURLConnection httpConnection = (HttpURLConnection) imageUrl .openConnection(); httpConnection.setDoInput(true); httpConnection.connect(); int length = httpConnection.getContentLength(); InputStream is = httpConnection.getInputStream(); bitmapImage = BitmapFactory.decodeStream(is); } catch (IOException e) { e.printStackTrace(); bitmapImage = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); } return bitmapImage; } } class FlickrPhoto { String id; String owner; String secret; String server; String title; String farm; public FlickrPhoto(String _id, String _owner, String _secret, String _server, String _title, String _farm) { id = _id; owner = _owner; secret = _secret; server = _server; title = _title; farm = _farm; } public String makeURL() { return "http://farm" + farm + ".static.flickr.com/" + server + "/" + id + "_" + secret + "_m.jpg"; // http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstzb].jpg } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ListView"></ListView> </LinearLayout>
Using JSON
package app.test; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class Test extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String JSONData = "" + "{\"results\":{\"aname\":\"value\", \"anumber\":1234, \"aboolean\":false, " + "\"anarray\":[{\"arrayelement\":\"Array Element 1\"}, {\"arrayelement\":\"Array Element 2\"}]}}"; try { JSONObject overallJSONObject = new JSONObject(JSONData); Log.v("SIMPLEJSON", overallJSONObject.toString()); JSONObject resultsObject = overallJSONObject .getJSONObject("results"); Log.v("SIMPLEJSON", resultsObject.toString()); String aname = resultsObject.getString("aname"); Log.v("SIMPLEJSON", aname); int anumber = resultsObject.getInt("anumber"); Log.v("SIMPLEJSON", "" + anumber); boolean aboolean = resultsObject.getBoolean("aboolean"); Log.v("SIMPLEJSON", "" + aboolean); JSONArray anarray = resultsObject.getJSONArray("anarray"); for (int i = 0; i < anarray.length(); i++) { JSONObject arrayElementObject = anarray.getJSONObject(i); String arrayelement = arrayElementObject .getString("arrayelement"); Log.v("SIMPLEJSON", arrayelement); } } catch (JSONException e) { e.printStackTrace(); } } }
Json Client
//package com.mediaportal.ampdroid.api; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HTTP; import android.util.Log; public class JsonClient { public static int DEFAULT_TIMEOUT = 5000; public enum RequestMethod { GET, POST } private ArrayList<NameValuePair> headers; private String url; private String mUser; private String mPass; private boolean mUseAuth; private int responseCode; private String message; private String response; public String getResponse() { return response; } public String getErrorMessage() { return message; } public int getResponseCode() { return responseCode; } public JsonClient(String url, String _user, String _pass, boolean _useAuth) { this.url = url; mUser = _user; mPass = _pass; mUseAuth = _useAuth; headers = new ArrayList<NameValuePair>(); } // public JsonClient(String url) { // this(url, null, null, false); // } public void AddHeader(String name, String value) { headers.add(new BasicNameValuePair(name, value)); } public String Execute(String methodName) { return Execute(methodName, DEFAULT_TIMEOUT, RequestMethod.GET); } public String Execute(String methodName, int _timeout) { return Execute(methodName, _timeout, RequestMethod.GET); } public String Execute(String methodName, int _timeout, NameValuePair... _params) { return Execute(methodName, _timeout, RequestMethod.GET, _params); } public String Execute(String methodName, NameValuePair... _params) { return Execute(methodName, RequestMethod.GET, _params); } public String Execute(String methodName, RequestMethod methodType, NameValuePair... _params) { try { return DoExecute(methodName, DEFAULT_TIMEOUT, methodType, _params); } catch (Exception e) { return null; } } public String Execute(String methodName, int _timeout, RequestMethod methodType, NameValuePair... _params) { try { return DoExecute(methodName, _timeout, methodType, _params); } catch (Exception e) { return null; } } private String DoExecute(String methodName, int _timeout, RequestMethod methodType, NameValuePair... _params) throws Exception { switch (methodType) { case GET: { // add parameters String combinedParams = ""; if (_params.length > 0) { combinedParams += "?"; for (NameValuePair p : _params) { String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(), "UTF-8"); if (combinedParams.length() > 1) { combinedParams += "&" + paramString; } else { combinedParams += paramString; } } } HttpGet request = new HttpGet(url + "/" + methodName + combinedParams); // add headers for (NameValuePair h : headers) { request.addHeader(h.getName(), h.getValue()); } return executeRequest(request, _timeout, url); } case POST: { HttpPost request = new HttpPost(url + "/" + methodName); // add headers for (NameValuePair h : headers) { request.addHeader(h.getName(), h.getValue()); } if (_params.length > 0) { List<NameValuePair> paramList = new ArrayList<NameValuePair>(); for (NameValuePair p : _params) { paramList.add(p); } request.setEntity(new UrlEncodedFormEntity(paramList, HTTP.UTF_8)); } return executeRequest(request, _timeout, url); } default: return null; } } private String executeRequest(HttpUriRequest request, int _timeout, String url) { HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, _timeout); HttpConnectionParams.setSoTimeout(httpParameters, _timeout); HttpConnectionParams.setTcpNoDelay(httpParameters, true); DefaultHttpClient client = new DefaultHttpClient(httpParameters); request.setHeader("User-Agent", "USER_AGENT"); if (mUseAuth) { CredentialsProvider credProvider = new BasicCredentialsProvider(); credProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), new UsernamePasswordCredentials(mUser, mPass)); client.setCredentialsProvider(credProvider); } HttpResponse httpResponse; try { httpResponse = client.execute(request); responseCode = httpResponse.getStatusLine().getStatusCode(); message = httpResponse.getStatusLine().getReasonPhrase(); HttpEntity entity = httpResponse.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); response = convertStreamToString(instream); // Closing the input stream will trigger connection release instream.close(); return response; } } catch (ClientProtocolException e) { client.getConnectionManager().shutdown(); e.printStackTrace(); } catch (IOException e) { client.getConnectionManager().shutdown(); e.printStackTrace(); } return null; } private static String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } }
Get List From Json Object
//package com.xiledsystems.AlternateJavaBridgelib; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * * This was mostly copied from com.google.devtools.simple.runtime.components.util.JsonUtil. It has been modified to not * use the FString, or Yaillist classes (so Kawa library not needed) * * - Ryan Bis - www.xiledsystems.com * */ class JsonUtil2 { /** * Prevent instantiation. */ private JsonUtil2() { } /** * Returns a list of String objects from a JSONArray. This * does not do any kind of recursive unpacking of the array. * Thus, if the array includes other JSON arrays or JSON objects * their string representation will be a single item in the * returned list. * * @param jArray The JSONArray to convert. * @return A List of the String representation of each item in * the JSON array. * @throws JSONException if an element of jArray cannot be * converted to a String. */ public static List<String> getStringListFromJsonArray(JSONArray jArray) throws JSONException { List<String> returnList = new ArrayList<String>(); for (int i = 0; i < jArray.length(); i++) { String val = jArray.getString(i); returnList.add(val); } return returnList; } /** * Returns a Java Object list of a JSONArray with each item in * the array converted using convertJsonItem(). * * @param jArray The JSONArray to convert. * @return A List of Strings and more Object lists. * @throws JSONException if an element in jArray cannot be * converted properly. */ public static List<Object> getListFromJsonArray(JSONArray jArray) throws JSONException { List<Object> returnList = new ArrayList<Object>(); for (int i = 0; i < jArray.length(); i++) { returnList.add(convertJsonItem(jArray.get(i))); } return returnList; } /** * Returns a list containing one two item list per key in jObject. * Each two item list has the key String as its first element and * the result of calling convertJsonItem() on its value as the * second element. The sub-lists in the returned list will appear * in alphabetical order by key. * * @param jObject The JSONObject to convert. * @return A list of two item lists: [String key, Object value]. * @throws JSONException if an element in jObject cannot be * converted properly. */ @SuppressWarnings("unchecked") public static List<Object> getListFromJsonObject(JSONObject jObject) throws JSONException { List<Object> returnList = new ArrayList<Object>(); Iterator<String> keys = jObject.keys(); List<String> keysList = new ArrayList<String>(); while (keys.hasNext()) { keysList.add(keys.next()); } Collections.sort(keysList); for (String key : keysList) { List<Object> nestedList = new ArrayList<Object>(); nestedList.add(key); nestedList.add(convertJsonItem(jObject.get(key))); returnList.add(nestedList); } return returnList; } /** * Returns a Java object representation of objects that are * encountered inside of JSON created using the org.json package. * JSON arrays and objects are transformed into their list * representations using getListFromJsonArray and * getListFromJsonObject respectively. * * Java Boolean values and the Strings "true" and "false" (case * insensitive) are inserted as Booleans. Java Numbers are * inserted without modification and all other values are inserted * as their toString(). value. * * @param o An item in a JSON array or JSON object to convert. * @return A Java Object representing o or the String "null" * if o is null. * @throws JSONException if o fails to parse. */ public static Object convertJsonItem(Object o) throws JSONException { if (o == null) { return "null"; } if (o instanceof JSONObject) { return getListFromJsonObject((JSONObject) o); } if (o instanceof JSONArray) { return getListFromJsonArray((JSONArray) o); } if (o.equals(Boolean.FALSE) || (o instanceof String && ((String) o).equalsIgnoreCase("false"))) { return false; } if (o.equals(Boolean.TRUE) || (o instanceof String && ((String) o).equalsIgnoreCase("true"))) { return true; } if (o instanceof Number) { return o; } return o.toString(); } public static String getJsonRepresentation(Object value) throws JSONException { if (value == null || value.equals(null)) { return "null"; } /* * This has been commented out to prevent the need for the Kawa library. Do NOT use Fstring * or YailList in any of your data, otherwise this conversion won't work. * if (value instanceof FString) { return JSONObject.quote(value.toString()); } if (value instanceof YailList) { return ((YailList) value).toJSONString(); } */ if (value instanceof Number) { return JSONObject.numberToString((Number) value); } if (value instanceof Boolean) { return value.toString(); } if (value.getClass().isArray()) { StringBuilder sb = new StringBuilder(); sb.append("["); String separator = ""; for (Object o: (Object[]) value) { sb.append(separator).append(getJsonRepresentation(o)); separator = ","; } sb.append("]"); return sb.toString(); } if (value instanceof String) { return value.toString(); } return JSONObject.quote(value.toString()); } public static Object getObjectFromJson(String jsonString) throws JSONException { final Object value = (new JSONTokener(jsonString)).nextValue(); // Note that the JSONTokener may return a value equals() to null. if (value == null || value.equals(null)) { return null; } else if ((value instanceof String) || (value instanceof Number) || (value instanceof Boolean)) { return value; } else if (value instanceof JSONArray) { return getListFromJsonArray((JSONArray)value); } else if (value instanceof JSONObject) { return getListFromJsonObject((JSONObject)value); } throw new JSONException("Invalid JSON string."); } }
Create JSONObject
import java.io.File; import org.json.JSONObject; import org.json.JSONArray; import android.os.Environment; import android.util.Log; class FileUtil { public static JSONObject GetDirJSON(File dir) { JSONObject jsonObj=new JSONObject(); try { jsonObj.put("name", dir.getName()); jsonObj.put("directory", dir.isDirectory()); jsonObj.put("url", dir.getAbsolutePath()); if(dir.equals(Environment.getExternalStorageDirectory())) { jsonObj.put("root", true); } else { jsonObj.put("root", false); jsonObj.put("parent", dir.getParent()); } if(dir.isDirectory()) { File[] subFs=dir.listFiles(); JSONArray array=new JSONArray(); for(int i=0;i<subFs.length;i++) array.put(subFs[i].getName()); jsonObj.put("sub", array); } }catch(Exception e) { Log.d("Exec", e.getMessage()); } Log.d("FileUtil",jsonObj.toString()); return jsonObj; } }
JSON: Get node value,
//package com.omar.labs.tamtamy.JSON; import java.net.URLEncoder; import java.util.ArrayList; public class JSONUtility { public static String getNodeValue(String json, String propName){ String tmp = null; int match = json.indexOf(propName+":"); if(match!=-1){ int start = match + (propName+":").length(); int stop = json.indexOf(",", start); try{ if(stop>0 && stop-start>1 && json.charAt(start)=='"') tmp = json.substring(start+1, stop-1); else if(stop>0) tmp = json.substring(start, stop); else tmp = json.substring(start+1); }catch (Exception ex){ } if(tmp.indexOf("\"}")!=-1) tmp = tmp.substring(0, tmp.length()-2); } return tmp; } public static ArrayList getNodesValue(String json){ if(json.startsWith("\"")) json = json.substring(1); if(json.endsWith("\"")) json = json.substring(0, json.length()-1); if(json.startsWith("[")) json = json.substring(1); if(json.endsWith("]")) json = json.substring(0, json.length()-1); String[] tmp = json.split(","); ArrayList<String> tmpArr = new ArrayList<String>(); for(int t=0; t<tmp.length; t++){ String element = tmp[t]; if(element.startsWith("\"")) element = element.substring(1); if(element.endsWith("\"")) element = element.substring(0, element.length()-1); tmpArr.add(element); } return tmpArr; } /* public static String getNodeValueWithList(String json, String propName){ String tmp = null; int start = json.indexOf(propName+":") + (propName+":").length(); int stop = json.indexOf("]", start); try{ if(stop>0) tmp = json.substring(start, stop); else tmp = json.substring(start); }catch (Exception ex){ } if(tmp.indexOf("\"")!=-1) tmp = tmp.substring(1, tmp.length()-1); return tmp; } */ public static ArrayList<String> getNodeValueWithList(String json, String propName){ ArrayList<String> tmpA = new ArrayList<String>(); String tmp = null; int start = json.indexOf(propName+":") + (propName+":").length(); int stop = json.indexOf("]", start); int stop1 = json.lastIndexOf("]"); try{ if (stop>0 && stop == stop1){ tmp = json.substring(start+1, stop); }else if(stop1>0){ tmp = json.substring(start+1, stop1); }else{ tmp = json.substring(start, json.length()-1); } }catch (Exception ex){ ex.printStackTrace(); } //if(tmp.indexOf("\"")!=-1) // tmp = tmp.substring(1, tmp.length()); String[] items = null; if(tmp.indexOf("},{")==-1 && !propName.equals("\"list\"")) items = tmp.split(","); else items = tmp.split("\\},\\{"); for(int i=0; i<items.length; i++){ tmpA.add(items[i]); } return tmpA; } }
Data type conversion for JSON
//package org.beryl.util; import org.json.JSONException; import org.json.JSONObject; class TryParse { public static int toInt(String value, int defaultValue) { int result; try { result = Integer.parseInt(value); } catch(NumberFormatException e) { result = defaultValue; } return result; } public static String toString(JSONObject json, String name, String defaultValue) { String result; try { result = json.getString(name); } catch(JSONException e) { result = defaultValue; } return result; } public static int toInt(JSONObject json, String name, int defaultValue) { int result; try { result = json.getInt(name); } catch(JSONException e) { result = defaultValue; } return result; } public static boolean toBoolean(JSONObject json, String name, boolean defaultValue) { boolean result; try { result = json.getBoolean(name); } catch(JSONException e) { result = defaultValue; } return result; } }
Object to JSON
//package org.comet4j.core.util; import java.math.BigDecimal; import java.math.BigInteger; import java.util.List; import java.util.Map; import java.util.Set; /** * ????????json???,??????? * @author xiaojinghai * @date 2011-7-18 */ public class JSONUtil { public static String object2json(Object obj) { StringBuilder json = new StringBuilder(); if (obj == null) { json.append("\"\""); } else if (obj instanceof String || obj instanceof Integer || obj instanceof Float || obj instanceof Boolean || obj instanceof Short || obj instanceof Double || obj instanceof Long || obj instanceof BigDecimal || obj instanceof BigInteger || obj instanceof Byte) { json.append("\"").append(string2json(obj.toString())).append("\""); } else if (obj instanceof Object[]) { json.append(array2json((Object[]) obj)); } else if (obj instanceof List) { json.append(list2json((List<?>) obj)); } else if (obj instanceof Map) { json.append(map2json((Map<?, ?>) obj)); } else if (obj instanceof Set) { json.append(set2json((Set<?>) obj)); } return json.toString(); } public static String list2json(List<?> list) { StringBuilder json = new StringBuilder(); json.append("["); if (list != null && list.size() > 0) { for (Object obj : list) { json.append(object2json(obj)); json.append(","); } json.setCharAt(json.length() - 1, ']'); } else { json.append("]"); } return json.toString(); } public static String array2json(Object[] array) { StringBuilder json = new StringBuilder(); json.append("["); if (array != null && array.length > 0) { for (Object obj : array) { json.append(object2json(obj)); json.append(","); } json.setCharAt(json.length() - 1, ']'); } else { json.append("]"); } return json.toString(); } public static String map2json(Map<?, ?> map) { StringBuilder json = new StringBuilder(); json.append("{"); if (map != null && map.size() > 0) { for (Object key : map.keySet()) { json.append(object2json(key)); json.append(":"); json.append(object2json(map.get(key))); json.append(","); } json.setCharAt(json.length() - 1, '}'); } else { json.append("}"); } return json.toString(); } public static String set2json(Set<?> set) { StringBuilder json = new StringBuilder(); json.append("["); if (set != null && set.size() > 0) { for (Object obj : set) { json.append(object2json(obj)); json.append(","); } json.setCharAt(json.length() - 1, ']'); } else { json.append("]"); } return json.toString(); } public static String string2json(String s) { if (s == null) return ""; StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); switch (ch) { case '"': sb.append("\\\""); break; case '\\': sb.append("\\\\"); break; case '\b': sb.append("\\b"); break; case '\f': sb.append("\\f"); break; case '\n': sb.append("\\n"); break; case '\r': sb.append("\\r"); break; case '\t': sb.append("\\t"); break; case '/': sb.append("\\/"); break; default: if (ch >= '\u0000' && ch <= '\u001F') { String ss = Integer.toHexString(ch); sb.append("\\u"); for (int k = 0; k < 4 - ss.length(); k++) { sb.append('0'); } sb.append(ss.toUpperCase()); } else { sb.append(ch); } } } return sb.toString(); } }
Wikidictionary
package com.example.android.simplewiktionary; import com.example.android.simplewiktionary.SimpleWikiHelper.ApiException; import com.example.android.simplewiktionary.SimpleWikiHelper.ParseException; import android.app.PendingIntent; import android.app.Service; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.IBinder; import android.text.format.Time; import android.util.Log; import android.widget.RemoteViews; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; class SimpleWikiHelper { private static final String TAG = "SimpleWikiHelper"; public static final String WORD_OF_DAY_REGEX = "(?s)\\{\\{wotd\\|(.+?)\\|(.+?)\\|([^#\\|]+).*?\\}\\}"; private static final String WIKTIONARY_PAGE = "http://en.wiktionary.org/w/api.php?action=query&prop=revisions&titles=%s&" + "rvprop=content&format=json%s"; /** * Partial URL to append to {@link #WIKTIONARY_PAGE} when you want to expand * any templates found on the requested page. This is useful when browsing * full entries, but may use more network bandwidth. */ private static final String WIKTIONARY_EXPAND_TEMPLATES = "&rvexpandtemplates=true"; /** * {@link StatusLine} HTTP status code when no server error has occurred. */ private static final int HTTP_STATUS_OK = 200; /** * Shared buffer used by {@link #getUrlContent(String)} when reading results * from an API request. */ private static byte[] sBuffer = new byte[512]; /** * User-agent string to use when making requests. Should be filled using * {@link #prepareUserAgent(Context)} before making any other calls. */ private static String sUserAgent = null; /** * Thrown when there were problems contacting the remote API server, either * because of a network error, or the server returned a bad status code. */ public static class ApiException extends Exception { public ApiException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); } public ApiException(String detailMessage) { super(detailMessage); } } public static class ParseException extends Exception { public ParseException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); } } public static void prepareUserAgent(Context context) { try { // Read package name and version number from manifest PackageManager manager = context.getPackageManager(); PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0); sUserAgent = String.format(context.getString(R.string.template_user_agent), info.packageName, info.versionName); } catch(NameNotFoundException e) { Log.e(TAG, "Couldn't find package information in PackageManager", e); } } public static String getPageContent(String title, boolean expandTemplates) throws ApiException, ParseException { // Encode page title and expand templates if requested String encodedTitle = Uri.encode(title); String expandClause = expandTemplates ? WIKTIONARY_EXPAND_TEMPLATES : ""; // Query the API for content String content = getUrlContent(String.format(WIKTIONARY_PAGE, encodedTitle, expandClause)); try { // Drill into the JSON response to find the content body JSONObject response = new JSONObject(content); JSONObject query = response.getJSONObject("query"); JSONObject pages = query.getJSONObject("pages"); JSONObject page = pages.getJSONObject((String) pages.keys().next()); JSONArray revisions = page.getJSONArray("revisions"); JSONObject revision = revisions.getJSONObject(0); return revision.getString("*"); } catch (JSONException e) { throw new ParseException("Problem parsing API response", e); } } protected static synchronized String getUrlContent(String url) throws ApiException { if (sUserAgent == null) { throw new ApiException("User-Agent string must be prepared"); } // Create client and set our specific user-agent string HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(url); request.setHeader("User-Agent", sUserAgent); try { HttpResponse response = client.execute(request); // Check if server response is valid StatusLine status = response.getStatusLine(); if (status.getStatusCode() != HTTP_STATUS_OK) { throw new ApiException("Invalid response from server: " + status.toString()); } // Pull content stream from response HttpEntity entity = response.getEntity(); InputStream inputStream = entity.getContent(); ByteArrayOutputStream content = new ByteArrayOutputStream(); // Read response into a buffered stream int readBytes = 0; while ((readBytes = inputStream.read(sBuffer)) != -1) { content.write(sBuffer, 0, readBytes); } // Return result from buffered stream return new String(content.toByteArray()); } catch (IOException e) { throw new ApiException("Problem communicating with API", e); } } } /** * Define a simple widget that shows the Wiktionary "Word of the day." To build * an update we spawn a background {@link Service} to perform the API queries. */ public class WordWidget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // To prevent any ANR timeouts, we perform the update in a service context.startService(new Intent(context, UpdateService.class)); } public static class UpdateService extends Service { @Override public void onStart(Intent intent, int startId) { // Build the widget update for today RemoteViews updateViews = buildUpdate(this); // Push update for this widget to the home screen ComponentName thisWidget = new ComponentName(this, WordWidget.class); AppWidgetManager manager = AppWidgetManager.getInstance(this); manager.updateAppWidget(thisWidget, updateViews); } /** * Build a widget update to show the current Wiktionary * "Word of the day." Will block until the online API returns. */ public RemoteViews buildUpdate(Context context) { // Pick out month names from resources Resources res = context.getResources(); String[] monthNames = res.getStringArray(R.array.month_names); // Find current month and day Time today = new Time(); today.setToNow(); // Build today's page title, like "Wiktionary:Word of the day/March 21" String pageName = res.getString(R.string.template_wotd_title, monthNames[today.month], today.monthDay); RemoteViews updateViews = null; String pageContent = ""; try { // Try querying the Wiktionary API for today's word SimpleWikiHelper.prepareUserAgent(context); pageContent = SimpleWikiHelper.getPageContent(pageName, false); } catch (ApiException e) { Log.e("WordWidget", "Couldn't contact API", e); } catch (ParseException e) { Log.e("WordWidget", "Couldn't parse API response", e); } // Use a regular expression to parse out the word and its definition Pattern pattern = Pattern.compile(SimpleWikiHelper.WORD_OF_DAY_REGEX); Matcher matcher = pattern.matcher(pageContent); if (matcher.find()) { // Build an update that holds the updated widget contents updateViews = new RemoteViews(context.getPackageName(), R.layout.widget_word); String wordTitle = matcher.group(1); updateViews.setTextViewText(R.id.word_title, wordTitle); updateViews.setTextViewText(R.id.word_type, matcher.group(2)); updateViews.setTextViewText(R.id.definition, matcher.group(3).trim()); // When user clicks on widget, launch to Wiktionary definition page String definePage = res.getString(R.string.template_define_url, Uri.encode(wordTitle)); Intent defineIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(definePage)); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0 /* no requestCode */, defineIntent, 0 /* no flags */); updateViews.setOnClickPendingIntent(R.id.widget, pendingIntent); } else { // Didn't find word of day, so show error message updateViews = new RemoteViews(context.getPackageName(), R.layout.widget_message); CharSequence errorMessage = context.getText(R.string.widget_error); updateViews.setTextViewText(R.id.message, errorMessage); } return updateViews; } @Override public IBinder onBind(Intent intent) { // We don't need to bind to this service return null; } } } // //res\layout\widget_message.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" style="@style/WidgetBackground"> <TextView android:id="@+id/message" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dip" android:padding="10dip" android:gravity="center" android:text="@string/widget_loading" style="@style/Text.Loading" /> </LinearLayout> //res\layout\widget_word.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="true" style="@style/WidgetBackground"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:src="@drawable/star_logo" /> <TextView android:id="@+id/word_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="14dip" android:layout_marginBottom="1dip" android:includeFontPadding="false" android:singleLine="true" android:ellipsize="end" style="@style/Text.WordTitle" /> <TextView android:id="@+id/word_type" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_toRightOf="@id/word_title" android:layout_toLeftOf="@id/icon" android:layout_alignBaseline="@id/word_title" android:paddingLeft="4dip" android:includeFontPadding="false" android:singleLine="true" android:ellipsize="end" style="@style/Text.WordType" /> <TextView android:id="@+id/bullet" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/word_title" android:paddingRight="4dip" android:includeFontPadding="false" android:singleLine="true" style="@style/BulletPoint" /> <TextView android:id="@+id/definition" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/word_title" android:layout_toRightOf="@id/bullet" android:paddingRight="5dip" android:paddingBottom="4dip" android:includeFontPadding="false" android:lineSpacingMultiplier="0.9" android:maxLines="4" android:fadingEdge="vertical" style="@style/Text.Definition" /> </RelativeLayout> // //res\values\strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Wiktionary simple example</string> <string name="template_user_agent" translatable="false">"%1$s/%2$s (Linux; Android)"</string> <string name="template_wotd_title">"Wiktionary:Word of the day/%1$s %2$s"</string> <string name="template_define_url" translatable="false">"http://en.wiktionary.org/wiki/%s"</string> <string name="widget_name">Wiktionary simple</string> <string name="widget_loading">Loading word\nof day\u2026</string> <string name="widget_error">No word of\nday found</string> <string-array name="month_names"> <item>January</item> <item>February</item> <item>March</item> <item>April</item> <item>May</item> <item>June</item> <item>July</item> <item>August</item> <item>September</item> <item>October</item> <item>November</item> <item>December</item> </string-array> </resources> //res\values\styles.xml <?xml version="1.0" encoding="utf-8"?> <resources> <style name="WidgetBackground"> <item name="android:background">@drawable/widget_bg</item> </style> <style name="BulletPoint"> <item name="android:textSize">13sp</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text" /> <style name="Text.Loading"> <item name="android:textSize">14sp</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text.WordTitle"> <item name="android:textSize">16sp</item> <item name="android:textStyle">bold</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text.WordType"> <item name="android:textSize">14sp</item> <item name="android:textStyle">italic</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text.Definition"> <item name="android:textSize">13sp</item> <item name="android:textColor">@android:color/black</item> </style> </resources> // //res\xml\widget_word.xml <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="146dip" android:minHeight="72dip" android:updatePeriodMillis="86400000" android:initialLayout="@layout/widget_message" />
Browse through Wiktionary content
package com.example.android.wiktionary; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.net.Uri; import android.text.TextUtils; import android.webkit.WebView; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Extended version of {@link SimpleWikiHelper}. This version adds methods to * pick a random word, and to format generic wiki-style text into HTML. */ public class ExtendedWikiHelper extends SimpleWikiHelper { /** * HTML style sheet to include with any {@link #formatWikiText(String)} HTML * results. It formats nicely for a mobile screen, and hides some content * boxes to keep things tidy. */ private static final String STYLE_SHEET = "<style>h2 {font-size:1.2em;font-weight:normal;} " + "a {color:#6688cc;} ol {padding-left:1.5em;} blockquote {margin-left:0em;} " + ".interProject, .noprint {display:none;} " + "li, blockquote {margin-top:0.5em;margin-bottom:0.5em;}</style>"; /** * Pattern of section titles we're interested in showing. This trims out * extra sections that can clutter things up on a mobile screen. */ private static final Pattern sValidSections = Pattern.compile("(verb|noun|adjective|pronoun|interjection)", Pattern.CASE_INSENSITIVE); /** * Pattern that can be used to split a returned wiki page into its various * sections. Doesn't treat children sections differently. */ private static final Pattern sSectionSplit = Pattern.compile("^=+(.+?)=+.+?(?=^=)", Pattern.MULTILINE | Pattern.DOTALL); /** * When picking random words in {@link #getRandomWord()}, we sometimes * encounter special articles or templates. This pattern ignores any words * like those, usually because they have ":" or other punctuation. */ private static final Pattern sInvalidWord = Pattern.compile("[^A-Za-z0-9 ]"); /** * {@link Uri} authority to use when creating internal links. */ public static final String WIKI_AUTHORITY = "wiktionary"; /** * {@link Uri} host to use when creating internal links. */ public static final String WIKI_LOOKUP_HOST = "lookup"; /** * Mime-type to use when showing parsed results in a {@link WebView}. */ public static final String MIME_TYPE = "text/html"; /** * Encoding to use when showing parsed results in a {@link WebView}. */ public static final String ENCODING = "utf-8"; /** * {@link Uri} to use when requesting a random page. */ private static final String WIKTIONARY_RANDOM = "http://en.wiktionary.org/w/api.php?action=query&list=random&format=json"; /** * Fake section to insert at the bottom of a wiki response before parsing. * This ensures that {@link #sSectionSplit} will always catch the last * section, as it uses section headers in its searching. */ private static final String STUB_SECTION = "\n=Stub section="; /** * Number of times to try finding a random word in {@link #getRandomWord()}. * These failures are usually when the found word fails the * {@link #sInvalidWord} test, or when a network error happens. */ private static final int RANDOM_TRIES = 3; /** * Internal class to hold a wiki formatting rule. It's mostly a wrapper to * simplify {@link Matcher#replaceAll(String)}. */ private static class FormatRule { private Pattern mPattern; private String mReplaceWith; /** * Create a wiki formatting rule. * * @param pattern Search string to be compiled into a {@link Pattern}. * @param replaceWith String to replace any found occurances with. This * string can also include back-references into the given * pattern. * @param flags Any flags to compile the {@link Pattern} with. */ public FormatRule(String pattern, String replaceWith, int flags) { mPattern = Pattern.compile(pattern, flags); mReplaceWith = replaceWith; } /** * Create a wiki formatting rule. * * @param pattern Search string to be compiled into a {@link Pattern}. * @param replaceWith String to replace any found occurances with. This * string can also include back-references into the given * pattern. */ public FormatRule(String pattern, String replaceWith) { this(pattern, replaceWith, 0); } /** * Apply this formatting rule to the given input string, and return the * resulting new string. */ public String apply(String input) { Matcher m = mPattern.matcher(input); return m.replaceAll(mReplaceWith); } } /** * List of internal formatting rules to apply when parsing wiki text. These * include indenting various bullets, apply italic and bold styles, and * adding internal linking. */ private static final List<FormatRule> sFormatRules = new ArrayList<FormatRule>(); static { // Format header blocks and wrap outside content in ordered list sFormatRules.add(new FormatRule("^=+(.+?)=+", "</ol><h2>$1</h2><ol>", Pattern.MULTILINE)); // Indent quoted blocks, handle ordered and bullet lists sFormatRules.add(new FormatRule("^#+\\*?:(.+?)$", "<blockquote>$1</blockquote>", Pattern.MULTILINE)); sFormatRules.add(new FormatRule("^#+:?\\*(.+?)$", "<ul><li>$1</li></ul>", Pattern.MULTILINE)); sFormatRules.add(new FormatRule("^#+(.+?)$", "<li>$1</li>", Pattern.MULTILINE)); // Add internal links sFormatRules.add(new FormatRule("\\[\\[([^:\\|\\]]+)\\]\\]", String.format("<a href=\"%s://%s/$1\">$1</a>", WIKI_AUTHORITY, WIKI_LOOKUP_HOST))); sFormatRules.add(new FormatRule("\\[\\[([^:\\|\\]]+)\\|([^\\]]+)\\]\\]", String.format("<a href=\"%s://%s/$1\">$2</a>", WIKI_AUTHORITY, WIKI_LOOKUP_HOST))); // Add bold and italic formatting sFormatRules.add(new FormatRule("'''(.+?)'''", "<b>$1</b>")); sFormatRules.add(new FormatRule("([^'])''([^'].*?[^'])''([^'])", "$1<i>$2</i>$3")); // Remove odd category links and convert remaining links into flat text sFormatRules.add(new FormatRule("(\\{+.+?\\}+|\\[\\[[^:]+:[^\\\\|\\]]+\\]\\]|" + "\\[http.+?\\]|\\[\\[Category:.+?\\]\\])", "", Pattern.MULTILINE | Pattern.DOTALL)); sFormatRules.add(new FormatRule("\\[\\[([^\\|\\]]+\\|)?(.+?)\\]\\]", "$2", Pattern.MULTILINE)); } public static String getRandomWord() throws ApiException, ParseException { // Keep trying a few times until we find a valid word int tries = 0; while (tries++ < RANDOM_TRIES) { // Query the API for a random word String content = getUrlContent(WIKTIONARY_RANDOM); try { // Drill into the JSON response to find the returned word JSONObject response = new JSONObject(content); JSONObject query = response.getJSONObject("query"); JSONArray random = query.getJSONArray("random"); JSONObject word = random.getJSONObject(0); String foundWord = word.getString("title"); // If we found an actual word, and it wasn't rejected by our invalid // filter, then accept and return it. if (foundWord != null && !sInvalidWord.matcher(foundWord).find()) { return foundWord; } } catch (JSONException e) { throw new ParseException("Problem parsing API response", e); } } // No valid word found in number of tries, so return null return null; } /** * Format the given wiki-style text into formatted HTML content. This will * create headers, lists, internal links, and style formatting for any wiki * markup found. * * @param wikiText The raw text to format, with wiki-markup included. * @return HTML formatted content, ready for display in {@link WebView}. */ public static String formatWikiText(String wikiText) { if (wikiText == null) { return null; } // Insert a fake last section into the document so our section splitter // can correctly catch the last section. wikiText = wikiText.concat(STUB_SECTION); // Read through all sections, keeping only those matching our filter, // and only including the first entry for each title. HashSet<String> foundSections = new HashSet<String>(); StringBuilder builder = new StringBuilder(); Matcher sectionMatcher = sSectionSplit.matcher(wikiText); while (sectionMatcher.find()) { String title = sectionMatcher.group(1); if (!foundSections.contains(title) && sValidSections.matcher(title).matches()) { String sectionContent = sectionMatcher.group(); foundSections.add(title); builder.append(sectionContent); } } // Our new wiki text is the selected sections only wikiText = builder.toString(); // Apply all formatting rules, in order, to the wiki text for (FormatRule rule : sFormatRules) { wikiText = rule.apply(wikiText); } // Return the resulting HTML with style sheet, if we have content left if (!TextUtils.isEmpty(wikiText)) { return STYLE_SHEET + wikiText; } else { return null; } } } //src\com\example\android\wiktionary\LookupActivity.java package com.example.android.wiktionary; import com.example.android.wiktionary.SimpleWikiHelper.ApiException; import com.example.android.wiktionary.SimpleWikiHelper.ParseException; import android.app.Activity; import android.app.AlertDialog; import android.app.SearchManager; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.SystemClock; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Animation.AnimationListener; import android.webkit.WebView; import android.widget.ProgressBar; import android.widget.TextView; import java.util.Stack; /** * Activity that lets users browse through Wiktionary content. This is just the * user interface, and all API communication and parsing is handled in * {@link ExtendedWikiHelper}. */ public class LookupActivity extends Activity implements AnimationListener { private static final String TAG = "LookupActivity"; private View mTitleBar; private TextView mTitle; private ProgressBar mProgress; private WebView mWebView; private Animation mSlideIn; private Animation mSlideOut; /** * History stack of previous words browsed in this session. This is * referenced when the user taps the "back" key, to possibly intercept and * show the last-visited entry, instead of closing the activity. */ private Stack<String> mHistory = new Stack<String>(); private String mEntryTitle; /** * Keep track of last time user tapped "back" hard key. When pressed more * than once within {@link #BACK_THRESHOLD}, we treat let the back key fall * through and close the app. */ private long mLastPress = -1; private static final long BACK_THRESHOLD = DateUtils.SECOND_IN_MILLIS / 2; /** * {@inheritDoc} */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.lookup); // Load animations used to show/hide progress bar mSlideIn = AnimationUtils.loadAnimation(this, R.anim.slide_in); mSlideOut = AnimationUtils.loadAnimation(this, R.anim.slide_out); // Listen for the "in" animation so we make the progress bar visible // only after the sliding has finished. mSlideIn.setAnimationListener(this); mTitleBar = findViewById(R.id.title_bar); mTitle = (TextView) findViewById(R.id.title); mProgress = (ProgressBar) findViewById(R.id.progress); mWebView = (WebView) findViewById(R.id.webview); // Make the view transparent to show background mWebView.setBackgroundColor(0); // Prepare User-Agent string for wiki actions ExtendedWikiHelper.prepareUserAgent(this); // Handle incoming intents as possible searches or links onNewIntent(getIntent()); } /** * Intercept the back-key to try walking backwards along our word history * stack. If we don't have any remaining history, the key behaves normally * and closes this activity. */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Handle back key as long we have a history stack if (keyCode == KeyEvent.KEYCODE_BACK && !mHistory.empty()) { // Compare against last pressed time, and if user hit multiple times // in quick succession, we should consider bailing out early. long currentPress = SystemClock.uptimeMillis(); if (currentPress - mLastPress < BACK_THRESHOLD) { return super.onKeyDown(keyCode, event); } mLastPress = currentPress; // Pop last entry off stack and start loading String lastEntry = mHistory.pop(); startNavigating(lastEntry, false); return true; } // Otherwise fall through to parent return super.onKeyDown(keyCode, event); } /** * Start navigating to the given word, pushing any current word onto the * history stack if requested. The navigation happens on a background thread * and updates the GUI when finished. * * @param word The dictionary word to navigate to. * @param pushHistory If true, push the current word onto history stack. */ private void startNavigating(String word, boolean pushHistory) { // Push any current word onto the history stack if (!TextUtils.isEmpty(mEntryTitle) && pushHistory) { mHistory.add(mEntryTitle); } // Start lookup for new word in background new LookupTask().execute(word); } /** * {@inheritDoc} */ @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.lookup, menu); return true; } /** * {@inheritDoc} */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.lookup_search: { onSearchRequested(); return true; } case R.id.lookup_random: { startNavigating(null, true); return true; } case R.id.lookup_about: { showAbout(); return true; } } return false; } /** * Show an about dialog that cites data sources. */ protected void showAbout() { // Inflate the about message contents View messageView = getLayoutInflater().inflate(R.layout.about, null, false); // When linking text, force to always use default color. This works // around a pressed color state bug. TextView textView = (TextView) messageView.findViewById(R.id.about_credits); int defaultColor = textView.getTextColors().getDefaultColor(); textView.setTextColor(defaultColor); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setIcon(R.drawable.app_icon); builder.setTitle(R.string.app_name); builder.setView(messageView); builder.create(); builder.show(); } /** * Because we're singleTop, we handle our own new intents. These usually * come from the {@link SearchManager} when a search is requested, or from * internal links the user clicks on. */ @Override public void onNewIntent(Intent intent) { final String action = intent.getAction(); if (Intent.ACTION_SEARCH.equals(action)) { // Start query for incoming search request String query = intent.getStringExtra(SearchManager.QUERY); startNavigating(query, true); } else if (Intent.ACTION_VIEW.equals(action)) { // Treat as internal link only if valid Uri and host matches Uri data = intent.getData(); if (data != null && ExtendedWikiHelper.WIKI_LOOKUP_HOST .equals(data.getHost())) { String query = data.getPathSegments().get(0); startNavigating(query, true); } } else { // If not recognized, then start showing random word startNavigating(null, true); } } /** * Set the title for the current entry. */ protected void setEntryTitle(String entryText) { mEntryTitle = entryText; mTitle.setText(mEntryTitle); } /** * Set the content for the current entry. This will update our * {@link WebView} to show the requested content. */ protected void setEntryContent(String entryContent) { mWebView.loadDataWithBaseURL(ExtendedWikiHelper.WIKI_AUTHORITY, entryContent, ExtendedWikiHelper.MIME_TYPE, ExtendedWikiHelper.ENCODING, null); } /** * Background task to handle Wiktionary lookups. This correctly shows and * hides the loading animation from the GUI thread before starting a * background query to the Wiktionary API. When finished, it transitions * back to the GUI thread where it updates with the newly-found entry. */ private class LookupTask extends AsyncTask<String, String, String> { /** * Before jumping into background thread, start sliding in the * {@link ProgressBar}. We'll only show it once the animation finishes. */ @Override protected void onPreExecute() { mTitleBar.startAnimation(mSlideIn); } /** * Perform the background query using {@link ExtendedWikiHelper}, which * may return an error message as the result. */ @Override protected String doInBackground(String... args) { String query = args[0]; String parsedText = null; try { // If query word is null, assume request for random word if (query == null) { query = ExtendedWikiHelper.getRandomWord(); } if (query != null) { // Push our requested word to the title bar publishProgress(query); String wikiText = ExtendedWikiHelper.getPageContent(query, true); parsedText = ExtendedWikiHelper.formatWikiText(wikiText); } } catch (ApiException e) { Log.e(TAG, "Problem making wiktionary request", e); } catch (ParseException e) { Log.e(TAG, "Problem making wiktionary request", e); } if (parsedText == null) { parsedText = getString(R.string.empty_result); } return parsedText; } /** * Our progress update pushes a title bar update. */ @Override protected void onProgressUpdate(String... args) { String searchWord = args[0]; setEntryTitle(searchWord); } /** * When finished, push the newly-found entry content into our * {@link WebView} and hide the {@link ProgressBar}. */ @Override protected void onPostExecute(String parsedText) { mTitleBar.startAnimation(mSlideOut); mProgress.setVisibility(View.INVISIBLE); setEntryContent(parsedText); } } /** * Make the {@link ProgressBar} visible when our in-animation finishes. */ public void onAnimationEnd(Animation animation) { mProgress.setVisibility(View.VISIBLE); } public void onAnimationRepeat(Animation animation) { // Not interested if the animation repeats } public void onAnimationStart(Animation animation) { // Not interested when the animation starts } } //src\com\example\android\wiktionary\SimpleWikiHelper.java package com.example.android.wiktionary; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; public class SimpleWikiHelper { private static final String TAG = "SimpleWikiHelper"; private static final String WIKTIONARY_PAGE = "http://en.wiktionary.org/w/api.php?action=query&prop=revisions&titles=%s&" + "rvprop=content&format=json%s"; private static final String WIKTIONARY_EXPAND_TEMPLATES = "&rvexpandtemplates=true"; /** * {@link StatusLine} HTTP status code when no server error has occurred. */ private static final int HTTP_STATUS_OK = 200; private static byte[] sBuffer = new byte[512]; private static String sUserAgent = null; public static class ApiException extends Exception { public ApiException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); } public ApiException(String detailMessage) { super(detailMessage); } } public static class ParseException extends Exception { public ParseException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); } } public static void prepareUserAgent(Context context) { try { // Read package name and version number from manifest PackageManager manager = context.getPackageManager(); PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0); sUserAgent = String.format(context.getString(R.string.template_user_agent), info.packageName, info.versionName); } catch(NameNotFoundException e) { Log.e(TAG, "Couldn't find package information in PackageManager", e); } } public static String getPageContent(String title, boolean expandTemplates) throws ApiException, ParseException { // Encode page title and expand templates if requested String encodedTitle = Uri.encode(title); String expandClause = expandTemplates ? WIKTIONARY_EXPAND_TEMPLATES : ""; // Query the API for content String content = getUrlContent(String.format(WIKTIONARY_PAGE, encodedTitle, expandClause)); try { // Drill into the JSON response to find the content body JSONObject response = new JSONObject(content); JSONObject query = response.getJSONObject("query"); JSONObject pages = query.getJSONObject("pages"); JSONObject page = pages.getJSONObject((String) pages.keys().next()); JSONArray revisions = page.getJSONArray("revisions"); JSONObject revision = revisions.getJSONObject(0); return revision.getString("*"); } catch (JSONException e) { throw new ParseException("Problem parsing API response", e); } } protected static synchronized String getUrlContent(String url) throws ApiException { if (sUserAgent == null) { throw new ApiException("User-Agent string must be prepared"); } // Create client and set our specific user-agent string HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(url); request.setHeader("User-Agent", sUserAgent); try { HttpResponse response = client.execute(request); // Check if server response is valid StatusLine status = response.getStatusLine(); if (status.getStatusCode() != HTTP_STATUS_OK) { throw new ApiException("Invalid response from server: " + status.toString()); } // Pull content stream from response HttpEntity entity = response.getEntity(); InputStream inputStream = entity.getContent(); ByteArrayOutputStream content = new ByteArrayOutputStream(); // Read response into a buffered stream int readBytes = 0; while ((readBytes = inputStream.read(sBuffer)) != -1) { content.write(sBuffer, 0, readBytes); } // Return result from buffered stream return new String(content.toByteArray()); } catch (IOException e) { throw new ApiException("Problem communicating with API", e); } } } //src\com\example\android\wiktionary\WordWidget.java package com.example.android.wiktionary; import com.example.android.wiktionary.SimpleWikiHelper.ApiException; import com.example.android.wiktionary.SimpleWikiHelper.ParseException; import android.app.PendingIntent; import android.app.Service; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.net.Uri; import android.os.IBinder; import android.text.format.Time; import android.util.Log; import android.widget.RemoteViews; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Define a simple widget that shows the Wiktionary "Word of the day." To build * an update we spawn a background {@link Service} to perform the API queries. */ public class WordWidget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // To prevent any ANR timeouts, we perform the update in a service context.startService(new Intent(context, UpdateService.class)); } public static class UpdateService extends Service { @Override public void onStart(Intent intent, int startId) { // Build the widget update for today RemoteViews updateViews = buildUpdate(this); // Push update for this widget to the home screen ComponentName thisWidget = new ComponentName(this, WordWidget.class); AppWidgetManager manager = AppWidgetManager.getInstance(this); manager.updateAppWidget(thisWidget, updateViews); } @Override public IBinder onBind(Intent intent) { return null; } /** * Regular expression that splits "Word of the day" entry into word * name, word type, and the first description bullet point. */ private static final String WOTD_PATTERN = "(?s)\\{\\{wotd\\|(.+?)\\|(.+?)\\|([^#\\|]+).*?\\}\\}"; /** * Build a widget update to show the current Wiktionary * "Word of the day." Will block until the online API returns. */ public RemoteViews buildUpdate(Context context) { // Pick out month names from resources Resources res = context.getResources(); String[] monthNames = res.getStringArray(R.array.month_names); // Find current month and day Time today = new Time(); today.setToNow(); // Build the page title for today, such as "March 21" String pageName = res.getString(R.string.template_wotd_title, monthNames[today.month], today.monthDay); String pageContent = null; try { // Try querying the Wiktionary API for today's word SimpleWikiHelper.prepareUserAgent(context); pageContent = SimpleWikiHelper.getPageContent(pageName, false); } catch (ApiException e) { Log.e("WordWidget", "Couldn't contact API", e); } catch (ParseException e) { Log.e("WordWidget", "Couldn't parse API response", e); } RemoteViews views = null; Matcher matcher = Pattern.compile(WOTD_PATTERN).matcher(pageContent); if (matcher.find()) { // Build an update that holds the updated widget contents views = new RemoteViews(context.getPackageName(), R.layout.widget_word); String wordTitle = matcher.group(1); views.setTextViewText(R.id.word_title, wordTitle); views.setTextViewText(R.id.word_type, matcher.group(2)); views.setTextViewText(R.id.definition, matcher.group(3).trim()); // When user clicks on widget, launch to Wiktionary definition page String definePage = String.format("%s://%s/%s", ExtendedWikiHelper.WIKI_AUTHORITY, ExtendedWikiHelper.WIKI_LOOKUP_HOST, wordTitle); Intent defineIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(definePage)); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0 /* no requestCode */, defineIntent, 0 /* no flags */); views.setOnClickPendingIntent(R.id.widget, pendingIntent); } else { // Didn't find word of day, so show error message views = new RemoteViews(context.getPackageName(), R.layout.widget_message); views.setTextViewText(R.id.message, context.getString(R.string.widget_error)); } return views; } } } // //res\anim\slide_in.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <translate android:fromXDelta="-26" android:toXDelta="0" android:duration="400" /> </set> //res\anim\slide_out.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <translate android:fromXDelta="0" android:toXDelta="-26" android:duration="400" /> </set> // //res\layout\about.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="20dip"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="16sp" android:text="@string/app_descrip" android:textColor="?android:attr/textColorPrimaryInverse" /> <TextView android:id="@+id/about_credits" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="20dip" android:textSize="16sp" android:text="@string/app_credits" android:autoLink="web" android:textColor="?android:attr/textColorPrimaryInverse" /> </LinearLayout> //res\layout\lookup.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/title_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical"> <ProgressBar android:id="@+id/progress" android:layout_width="18dip" android:layout_height="18dip" android:layout_marginLeft="10dip" android:visibility="invisible" android:indeterminateOnly="true" android:indeterminateDrawable="@drawable/progress_spin" android:indeterminateBehavior="repeat" android:indeterminateDuration="3500" /> <TextView android:id="@+id/title" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:padding="10dip" style="@style/LookupTitle" /> </LinearLayout> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" /> </LinearLayout> //res\layout\widget_message.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" style="@style/WidgetBackground"> <TextView android:id="@+id/message" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dip" android:padding="10dip" android:gravity="center" android:text="@string/widget_loading" style="@style/Text.Loading" /> </LinearLayout> //res\layout\widget_word.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="true" style="@style/WidgetBackground"> <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:src="@drawable/star_logo" /> <TextView android:id="@+id/word_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="14dip" android:layout_marginBottom="1dip" android:includeFontPadding="false" android:singleLine="true" android:ellipsize="end" style="@style/Text.WordTitle" /> <TextView android:id="@+id/word_type" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_toRightOf="@id/word_title" android:layout_toLeftOf="@id/icon" android:layout_alignBaseline="@id/word_title" android:paddingLeft="4dip" android:includeFontPadding="false" android:singleLine="true" android:ellipsize="end" style="@style/Text.WordType" /> <TextView android:id="@+id/bullet" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/word_title" android:paddingRight="4dip" android:includeFontPadding="false" android:singleLine="true" style="@style/BulletPoint" /> <TextView android:id="@+id/definition" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/word_title" android:layout_toRightOf="@id/bullet" android:paddingRight="5dip" android:paddingBottom="4dip" android:includeFontPadding="false" android:lineSpacingMultiplier="0.9" android:maxLines="4" android:fadingEdge="vertical" style="@style/Text.Definition" /> </RelativeLayout> // //res\menu\lookup.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/lookup_search" android:title="@string/lookup_search" android:icon="@android:drawable/ic_menu_search" /> <item android:id="@+id/lookup_random" android:title="@string/lookup_random" android:icon="@drawable/ic_menu_shuffle" /> <item android:id="@+id/lookup_about" android:title="@string/lookup_about" android:icon="@android:drawable/ic_menu_help" /> </menu> // //res\values\strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Wiktionary example</string> <string name="app_descrip">Example of a fast Wiktionary browser and Word-of-day widget</string> <string name="app_credits">"All dictionary content provided by Wiktionary under a GFDL license. http://en.wiktionary.org\n\nIcon derived from Tango Desktop Project under a public domain license. http://tango.freedesktop.org"</string> <string name="template_user_agent" translatable="false">"%1$s/%2$s (Linux; Android)"</string> <string name="template_wotd_title">"Wiktionary:Word of the day/%1$s %2$s"</string> <string name="template_define_url" translatable="false">"http://en.wiktionary.org/wiki/%s"</string> <string name="widget_name">Wiktionary</string> <string name="widget_loading">"Loading word\nof day\u2026"</string> <string name="widget_error">No word of day found</string> <string-array name="month_names"> <item>January</item> <item>February</item> <item>March</item> <item>April</item> <item>May</item> <item>June</item> <item>July</item> <item>August</item> <item>September</item> <item>October</item> <item>November</item> <item>December</item> </string-array> <string name="search_label">Wiktionary search</string> <string name="search_hint">Define word</string> <string name="lookup_search">Search</string> <string name="lookup_random">Random</string> <string name="lookup_about">About</string> <string name="empty_result">No entry found for this word, or problem reading data.</string> </resources> //res\values\styles.xml <?xml version="1.0" encoding="utf-8"?> <resources> <style name="WidgetBackground"> <item name="android:background">@drawable/widget_bg</item> </style> <style name="BulletPoint"> <item name="android:textSize">13sp</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text" /> <style name="Text.Loading"> <item name="android:textSize">14sp</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text.WordTitle"> <item name="android:textSize">16sp</item> <item name="android:textStyle">bold</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text.WordType"> <item name="android:textSize">14sp</item> <item name="android:textStyle">italic</item> <item name="android:textColor">@android:color/black</item> </style> <style name="Text.Definition"> <item name="android:textSize">13sp</item> <item name="android:textColor">@android:color/black</item> </style> <style name="LookupProgress"> <item name="android:indeterminateOnly">true</item> <item name="android:indeterminateDrawable">@drawable/progress_spin</item> <item name="android:indeterminateBehavior">repeat</item> <item name="android:indeterminateDuration">3500</item> </style> <style name="LookupTitle"> <item name="android:textSize">30sp</item> <item name="android:textStyle">bold</item> <item name="android:textColor">?android:attr/textColorPrimary</item> </style> </resources> //res\values\themes.xml <?xml version="1.0" encoding="utf-8"?> <resources> <style name="LookupTheme" parent="@android:style/Theme.Light.NoTitleBar"> <item name="android:windowBackground">@drawable/lookup_bg</item> </style> </resources> // //res\xml\searchable.xml <?xml version="1.0" encoding="utf-8"?> <searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/search_label" android:hint="@string/search_hint" /> //res\xml\widget_word.xml <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="146dip" android:minHeight="72dip" android:updatePeriodMillis="86400000" android:initialLayout="@layout/widget_message" />
Utility class supporting the Facebook Object.
//package com.facebook.android; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import org.json.JSONException; import org.json.JSONObject; import android.app.AlertDialog.Builder; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; /** * Utility class supporting the Facebook Object. * * @author ssoneff@facebook.com * */ final class Util { /** * Generate the multi-part post body providing the parameters and boundary * string * * @param parameters the parameters need to be posted * @param boundary the random string as boundary * @return a string of the post body */ public static String encodePostBody(Bundle parameters, String boundary) { if (parameters == null) return ""; StringBuilder sb = new StringBuilder(); for (String key : parameters.keySet()) { if (parameters.getByteArray(key) != null) { continue; } sb.append("Content-Disposition: form-data; name=\"" + key + "\"\r\n\r\n" + parameters.getString(key)); sb.append("\r\n" + "--" + boundary + "\r\n"); } return sb.toString(); } public static String encodeUrl(Bundle parameters) { if (parameters == null) { return ""; } StringBuilder sb = new StringBuilder(); boolean first = true; for (String key : parameters.keySet()) { if (first) first = false; else sb.append("&"); sb.append(URLEncoder.encode(key) + "=" + URLEncoder.encode(parameters.getString(key))); } return sb.toString(); } public static Bundle decodeUrl(String s) { Bundle params = new Bundle(); if (s != null) { String array[] = s.split("&"); for (String parameter : array) { String v[] = parameter.split("="); params.putString(URLDecoder.decode(v[0]), URLDecoder.decode(v[1])); } } return params; } /** * Parse a URL query and fragment parameters into a key-value bundle. * * @param url the URL to parse * @return a dictionary bundle of keys and values */ public static Bundle parseUrl(String url) { // hack to prevent MalformedURLException url = url.replace("fbconnect", "http"); try { URL u = new URL(url); Bundle b = decodeUrl(u.getQuery()); b.putAll(decodeUrl(u.getRef())); return b; } catch (MalformedURLException e) { return new Bundle(); } } public static String openUrl(String url, String method, Bundle params) throws MalformedURLException, IOException { // random string as boundary for multi-part http post String strBoundary = "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f"; String endLine = "\r\n"; OutputStream os; if (method.equals("GET")) { url = url + "?" + encodeUrl(params); } Log.d("Facebook-Util", method + " URL: " + url); HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); conn.setRequestProperty("User-Agent", System.getProperties(). getProperty("http.agent") + " FacebookAndroidSDK"); if (!method.equals("GET")) { Bundle dataparams = new Bundle(); for (String key : params.keySet()) { if (params.getByteArray(key) != null) { dataparams.putByteArray(key, params.getByteArray(key)); } } // use method override if (!params.containsKey("method")) { params.putString("method", method); } if (params.containsKey("access_token")) { String decoded_token = URLDecoder.decode(params.getString("access_token")); params.putString("access_token", decoded_token); } conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+strBoundary); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestProperty("Connection", "Keep-Alive"); conn.connect(); os = new BufferedOutputStream(conn.getOutputStream()); os.write(("--" + strBoundary +endLine).getBytes()); os.write((encodePostBody(params, strBoundary)).getBytes()); os.write((endLine + "--" + strBoundary + endLine).getBytes()); if (!dataparams.isEmpty()) { for (String key: dataparams.keySet()){ os.write(("Content-Disposition: form-data; filename=\"" + key + "\"" + endLine).getBytes()); os.write(("Content-Type: content/unknown" + endLine + endLine).getBytes()); os.write(dataparams.getByteArray(key)); os.write((endLine + "--" + strBoundary + endLine).getBytes()); } } os.flush(); } String response = ""; try { response = read(conn.getInputStream()); } catch (FileNotFoundException e) { // Error Stream contains JSON that we can parse to a FB error response = read(conn.getErrorStream()); } return response; } private static String read(InputStream in) throws IOException { StringBuilder sb = new StringBuilder(); BufferedReader r = new BufferedReader(new InputStreamReader(in), 1000); for (String line = r.readLine(); line != null; line = r.readLine()) { sb.append(line); } in.close(); return sb.toString(); } public static void clearCookies(Context context) { // Edge case: an illegal state exception is thrown if an instance of // CookieSyncManager has not be created. CookieSyncManager is normally // created by a WebKit view, but this might happen if you start the // app, restore saved state, and click logout before running a UI // dialog in a WebView -- in which case the app crashes @SuppressWarnings("unused") CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(context); CookieManager cookieManager = CookieManager.getInstance(); cookieManager.removeAllCookie(); } public static JSONObject parseJson(String response) throws JSONException, Exception { // Edge case: when sending a POST request to /[post_id]/likes // the return value is 'true' or 'false'. Unfortunately // these values cause the JSONObject constructor to throw // an exception. if (response.equals("false")) { throw new Exception("request failed"); } if (response.equals("true")) { response = "{value : true}"; } JSONObject json = new JSONObject(response); // errors set by the server are not consistent // they depend on the method and endpoint if (json.has("error")) { JSONObject error = json.getJSONObject("error"); // throw new Exception("type"); } if (json.has("error_code") && json.has("error_msg")) { // throw new Exception(json.getString("error_msg"), "", // Integer.parseInt(json.getString("error_code"))); } if (json.has("error_code")) { // throw new Exception("request failed", "", // Integer.parseInt(json.getString("error_code"))); } if (json.has("error_msg")) { throw new Exception(json.getString("error_msg")); } if (json.has("error_reason")) { throw new Exception(json.getString("error_reason")); } return json; } public static void showAlert(Context context, String title, String text) { Builder alertBuilder = new Builder(context); alertBuilder.setTitle(title); alertBuilder.setMessage(text); alertBuilder.create().show(); } }