MainActivity.java
//##########################################
package com.ca.kopja02.maadata;
import android.app.Activity;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.text.method.ScrollingMovementMethod;
import android.util.Base64;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
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.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
// Android app code to consume CA MAA Web Services reports. kopja02@ca.com @CA Technologies, 2015
public class MainActivity extends Activity implements View.OnClickListener {
// Initiate public String for capturing API call result
public String GETresult = null;
public String GETmsg = null;
private Button btn;
private CheckBox saveLoginCheckBox;
private static final String USERNAME = "username";
private static final String TENANT = "tenant";
private static final String SERVER = "server";
public static final String PREFS_NAME = "MyPrefsFile";
LinearLayout linearChart;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// value=(EditText)findViewById(R.id.editText1);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(this);
// Change static field font to CA Sans, and CA logo to imageButton
TextView caTextView = (TextView) findViewById(R.id.txtLogin);
TextView result = (TextView) findViewById(R.id.txtResult);
// set a soft shadow to text to mark it as result output
// result.setShadowLayer(10, 0, 0, Color.WHITE);
// Set CA typeface
Typeface myCA = Typeface.createFromAsset(getAssets(), "fonts/CA Sans-Bold.ttf");
caTextView.setTypeface(myCA);
btn.setTypeface(myCA);
result.setMovementMethod(new ScrollingMovementMethod());
// RETRIEVE SAVED USERNAME, tenant and server URL
SharedPreferences pref = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
String username = pref.getString(USERNAME, null);
String cohort = pref.getString(TENANT, null);
String serverURL = pref.getString(SERVER, null);
EditText uname = (EditText) findViewById(R.id.fld_username);
uname.setText(username);
EditText server = (EditText) findViewById(R.id.fld_server);
server.setText(serverURL);
EditText tenant = (EditText) findViewById(R.id.fld_enter_org);
tenant.setText(cohort);
}
public void onClick(View v) {
// check for entered username, pwd etc and set output initial 'processing' messages
TextView resText = (TextView) findViewById(R.id.txtResult);
TextView resText2 = (TextView) findViewById(R.id.txtResult2);
TextView resTextRaw = (TextView) findViewById(R.id.txtResultRaw);
resText.setText("Check login information");
resText2.setText("");
resTextRaw.setText("");
EditText uname = (EditText) findViewById(R.id.fld_username);
EditText password = (EditText) findViewById(R.id.fld_password);
EditText server = (EditText) findViewById(R.id.fld_server);
EditText tenant = (EditText) findViewById(R.id.fld_enter_org);
String strUserName = uname.getText().toString();
String strPwd = password.getText().toString();
String svr = server.getText().toString();
String ten = tenant.getText().toString();
// hide soft keyboard after button click
InputMethodManager inputManager = (InputMethodManager)
getSystemService(this.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow((null == getCurrentFocus()) ? null : getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
// save username into local preferences file "MyPrefsFile" if saveLogin is checked
CheckBox saveLogin = (CheckBox) findViewById(R.id.saveLoginCheckBox);
if (saveLogin.isChecked()) {
getSharedPreferences(PREFS_NAME, MODE_PRIVATE)
.edit()
.putString(USERNAME, strUserName)
.putString(TENANT, ten)
.putString(SERVER, svr)
.commit();
}
// check all input fields to make sure they have a value before executing
if (!isValidPassword(strUserName)) {
uname.setError("Username required");
//finish();
} else if (!isValidPassword(strPwd)) {
password.setError("Password required");
//finish();
} else if (!isValidPassword(ten)) {
tenant.setError("MAA Tenant ID required");
// finish();
} else if (!isValidPassword(svr)) {
server.setError("Server base URL required");
// finish();
// Test if entered URL has connectivity
} else if (!conn_test(svr)) {
server.setError("URL has no connectivity");
} else {
// Process login request
resText.setText("Processing...");
resText2.setText("");
resTextRaw.setText("");
// All required fields have a correct value. Execute async background process to POST and GET data.
new MyAsyncTask().execute("test");
}
}
private class MyAsyncTask extends AsyncTask<String, String, String> {
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
postData(GETresult);
return null;
}
protected void onPostExecute(String result) {
// Toast toast = Toast.makeText(getApplicationContext(), "Data received", Toast.LENGTH_SHORT);
// toast.setGravity(Gravity.TOP | Gravity.RIGHT, 0, 0);
// toast.show();
// Appending the API call result from global string GETresult to TextViews. Parse first
// set initial responses - input2 for parsing output if present, input3 for login errors and raw output
String input2 = GETresult;
String input3 = GETresult;
// Parsing according to report type and spinner1 selection.....they all output different data
try {
Spinner urls = (Spinner) findViewById(R.id.spinner1);
//############ USERS ##################
if (urls.getSelectedItem().toString().equals("Users")) {
input2 = input2.replaceAll("00:00:00", "").replaceAll("\"", "").replaceAll("\\],", " \n").replaceAll("\\[|\\]", "").replaceAll("\\{|\\}", "");
// Go through parsed input2 line by line to only get certain data from it
Scanner scan = new Scanner(new StringReader(input2));
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
while (scan.hasNextLine()) {
String line = scan.nextLine();
// System.out.println(line);
// only split on the first : delimiter (split(":",2) to preserve further constructs like 'LENOVO: avg_cpu: 35' on the same line with device performace report
String[] parts = line.split(",");
// loop throug resulting string array. check items length to avoid arrayOutOfBounds -exceptions and look for certain values only
// Construct semicolon separated input2 -string for display using date format found
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
Pattern p = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\d");
for (int i = 0; i < parts.length - 1; i++) {
Matcher m = p.matcher(parts[i].trim());
if (m.find()) {
sb1.append("Date:" + parts[i] + "\n");
sb1.append("Total users:" + parts[i + 1] + "\n");
sb1.append("New users:" + parts[i + 2] + "\n");
sb1.append("Repeat users:" + parts[i + 3] + "\n");
}
}
input2 = sb1.toString();
}
//############ ACTIVE USERS ##################
} else if (urls.getSelectedItem().toString().equals("Active Users")) {
input2 = input2.replaceAll("00:00:00", "").replaceAll("\"", "").replaceAll("\\],", " \n").replaceAll("\\[|\\]", "").replaceAll("\\{|\\}", "");
// Go through input2 to only get certain data from it
Scanner scan = new Scanner(new StringReader(input2));
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
while (scan.hasNextLine()) {
String line = scan.nextLine();
// System.out.println(line);
// only split on the first : delimiter (split(":",2) to preserve further constructs like 'LENOVO: avg_cpu: 35' on the same line with device performace report
String[] parts = line.split(",");
// loop throug resulting string array. check items length to avoid arrayOutOfBounds -exceptions and look for certain values only
// Construct semicolon separated input2 -string for display
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
Pattern p = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\d");
for (int i = 0; i < parts.length - 1; i++) {
Matcher m = p.matcher(parts[i].trim());
if (m.find()) {
// if (parts[i].matches("^*[0-9]{4}-*")) {
sb1.append(parts[i] + ":" + parts[i + 1] + "\n");
}
}
input2 = sb1.toString();
}
//############ SESSIONS ##################
} else if (urls.getSelectedItem().toString().equals("Sessions")) {
input2 = input2.replaceAll("00:00:00", "").replaceAll("\"", "").replaceAll("\\],", " \n").replaceAll("\\[|\\]", "").replaceAll("\\{|\\}", "").trim();
// Go through input2 to only get certain data from it
Scanner scan = new Scanner(new StringReader(input2));
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
while (scan.hasNextLine()) {
String line = scan.nextLine();
//System.out.println(line);
// only split on the first : delimiter (split(":",2) to preserve further constructs like 'LENOVO: avg_cpu: 35' on the same line with device performace report
String[] parts = line.split(",");
// loop throug resulting string array. check items length to avoid arrayOutOfBounds -exceptions and look for certain values only
// Construct semicolon separated input2 -string for display
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");
Pattern p = Pattern.compile("\\d\\d\\d\\d-\\d\\d-\\d\\d");
for (int i = 0; i < parts.length - 1; i++) {
Matcher m = p.matcher(parts[i].trim());
if (m.find()) {
// if (parts[i].matches("^*[0-9]{4}-*")) {
sb1.append(parts[i] + ":" + parts[i + 2] + "\n");
}
}
input2 = sb1.toString();
}
//############ REGISTERED APPS ##################
} else if (urls.getSelectedItem().toString().equals("Registered Apps")) {
// not a valid JSON object, so just parse the whole result
input2 = input2.replaceAll("appId", "Application name").replaceAll("\",", " \n").replaceAll("\"", "").replaceAll(",", " \n").replaceAll("\\[|\\]", "").replaceAll("\\{|\\}", "").replaceAll("_", " ");
// Go through input2 to only get appId data from it
Scanner scan = new Scanner(new StringReader(input2));
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
while (scan.hasNextLine()) {
String line = scan.nextLine();
// System.out.println(line);
// only split on the first : delimiter (split(":",2) to preserve further constructs like 'LENOVO: avg_cpu: 35' on the same line with device performace report
String[] parts = line.split(":", 2);
// loop throug resulting string array. check items length to avoid arrayOutOfBounds -exceptions and look for certain values only
final Set<String> values = new HashSet<String>(Arrays.asList("Application name", "status", "secure", "state"));
for (int i = 0; i < parts.length - 1; i++) {
if (values.contains(parts[i])) {
sb1.append(parts[i] + ":" + (parts[i + 1] + "\n"));
}
}
input2 = sb1.toString();
}
//############ APP PERFORMANCE ##################
} else if (urls.getSelectedItem().toString().equals("App Performance")) {
JSONObject jObject = new JSONObject(GETresult);
input2 = jObject.getString("averages");
input2 = input2.replaceAll("],", "\n").replaceAll("\\[|\\]", "").replaceAll("00:00", "00").replaceAll("\\{|\\}", "").replace("\"", "").replaceAll(",", "\n").replaceAll("_", " ");
//############ DEVICE PERFORMANCE ##################
} else if (urls.getSelectedItem().toString().equals("Device Performance")) {
JSONObject jObject = new JSONObject(GETresult);
input2 = jObject.getString("result");
input2 = input2.replaceAll("],", "\n").replaceAll("\\[|\\]", "").replaceAll("\\{|\\}", "").replace("\"", "").replaceAll(",", "\n").replaceAll("_", " ");
//############ ACTIVITY BY GEO ##################
} else if (urls.getSelectedItem().toString().equals("Activity by Geo")) {
JSONObject jObject = new JSONObject(GETresult);
input2 = jObject.getString("countries");
input2 = input2.replaceAll("],", "\n").replaceAll("\\[|\\]", "").replaceAll("\\{|\\}", "").replace("\"", "").replaceAll(",", ":");
//############ CRASH SUMMARY ##################
} else if (urls.getSelectedItem().toString().equals("Crash Summary")) {
JSONObject jObject = new JSONObject(GETresult);
input2 = jObject.getString("total_summary");
// Among other things, replace 00:00 time constructs with 00 to make splitting easier
input2 = input2.replaceAll("],", "\n").replaceAll("00:00", "00").replaceAll("\\[|\\]", "").replaceAll("\\{|\\}", "").replace("\"", "").replaceAll(",", "\n").replaceAll("_", " ");
//############ CRASH SUMMARY BY APPS ##################
} else if (urls.getSelectedItem().toString().equals("Crash Summary by Apps")) {
JSONObject jObject = new JSONObject(GETresult);
input2 = jObject.getString("result");
input2 = input2.replaceAll("\\],", "\n").replaceAll("\\[|\\]", "").replace("\"", "").replace(",", ":").replaceAll("_", " ");
//############ OTHER ##################
} else {
// just show input without parsing
input2 = input2.replaceAll("\\],", "\n").replaceAll("\\[|\\]", "").replace("\"", "").replace(",", ": ").replaceAll("_", " ");
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// comment out debug messages
// System.out.print("OUTPUT: "+input2);
// parse error message if there
input3 = input3.replaceAll("\\{|\\}", "").replace("\"", "").replace(",", ": ").replaceAll("_", " ");
// if actual responseis empty, use error message
if (input2.length() < 1) input2 = input3;
// scan the input string line by line and separate tokens into two text views for clarity
Scanner scan = new Scanner(new StringReader(input2));
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
while (scan.hasNextLine()) {
String line = scan.nextLine();
// only split on the first : delimiter (split(":",2) to preserve further constructs like 'LENOVO: avg_cpu: 35' on the same line with device performace report
String[] parts = line.split(":", 2);
// loop throug resulting string array. check items length to avoid arrayOutOfBounds -exceptions for empty ones
for (int i = 0; i < parts.length - 1; i++) {
sb1.append(parts[i].trim() + "\n");
sb2.append(parts[i + 1].trim() + "\n");
}
}
TextView resText1 = (TextView) findViewById(R.id.txtResult);
TextView resText2 = (TextView) findViewById(R.id.txtResult2);
TextView resTextRaw = (TextView) findViewById(R.id.txtResultRaw);
//Display raw or parsed output depending on user selection
CheckBox rawOutput = (CheckBox) findViewById(R.id.rawOutputCheckBox);
Typeface myCA = Typeface.createFromAsset(getAssets(), "fonts/CA Sans-Bold.ttf");
rawOutput.setTypeface(myCA);
if (rawOutput.isChecked()) {
resTextRaw.setText(GETresult);
resText1.setText("");
} else {
resText1.setText(sb1);
resText2.setText(sb2);
resTextRaw.setText("");
}
}
public String postData(String valueIWantToSend) {
// execute the httpClient requests in sequence: first POST to get token, and GET to get data
EditText uname = (EditText) findViewById(R.id.fld_username);
EditText password = (EditText) findViewById(R.id.fld_password);
EditText server = (EditText) findViewById(R.id.fld_server);
EditText tenant = (EditText) findViewById(R.id.fld_enter_org);
String username = uname.getText().toString();
String pwd = password.getText().toString();
String targeturl = server.getText().toString();
String org = tenant.getText().toString();
// POST first to get Basic token - base64 encode
String POSTtarget = targeturl + "/ess/security/v1/token";
String headerOrg = new String("Basic " + Base64.encodeToString(org.getBytes(), Base64.NO_WRAP));
//System.out.println(headerOrg);
try {
// Create a new HttpClient
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(POSTtarget);
// Add your headers with tenant base64 authorization
httppost.setHeader("Content-type", "application/x-www-form-urlencoded");
httppost.setHeader("Authorization", headerOrg);
httppost.setHeader("Cache-Control", "no-cache");
// pass the body of the request as a String entity
String myPayload = ("username=" + username + "&password=" + pwd + "&grant_type=PASSWORD");
HttpEntity entity = new ByteArrayEntity(myPayload.getBytes("UTF-8"));
httppost.setEntity(entity);
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
// System.out.println(response);
// read response line by line to string builder to build a json object for parsing
BufferedReader br = new BufferedReader(new InputStreamReader(
(response.getEntity().getContent())));
StringBuilder sb = new StringBuilder();
String output;
// System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
//System.out.println(output);
sb.append(output + "\n");
}
String result = sb.toString();
// set initial response in case failures - this will output if login fails or something else goes wrong with the authorization
GETresult = result;
String bearerTkn = null;
String errTkn = null;
try {
JSONObject jObject = new JSONObject(result);
// get access token by parsing the JSON object tkn -value
bearerTkn = jObject.getString("tkn");
//System.out.println("tkn " + bearerTkn);
} catch (JSONException je) {
je.printStackTrace();
}
// Build Bearer token and encode it
String bearerToken = "{\"tkn\":\"" + bearerTkn + "\",\"all\":\"true\"}";
String headerAz = new String("Bearer " + Base64.encodeToString(bearerToken.getBytes(), Base64.NO_WRAP));
//System.out.println("Bearer " + headerAz);
// get a reference to selected period from spinner2
Spinner periods = (Spinner) findViewById(R.id.spinner1_new);
String period_ext = periods.getSelectedItem().toString();
// Get a reference to the selected report spinner1
Spinner urls = (Spinner) findViewById(R.id.spinner1);
String url_ext = null;
// Build correct URL extension for each report
if (urls.getSelectedItem().toString().equals("Registered Apps"))
url_ext = "/mdo/v1/apps";
else if (urls.getSelectedItem().toString().equals("App Performance"))
url_ext = "/mdo/v1/performance/apps";
// else if (urls.getSelectedItem().toString().equals("URL Performance"))
// url_ext = "/mdo/v1/performance/urls";
// else if (urls.getSelectedItem().toString().equals("Carrier Performance"))
// url_ext = "/mdo/v1/performance/carrier";
else if (urls.getSelectedItem().toString().equals("Device Performance"))
url_ext = "/mdo/v1/performance/devices";
else if (urls.getSelectedItem().toString().equals("Error Codes"))
url_ext = "/mdo/v1/performance/errorcodes";
// else if (urls.getSelectedItem().toString().equals("App Summary"))
// url_ext = "/mdo/v1/performance/apps_summary";
else if (urls.getSelectedItem().toString().equals("Users"))
url_ext = "/mdo/v1/usage/users";
else if (urls.getSelectedItem().toString().equals("Active Users"))
url_ext = "/mdo/v1/usage/active_users";
else if (urls.getSelectedItem().toString().equals("Sessions"))
url_ext = "/mdo/v1/usage/sessions";
else if (urls.getSelectedItem().toString().equals("Activity by Geo"))
url_ext = "/mdo/v1/usage/geo";
else if (urls.getSelectedItem().toString().equals("Crash Summary"))
url_ext = "/mdo/v1/crashes/crash_summary";
else if (urls.getSelectedItem().toString().equals("Crash Summary by Apps"))
url_ext = "/mdo/v1/crashes/crash_summary_by_apps";
else url_ext = urls.getSelectedItem().toString();
// Get start date of -30, -7 and -1 days ago. Construct filter URL extension for aggregation and start / end accordingly
Calendar cal = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
cal.add(Calendar.DATE, +1);
String today = String.valueOf(dateFormat.format(cal.getTime()));
cal.add(Calendar.DATE, -1);
String yesterday = String.valueOf(dateFormat.format(cal.getTime()));
cal.add(Calendar.DATE, -7);
String week = String.valueOf(dateFormat.format(cal.getTime()));
cal.add(Calendar.DATE, -30);
String month = String.valueOf(dateFormat.format(cal.getTime()));
String p = null;
// build the correct period URL extensions for monthly, weekly and daily reports
if (period_ext.equals("Month")) {
p = "?aggregation=month&end_date=" + today + "&start_date=" + month;
// System.out.println("Fetching data for month: end_date=" + today + ", start_date=" + month);
} else if (period_ext.equals("Week")) {
p = "?aggregation=week&end_date=" + today + "&start_date=" + week;
// System.out.println("Fetching data for last 7 days");
} else if (period_ext.equals("Day")) {
p = "?aggregation=day&end_date=" + today + "&start_date=" + yesterday;
// System.out.println("Fetching data for last 24 hours");
} else p = "?aggregation=month&end_date=" + today + "&start_date=" + month;
//System.out.println(p);
// Build complete GET URLkopja02
String GETtarget = targeturl + url_ext + p;
// System.out.println(GETtarget);
// Create a new HttpClient and Post Header
HttpClient httpclient2 = new DefaultHttpClient();
HttpGet httpget = new HttpGet(GETtarget);
//httppost2.setHeader("Content-type", "application/x-www-form-urlencoded");
httpget.setHeader("Authorization", headerAz);
httpget.setHeader("Cache-Control", "no-cache");
httpget.setHeader("Accept", "Application/json");
// Execute HTTP Post Request
HttpResponse response2 = httpclient.execute((httpget));
// System.out.println(response2);
// read response line by line to string builder to build a json object for parsing
BufferedReader br2 = new BufferedReader(new InputStreamReader(
(response2.getEntity().getContent())));
StringBuilder sb2 = new StringBuilder();
String output2;
// System.out.println("GET Output from Server .... \n");
while ((output2 = br2.readLine()) != null) {
//System.out.println(output2);
sb2.append(output2 + "\n");
}
String result2 = sb2.toString();
//System.out.print(result2);
GETresult = result2;
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
// } catch (JSONException e) {
e.printStackTrace();
}
return GETresult;
}
}
// ######### validate username etc fields to make sure they contain characters #########
private boolean isValidPassword(String pass) {
if (pass != null && pass.length() > 0 && !pass.equals("")) {
return true;
}
return false;
}
//################# check URL connectio #############
public boolean conn_test(String URL) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
EditText server = (EditText) findViewById(R.id.fld_server);
String targeturl = server.getText().toString();
boolean res = false;
String POSTtarget = targeturl + "/admin/maa";
// System.out.println(POSTtarget);
try {
URL url = new URL(POSTtarget);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(5000);
conn.connect();
res = true;
} catch (Exception e) {
res = false;
//System.out.println("can't connect / " + e.toString());
}
return res;
}
//###############
}
//### END END END #################################