package com.radicaldynamic.groupinform.activities;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.TextView;
import android.widget.Toast;
import com.radicaldynamic.gcmobile.android.preferences.PreferencesActivity;
import com.radicaldynamic.groupinform.R;
import com.radicaldynamic.groupinform.application.Collect;
import com.radicaldynamic.groupinform.listeners.SynchronizeFoldersListener;
import com.radicaldynamic.groupinform.logic.InformOnlineState;
import com.radicaldynamic.groupinform.tasks.SynchronizeFoldersTask;
import com.radicaldynamic.groupinform.utilities.HttpUtils;
/*
* This screen displays information about the current client installation, status and
* other information pertaining to the device's registration with Inform Online.
*
* Things that the user should be able to see on this screen are:
*
* a) Inform Client version
* b) Inform Online account number
* c) Inform Online account key? (perhaps only if they are the account owner)
* d) Inform Online device PIN
* e) Current operation mode: online (direct connect vs. using local databases + synchronisation)
* OR disconnected (using local databases)
* f) Whether or not CouchDB is installed locally (and option to install if not installed and stop/start/restart the installed Couch)
* g) Local data storage usage
*/
public class ClientInformationActivity extends Activity implements SynchronizeFoldersListener
{
private static final String t = "ClientInformationActivity: ";
private static final int MENU_ACCOUNT_MEMBERS = 0;
private static final int MENU_PREFERENCES = 1;
private static final int MENU_RESET_PROFILE = 2;
// Dialog constants
private static final int CONFIRM_RESET_DIALOG = 0;
private static final int RESET_SUCCESSFUL_DIALOG = 1;
private static final int RESET_FAILED_DIALOG = 2;
private static final int RESET_PROGRESS_DIALOG = 3;
private SynchronizeFoldersTask mSynchronizeFoldersTask;
private Dialog mDialog;
private ProgressDialog mProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.about_gc);
setTitle(getString(R.string.main_menu_message));
TextView accountNumber = (TextView) findViewById(R.id.accountNumber);
TextView accountKey = (TextView) findViewById(R.id.accountKey);
accountNumber.setText(Collect.getInstance().getInformOnlineState().getAccountNumber());
accountKey.setText(Collect.getInstance().getInformOnlineState().getAccountKey());
TextView devicePin = (TextView) findViewById(R.id.devicePin);
TextView deviceEmail = (TextView) findViewById(R.id.deviceEmail);
devicePin.setText(Collect.getInstance().getInformOnlineState().getDevicePin());
try {
deviceEmail.setText(
Collect
.getInstance()
.getInformOnlineState()
.getAccountDevices()
.get(Collect.getInstance().getInformOnlineState().getDeviceId())
.getEmail()
);
} catch (NullPointerException e) {
// In the event that the device does not have access to this information yet
deviceEmail.setText(getString(R.string.tf_unavailable));
}
// Retrieve persistent data structures and processes
Object data = getLastNonConfigurationInstance();
if (data instanceof SynchronizeFoldersTask) {
mSynchronizeFoldersTask = (SynchronizeFoldersTask) data;
}
}
protected Dialog onCreateDialog(int id)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
mDialog = null;
switch (id) {
case CONFIRM_RESET_DIALOG:
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_alert)
.setMessage(R.string.tf_reset_warning_msg)
.setTitle(getString(R.string.tf_reset_inform) + "?")
.setPositiveButton(R.string.tf_reset, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mSynchronizeFoldersTask = new SynchronizeFoldersTask();
mSynchronizeFoldersTask.setListener(ClientInformationActivity.this);
mSynchronizeFoldersTask.setTransferMode(SynchronizeFoldersListener.MODE_PUSH);
mSynchronizeFoldersTask.execute();
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
mDialog = builder.create();
break;
case RESET_SUCCESSFUL_DIALOG:
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_info)
.setMessage(R.string.tf_reset_complete_msg)
.setTitle(R.string.tf_reset_complete)
.setPositiveButton(R.string.tf_exit_inform, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
setResult(RESULT_OK);
finish();
}
});
mDialog = builder.create();
break;
case RESET_FAILED_DIALOG:
builder
.setCancelable(false)
.setIcon(R.drawable.ic_dialog_alert)
.setMessage(R.string.tf_reset_incomplete_msg)
.setTitle(getString(R.string.tf_something_failed, R.string.tf_reset))
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
mDialog = builder.create();
break;
case RESET_PROGRESS_DIALOG:
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getText(R.string.tf_resetting_please_wait));
mProgressDialog.setIndeterminate(true);
mProgressDialog.setCancelable(false);
return mProgressDialog;
}
return mDialog;
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
menu.add(0, MENU_ACCOUNT_MEMBERS, 0, getString(R.string.tf_administer)).setIcon(R.drawable.ic_menu_allfriends);
menu.add(0, MENU_PREFERENCES, 0, getString(R.string.tf_preferences)).setIcon(R.drawable.ic_menu_preferences);
menu.add(0, MENU_RESET_PROFILE, 0, getString(R.string.tf_reset_device)).setIcon(R.drawable.ic_menu_close_clear_cancel).setEnabled(Collect.getInstance().getIoService().isSignedIn());
return true;
}
@Override
protected void onDestroy()
{
if (mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.dismiss();
// Clean up folder synchronization task
if (mSynchronizeFoldersTask != null) {
mSynchronizeFoldersTask.setListener(null);
if (mSynchronizeFoldersTask.getStatus() == AsyncTask.Status.FINISHED) {
mSynchronizeFoldersTask.cancel(true);
}
}
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
Intent i;
switch (item.getItemId()) {
case MENU_ACCOUNT_MEMBERS:
i = new Intent(this, AccountDeviceList.class);
startActivity(i);
break;
case MENU_PREFERENCES:
i = new Intent(this, PreferencesActivity.class);
startActivity(i);
break;
case MENU_RESET_PROFILE:
showDialog(CONFIRM_RESET_DIALOG);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onResume()
{
super.onResume();
// Handle resume of folder synchronization task
if (mSynchronizeFoldersTask != null) {
mSynchronizeFoldersTask.setListener(this);
if (mSynchronizeFoldersTask != null) {
if (mSynchronizeFoldersTask.getStatus() == AsyncTask.Status.RUNNING) {
synchronizationHandler(null);
} else if (mSynchronizeFoldersTask.getStatus() == AsyncTask.Status.FINISHED) {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
}
}
}
}
@Override
public Object onRetainNonConfigurationInstance()
{
if (mSynchronizeFoldersTask != null && mSynchronizeFoldersTask.getStatus() != AsyncTask.Status.FINISHED)
return mSynchronizeFoldersTask;
return null;
}
public class ResetDeviceTask extends AsyncTask<Void, Void, String>
{
@Override
protected String doInBackground(Void... params)
{
String url = Collect.getInstance().getInformOnlineState().getServerUrl() + "/device/reset";
return HttpUtils.getUrlData(url);
}
@Override
protected void onPreExecute()
{
// Ignore orientation changes (hacky but keeps this task simple)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
showDialog(RESET_PROGRESS_DIALOG);
}
@Override
protected void onPostExecute(String getResult)
{
dismissDialog(RESET_PROGRESS_DIALOG);
JSONObject result;
boolean success = false;
try {
result = (JSONObject) new JSONTokener(getResult).nextValue();
if (result.optString(InformOnlineState.RESULT, InformOnlineState.FAILURE).equals(InformOnlineState.OK))
success = true;
} catch (NullPointerException e) {
// Communication error
if (Collect.Log.ERROR) Log.e(Collect.LOGTAG, t + "no getResult to parse. Communication error with node.js server?");
e.printStackTrace();
} catch (JSONException e) {
// Parse error (malformed result)
if (Collect.Log.ERROR) Log.e(Collect.LOGTAG, t + "failed to parse getResult " + getResult);
e.printStackTrace();
}
if (success) {
Collect.getInstance().getInformOnlineState().resetDevice();
showDialog(RESET_SUCCESSFUL_DIALOG);
} else {
showDialog(RESET_FAILED_DIALOG);
}
}
}
@Override
public void synchronizationHandler(Message msg)
{
if (msg == null) {
// Close any existing progress dialogs
if (mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.dismiss();
// Start new dialog with suitable message
mProgressDialog = new ProgressDialog(ClientInformationActivity.this);
mProgressDialog.setMessage(getString(R.string.tf_synchronizing_folders_dialog_msg));
mProgressDialog.show();
} else {
// Update progress dialog
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.setMessage(getString(R.string.tf_synchronizing_folder_count_dialog_msg, msg.arg1, msg.arg2));
}
}
}
@Override
public void synchronizationTaskFinished(Bundle data)
{
if (mProgressDialog != null && mProgressDialog.isShowing())
mProgressDialog.dismiss();
if (data.getBoolean(SynchronizeFoldersListener.SUCCESSFUL)) {
new ResetDeviceTask().execute();
} else {
Toast.makeText(getApplicationContext(), getString(R.string.tf_communication_error_try_again), Toast.LENGTH_LONG).show();
}
}
}