Java tutorial
/* * 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()); } }