Java tutorial
/******************************************************************************* * Copyright 2011 EscAbe * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package org.escabe.trakt; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.SharedPreferences; import android.os.AsyncTask; import android.preference.PreferenceManager; import android.util.Log; import android.view.View; import android.widget.Toast; /** * Class for interacting with the trakt.tv API * @author escabe * */ public class TraktAPI { private static final String TAG = "TraktAPI"; public enum ShowMovie { Show, Movie }; public enum MarkMode { Watched, Unwatched, Loved, Unloved, Hated, Unhated }; private Context context; // "Constants" private String apikey = "682912f6e62d666428d261544d619d7c"; private String baseurl = "http://api.trakt.tv/"; private String username; private String password; private SharedPreferences prefs; /** * Constructor. * @param c Context which is needed to be able to retrieve the Preferences. */ public TraktAPI(Context c) { // Get preferences object and retrieve username and password context = c; prefs = PreferenceManager.getDefaultSharedPreferences(c); username = prefs.getString("user", ""); password = EncodePassword(prefs.getString("password", "")); } public String ResizePoster(String image, int size) { String p = image.replaceAll("/(\\d*)(\\.?\\d*?)?\\.jpg", "/$1-138$2.jpg"); return p; /* switch (size) { case 1: return "http://escabe.org/resize.php?image=" + p + "&h=" + context.getResources().getDimensionPixelSize(R.dimen.PosterSmallHeight) + "&w=" + context.getResources().getDimensionPixelSize(R.dimen.PosterSmallWidth); case 2: return "http://escabe.org/resize.php?image=" + p + "&h=" + context.getResources().getDimensionPixelSize(R.dimen.PosterMediumHeight) + "&w=" + context.getResources().getDimensionPixelSize(R.dimen.PosterMediumWidth); default: return p; } */ } public String ResizeAvatar(String image, int size) { return image; /* switch (size) { case 1: return "http://escabe.org/resize.php?image=" + image + "&h=" + context.getResources().getDimensionPixelSize(R.dimen.AvatarSmallHeight) + "&w=" + context.getResources().getDimensionPixelSize(R.dimen.AvatarSmallWidth); case 2: return "http://escabe.org/resize.php?image=" + image + "&h=" + context.getResources().getDimensionPixelSize(R.dimen.AvatarMediumHeight) + "&w=" + context.getResources().getDimensionPixelSize(R.dimen.AvatarMediumWidth); default: return image; } */ } public String ResizeScreen(String image, int size) { String s = image.replaceAll("/(\\d*)(\\.?\\d*?)?\\.jpg", "/$1-218$2.jpg"); return s; /* switch (size) { case 1: return "http://escabe.org/resize.php?image=" + s + "&h=" + context.getResources().getDimensionPixelSize(R.dimen.ScreenSmallHeight) + "&w=" + context.getResources().getDimensionPixelSize(R.dimen.ScreenSmallWidth); case 2: default: return s; } */ } public void Mark(Activity parent, Object... params) { Marker m = new Marker(parent); m.execute(params); } public boolean LoggedIn() { JSONObject result = getDataObjectFromJSON("account/test/%k", true); if (result == null) return false; if (result.optString("status").equals("success")) return true; Toast.makeText(context, "Trakt returned " + result.optString("error"), Toast.LENGTH_SHORT).show(); return false; } public void Shout(View parent, Object... params) { Shouter s = new Shouter(parent); s.execute(params); } public class Shouter extends AsyncTask<Object, Void, Boolean> { View parent; ProgressDialog progressdialog; public Shouter(View parent) { this.parent = parent; } @Override protected void onPreExecute() { progressdialog = ProgressDialog.show(context, "", String.format("Shouting..."), true); } @Override protected Boolean doInBackground(Object... params) { String type = (String) params[0]; String shout = (String) params[1]; if (type.equals("movie")) { try { String url = "shout/movie/%k"; JSONObject post = new JSONObject(); post.put("imdb_id", (String) params[2]); post.put("shout", shout); JSONObject data = getDataObjectFromJSON(url, true, post); return data != null; } catch (JSONException e) { Log.e(TAG, "Shouting failed", e); } } else if (type.equals("show")) { try { String url = "shout/show/%k"; JSONObject post = new JSONObject(); post.put("tvdb_id", (String) params[2]); post.put("shout", shout); JSONObject data = getDataObjectFromJSON(url, true, post); return data != null; } catch (JSONException e) { Log.e(TAG, "Shouting failed", e); } } else if (type.equals("episode")) { try { String url = "shout/episode/%k"; JSONObject post = new JSONObject(); post.put("season", (Integer) params[3]); post.put("episode", (Integer) params[4]); post.put("tvdb_id", (String) params[2]); post.put("shout", shout); JSONObject data = getDataObjectFromJSON(url, true, post); return data != null; } catch (JSONException e) { Log.e(TAG, "Shouting failed", e); } } return false; } @Override protected void onPostExecute(Boolean result) { String message; if (result) { message = "Shouting succeeded"; } else { message = "Shouting failed"; } progressdialog.dismiss(); Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_SHORT).show(); ((ActivityWithUpdate) parent).DoUpdate(); } } public class Marker extends AsyncTask<Object, Void, Boolean> { Activity parent; ProgressDialog progressdialog; public Marker(Activity parent) { this.parent = parent; } @Override protected void onPreExecute() { progressdialog = ProgressDialog.show(context, "", String.format("Marking..."), true); } @Override protected Boolean doInBackground(Object... params) { String type = (String) params[0]; String status = (String) params[1]; if (status.equals("seen") || status.equals("unseen") || status.equals("watchlist") || status.equals("unwatchlist")) { if (type.equals("movie") || type.equals("show")) { try { String url = type + "/"; JSONObject post = new JSONObject(); // Movies Array JSONArray ms = new JSONArray(); // Movie Element JSONObject m = new JSONObject(); m.put("imdb_id", (String) params[2]); ms.put(m); post.put(type + "s", ms); url += status + "/%k"; JSONObject data = getDataObjectFromJSON(url, true, post); return data != null; } catch (JSONException e) { // TODO Auto-generated catch block Log.w(TAG, "Marking failed", e); } } else if (type.equals("episode")) { try { String url = "show/episode/"; JSONObject post = new JSONObject(); // Episodes Array JSONArray es = new JSONArray(); // Episode Element JSONObject e = new JSONObject(); e.put("season", (Integer) params[3]); e.put("episode", (Integer) params[4]); es.put(e); post.put("episodes", es); post.put("tvdb_id", (String) params[2]); url += status + "/%k"; JSONObject data = getDataObjectFromJSON(url, true, post); return data != null; } catch (JSONException e) { // TODO Auto-generated catch block Log.w(TAG, "Marking failed", e); } } } else { if (type.equals("movie") || type.equals("show")) { try { String url = "rate/" + type + "/%k"; JSONObject post = new JSONObject(); post.put("imdb_id", (String) params[2]); post.put("rating", status); JSONObject data = getDataObjectFromJSON(url, true, post); return data != null; } catch (JSONException e) { // TODO Auto-generated catch block Log.e(TAG, "Marking failed", e); } } else if (type.equals("episode")) { try { String url = "rate/" + type + "/%k"; JSONObject post = new JSONObject(); post.put("tvdb_id", (String) params[2]); post.put("season", (Integer) params[3]); post.put("episode", (Integer) params[4]); post.put("rating", status); JSONObject data = getDataObjectFromJSON(url, true, post); return data != null; } catch (JSONException e) { // TODO Auto-generated catch block Log.e(TAG, "Marking failed", e); } } } return false; } @Override protected void onPostExecute(Boolean result) { String message; if (result) { message = "Marking succeeded"; } else { message = "Marking failed"; } progressdialog.dismiss(); Toast.makeText(parent.getApplicationContext(), message, Toast.LENGTH_SHORT).show(); ((ActivityWithUpdate) parent).DoUpdate(); } } /** * Encodes p as SHA1 Hash. * @param p Password. * @return SHA1 encoded password. */ private String EncodePassword(String p) { MessageDigest sha; try { sha = MessageDigest.getInstance("SHA-1"); sha.update(p.getBytes("iso-8859-1")); byte[] hash = sha.digest(); p = ""; for (int i = 0; i < hash.length; i++) { //FIX for http://code.google.com/p/trakt-app/issues/detail?id=1 p = String.format("%s%02x", p, hash[i] & 0xFF); } } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block Log.e(TAG, e.getMessage()); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block Log.e(TAG, e.getMessage()); } return p; } private Object getDataFromJSON(String url, boolean login, String type) { return getDataFromJSON(url, login, type, null); } /** * Actually retrieve data from the server and encode as either JSONObject or JSONArray * @param url API URL (baseurl part needs to be omitted). * @param login send user login details to API. * @param type "array" or "object" specifying return type. * @return JSONObject or JSONArray which was returned by the server. */ private Object getDataFromJSON(String url, boolean login, String type, JSONObject postdata) { // Build URL. URLS may contain certain tags which will be replaced url = baseurl + url; url = url.replaceAll("%k", apikey); url = url.replaceAll("%u", username); // Construct HttpClient HttpClient httpclient = new DefaultHttpClient(); if (login) { // If login add login information to a JSONObject HttpPost httppost = new HttpPost(url); JSONObject jsonpost; if (postdata == null) { jsonpost = new JSONObject(); } else { jsonpost = postdata; } try { jsonpost.put("username", username); jsonpost.put("password", password); httppost.setEntity(new StringEntity(jsonpost.toString())); // Perform POST String response = httpclient.execute(httppost, new BasicResponseHandler()); // Return the data in the requested format if (type == "array") { return new JSONArray(response); } else { return new JSONObject(response); } } catch (JSONException e) { // TODO Auto-generated catch block Log.e(TAG, "getDataFromJSON with login failed", e); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block Log.e(TAG, "getDataFromJSON with login failed", e); } catch (ClientProtocolException e) { // TODO Auto-generated catch block Log.e(TAG, "getDataFromJSON with login failed", e); } catch (IOException e) { // TODO Auto-generated catch block Toast.makeText(context.getApplicationContext(), "Connection to Trakt.tv host failed. Do you have internet access?", Toast.LENGTH_SHORT) .show(); Log.e(TAG, "getDataFromJSON with login failed", e); } } else { // No login // Simply perform a GET HttpGet httpget = new HttpGet(url); try { String response = httpclient.execute(httpget, new BasicResponseHandler()); // Return the data in the requested format if (type == "array") { return new JSONArray(response); } else { return new JSONObject(response); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block Log.e(TAG, "getDataFromJSON without login failed", e); } catch (IOException e) { // TODO Auto-generated catch block Toast.makeText(context.getApplicationContext(), "Connection to Trakt.tv host failed. Do you have internet access?", Toast.LENGTH_SHORT) .show(); Log.e(TAG, "getDataFromJSON without login failed", e); } catch (JSONException e) { // TODO Auto-generated catch block Log.e(TAG, "getDataFromJSON without login failed", e); } } return null; } /** * Retrieve an array of data without logging in. * @param url API URL. * @return JSONArray containing data returned by server. */ public JSONArray getDataArrayFromJSON(String url) { return (JSONArray) getDataFromJSON(url, false, "array"); } /** * Retrieve an array of data allows logging in. * @param url API URL. * @param login Send login to server * @return JSONArray containing data returned by server. */ public JSONArray getDataArrayFromJSON(String url, boolean login) { return (JSONArray) getDataFromJSON(url, login, "array"); } /** * Retrieve a single object of data. * @param url API URL. * @param login Send login to server * @return JSONObject containing data returned by server. */ public JSONObject getDataObjectFromJSON(String url, boolean login) { return (JSONObject) getDataFromJSON(url, login, "object"); } public JSONObject getDataObjectFromJSON(String url, boolean login, JSONObject post) { return (JSONObject) getDataFromJSON(url, login, "object", post); } }