com.radicaldynamic.groupinform.activities.AccountDeviceList.java Source code

Java tutorial

Introduction

Here is the source code for com.radicaldynamic.groupinform.activities.AccountDeviceList.java

Source

/*
 * Copyright (C) 2009 University of Washington
 * 
 * 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 com.radicaldynamic.groupinform.activities;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.app.ListActivity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.radicaldynamic.groupinform.R;
import com.radicaldynamic.groupinform.adapters.AccountDeviceListAdapter;
import com.radicaldynamic.groupinform.application.Collect;
import com.radicaldynamic.groupinform.logic.AccountDevice;
import com.radicaldynamic.groupinform.logic.InformOnlineState;
import com.radicaldynamic.groupinform.utilities.FileUtilsExtended;
import com.radicaldynamic.groupinform.utilities.HttpUtils;

/*
 * 
 */
public class AccountDeviceList extends ListActivity {
    private static final String t = "AccountDeviceList: ";

    private static final int MENU_ADD = Menu.FIRST;

    private RefreshViewTask mRefreshViewTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

        setContentView(R.layout.generic_list);
        setTitle(getString(R.string.app_name) + " > " + getString(R.string.tf_administer_devices));
    }

    @Override
    protected void onResume() {
        super.onResume();
        loadScreen();
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        //        menu.add(0, MENU_ADD, 0, getString(R.string.tf_create_group)).setIcon(R.drawable.ic_menu_add);
        return true;
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        // AdapterContextMenuInfo info = (AdapterContextMenuInfo)
        // item.getMenuInfo();
        switch (item.getItemId()) {
        default:
            return super.onContextItemSelected(item);
        }
    }

    /**
     * Stores the path of selected form and finishes.
     */
    @Override
    protected void onListItemClick(ListView listView, View view, int position, long id) {
        AccountDevice device = (AccountDevice) getListAdapter().getItem(position);

        // Only account owners should proceed to the next screen
        if (Collect.getInstance().getInformOnlineState().isAccountOwner()
                || Collect.getInstance().getInformOnlineState().getDeviceRole().equals(AccountDevice.ROLE_ADMIN)) {
            Intent i = new Intent(this, AccountDeviceActivity.class);
            i.putExtra(AccountDeviceActivity.KEY_DEVICE_ID, device.getId());
            startActivity(i);
        } else {
            Toast.makeText(getApplicationContext(), getString(R.string.tf_action_reserved_for_admin),
                    Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case MENU_ADD:
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /*
     * Refresh the main form browser view as requested by the user
     */
    private class RefreshViewTask extends AsyncTask<Void, Void, Void> {
        private ArrayList<AccountDevice> devices = new ArrayList<AccountDevice>();

        @Override
        protected Void doInBackground(Void... nothing) {
            if (FileUtilsExtended.isFileOlderThan(
                    getCacheDir() + File.separator + FileUtilsExtended.DEVICE_CACHE_FILE,
                    FileUtilsExtended.TIME_TWO_MINUTES))
                fetchDeviceList(false);

            devices = loadDeviceList();

            return null;
        }

        @Override
        protected void onPreExecute() {
            setProgressBarIndeterminateVisibility(true);
        }

        @Override
        protected void onPostExecute(Void nothing) {
            RelativeLayout onscreenProgress = (RelativeLayout) findViewById(R.id.progress);
            onscreenProgress.setVisibility(View.GONE);

            if (devices.isEmpty()) {
                TextView nothingToDisplay = (TextView) findViewById(R.id.nothingToDisplay);
                nothingToDisplay.setVisibility(View.VISIBLE);
            } else {
                AccountDeviceListAdapter adapter;

                adapter = new AccountDeviceListAdapter(getApplicationContext(), R.layout.folder_list_item, devices);

                setListAdapter(adapter);
            }

            setProgressBarIndeterminateVisibility(false);
        }
    }

    /*
     * Fetch a new device list from Inform Online and store it on disk 
     * (also store a hashed copy for later)
     */
    static public void fetchDeviceList(boolean fetchAnyway) {
        if (Collect.getInstance().getIoService().isSignedIn() || fetchAnyway) {
            if (Collect.Log.INFO)
                Log.i(Collect.LOGTAG, t + "fetching list of devices");
        } else {
            if (Collect.Log.INFO)
                Log.i(Collect.LOGTAG, t + "not signed in, skipping device list fetch");
            return;
        }

        // Try to ping the service to see if it is "up"
        String deviceListUrl = Collect.getInstance().getInformOnlineState().getServerUrl() + "/device/list";
        String getResult = HttpUtils.getUrlData(deviceListUrl);
        JSONObject jsonDeviceList;

        try {
            jsonDeviceList = (JSONObject) new JSONTokener(getResult).nextValue();

            String result = jsonDeviceList.optString(InformOnlineState.RESULT, InformOnlineState.ERROR);

            if (result.equals(InformOnlineState.OK)) {
                // Write out list of jsonDevices for later retrieval by loadDevicesList() and InformOnlineService.loadDevicesHash()                
                JSONArray jsonDevices = jsonDeviceList.getJSONArray("devices");

                //                // Record the number of seats that this account is licenced for
                //                Collect
                //                    .getInstance()
                //                    .getInformOnlineState()
                //                    .setAccountLicencedSeats(jsonDeviceList.getInt("licencedSeats"));       

                //                // Record the plan type for this account (this is a weird place to do it in but it makes sense to piggyback)
                //                Collect
                //                    .getInstance()
                //                    .getInformOnlineState()
                //                    .setAccountPlan(jsonDeviceList.getString("planType"));
                try {
                    // Write out a device list cache file
                    FileOutputStream fos = new FileOutputStream(
                            new File(Collect.getInstance().getCacheDir(), FileUtilsExtended.DEVICE_CACHE_FILE));
                    fos.write(jsonDevices.toString().getBytes());
                    fos.close();
                } catch (Exception e) {
                    if (Collect.Log.ERROR)
                        Log.e(Collect.LOGTAG, t + "unable to write device cache: " + e.toString());
                    e.printStackTrace();
                }
            } else {
                // There was a problem... handle it!
            }
        } 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();
        }
    }

    public static ArrayList<AccountDevice> loadDeviceList() {
        if (Collect.Log.DEBUG)
            Log.d(Collect.LOGTAG, t + "loading device cache");

        ArrayList<AccountDevice> devices = new ArrayList<AccountDevice>();

        if (!new File(Collect.getInstance().getCacheDir(), FileUtilsExtended.DEVICE_CACHE_FILE).exists()) {
            if (Collect.Log.WARN)
                Log.w(Collect.LOGTAG, t + "device cache file cannot be read: aborting loadDeviceList()");
            return devices;
        }

        try {
            FileInputStream fis = new FileInputStream(
                    new File(Collect.getInstance().getCacheDir(), FileUtilsExtended.DEVICE_CACHE_FILE));
            InputStreamReader reader = new InputStreamReader(fis);
            BufferedReader buffer = new BufferedReader(reader, 8192);
            StringBuilder sb = new StringBuilder();

            String cur;

            while ((cur = buffer.readLine()) != null) {
                sb.append(cur + "\n");
            }

            buffer.close();
            reader.close();
            fis.close();

            try {
                //                int assignedSeats = 0;

                JSONArray jsonDevices = (JSONArray) new JSONTokener(sb.toString()).nextValue();

                for (int i = 0; i < jsonDevices.length(); i++) {
                    JSONObject jsonDevice = jsonDevices.getJSONObject(i);

                    AccountDevice device = new AccountDevice(jsonDevice.getString("id"),
                            jsonDevice.getString("rev"), jsonDevice.getString("alias"),
                            jsonDevice.getString("email"), jsonDevice.getString("status"));

                    // Optional information that will only be present if the user is also an account owner
                    device.setLastCheckin(jsonDevice.optString("lastCheckin"));
                    device.setPin(jsonDevice.optString("pin"));
                    device.setRole(jsonDevice.optString("role"));

                    // Update the lookup hash
                    Collect.getInstance().getInformOnlineState().getAccountDevices().put(device.getId(), device);

                    // Show a device so long as it hasn't been marked as removed
                    if (!device.getStatus().equals("removed")) {
                        devices.add(device);
                        //                        assignedSeats++;
                    }
                }

                //                // Record the number of seats in this account that are assigned & allocated (not necessarily "active")
                //                Collect.getInstance().getInformOnlineState().setAccountAssignedSeats(assignedSeats);
            } catch (JSONException e) {
                // Parse error (malformed result)
                if (Collect.Log.ERROR)
                    Log.e(Collect.LOGTAG, t + "failed to parse JSON " + sb.toString());
                e.printStackTrace();
            }
        } catch (Exception e) {
            if (Collect.Log.ERROR)
                Log.e(Collect.LOGTAG, t + "unable to read device cache: " + e.toString());
            e.printStackTrace();
        }

        return devices;
    }

    /**
     * Load the various elements of the screen that must wait for other tasks to
     * complete
     */
    private void loadScreen() {
        mRefreshViewTask = new RefreshViewTask();
        mRefreshViewTask.execute();

        registerForContextMenu(getListView());
    }
}