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() );
}
}
//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();
}
}