package org.wordpress.android;
/**
* In order to make requests for WPCOM stats for a given blog you need some specific information.
* In order to get this additional info a new URL was created:
https://public-api.wordpress.com/getuserblogs.php
http://stats.wordpress.com/csv.php
It requires SSL, uses HTTP BASIC AUTHENTICATION and returns XML data
that looks like:
<?xml version="1.0" encoding="UTF-8"?>
<userinfo>
<apikey>XXXXXXXXXXX</apikey>
<blog>
<id>XYXYXY</id>
<url>http://example.wordpress.com/</url>
</blog>
<blog>
<id>XYXYXY</id>
<url>http://myblog.example.com/</url>
</blog>
</userinfo>
Optionally you can get the data in JSON format -
https://public-api.wordpress.com/getuserblogs.php?f=json
*/
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Vector;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.wordpress.android.util.WPTitleBar;
import org.wordpress.android.util.WPTitleBar.OnBlogChangedListener;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlrpc.android.ConnectionClient;
import org.xmlrpc.android.XMLRPCClient;
import org.xmlrpc.android.XMLRPCException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.util.Linkify;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
public class ViewStats extends Activity {
public boolean success = false;
public String blogURL, xmlrpcURL, vsoURI;
private ConnectionClient client;
private HttpPost postMethod;
private HttpParams httpParams;
String errorMsg = "";
boolean loginShowing = false;
private int firstRun = 0;
private WPTitleBar titleBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.view_stats);
titleBar = (WPTitleBar) findViewById(R.id.actionBar);
// get the ball rolling...
initStats();
Button saveStatsLogin = (Button) findViewById(R.id.saveDotcom);
saveStatsLogin.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
EditText dotcomUsername = (EditText) findViewById(R.id.dotcomUsername);
EditText dotcomPassword = (EditText) findViewById(R.id.dotcomPassword);
String dcUsername = dotcomUsername.getText().toString();
String dcPassword = dotcomPassword.getText().toString();
if (dcUsername.equals("") || dcPassword.equals("")) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(
ViewStats.this);
dialogBuilder.setTitle(getResources().getText(
R.string.required_fields));
dialogBuilder.setMessage(getResources().getText(
R.string.username_password_required));
dialogBuilder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// just close the dialog
}
});
dialogBuilder.setCancelable(true);
if (!isFinishing()) {
dialogBuilder.create().show();
}
} else {
WordPress.currentBlog.setDotcom_username(dcUsername);
WordPress.currentBlog.setDotcom_password(dcPassword);
WordPress.currentBlog.save(ViewStats.this,
WordPress.currentBlog.getUsername());
showOrHideLoginForm();
initStats(); // start over again now that we have the login
}
}
});
final Button go = (Button) findViewById(R.id.go);
go.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Spinner reportType = (Spinner) findViewById(R.id.reportType);
Spinner reportInterval = (Spinner) findViewById(R.id.reportInterval);
final String type = parseType(reportType
.getSelectedItemPosition());
final int interval = parseInterval(reportInterval
.getSelectedItemPosition());
final String apiKey = WordPress.currentBlog.getApi_key();
final String apiBlogID = WordPress.currentBlog.getApi_blogid();
if (!isFinishing())
titleBar.startRotatingRefreshIcon();
new getStatsDataTask().execute(apiKey, apiBlogID, type,
interval);
}
});
titleBar.refreshButton
.setOnClickListener(new ImageButton.OnClickListener() {
public void onClick(View v) {
go.performClick();
}
});
titleBar.setOnBlogChangedListener(new OnBlogChangedListener() {
// user selected new blog in the title bar
@Override
public void OnBlogChanged() {
// hide all of the report views
ImageView iv = (ImageView) findViewById(R.id.chart);
iv.setVisibility(View.GONE);
RelativeLayout filters = (RelativeLayout) findViewById(R.id.filters);
filters.setVisibility(View.GONE);
TableLayout tl = (TableLayout) findViewById(R.id.dataTable);
tl.removeAllViews();
RelativeLayout moderationBar = (RelativeLayout) findViewById(R.id.dotcomLogin);
moderationBar.setVisibility(View.GONE);
TextView reportTitle = (TextView) findViewById(R.id.chartTitle);
reportTitle.setVisibility(View.GONE);
// load stats again for the new blog
initStats();
}
});
TextView wpcomHelp = (TextView) findViewById(R.id.wpcomHelp);
wpcomHelp.setOnClickListener(new TextView.OnClickListener() {
public void onClick(View v) {
Intent intent1 = new Intent(Intent.ACTION_VIEW);
intent1.setData(Uri
.parse("http://en.support.wordpress.com/stats/"));
startActivity(intent1);
}
});
Spinner reportInterval = (Spinner) findViewById(R.id.reportInterval);
reportInterval.setSelection(1);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
titleBar.refreshBlog();
initStats();
}
protected int parseInterval(int position) {
int interval = 0;
switch (position) {
case 0:
interval = 1;
break;
case 1:
interval = 7;
break;
case 2:
interval = 30;
break;
case 3:
interval = 90;
break;
case 4:
interval = 365;
break;
case 5:
interval = -1;
break;
}
;
return interval;
}
protected String parseType(int position) {
String type = "";
switch (position) {
case 0:
type = "views";
break;
case 1:
type = "postviews";
break;
case 2:
type = "referrers";
break;
case 3:
type = "searchterms";
break;
case 4:
type = "clicks";
break;
case 5:
type = "videoplays";
break;
}
;
return type;
}
private void initStats() {
String sUsername, sPassword;
if (WordPress.currentBlog.getApi_key() == null) {
if (WordPress.currentBlog.getDotcom_username() != null) {
// we have an alternate login, use that instead
sUsername = WordPress.currentBlog.getDotcom_username();
sPassword = WordPress.currentBlog.getDotcom_password();
} else {
sUsername = WordPress.currentBlog.getUsername();
sPassword = WordPress.currentBlog.getPassword();
}
titleBar.startRotatingRefreshIcon();
new statsUserDataTask().execute(sUsername, sPassword,
WordPress.currentBlog.getUrl(),
String.valueOf(WordPress.currentBlog.getBlogId()));
} else {
// apiKey found, load default views chart and table
if (titleBar == null)
titleBar = (WPTitleBar) findViewById(R.id.actionBar);
titleBar.startRotatingRefreshIcon();
new getStatsDataTask().execute(WordPress.currentBlog.getApi_key(),
WordPress.currentBlog.getApi_blogid(), "views", 7);
}
}
private Vector<String> getAPIInfo(String username, String password,
String url, String storedBlogID) {
Vector<String> apiInfo = null;
if (!WordPress.currentBlog.isDotcomFlag()) {
// get the blog's url
XMLRPCClient xmlClient = new XMLRPCClient(url,
WordPress.currentBlog.getHttpuser(),
WordPress.currentBlog.getHttppassword());
Object[] params = { WordPress.currentBlog.getUsername(),
WordPress.currentBlog.getPassword() };
try {
Object[] result = (Object[]) xmlClient.call("wp.getUsersBlogs",
params);
if (result != null) {
if (result.length == 1) {
// with one result, let's just match on the host
HashMap<?, ?> blog_info = (HashMap<?, ?>) result[0];
if (blog_info != null) {
if (blog_info.get("url") != null) {
String apiURL = blog_info.get("url").toString();
URI apiURI = new URI(apiURL);
String apiHost = apiURI.getHost().replace(
"www.", "");
URI localURI = new URI(url);
String localHost = localURI.getHost().replace(
"www.", "");
if (localHost.equals(apiHost)) {
url = apiURL;
}
}
}
} else {
// for multiple results, let's match on the host+path
for (int i = 0; i < result.length; i++) {
HashMap<?, ?> blog_info = (HashMap<?, ?>) result[i];
if (blog_info != null) {
if (blog_info.get("url") != null) {
String apiURL = blog_info.get("url")
.toString();
URI apiURI = new URI(apiURL);
String apiHost = apiURI.getHost().replace(
"www.", "");
URI localURI = new URI(url);
String localHost = localURI.getHost()
.replace("www.", "");
String apiURIPath = "", localURIPath = "";
if (apiURI.getPath() != null) {
apiURIPath = apiURI.getPath();
}
if (localURI.getPath() != null) {
if (localURI.getPath().lastIndexOf("/") > 0)
localURIPath = localURI
.getPath()
.substring(
0,
localURI.getPath()
.lastIndexOf(
"/") + 1);
}
if ((localHost + localURIPath)
.equals(apiHost + apiURIPath)) {
url = apiURL;
break;
}
}
}
}
}
}
} catch (XMLRPCException e) {
url = url.replace("xmlrpc.php", "");
} catch (URISyntaxException e) {
url = url.replace("xmlrpc.php", "");
}
} else {
url = url.replace("xmlrpc.php", "");
}
String wwwURL = "";
if (url.indexOf("http://www.") >= 0) {
wwwURL = url;
url = url.replace("http://www.", "http://");
} else {
wwwURL = url.replace("http://", "http://www.");
}
if (!url.endsWith("/")) {
url += "/";
wwwURL += "/";
}
URI uri = URI
.create("https://public-api.wordpress.com/getuserblogs.php");
configureClient(uri, username, password);
// execute HTTP POST request
HttpResponse response;
try {
response = client.execute(postMethod);
/*
* ByteArrayOutputStream outstream = new ByteArrayOutputStream();
* response.getEntity().writeTo(outstream); String text =
* outstream.toString(); Log.i("WordPress", text);
*/
// check status code
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
throw new IOException("HTTP status code: " + statusCode
+ " was returned. "
+ response.getStatusLine().getReasonPhrase());
}
// setup pull parser
try {
XmlPullParser pullParser = XmlPullParserFactory.newInstance()
.newPullParser();
HttpEntity entity = response.getEntity();
// change to pushbackinput stream 1/18/2010 to handle self
// installed wp sites that insert the BOM
PushbackInputStream is = new PushbackInputStream(
entity.getContent());
// get rid of junk characters before xml response. 60 = '<'.
// Added stopper to prevent infinite loop
int bomCheck = is.read();
int stopper = 0;
while (bomCheck != 60 && stopper < 20) {
bomCheck = is.read();
stopper++;
}
is.unread(bomCheck);
pullParser.setInput(is, "UTF-8");
int eventType = pullParser.getEventType();
String apiKey = "";
boolean foundKey = false;
boolean foundID = false;
boolean foundURL = false;
String curBlogID = "";
String curBlogURL = "";
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
// System.out.println("Start document");
} else if (eventType == XmlPullParser.END_DOCUMENT) {
// System.out.println("End document");
} else if (eventType == XmlPullParser.START_TAG) {
if (pullParser.getName().equals("apikey")) {
foundKey = true;
} else if (pullParser.getName().equals("id")) {
foundID = true;
} else if (pullParser.getName().equals("url")) {
foundURL = true;
}
} else if (eventType == XmlPullParser.END_TAG) {
// System.out.println("End tag "+pullParser.getName());
} else if (eventType == XmlPullParser.TEXT) {
// System.out.println("Text "+pullParser.getText().toString());
if (foundKey) {
apiKey = pullParser.getText();
foundKey = false;
} else if (foundID) {
curBlogID = pullParser.getText();
foundID = false;
} else if (foundURL) {
curBlogURL = pullParser.getText();
foundURL = false;
// make sure we're matching with a '/' at the end of
// the string, the api returns both with and w/o
if (!curBlogURL.endsWith("/"))
curBlogURL += "/";
if (((curBlogURL.equals(url) || (curBlogURL
.equals(wwwURL))) || storedBlogID
.equals(curBlogID))
&& !curBlogID.equals("1")) {
// yay, found a match
apiInfo = new Vector<String>();
apiInfo.add(apiKey);
apiInfo.add(curBlogID);
}
}
}
eventType = pullParser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
errorMsg = e.getLocalizedMessage();
e.printStackTrace();
}
return apiInfo;
}
private void configureClient(URI uri, String username, String password) {
postMethod = new HttpPost(uri);
postMethod.addHeader("charset", "UTF-8");
// UPDATE THE VERSION NUMBER BEFORE RELEASE! <3 Dan
postMethod.addHeader("User-Agent", "wp-android/2.1");
httpParams = postMethod.getParams();
HttpProtocolParams.setUseExpectContinue(httpParams, false);
UsernamePasswordCredentials creds;
// username & password for basic http auth
if (username != null) {
creds = new UsernamePasswordCredentials(username, password);
} else {
creds = new UsernamePasswordCredentials("", "");
}
// this gets connections working over https
if (uri.getScheme() != null) {
if (uri.getScheme().equals("https")) {
if (uri.getPort() == -1)
try {
client = new ConnectionClient(creds, 443);
} catch (KeyManagementException e) {
client = new ConnectionClient(creds);
} catch (NoSuchAlgorithmException e) {
client = new ConnectionClient(creds);
} catch (KeyStoreException e) {
client = new ConnectionClient(creds);
} catch (UnrecoverableKeyException e) {
client = new ConnectionClient(creds);
}
else
try {
client = new ConnectionClient(creds, uri.getPort());
} catch (KeyManagementException e) {
client = new ConnectionClient(creds);
} catch (NoSuchAlgorithmException e) {
client = new ConnectionClient(creds);
} catch (KeyStoreException e) {
client = new ConnectionClient(creds);
} catch (UnrecoverableKeyException e) {
client = new ConnectionClient(creds);
}
} else {
client = new ConnectionClient(creds);
}
} else {
client = new ConnectionClient(creds);
}
}
private class statsUserDataTask extends AsyncTask<String, Void, Vector<?>> {
protected void onPostExecute(Vector<?> result) {
titleBar.stopRotatingRefreshIcon();
if (result != null) {
// user's original login data worked
// store the api key and blog id
final String apiKey = result.get(0).toString();
final String apiBlogID = result.get(1).toString();
WordPress.currentBlog.setApi_blogid(apiBlogID);
WordPress.currentBlog.setApi_key(apiKey);
WordPress.currentBlog.save(ViewStats.this, "");
if (!isFinishing())
titleBar.startRotatingRefreshIcon();
new getStatsDataTask().execute(apiKey, apiBlogID, "views", 7);
} else {
// prompt for the username and password
if (firstRun > 0) {
Toast.makeText(
ViewStats.this,
getResources().getText(R.string.invalid_login)
+ " "
+ getResources().getText(
R.string.site_not_found),
Toast.LENGTH_SHORT).show();
}
firstRun++;
if (errorMsg.equals("")) {
showOrHideLoginForm();
} else {
errorMsg = "";
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(
ViewStats.this);
dialogBuilder.setTitle(getResources().getText(
R.string.connection_error));
dialogBuilder.setMessage(R.string.connection_error_occured);
dialogBuilder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// Just close the window.
}
});
dialogBuilder.setCancelable(true);
if (!isFinishing())
dialogBuilder.create().show();
}
}
}
@Override
protected Vector<?> doInBackground(String... args) {
Vector<?> apiInfo = getAPIInfo(args[0], args[1], args[2], args[3]);
return apiInfo;
}
}
public void showOrHideLoginForm() {
AnimationSet set = new AnimationSet(true);
if (loginShowing) {
loginShowing = !loginShowing;
Animation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setDuration(500);
set.addAnimation(animation);
animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 1.0f);
animation.setDuration(500);
set.addAnimation(animation);
;
RelativeLayout moderationBar = (RelativeLayout) findViewById(R.id.dotcomLogin);
moderationBar.clearAnimation();
moderationBar.startAnimation(set);
moderationBar.setVisibility(View.INVISIBLE);
} else {
loginShowing = !loginShowing;
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(500);
set.addAnimation(animation);
animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 1.0f,
Animation.RELATIVE_TO_SELF, 0.0f);
animation.setDuration(500);
set.addAnimation(animation);
RelativeLayout moderationBar = (RelativeLayout) findViewById(R.id.dotcomLogin);
moderationBar.setVisibility(View.VISIBLE);
moderationBar.startAnimation(set);
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && titleBar.isShowingDashboard) {
titleBar.hideDashboardOverlay();
return false;
}
return super.onKeyDown(keyCode, event);
}
private class statsChartTask extends AsyncTask<String, Bitmap, Bitmap> {
protected void onPostExecute(Bitmap bm) {
if (bm != null) {
ImageView iv = (ImageView) findViewById(R.id.chart);
iv.setImageBitmap(bm);
}
}
@Override
protected Bitmap doInBackground(String... args) {
Bitmap bm = null;
try {
URL url = new URL(args[0]);
URLConnection conn = url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bm;
}
}
private class getStatsDataTask extends AsyncTask<Object, String, String> {
String reportType;
int interval;
Vector<HashMap<String, String>> dataSet = new Vector<HashMap<String, String>>();
Vector<Integer> numDataSet = new Vector<Integer>();
protected void onPostExecute(String result) {
if (result != null) {
try {
if (dataSet.size() > 0) {
// only continue if we received data from the api
// ui thread
final int intervalT = interval;
RelativeLayout filters = (RelativeLayout) findViewById(R.id.filters);
filters.setVisibility(View.VISIBLE);
TextView reportTitle = (TextView) findViewById(R.id.chartTitle);
reportTitle.setVisibility(View.VISIBLE);
ImageView iv = (ImageView) findViewById(R.id.chart);
if (reportType.equals("views")) {
if (intervalT != 1) {
iv.setVisibility(View.VISIBLE);
} else {
iv.setVisibility(View.GONE);
}
reportTitle.setText(getResources().getText(
R.string.report_views));
String dataValues = "", dateStrings = "", xLabels = "";
Object[] key = numDataSet.toArray();
Arrays.sort(key);
// also adding data to table for display here
TableLayout tl = (TableLayout) findViewById(R.id.dataTable);
// clear out all existing rows
tl.removeAllViews();
// add header row
LayoutInflater inflater = getLayoutInflater();
TableRow table_row = (TableRow) inflater.inflate(
R.layout.table_row_header, tl, false);
TextView col_1 = (TextView) table_row
.findViewById(R.id.col1);
col_1.setText(getResources().getText(R.string.date));
col_1.setTypeface(Typeface.DEFAULT_BOLD);
TextView col_2 = (TextView) table_row
.findViewById(R.id.col2);
col_2.setText(getResources().getText(
R.string.report_views));
col_2.setTypeface(Typeface.DEFAULT_BOLD);
// Add row to TableLayout.
tl.addView(table_row);
HashMap<?, ?> row;
for (int i = 0; i < dataSet.size(); i++) {
row = (HashMap<?, ?>) dataSet.get(i);
String date;
try {
date = row.get("date").toString();
} catch (Exception e) {
return;
}
String value = numDataSet.get(i).toString();
dateStrings += date + ",";
dataValues += value + ",";
if (i == 0)
xLabels += date + "|";
else if (i == (dataSet.size() - 1))
xLabels += date;
else
xLabels += "|";
// table display work
// Create a new row to be added.
TableRow tr = (TableRow) inflater.inflate(
R.layout.table_row, tl, false);
// Create a view to be the row-content.
TextView col1 = (TextView) tr
.findViewById(R.id.col1);
col1.setText(date);
TextView col2 = (TextView) tr
.findViewById(R.id.col2);
col2.setText(value);
if (i % 2 == 0) {
// different background color for
// alternating rows
tr.setBackgroundColor(Color
.parseColor("#FFE6F0FF"));
// col1.setBackgroundColor(Color.parseColor("#FFE6F0FF"));
// col2.setBackgroundColor(Color.parseColor("#FFE6F0FF"));
}
// Add row to TableLayout.
tl.addView(tr);
}
int maxValue = Integer.parseInt(key[key.length - 1]
.toString());
int minValue = Integer.parseInt(key[0].toString());
dataValues = dataValues.substring(0,
dataValues.length() - 1);
dateStrings = dateStrings.substring(0,
dateStrings.length() - 1);
long minBuffer = Math.round(minValue
- (maxValue * .10));
if (minBuffer < 0) {
minBuffer = 0;
}
long maxBuffer = Math.round(maxValue
+ (maxValue * .10));
// round to the lowest 10 for prettier charts
for (int i = 0; i < 9; i++) {
if (minBuffer % 10 == 0)
break;
else {
minBuffer--;
}
}
for (int i = 0; i < 9; i++) {
if (maxBuffer % 10 == 0)
break;
else {
maxBuffer++;
}
}
long yInterval = maxBuffer / 10;
// round the gap in y axis of the chart
for (int i = 0; i < 9; i++) {
if (yInterval % 10 == 0)
break;
else {
yInterval++;
}
}
// calculate the grid spacing variables
float xGrid = 100.00f / 6;
if (yInterval == 0) {
// don't divide by zero!
yInterval = 1;
}
long numRows = (maxBuffer - minBuffer) / yInterval;
float yGrid = 100.00f / numRows;
// scale to screen size
Display display = getWindowManager()
.getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
String screenSize = "320x240";
if (width > 480 || height > 480) {
screenSize = "480x360";
}
// build the google chart api url
final String chartViewURL = "http://chart.apis.google.com/chart?chts=464646,20"
+ "&cht=bvs" + "&chbh=a" + "&chd=t:"
+ dataValues
+ "&chs="
+ screenSize
+ "&chxt=y,x"
+ "&chxl=1:|"
+ xLabels
+ "&chds="
+ minBuffer
+ ","
+ maxBuffer
+ "&chxr=0,"
+ minBuffer
+ ","
+ maxBuffer
+ ","
+ yInterval
+ "&chf=c,lg,90,FFFFFF,0,FFFFFF,0.5"
+ "&chco=a3bcd3,cccccc77"
+ "&chls=4"
+ "&chf=c,lg,90,FFFFFF,0,FFFFFF,0.5&chls=4&chxs=0,464646,19,0,t|1,464646,16,0,t,ffffff&chxtc=0,0"
+ "&chg=" + xGrid + "," + yGrid + ",1,0";
new statsChartTask().execute(chartViewURL);
} else if (reportType.equals("postviews")) {
reportTitle.setText(getResources().getText(
R.string.report_postviews));
iv.setVisibility(View.GONE);
Object[] key = numDataSet.toArray();
Arrays.sort(key);
// also adding data to table for display here
TableLayout tl = (TableLayout) findViewById(R.id.dataTable);
// clear out all existing rows
tl.removeAllViews();
// add header row
LayoutInflater inflater = getLayoutInflater();
TableRow table_row = (TableRow) inflater.inflate(
R.layout.table_row_header, tl, false);
// Create a Button to be the row-content.
TextView col_1 = (TextView) table_row
.findViewById(R.id.col1);
col_1.setText(getResources().getText(
R.string.report_post_title));
col_1.setTypeface(Typeface.DEFAULT_BOLD);
TextView col_2 = (TextView) table_row
.findViewById(R.id.col2);
col_2.setText(getResources().getText(
R.string.report_views));
col_2.setTypeface(Typeface.DEFAULT_BOLD);
// Add row to TableLayout.
tl.addView(table_row);
HashMap<?, ?> row;
for (int i = 0; i < dataSet.size(); i++) {
row = (HashMap<?, ?>) dataSet.get(i);
String date = row.get("title").toString();
String value = numDataSet.get(i).toString();
// table display work
// Create a new row to be added.
TableRow tr = (TableRow) inflater.inflate(
R.layout.table_row, tl, false);
// Create a Button to be the row-content.
TextView col1 = (TextView) tr
.findViewById(R.id.col1);
col1.setText(date);
TextView col2 = (TextView) tr
.findViewById(R.id.col2);
col2.setText(value);
if (i % 2 == 0) {
// different background color for
// alternating rows
tr.setBackgroundColor(Color
.parseColor("#FFE6F0FF"));
// col1.setBackgroundColor(Color.parseColor("#FFE6F0FF"));
// col2.setBackgroundColor(Color.parseColor("#FFE6F0FF"));
}
// Add row to TableLayout.
tl.addView(tr);
}
} else if (reportType.equals("referrers")
|| reportType.equals("searchterms")
|| reportType.equals("clicks")) {
iv.setVisibility(View.GONE);
Object[] key = numDataSet.toArray();
Arrays.sort(key);
// also adding data to table for display here
TableLayout tl = (TableLayout) findViewById(R.id.dataTable);
// clear out all existing rows
tl.removeAllViews();
// add header row
LayoutInflater inflater = getLayoutInflater();
TableRow table_row = (TableRow) inflater.inflate(
R.layout.table_row_header, tl, false);
// Create a Button to be the row-content.
TextView col_1 = (TextView) table_row
.findViewById(R.id.col1);
if (reportType.equals("referrers")) {
col_1.setText(getResources().getText(
R.string.report_referrers));
reportTitle.setText(getResources().getText(
R.string.report_referrers));
} else if (reportType.equals("searchterms")) {
reportTitle.setText(getResources().getText(
R.string.report_searchterms));
col_1.setText(getResources().getText(
R.string.report_searchterms));
} else {
reportTitle.setText(getResources().getText(
R.string.report_clicks));
col_1.setText(getResources().getText(
R.string.report_clicks));
}
col_1.setTypeface(Typeface.DEFAULT_BOLD);
TextView col_2 = (TextView) table_row
.findViewById(R.id.col2);
col_2.setText("Views");
col_2.setTypeface(Typeface.DEFAULT_BOLD);
// Add row to TableLayout.
tl.addView(table_row);
HashMap<?, ?> row;
for (int i = 0; i < dataSet.size(); i++) {
row = (HashMap<?, ?>) dataSet.get(i);
String date = row.get("value").toString();
String value = numDataSet.get(i).toString();
// table display work
// Create a new row to be added.
TableRow tr = (TableRow) inflater.inflate(
R.layout.table_row, tl, false);
// Create a Button to be the row-content.
TextView col1 = (TextView) tr
.findViewById(R.id.col1);
col1.setText(date);
Linkify.addLinks(col1, Linkify.WEB_URLS);
TextView col2 = (TextView) tr
.findViewById(R.id.col2);
col2.setText(value);
if (i % 2 == 0) {
// different background color for
// alternating rows
tr.setBackgroundColor(Color
.parseColor("#FFE6F0FF"));
// col1.setBackgroundColor(Color.parseColor("#FFE6F0FF"));
// col2.setBackgroundColor(Color.parseColor("#FFE6F0FF"));
}
// Add row to TableLayout.
tl.addView(tr);
}
}
if (!isFinishing())
titleBar.stopRotatingRefreshIcon();
} else {
titleBar.stopRotatingRefreshIcon();
RelativeLayout filters = (RelativeLayout) findViewById(R.id.filters);
filters.setVisibility(View.VISIBLE);
Toast.makeText(ViewStats.this,
getResources().getText(R.string.no_data_found),
Toast.LENGTH_SHORT).show();
}
} catch (NumberFormatException e) {
errorMsg = e.getMessage();
} catch (IllegalStateException e) {
errorMsg = e.getMessage();
} catch (NotFoundException e) {
errorMsg = e.getMessage();
}
}
if (!errorMsg.equals("")) {
titleBar.stopRotatingRefreshIcon();
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(
ViewStats.this);
dialogBuilder.setTitle(getResources().getText(
R.string.connection_error));
dialogBuilder.setMessage(errorMsg);
dialogBuilder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// Just close the window.
}
});
dialogBuilder.setCancelable(true);
if (!isFinishing()) {
dialogBuilder.create().show();
}
} else {
titleBar.stopRotatingRefreshIcon();
}
}
@Override
protected String doInBackground(Object... args) {
if (isFinishing()) {
finish();
}
String apiKey = (String) args[0];
String blogID = (String) args[1];
reportType = (String) args[2];
interval = (Integer) args[3];
String DATE_FORMAT = "yyyy-MM-dd";
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance(); // today
String period = "";
if (interval == 90) {
period = "&period=week";
interval = 12;
} else if (interval == 365) {
period = "&period=month";
interval = 11;
} else if (interval == -1) {
period = "&period=month";
}
String uriString = "https://ssl-stats.wordpress.com/csv.php"
+ "?api_key=" + apiKey + "&blog_id=" + blogID
+ "&format=xml&table=" + reportType + "&end="
+ sdf.format(c1.getTime()) + "&days=" + interval
+ "&limit=-1" + period;
vsoURI = uriString;
if (!reportType.equals("views")) {
uriString += "&summarize";
}
URI uri = URI.create(uriString);
configureClient(uri, null, null);
// execute HTTP POST request
HttpResponse response;
try {
response = client.execute(postMethod);
XmlPullParser pullParser = XmlPullParserFactory.newInstance()
.newPullParser();
HttpEntity entity = response.getEntity();
// change to pushbackinput stream 1/18/2010 to handle self
// installed
// wp sites that insert the BOM
PushbackInputStream is = new PushbackInputStream(
entity.getContent());
// get rid of junk characters before xml response. 60 = '<'.
// Added
// stopper to prevent infinite loop
int bomCheck = is.read();
int stopper = 0;
while (bomCheck != 60 && stopper < 20) {
bomCheck = is.read();
stopper++;
}
is.unread(bomCheck);
pullParser.setInput(is, "UTF-8");
int eventType = pullParser.getEventType();
boolean foundDataItem = false;
int rowCount = 0;
// parse the xml response
// most replies follow the same xml structure, so the data
// is stored
// in a vector for display after parsing
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
// System.out.println("Start document");
} else if (eventType == XmlPullParser.END_DOCUMENT) {
// System.out.println("End document");
} else if (eventType == XmlPullParser.START_TAG) {
String name = pullParser.getName();
if (name.equals("views") || name.equals("postviews")
|| name.equals("referrers")
|| name.equals("clicks")
|| name.equals("searchterms")
|| name.equals("videoplays")) {
} else if (pullParser.getName().equals("total")) {
// that'll do, pig. that'll do.
break;
} else {
foundDataItem = true;
// loop through the attributes, add them to the
// hashmap
HashMap<String, String> dataRow = new HashMap<String, String>();
for (int i = 0; i < pullParser.getAttributeCount(); i++) {
dataRow.put(pullParser.getAttributeName(i)
.toString(), pullParser
.getAttributeValue(i).toString());
}
if (dataRow != null) {
dataSet.add(rowCount, dataRow);
}
}
} else if (eventType == XmlPullParser.END_TAG) {
// System.out.println("End tag "+pullParser.getName());
} else if (eventType == XmlPullParser.TEXT) {
if (foundDataItem) {
if (pullParser.getText().toString() == "") {
numDataSet.add(rowCount, 0);
} else {
int value = 0;
// sometimes we get an empty string from the
// stats api, adding a catch here.
try {
value = Integer.parseInt(pullParser
.getText().toString());
} catch (NumberFormatException e) {
}
numDataSet.add(rowCount, value);
}
rowCount++;
foundDataItem = false;
}
}
eventType = pullParser.next();
}
return "OK";
} catch (ClientProtocolException e) {
errorMsg = e.getMessage();
return null;
} catch (IOException e) {
errorMsg = e.getMessage();
return null;
} catch (XmlPullParserException e) {
errorMsg = e.getMessage();
return null;
}
}
}
}