package com.ushahidi.android.app.ui.tablet; import java.util.Date; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import com.actionbarsherlock.view.MenuItem; import com.ushahidi.android.app.Preferences; import com.ushahidi.android.app.R; import com.ushahidi.android.app.Settings; import com.ushahidi.android.app.adapters.ListMapAdapter; import com.ushahidi.android.app.fragments.BaseListFragment; import com.ushahidi.android.app.helpers.ActionModeHelper; import com.ushahidi.android.app.models.ListMapModel; import com.ushahidi.android.app.services.FetchReports; import com.ushahidi.android.app.services.SyncServices; import com.ushahidi.android.app.tasks.LoadMapTask; import com.ushahidi.android.app.ui.phone.ReportTabActivity; import com.ushahidi.android.app.util.Util; import com.ushahidi.android.app.views.AddMapView; import com.ushahidi.android.app.views.ListMapView; public class ListMapFragment extends BaseListFragment<ListMapView, ListMapModel, ListMapAdapter> implements LocationListener { private final String[] items = { "50", "100", "250", "500", "750", "1000", "1500" }; public static final int DIALOG_DISTANCE = 0; public static final int DIALOG_CLEAR_DEPLOYMENT = 1; public static final int DIALOG_ADD_DEPLOYMENT = 2; public static final int DIALOG_SHOW_MESSAGE = 3; private LocationManager mLocationMgr = null; private static Location location; private String distance = ""; private Handler mHandler; private int mId = 0; private int mapId = 0; private int sId = 0; private ListMapModel mListMapModel; public boolean edit = true; private String filter; private ListMapFragmentListener listener = null; private String errorMessage = ""; private static final String STATE_CHECKED = "com.ushahidi.android.app.activity.STATE_CHECKED"; public static final String BUG_1997_FIX = "bug_19917_fix"; private Intent fetchReports; private LoadMapTask mDeploymentTask; public ProgressDialog dialog; public ListMapFragment() { super(ListMapView.class, ListMapAdapter.class, R.layout.list_map, 0, android.R.id.list); mHandler = new Handler(); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setHasOptionsMenu(true); mListMapModel = new ListMapModel(); this.dialog = new ProgressDialog(getActivity()); this.dialog.setCancelable(true); this.dialog.setIndeterminate(true); this.dialog.setMessage(getString(R.string.please_wait)); if (Util.isHoneycomb()) { listView.setLongClickable(true); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setOnItemLongClickListener(new ActionModeHelper(this, listView)); } else { registerForContextMenu(listView); } // filter map list if (view != null) { if (view.mSearchMap != null) { view.mSearchMap.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable arg0) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { if (!(TextUtils.isEmpty(s.toString()))) { filter = s.toString(); mHandler.post(filterMapList); } else { mHandler.post(fetchMapList); } } }); } } if (savedInstanceState != null) { int position = savedInstanceState.getInt(STATE_CHECKED, -1); if (position > -1) { listView.setItemChecked(position, true); } } } private void fetchReports(int id) { if (id != 0) { mListMapModel.activateDeployment(getActivity(), id); dialog.show(); fetchReports = new Intent(getActivity(), FetchReports.class); getActivity().startService(fetchReports); } } @Override public void onSaveInstanceState(Bundle state) { if (state.isEmpty()) { state.putBoolean("bug_19917_fix", true); } state.putInt(STATE_CHECKED, listView.getCheckedItemPosition()); super.onSaveInstanceState(state); } @Override public void onResume() { super.onResume(); getActivity().registerReceiver(broadcastReceiver, new IntentFilter(SyncServices.SYNC_SERVICES_ACTION)); mHandler.post(fetchMapList); } @Override public void onStart() { super.onStart(); } @Override public void onDestroy() { super.onDestroy(); stopLocating(); } public void onPause() { super.onPause(); try { getActivity().unregisterReceiver(broadcastReceiver); } catch (IllegalArgumentException e) { } if (mDeploymentTask != null) { mDeploymentTask.cancel(true); } } public void setListMapListener(ListMapFragmentListener listener) { this.listener = listener; } public void enablePersistentSelection() { getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); } /** * Delete individual messages 0 - Successfully deleted. 1 - There is nothing * to be deleted. */ final Runnable mDeleteMapById = new Runnable() { public void run() { boolean status = false; status = mListMapModel.deleteMapById(mId); try { if (status) { toastShort(R.string.map_deleted); refreshMapLists(); } else { toastShort(R.string.map_deleted_failed); } } catch (Exception e) { return; } } }; /** * Refresh the list view with new items */ final Runnable fetchMapList = new Runnable() { public void run() { try { adapter.refresh(); } catch (Exception e) { return; } } }; /** * Filter the list view with new items */ final Runnable filterMapList = new Runnable() { public void run() { try { adapter.getFilter().filter(filter); } catch (Exception e) { return; } } }; /** * Delete all fetched maps */ final Runnable deleteAllMaps = new Runnable() { public void run() { boolean status = false; status = mListMapModel.deleteAllMap(getActivity()); try { if (status) { toastShort(R.string.map_deleted); refreshMapLists(); } else { toastShort(R.string.map_deleted_failed); } } catch (Exception e) { return; } } }; final Runnable refreshMapList = new Runnable() { public void run() { try { refreshMapLists(); } catch (Exception e) { return; } } }; public void refreshMapLists() { adapter.refresh(); } // Context Menu Stuff @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { new MenuInflater(getActivity()).inflate(R.menu.list_map_context, menu); } @Override public boolean onContextItemSelected(android.view.MenuItem item) { AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item .getMenuInfo(); boolean result = performAction(item, info.position); if (!result) { result = super.onContextItemSelected(item); } return result; } public boolean performAction(android.view.MenuItem item, int position) { mId = adapter.getItem(position).getId(); mapId = adapter.getItem(position).getMapId(); if (item.getItemId() == R.id.map_delete) { // Delete by ID edit = false; mHandler.post(mDeleteMapById); return (true); } else if (item.getItemId() == R.id.map_edit) { // edit existing map edit = true; createDialog(DIALOG_ADD_DEPLOYMENT); return (true); } return (false); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.clear_map) { createDialog(DIALOG_CLEAR_DEPLOYMENT); return true; } else if (item.getItemId() == R.id.menu_find) { createDialog(DIALOG_DISTANCE); return true; } else if (item.getItemId() == R.id.menu_add) { edit = false; createDialog(DIALOG_ADD_DEPLOYMENT); return true; } else if (item.getItemId() == R.id.app_settings) { startActivity(new Intent(getActivity(), Settings.class)); return true; } return super.onOptionsItemSelected(item); } private void onListItemTap(int id) { if (isMapActive(sId)) { if (Util.isTablet(getActivity())) { if (listener != null) { listener.onMapSelected(); refreshMapLists(); } } else { goToReports(); } } else { fetchReports(sId); } } public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { log("on map itemClicked"); final int sId = adapter.getItem(position).getId(); onListItemTap(sId); } @Override public void onListItemClick(ListView l, View v, int position, long id) { l.setItemChecked(position, true); log("on listItemClicked"); sId = adapter.getItem(position).getId(); onListItemTap(sId); } private void goToReports() { Intent launchIntent; launchIntent = new Intent(getActivity(), ReportTabActivity.class); this.startActivityForResult(launchIntent, 0); getActivity().overridePendingTransition(R.anim.home_enter, R.anim.home_exit); getActivity().setResult(Activity.RESULT_OK); } /** * Check if a deployment is the active one * * @param id - map's id * @return boolean */ public boolean isMapActive(int id) { Preferences.loadSettings(getActivity()); if (Preferences.activeDeployment == id) { return true; } return false; } /** * Create an alert dialog */ public void createDialog(int d) { switch (d) { case DIALOG_SHOW_MESSAGE: AlertDialog.Builder messageBuilder = new AlertDialog.Builder( getActivity()); messageBuilder.setMessage(errorMessage).setPositiveButton( getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog showDialog = messageBuilder.create(); showDialog.show(); break; case DIALOG_DISTANCE: AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.select_distance); builder.setSingleChoiceItems(items, Preferences.selectedDistance, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { distance = items[item]; setDeviceLocation(); Preferences.selectedDistance = item; // save prefrences Preferences.saveSettings(getActivity()); dialog.cancel(); toastLong(R.string.finding_map); } }); AlertDialog alert = builder.create(); alert.show(); break; case DIALOG_CLEAR_DEPLOYMENT: AlertDialog.Builder clearBuilder = new AlertDialog.Builder( getActivity()); clearBuilder .setMessage(getString(R.string.confirm_clear)) .setCancelable(false) .setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { mHandler.post(deleteAllMaps); } }) .setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog clearDialog = clearBuilder.create(); clearDialog.show(); break; case DIALOG_ADD_DEPLOYMENT: LayoutInflater factory = LayoutInflater.from(getActivity()); final View textEntryView = factory.inflate(R.layout.add_map, null); final AddMapView addMapView = new AddMapView(textEntryView); // if edit was selected at the context menu, populate fields // with existing map details if (edit) { final List<ListMapModel> listMap = mListMapModel.loadMapById( mId, mapId); if (listMap.size() > 0) { addMapView.setMapName(listMap.get(0).getName()); addMapView.setMapDescription(listMap.get(0).getDesc()); addMapView.setMapUrl(listMap.get(0).getUrl()); addMapView.setMapId(listMap.get(0).getId()); } } final AlertDialog.Builder addBuilder = new AlertDialog.Builder( getActivity()); addBuilder .setTitle(R.string.enter_map_details) .setView(textEntryView) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // edit was selected if (edit) { if (!addMapView.updateMapDetails()) toastLong(R.string.fix_error); else mHandler.post(refreshMapList); } else { if (!addMapView.addMapDetails()) toastLong(R.string.fix_error); else mHandler.post(fetchMapList); } } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { dialog.cancel(); } }); AlertDialog deploymentDialog = addBuilder.create(); deploymentDialog.show(); break; } } @Override protected void onLoaded(boolean success) { try { if (success) { if (Util.isTablet(getActivity())) { if (listener != null) { listener.onMapSelected(); refreshMapLists(); } } else { goToReports(); } } else { toastLong(R.string.failed); } } catch (IllegalArgumentException e) { log(e.toString()); } } /** Location stuff **/ // Fetches the current location of the device. protected void setDeviceLocation() { mLocationMgr = (LocationManager) getActivity().getSystemService( Context.LOCATION_SERVICE); // Get last known location from either GPS or Network provider Location loc = null; boolean netAvail = (mLocationMgr .getProvider(LocationManager.NETWORK_PROVIDER) != null); boolean gpsAvail = (mLocationMgr .getProvider(LocationManager.GPS_PROVIDER) != null); if (gpsAvail) { loc = mLocationMgr .getLastKnownLocation(LocationManager.GPS_PROVIDER); } else if (netAvail) { loc = mLocationMgr .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); } // Just use last location if it's less than 10 minutes old if (loc != null && ((new Date()).getTime() - loc.getTime() < 10 * 60 * 1000)) { onLocationChanged(loc); } else { if (gpsAvail) { mLocationMgr.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, this); } if (netAvail) { mLocationMgr.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 0, 0, this); } } } public void stopLocating() { if (mLocationMgr != null) { try { mLocationMgr.removeUpdates(this); } catch (Exception ex) { ex.printStackTrace(); } mLocationMgr = null; } } public void onLocationChanged(Location loc) { if (loc != null) { location = loc; if (mDeploymentTask == null) { mDeploymentTask = new LoadMapTask(getActivity()); mDeploymentTask.location = location; mDeploymentTask.distance = distance; mDeploymentTask.adapter = adapter; mDeploymentTask.execute(); } stopLocating(); } } public void onProviderDisabled(String provider) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } /* * (non-Javadoc) * @see com.ushahidi.android.app.fragments.BaseListFragment#headerView() */ @Override protected View headerView() { // TODO Auto-generated method stub return null; } private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent != null) { int status = intent.getIntExtra("status", 113); getActivity().stopService(fetchReports); dialog.cancel(); if (status == 0) { onLoaded(true); } else if (status == 100) { errorMessage = getString(R.string.internet_connection); createDialog(DIALOG_SHOW_MESSAGE); } else if (status == 99) { errorMessage = getString(R.string.failed); createDialog(DIALOG_SHOW_MESSAGE); } else if (status == 112) { errorMessage = getString(R.string.network_error); createDialog(DIALOG_SHOW_MESSAGE); } else { errorMessage = getString(R.string.error_occured); createDialog(DIALOG_SHOW_MESSAGE); } } else { toastLong(R.string.failed); } } }; }