package eu.hellek.viajafacil.android; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.ClientPNames; import org.apache.http.cookie.Cookie; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.cookie.BasicClientCookie; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.location.Address; import android.location.Geocoder; import android.location.Location; import android.location.LocationManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.provider.ContactsContract; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.view.View.OnKeyListener; import android.widget.Button; import android.widget.ImageButton; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.Overlay; import com.google.protobuf.CodedOutputStream; import eu.hellek.gba.proto.Helpers; import eu.hellek.gba.proto.LoginInfoProtos.LoginInfo; import eu.hellek.gba.proto.LoginInfoProtos.LoginInfo.UserFavouritePositionProxy; import eu.hellek.gba.proto.RequestsProtos.DirectSearchRequest; import eu.hellek.gba.proto.RequestsProtos.IndirectSearchRequest; import eu.hellek.gba.shared.ConnectionProxy; import eu.hellek.gba.shared.ConnectionProxyComparator; import eu.hellek.gba.shared.LineProxy; import eu.hellek.gba.shared.SearchResultProxy; import eu.hellek.viajafacil.android.map.LineOverlay; import eu.hellek.viajafacil.android.map.MapGestureDetectorOverlay; import eu.hellek.viajafacil.android.map.MarkerCircleOverlay; import eu.hellek.viajafacil.android.map.MarkersOverlay; import eu.hellek.viajafacil.android.map.MeinLocationOverlay; import eu.hellek.viajafacil.android.map.MyOnGestureListener; import eu.hellek.viajafacil.android.map.StationOverlay; public class ViajaFacilActivity extends MapActivity { static final int DIALOG_SELECTFROM = 0; static final int DIALOG_SELECTTO = 1; public static final int DIALOG_FROMMAP = 2; static final int DIALOG_CHOOSEADDR = 3; static final int DIALOG_AB_NEEDED = 4; static final int DIALOG_NO_LOCATION_YET = 5; static final int DIALOG_ADDRESS_GEOCODING_FAILED = 6; static final int DIALOG_EXIT_APP = 7; public static final int FROM = 0; public static final int TO = 1; public static final String[] colors = { "#ff0000", "#0000ff", "#009900", "#ff00ff", "#00ffff" }; public static final int NUM_COLORS = colors.length; public static final int GET_RESULT_TO_DISPLAY = 0; public static final int GET_ADDR_FROM_CONTACTS = 1; public static final int GET_FAVORITE = 2; public static final int GET_ACCOUNTS_THEN_SHOW_FAVS = 3; public static final int ACCOUNT_MANAGER_INTENT = 4; private static final String appurl = "www.viaja-facil.com"; // URL used for direct-search. might also use the SSL url below if desired public static final String appurlssl = "viaja-facil.appspot.com"; // URL used to communicate in SSL-mode for login and adding/deleting favorites, also for indirect searches since they take so long that a few ms more due to overhead really don't matter /*private static final String appurl = "10.0.2.2:8888"; private static final String appurlssl = appurl;*/ /* * stuff related to the login-cookie */ private static final String PREFS_COOKIE_PREFS = "cookieprefs"; private static final String PREFS_COOKIE_NAME = "cookiename"; private static final String PREFS_COOKIE_VALUE = "cookievalue"; private static final String PREFS_COOKIE_TIME = "cookietime"; public static final String PREFS_ACCOUNT_PREFS = "accountprefs"; public static final String PREFS_ACCOUNT_NAME = "accountname"; private LocationManager locationManager; private MyLocationListener locationListener; // location listener to detect users position private MeinLocationOverlay mlo; // overlay to display position private MapView mapView; private Menu menu; private MarkersOverlay markers; // overlay to display start/end points (A/B) private List<Overlay> resultOverlays; // overlay that contains the results (displayed connection), mainly used to be able to remove it before drawing a new result public static Cookie appEngineCookie; private int mapLongTouchX; private int mapLongTouchY; private boolean useSubte = true; // whether the user desires to use subtes private boolean useTrains = true; // same for trains private int searchmode; // direct or indirect search private List<String> mlkSet1 = null; // keys of lines in results of direct search. they are ignored in indirect search private List<String> mlkSet2 = null; private String [] lastGeocodedAddr = { "", "" }; private List<Address> addressesToChooseFrom; private int chooseAddressFromOrTo; private int chooseContactFromOrTo; private int chooseFavoriteFromOrTo; public static boolean downloadedFavs = false; public static int getFavsReRuns = 0; // how many retries where done to fetch the favs. needs to be limited to avoid endless loop protected boolean doSearchAfterwards; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TOS.show(this); mapView = (MapView) findViewById(R.id.mapWidget); mapView.setBuiltInZoomControls(true); mapView.setLongClickable(true); mapView.setStreetView(false); locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); locationListener = new MyLocationListener(this); updateLocation(); MapController mapController = mapView.getController(); mapController.setZoom(11); mapController.setCenter(new GeoPoint(((int)(-34.604389 * 1E6)), ((int)(-58.410873 * 1E6)))); List<Overlay> mapOverlays = mapView.getOverlays(); mapOverlays.clear(); mapOverlays.add(new MapGestureDetectorOverlay(new MyOnGestureListener(this))); markers = new MarkersOverlay(this); mapOverlays.add(markers); mlo = new MeinLocationOverlay(this, mapView); mapOverlays.add(mlo); //mlo.enableCompass(); mlo.enableMyLocation(); resultOverlays = new ArrayList<Overlay>(); OnClickListener btnListener = new ButtonListener(); ImageButton btnFrom = (ImageButton) findViewById(R.id.btnFrom); btnFrom.setOnClickListener(btnListener); ImageButton btnTo = (ImageButton) findViewById(R.id.btnTo); btnTo.setOnClickListener(btnListener); Button btnSearch = (Button) findViewById(R.id.btnSearch); btnSearch.setOnClickListener(btnListener); Button btnResults = (Button) findViewById(R.id.btnResults); btnResults.setOnClickListener(btnListener); TextView txtFrom = (TextView)findViewById(R.id.txtFrom); TextView txtTo = (TextView)findViewById(R.id.txtTo); TextViewListener listenerFrom = new TextViewListener(FROM); TextViewListener listenerTo = new TextViewListener(TO); txtFrom.setOnEditorActionListener(listenerFrom); txtFrom.setOnFocusChangeListener(listenerFrom); txtFrom.setOnKeyListener(listenerFrom); txtTo.setOnEditorActionListener(listenerTo); txtTo.setOnFocusChangeListener(listenerTo); txtTo.setOnKeyListener(listenerTo); Intent intent = getIntent(); if(intent != null) { /* * handling of Android intents, i.e. when Viaja Facil was opened through "share" on a location in Google Maps, etc. */ double lat = 0.0; double lon = 0.0; String addr = null; if(intent.getData() != null) { /*System.err.println("host: " + intent.getData().getHost()); System.err.println("data: " + intent.getDataString());*/ if(intent.getScheme().equals("geo")) { String [] split1 = intent.getDataString().split(":"); String [] split2 = split1[1].split("?"); String [] reslatlon = split2[0].split(","); lat = Double.parseDouble(reslatlon[0]); lon = Double.parseDouble(reslatlon[1]); if(lat == 0 && lon == 0) { addr = intent.getData().getQueryParameter("q"); } } else if(intent.getScheme().equals("google.navigation")) { // URLEncodedUtils.parse(intent.getData(), URLEncodedUtils.CONTENT_TYPE); String [] split1 = intent.getDataString().split("ll="); String res = split1[1]; String [] split2 = res.split("&"); if(split2.length > 1) { res = split2[0]; } // System.err.println("Split string: " + res); String [] reslatlon = res.split(","); lat = Double.parseDouble(reslatlon[0]); lon = Double.parseDouble(reslatlon[1]); } } else if(intent.getExtras() != null) { /*System.err.println("other intent received"); Set<String> extrakeys = intent.getExtras().keySet(); for(String key : extrakeys) { System.err.println("Extra: (" + key + ")" + intent.getExtras().get(key)); }*/ String extra = intent.getExtras().getString("android.intent.extra.TEXT"); if(extra != null) { String split [] = extra.split("\n"); // System.err.println("Split: " + split[0]); addr = split[0]; } } if(lat != 0.0 && lon != 0.0) { GeoPoint p = new GeoPoint((int)(lat * 1E6),(int)(lon * 1E6)); new PointToAddressGeocoderTask(TO).execute(p); markers.updateMarkerPosition(TO, p); mapView.invalidate(); resetSearch(); } else if(addr != null) { new AddressToPointGeocoderTask(TO).execute(addr); txtTo.setText(addr); } } loadSavedInstance(); final SharedPreferences preferences1 = getSharedPreferences("favs", Activity.MODE_PRIVATE); long lastSavedFavs = preferences1.getLong("lastsaved", 0); final int MAX_FAV_AGE = 180000; // 3 minutes if(lastSavedFavs + MAX_FAV_AGE < System.currentTimeMillis()) { Account storedAccount = getStoredAccount(); //System.err.println("StoredAccount: " + storedAccount); if(storedAccount != null) { AccountManager accountManager = AccountManager.get(getApplicationContext()); final SharedPreferences preferences = getSharedPreferences(PREFS_COOKIE_PREFS, Activity.MODE_PRIVATE); String cookiename = preferences.getString(PREFS_COOKIE_NAME, null); String cookievalue = preferences.getString(PREFS_COOKIE_VALUE, null); long cookietime = preferences.getLong(PREFS_COOKIE_TIME, 0); //System.err.println("Cookie values: name: " + cookiename + ", expiry: " + cookietime + ", value: " + cookievalue); if(cookiename != null && cookievalue != null && cookietime != 0) { BasicClientCookie cookie = new BasicClientCookie(cookiename, cookievalue); cookie.setDomain("viaja-facil.appspot.com"); cookie.setPath("/"); cookie.setExpiryDate(new Date(cookietime)); if(cookiename.charAt(0) == 'S') { cookie.setSecure(true); } if(!cookie.isExpired(new Date())) { appEngineCookie = cookie; new GetFavoritesTask(false).execute(); } else { accountManager.getAuthToken(storedAccount, "ah", false, new GetAuthTokenCallback(false), null); } } else { accountManager.getAuthToken(storedAccount, "ah", false, new GetAuthTokenCallback(false), null); } } } } private void loadSavedInstance() { final Object data = getLastNonConfigurationInstance(); if(data != null) { StoredData stored = (StoredData) data; markers.updateMarkerPosition(FROM, stored.getMarker1()); markers.updateMarkerPosition(TO, stored.getMarker2()); mapView.getController().setCenter(stored.getMapcenter()); mapView.getController().setZoom(stored.getZoomlevel()); SearchResultHolder.getInstance().setResultList(stored.getSearchResults()); resultOverlays = stored.getResultOverlays(); mapView.getOverlays().addAll(resultOverlays); useSubte = stored.isUseSubte(); useTrains = stored.isUseTrains(); searchmode = stored.getSearchmode(); mlkSet1 = stored.getMlkSet1(); mlkSet2 = stored.getMlkSet2(); Button btnResults = (Button) findViewById(R.id.btnResults); btnResults.setEnabled(stored.isResultsEnabled()); Button btnSearch = (Button) findViewById(R.id.btnSearch); btnSearch.setText(stored.getBtnSearchText()); lastGeocodedAddr = stored.getLastGeocodedAddr(); } } @Override protected boolean isRouteDisplayed() { return resultOverlays.size() > 0; } @Override protected void onResume() { super.onResume(); updateLocation(); if(mlo != null) { //mlo.enableCompass(); mlo.enableMyLocation(); } } @Override protected void onPause() { super.onPause(); locationManager.removeUpdates(locationListener); if(mlo != null) { //mlo.disableCompass(); mlo.disableMyLocation(); } } @Override public Object onRetainNonConfigurationInstance() { Button btnResults = (Button) findViewById(R.id.btnResults); Button btnSearch = (Button) findViewById(R.id.btnSearch); final StoredData toStore = new StoredData(markers.getFromPos(), markers.getToPos(), mapView.getMapCenter(), mapView.getZoomLevel(), SearchResultHolder.getInstance().getResultList(), resultOverlays, useSubte, useTrains, searchmode, mlkSet1, mlkSet2, btnResults.isEnabled(), btnSearch.getText(), lastGeocodedAddr); return toStore; } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); this.menu = menu; return true; } @Override /* * what to do when an item in an (Options)Menu had been selected */ public boolean onOptionsItemSelected(MenuItem item) { // AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); switch (item.getItemId()) { case R.id.switchmapnormal: // switch map to certain mode mapView.setSatellite(false); mapView.setTraffic(false); item.setChecked(true); return true; case R.id.switchmapsat: mapView.setTraffic(false); mapView.setSatellite(true); item.setChecked(true); return true; case R.id.switchmaptraffic: mapView.setSatellite(false); mapView.setTraffic(true); item.setChecked(true); return true; case R.id.invert: // invert start/dest switchFromTo(); return true; case R.id.subte: // (de)select subte as allowed means of transport if(item.isChecked()) { item.setChecked(false); useSubte = false; } else { item.setChecked(true); useSubte = true; } performKey(); // to bring the menu back so that the user can also (de)select trains return false; case R.id.tren: if(item.isChecked()) { item.setChecked(false); useTrains = false; } else { item.setChecked(true); useTrains = true; } performKey(); return true; default: return super.onContextItemSelected(item); } } /* * manage creation of Dialogs */ protected Dialog onCreateDialog(int id) { Dialog dialog; AlertDialog.Builder builder = new AlertDialog.Builder(this); switch(id) { case DIALOG_SELECTFROM: // select Start from my Position or from contacts or from favorites (triggered by button on the right of the start-text-box builder.setTitle(R.string.selectStartPos); CharSequence [] items1 = { this.getResources().getString(R.string.myPos), this.getResources().getString(R.string.contacts), this.getResources().getString(R.string.favs)}; builder.setItems(items1, new DialogListener(id)); dialog = builder.create(); break; case DIALOG_SELECTTO: builder.setTitle(R.string.selectDestPos); CharSequence [] items2 = { this.getResources().getString(R.string.myPos), this.getResources().getString(R.string.contacts), this.getResources().getString(R.string.favs)}; builder.setItems(items2, new DialogListener(id)); dialog = builder.create(); break; case DIALOG_FROMMAP: // select start or dest from map CharSequence [] items3 = { this.getResources().getString(R.string.from) + " " + this.getResources().getString(R.string.here), this.getResources().getString(R.string.to) + " " + this.getResources().getString(R.string.here) }; builder.setTitle(R.string.fromMap); builder.setItems(items3, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { GeoPoint p = mapView.getProjection().fromPixels(mapLongTouchX, mapLongTouchY); new PointToAddressGeocoderTask(which).execute(p); // which = 0 for from and 1 for to markers.updateMarkerPosition(which, p); mapView.invalidate(); resetSearch(); } }); dialog = builder.create(); break; case DIALOG_CHOOSEADDR: // dialog to choose correct address if the geocoder gave several results CharSequence [] items4; if(addressesToChooseFrom.size() >= 5) { items4 = new CharSequence[5]; } else { items4 = new CharSequence[addressesToChooseFrom.size()]; } for(int i = 0; i < 5 && i < addressesToChooseFrom.size(); i++) { //items4[i] = addressesToChooseFrom.get(i).getAddressLine(0) + ", " + addressesToChooseFrom.get(i).getLocality(); String locality = addressesToChooseFrom.get(i).getLocality(); if(locality == null) { locality = addressesToChooseFrom.get(i).getSubLocality(); } if(locality == null) { locality = addressesToChooseFrom.get(i).getSubAdminArea(); } if(locality == null) { locality = addressesToChooseFrom.get(i).getPremises(); } items4[i] = addressesToChooseFrom.get(i).getAddressLine(0) + ", " + locality; } builder.setItems(items4, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { GeoPoint p = new GeoPoint((int)(addressesToChooseFrom.get(which).getLatitude() * 1E6),(int)(addressesToChooseFrom.get(which).getLongitude() * 1E6)); markers.updateMarkerPosition(chooseAddressFromOrTo, p); mapView.getController().setCenter(p); mapView.getController().setZoom(15); resetSearch(); removeDialog(DIALOG_CHOOSEADDR); if(doSearchAfterwards) { // is true if the geocoder was triggered by the search function and tells the activity to try searching again after user selected an address doSearchAfterwards = false; doSearch(); } } }); dialog = builder.create(); break; case DIALOG_AB_NEEDED: // tell user that start or destination are not set yet builder.setMessage(R.string.ab_needed); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); builder.setCancelable(true); dialog = builder.create(); break; case DIALOG_NO_LOCATION_YET: // tell the user that his location (GPS/network) is not available yet builder.setMessage(R.string.noLocationYet); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); builder.setCancelable(true); dialog = builder.create(); break; case DIALOG_ADDRESS_GEOCODING_FAILED: // dialog to inform that geocoding failed builder.setMessage(R.string.noaddr); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); builder.setCancelable(true); dialog = builder.create(); break; case DIALOG_EXIT_APP: // ask user if he really wants to quit builder.setTitle(R.string.question_exit); builder.setCancelable(true); builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { getContext().finish(); } }); builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); dialog = builder.create(); break; default: dialog = null; Log.e("onCreateDialog", "went to default dialog, that's bad!!!"); } return dialog; } @Override public void onBackPressed() { showDialog(DIALOG_EXIT_APP); } /* * presses the key "Q" which is set to bring up the menu that lets the user decide whether he wants to allow trains/subtes * there seems to be no better way to bring up such a menu */ private void performKey() { new Handler().postDelayed(new Runnable() { public void run() { menu.performShortcut(KeyEvent.KEYCODE_Q, new KeyEvent(0, KeyEvent.KEYCODE_Q), 0); } }, 200); } /* * start the location service and register the listener */ private void updateLocation() { locationManager.removeUpdates(locationListener); try { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); } catch (Exception e) { Log.e("updateLocation", "Location-Provider NETWORK did not work."); e.printStackTrace(); } try { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); } catch (Exception e) { Log.e("updateLocation", "Location-Provider GPS did not work."); e.printStackTrace(); } } private void switchFromTo() { TextView from = (TextView)findViewById(R.id.txtFrom); TextView to = (TextView)findViewById(R.id.txtTo); CharSequence tempS = from.getText(); from.setText(to.getText()); to.setText(tempS); String tempG = lastGeocodedAddr[FROM]; lastGeocodedAddr[FROM] = lastGeocodedAddr[TO]; lastGeocodedAddr[TO] = tempG; GeoPoint tempM = markers.getFromPos(); markers.updateMarkerPosition(0, markers.getToPos()); markers.updateMarkerPosition(1, tempM); mapView.invalidate(); resetSearch(); } private void resetSearch() { searchmode = 0; Button btnSearch = (Button)findViewById(R.id.btnSearch); btnSearch.setEnabled(true); btnSearch.setText(R.string.search); mlkSet1 = null; mlkSet2 = null; mapView.getOverlays().removeAll(resultOverlays); resultOverlays.clear(); } private static GeoPoint latLonToGeoPoint(double lat, double lon) { return new GeoPoint((int)(lat * 1E6), (int)(lon * 1E6)); } public void setMapLongTouchXY(int x, int y) { mapLongTouchX = x; mapLongTouchY = y; } private void doSearch() { if(markers.getFromPos().getLatitudeE6() != 0 && markers.getToPos().getLatitudeE6() != 0) { Button btnSearch = (Button)findViewById(R.id.btnSearch); btnSearch.setEnabled(false); btnSearch.setText(R.string.searching); centerMapOnMarkers(); if(searchmode == 0) { SearchResultHolder.getInstance().clear(); new DirectSearchTask().execute(); } else { new IndirectSearchTask().execute(); } } else { showDialog(DIALOG_AB_NEEDED); } } private void centerMapOnMarkers() { mapView.getController().zoomToSpan((int)(markers.getLatSpanE6() * 1.2), (int)(markers.getLonSpanE6() * 1.2)); int middlelat = (markers.getFromPos().getLatitudeE6() + markers.getToPos().getLatitudeE6()) / 2; int middlelon = (markers.getFromPos().getLongitudeE6() + markers.getToPos().getLongitudeE6()) / 2; mapView.getController().setCenter(new GeoPoint(middlelat, middlelon)); } protected synchronized void addSearchResult(eu.hellek.gba.shared.SearchResultProxy res) { SearchResultHolder.getInstance().add(res); } /* * When the Activity called another activity, i.e. to list user accounts, to list favorites, to show search-results * or anything like that, on returning to the main activity, this function gets called and handles the result that was passed * * (non-Javadoc) * @see android.app.Activity#onActivityResult(int, int, android.content.Intent) */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK && requestCode == GET_RESULT_TO_DISPLAY) { // show a result on the map if (data.hasExtra("resultid")) { //Toast.makeText(this, data.getExtras().getInt("resultid"), Toast.LENGTH_SHORT).show(); drawConnection(data.getExtras().getInt("resultid")); } if(data.hasExtra("geopoint")) { // zoom to a position if one had been passed int [] pos = data.getExtras().getIntArray("geopoint"); GeoPoint gp = new GeoPoint(pos[0], pos[1]); MarkerCircleOverlay mco = new MarkerCircleOverlay(gp); resultOverlays.add(mco); mapView.getOverlays().add(mco); mapView.getController().setCenter(gp); mapView.getController().setZoom(16); } } if(resultCode == RESULT_OK && requestCode == GET_ADDR_FROM_CONTACTS) { // if address was selected from contact list Uri contactData = data.getData(); Cursor c = managedQuery(contactData, null, null, null, null); if (c.moveToFirst()) { String address = c.getString(c.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS)); TextView tv; if(chooseContactFromOrTo == 0) { tv = (TextView)findViewById(R.id.txtFrom); } else { tv = (TextView)findViewById(R.id.txtTo); } tv.setText(address); new AddressToPointGeocoderTask(chooseContactFromOrTo).execute(address); } } if(resultCode == RESULT_OK && requestCode == GET_FAVORITE) { // if a favorite had been selected String address = data.getExtras().getString("addr"); float lat = data.getExtras().getFloat("lat"); float lon = data.getExtras().getFloat("lon"); GeoPoint gp = new GeoPoint((int)(lat * 1E6), (int)(lon * 1E6)); TextView tv; if(chooseFavoriteFromOrTo == 0) { tv = (TextView)findViewById(R.id.txtFrom); } else { tv = (TextView)findViewById(R.id.txtTo); } tv.setText(address); lastGeocodedAddr[chooseFavoriteFromOrTo] = address; markers.updateMarkerPosition(chooseFavoriteFromOrTo, gp); mapView.invalidate(); resetSearch(); } if(resultCode == RESULT_OK && requestCode == GET_ACCOUNTS_THEN_SHOW_FAVS) { // user selected an account Account acc = (Account)data.getExtras().getParcelable("account"); //System.err.println("Account: " + acc.toString()); AccountManager accountManager = AccountManager.get(getApplicationContext()); accountManager.getAuthToken(acc, "ah", false, new GetAuthTokenCallback(true), null); } if(requestCode == ACCOUNT_MANAGER_INTENT) { // app is returining after the user authorized the accountmanager Log.w("onActivitiyResult", "Accountmanager intent returned."); AccountManager accountManager = AccountManager.get(getApplicationContext()); accountManager.getAuthToken(getStoredAccount(), "ah", false, new GetAuthTokenCallback(true), null); } } /* * draw a connection on the map (lines, stations, etc.) */ private void drawConnection(int result) { List<Overlay> mapOverlays = mapView.getOverlays(); ConnectionProxy conn = SearchResultHolder.getInstance().getAtIndex(result); mapOverlays.removeAll(resultOverlays); resultOverlays.clear(); int col = 0; for(int i = 0; i < conn.getLines().size(); i++) { LineProxy lp = conn.getLines().get(i); if(lp.getType() != 0 || (i != 0 && i != conn.getLines().size()-1)) { if(col >= NUM_COLORS) { col = col % NUM_COLORS; } if(lp.getType() != 0) { List<GeoPoint> pathFull = new ArrayList<GeoPoint>(lp.getAllPoints().size()); for(int j = 0; j < lp.getAllPoints().size(); j = j+2) { GeoPoint latlng = new GeoPoint((int)(lp.getAllPoints().get(j) * 1E6), (int)(lp.getAllPoints().get(j+1) * 1E6)); pathFull.add(latlng); if(lp.getStations() != null && lp.getStations().size() > 0) { StationOverlay ov; if(lp.getType() == 3) { ov = new StationOverlay(lp.getStations().get(j/2), latlng, colors[col], 14); } else { ov = new StationOverlay(lp.getStations().get(j/2), latlng, colors[col], 15); } resultOverlays.add(ov); mapOverlays.add(ov); } } LineOverlay lo1 = new LineOverlay(pathFull, colors[col], 0); resultOverlays.add(lo1); mapOverlays.add(lo1); } List<GeoPoint> pathReal = new ArrayList<GeoPoint>(lp.getRelevantPoints().size()); for(int j = 0; j < lp.getRelevantPoints().size(); j = j+2) { GeoPoint latlng = new GeoPoint((int)(lp.getRelevantPoints().get(j) * 1E6), (int)(lp.getRelevantPoints().get(j+1) * 1E6)); pathReal.add(latlng); } LineOverlay lo2; if(lp.getType() == 0) { lo2 = new LineOverlay(pathReal, "#000000", 1); } else { lo2 = new LineOverlay(pathReal, colors[col], 1); col++; } resultOverlays.add(lo2); mapOverlays.add(lo2); } } centerMapOnMarkers(); } /* * returns the stored account that the user selected for log-in or null if none is found */ public Account getStoredAccount() { final SharedPreferences preferences = getSharedPreferences(PREFS_ACCOUNT_PREFS, Activity.MODE_PRIVATE); String accountname = preferences.getString(PREFS_ACCOUNT_NAME, null); AccountManager accountManager = AccountManager.get(getApplicationContext()); Account account = null; if(accountname != null) { Account[] accounts = accountManager.getAccountsByType("com.google"); for(Account a : accounts) { if(a.toString().equalsIgnoreCase(accountname)) { account = a; } } } return account; } public ViajaFacilActivity getContext() { return this; } class ButtonListener implements OnClickListener { @Override public void onClick(View v) { if(v.getId() == R.id.btnFrom) { showDialog(DIALOG_SELECTFROM); } else if(v.getId() == R.id.btnTo) { showDialog(DIALOG_SELECTTO); } else if(v.getId() == R.id.btnSearch) { TextView from = (TextView)findViewById(R.id.txtFrom); TextView to = (TextView)findViewById(R.id.txtTo); if(lastGeocodedAddr[FROM].equalsIgnoreCase(from.getText().toString()) && lastGeocodedAddr[TO].equalsIgnoreCase(to.getText().toString())) { doSearch(); } else if(!lastGeocodedAddr[FROM].equalsIgnoreCase(from.getText().toString())) { doSearchAfterwards = true; new AddressToPointGeocoderTask(FROM).execute(from.getText().toString()); } else if(!lastGeocodedAddr[TO].equalsIgnoreCase(to.getText().toString())) { doSearchAfterwards = true; new AddressToPointGeocoderTask(TO).execute(to.getText().toString()); } else { Log.e("ButtonListener", "This should not happen"); } } else if(v.getId() == R.id.btnResults) { Intent intent = new Intent(v.getContext(), ResultsActivity.class); startActivityForResult(intent, GET_RESULT_TO_DISPLAY); } else { Log.e("ButtonListener", "Did not match any buttons, this should not happen"); } } } /* * for the dialog that is opened by the button next to the from/to textfields */ class DialogListener implements DialogInterface.OnClickListener { int callingDialog; public DialogListener(int i) { this.callingDialog = i; } @Override public void onClick(DialogInterface dialog, int which) { switch(which) { case 0: // set start or dest to the user's current location Location location = locationListener.getBestLocation(); if(location != null) { GeoPoint p = latLonToGeoPoint(location.getLatitude(), location.getLongitude()); new PointToAddressGeocoderTask(callingDialog).execute(p); markers.updateMarkerPosition(callingDialog, p); mapView.invalidate(); mapView.getController().animateTo(latLonToGeoPoint(location.getLatitude(), location.getLongitude())); resetSearch(); } else { showDialog(DIALOG_NO_LOCATION_YET); // Toast.makeText(getBaseContext(), getBaseContext().getResources().getString(R.string.noLocationYet), Toast.LENGTH_SHORT).show(); } break; case 1: // start activity to pick from contacts Intent intent = new Intent(Intent.ACTION_PICK); intent.setType(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_TYPE); chooseContactFromOrTo = callingDialog; startActivityForResult(intent, GET_ADDR_FROM_CONTACTS); break; case 2: // start activities to choose from favorites. log-in first if necessary chooseFavoriteFromOrTo = callingDialog; if(getStoredAccount() != null) { if(appEngineCookie != null && !appEngineCookie.isExpired(new Date())) { Intent intent2 = new Intent(getBaseContext(), FavoritesActivity.class); startActivityForResult(intent2, GET_FAVORITE); } else { AccountManager accountManager = AccountManager.get(getApplicationContext()); accountManager.getAuthToken(getStoredAccount(), "ah", false, new GetAuthTokenCallback(true), null); } } else { Intent intent2 = new Intent(getBaseContext(), AccountListActivity.class); startActivityForResult(intent2, GET_ACCOUNTS_THEN_SHOW_FAVS); } break; } } } /* * listens to actions related to the from/to textviews */ class TextViewListener implements OnEditorActionListener, OnKeyListener, OnFocusChangeListener { int fromOrTo; public TextViewListener(int fromOrTo) { this.fromOrTo = fromOrTo; } @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if(v.getText().length() > 5) { new AddressToPointGeocoderTask(fromOrTo).execute(v.getText().toString()); } return true; } @Override public boolean onKey(View v, int actionId, KeyEvent event) { if((event.getAction() == KeyEvent.ACTION_DOWN) && (actionId == KeyEvent.KEYCODE_ENTER)) { TextView tv = (TextView) v; return onEditorAction(tv, actionId, event); } else { return false; } } @Override public void onFocusChange(View v, boolean hasFocus) { TextView tv = (TextView)v; if(!hasFocus) { if(tv.getText().length() > 5 && !lastGeocodedAddr[fromOrTo].equalsIgnoreCase(tv.getText().toString())) { new AddressToPointGeocoderTask(fromOrTo).execute(tv.getText().toString()); } } } } /* * Geocode a lat/lon to an Adress */ private class PointToAddressGeocoderTask extends AsyncTask<GeoPoint, Void, String> { private int fromOrTo; public PointToAddressGeocoderTask(int fromOrTo) { this.fromOrTo = fromOrTo; } protected String doInBackground(GeoPoint... p) { Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault()); try { List<Address> addresses = geoCoder.getFromLocation(p[0].getLatitudeE6() / 1E6, p[0].getLongitudeE6() / 1E6, 1); if(addresses.size() > 0) { String addr = addresses.get(0).getAddressLine(0); return addr; } return null; } catch (IOException e) { //e.printStackTrace(); Log.e("PointToAddressGeocoderTask", "Geocoder failed", e); return null; } } protected void onPostExecute(String addr) { if(addr != null) { lastGeocodedAddr[fromOrTo] = addr; } TextView tv; if(fromOrTo == FROM) { tv = (TextView)findViewById(R.id.txtFrom); } else { tv = (TextView)findViewById(R.id.txtTo); } tv.setText(addr); } } /* * geocode an address to a lat/lon Point. Might bring several results, in which case the user has to select the correct one */ private class AddressToPointGeocoderTask extends AsyncTask<String, Void, List<Address>> { private int fromOrTo; public AddressToPointGeocoderTask(int fromOrTo) { this.fromOrTo = fromOrTo; } protected List<Address> doInBackground(String... s) { lastGeocodedAddr[fromOrTo] = s[0]; Geocoder geoCoder = new Geocoder(getBaseContext(), Locale.getDefault()); try { Log.d("AddressGeoCoder", "Addr: " + s[0]); //List<Address> addresses = geoCoder.getFromLocationName(s[0], 5, -35.321848, -59.295959, -34.04697, -57.77298); List<Address> addresses = geoCoder.getFromLocationName(s[0], 5); return addresses; } catch (IOException e) { // e.printStackTrace(); Log.e("ADdressToPointGeocodertask", "Geocoder failed", e); return null; /*Address temp1 = new Address(Locale.getDefault()); temp1.setAddressLine(0, "test1 " + new Random().nextLong()); Address temp2 = new Address(Locale.getDefault()); temp2.setAddressLine(0, "test2 " + new Random().nextLong()); List<Address> list = new ArrayList<Address>(2); list.add(temp1); list.add(temp2); return list;*/ } } protected void onPostExecute(List<Address> addresses) { GeoPoint p = null; if(addresses == null || addresses.size() == 0) { showDialog(DIALOG_ADDRESS_GEOCODING_FAILED); if(doSearchAfterwards) { doSearchAfterwards = false; } // Toast.makeText(getBaseContext(), getBaseContext().getResources().getString(R.string.noaddr), Toast.LENGTH_LONG).show(); } else if(addresses.size() == 1) { Address addr = addresses.get(0); p = new GeoPoint((int)(addr.getLatitude() * 1E6),(int)(addr.getLongitude() * 1E6)); } else { addressesToChooseFrom = addresses; chooseAddressFromOrTo = fromOrTo; showDialog(DIALOG_CHOOSEADDR); } if(p != null) { markers.updateMarkerPosition(fromOrTo, p); mapView.getController().setCenter(p); mapView.getController().setZoom(15); resetSearch(); if(doSearchAfterwards) { doSearchAfterwards = false; doSearch(); } } } } /* * runs a direct search (that uses max. one bus line) * the result contains two sets (mlk1 and mlk2) which are keys that need to be stored to be passed to the indirect search */ private class DirectSearchTask extends AsyncTask<Void, Void, eu.hellek.gba.proto.SearchResultProtos.SearchResultProxy> { private ProgressDialog searching; private DirectSearchRequest req; @Override protected void onPreExecute() { searching = ProgressDialog.show(getContext(), "", getContext().getResources().getString(R.string.searching), true); DirectSearchRequest.Builder builder = DirectSearchRequest.newBuilder(); builder.setIgnoreSubte(!useSubte); // whether to use trains/subte. needs to be inverted since the server reads whether subte shall NOT be used builder.setIgnoreTrains(!useTrains); builder.setLat1((float)(markers.getFromPos().getLatitudeE6() / 1E6)); builder.setLon1((float)(markers.getFromPos().getLongitudeE6() / 1E6)); builder.setLat2((float)(markers.getToPos().getLatitudeE6() / 1E6)); builder.setLon2((float)(markers.getToPos().getLongitudeE6() / 1E6)); DirectSearchRequest req = builder.build(); this.req = req; } @Override protected eu.hellek.gba.proto.SearchResultProtos.SearchResultProxy doInBackground(Void... params) { try { URL url = new URL("http://"+appurl+"/rm/DirectSearchServlet"); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/x-protobuf"); conn.setRequestProperty("Content-Length", ""+req.getSerializedSize()); OutputStream out = conn.getOutputStream(); CodedOutputStream cout = CodedOutputStream.newInstance(out); req.writeTo(cout); cout.flush(); out.close(); eu.hellek.gba.proto.SearchResultProtos.SearchResultProxy srp = eu.hellek.gba.proto.SearchResultProtos.SearchResultProxy.parseFrom(conn.getInputStream()); return srp; } catch(Exception e) { Log.e("DirectSearchTask", "Error in search", e); e.printStackTrace(); return null; } } @Override protected void onPostExecute(eu.hellek.gba.proto.SearchResultProtos.SearchResultProxy srp) { Button btnSearch = (Button)findViewById(R.id.btnSearch); btnSearch.setEnabled(true); try { searching.dismiss(); } catch (Exception e) { Log.w("DirectSearchTask", "Dismissing the dialog threw an error: " + e); } if(srp != null) { mlkSet1 = srp.getMlkSet1StringList(); // store the important mlkSet1/mlkSet2 for a possible subsequent indirect search mlkSet2 = srp.getMlkSet2StringList(); SearchResultProxy resfinal = Helpers.copyFromProto(srp); searchmode = 1; if(resfinal.getError() == null || resfinal.getError().length() == 0) { Collections.sort(resfinal.getConnections(), new ConnectionProxyComparator()); /*System.err.println(srp.getConnectionsList().get(0).getLinesList().get(0).getLinenum()); for(ConnectionProxy cp : resfinal.getConnections()) { if(cp.getLines() != null) { System.err.println("Connection:"); for(LineProxy lp : cp.getLines()) { System.err.println(lp + " " + lp.getTime()); } } }*/ getContext().addSearchResult(resfinal); btnSearch.setText(R.string.searchindirect); Button btnResults = (Button) findViewById(R.id.btnResults); btnResults.setEnabled(true); Intent intent = new Intent(getContext(), ResultsActivity.class); startActivityForResult(intent, GET_RESULT_TO_DISPLAY); } else if(resfinal.getError().equals(SearchResultProxy.noResults)) { doSearch(); } else if(resfinal.getError().equals(SearchResultProxy.tooManyReqests)) { Toast.makeText(getContext(), getContext().getResources().getString(R.string.errRequests), Toast.LENGTH_LONG).show(); } else if(resfinal.getError().equals(SearchResultProxy.distanceTooLittle)) { Toast.makeText(getContext(), getContext().getResources().getString(R.string.errDistance), Toast.LENGTH_LONG).show(); } else { resetSearch(); Toast.makeText(getContext(), "Error: " + resfinal.getError(), Toast.LENGTH_LONG).show(); } } else { resetSearch(); Toast.makeText(getContext(), "Connection error", Toast.LENGTH_LONG).show(); } } @Override protected void onCancelled() { searching.dismiss(); resetSearch(); } } /* * indirect search (that might use more than one bus line or a combination of buses and trains/subtes) * can ONLY be run if a direct search had been run before since the direct search gathers some data that is needed for * the indirect search (contained in mlkSet1/mlkSet2) which need to be passed here * depending on the density of colectivos at the start point, it might separate them into parallel tasks * that are collected at the end. */ class IndirectSearchTask extends AsyncTask<Void, Integer, Void> { private ProgressDialog searching; private ArrayList<IndirectSearchRequest> reqs; private SearchResultProxy results; private int numThreads; private int finishedThreads; private final static int partitionMaxSize = 40; @Override protected void onPreExecute() { reqs = new ArrayList<IndirectSearchRequest>(); results = new SearchResultProxy(new ArrayList<ConnectionProxy>(), null, null); searching = new ProgressDialog(getContext()); searching.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); searching.setMessage(getContext().getResources().getString(R.string.searching)); searching.setCancelable(false); searching.show(); int partitions = 0; finishedThreads = 0; if(mlkSet1 != null && mlkSet1.size() != 0) { // create partitions for parallel tasks (at least one) partitions = (mlkSet1.size() / partitionMaxSize)+1; } for(int i = 0; i < partitions; i++) { // start task for each partition List<String> mlkSet1PartitionString = new ArrayList<String>(); if(i < partitions - 1) { mlkSet1PartitionString = mlkSet1.subList((mlkSet1.size()/partitions) * i, (mlkSet1.size()/partitions) * (i+1)); } else { mlkSet1PartitionString = mlkSet1.subList((mlkSet1.size()/partitions) * i, mlkSet1.size()); } List<String> mlkSet1Part = new ArrayList<String>(); for(String s : mlkSet1PartitionString) { mlkSet1Part.add(s); } IndirectSearchRequest.Builder builder = IndirectSearchRequest.newBuilder(); builder.setIgnoreSubte(!useSubte); builder.setIgnoreTrains(!useTrains); builder.setLat1((float)(markers.getFromPos().getLatitudeE6() / 1E6)); builder.setLon1((float)(markers.getFromPos().getLongitudeE6() / 1E6)); builder.setLat2((float)(markers.getToPos().getLatitudeE6() / 1E6)); builder.setLon2((float)(markers.getToPos().getLongitudeE6() / 1E6)); builder.addAllMlkSet1String(mlkSet1Part); builder.addAllMlkSet2String(mlkSet2); IndirectSearchRequest req = builder.build(); reqs.add(req); } } @Override /* * wait for threads to finish */ protected Void doInBackground(Void... params) { List<Thread> threads = new ArrayList<Thread>(); for(IndirectSearchRequest req : reqs) { Thread t = new Thread(new IndirectSearchThread(this, req)); threads.add(t); } numThreads = threads.size(); for(Thread t : threads) { t.start(); } for(Thread t : threads) { try { t.join(); } catch (InterruptedException e) { Log.w("IndirectSearchTask", "Interrupted", e); e.printStackTrace(); } } return null; } @Override /* * open results activity to show results */ protected void onPostExecute(Void result) { try { searching.dismiss(); } catch (Exception e) { Log.w("IndirectSearchTask", "Dismissing the dialog threw an error: " + e); } resetSearch(); if(results.getConnections().size() > 0) { Collections.sort(results.getConnections(), new ConnectionProxyComparator()); getContext().addSearchResult(results); Collections.reverse(SearchResultHolder.getInstance().getResultList()); Button btnResults = (Button) findViewById(R.id.btnResults); btnResults.setEnabled(true); /* System.err.println("Result:"); for(ConnectionProxy cp : results.getConnections()) { if(cp.getLines() != null) { System.err.println("Connection:"); for(LineProxy lp : cp.getLines()) { System.err.println(lp + " " + lp.getTime()); } } }*/ Intent intent = new Intent(getContext(), ResultsActivity.class); startActivityForResult(intent, GET_RESULT_TO_DISPLAY); } else if(results.getError() != null && results.getError().length() > 0){ Toast.makeText(getContext(), "Error: " + results.getError(), Toast.LENGTH_LONG).show(); } else { Toast.makeText(getContext(), getContext().getResources().getString(R.string.noresults), Toast.LENGTH_LONG).show(); } } @Override /* * update progress bar every time a task finishes */ protected void onProgressUpdate(Integer... progress) { searching.setProgress(progress[0]); } /* * here, child threads add their result before killing themselves */ public synchronized void addResult(SearchResultProxy result) { if(result.getConnections() != null && result.getConnections().size() > 0 && !results.getConnections().contains(result.getConnections().get(0))) { results.getConnections().addAll(result.getConnections()); } if(result.getError() != null && !result.getError().equals(SearchResultProxy.noResults)) { results.setError(result.getError()); } } public synchronized void reportFinish() { finishedThreads++; publishProgress((int) ((finishedThreads / (float) numThreads) * 100)); } } /* * stuff necessary for the login with google for synchronizing favorites */ private class GetAuthTokenCallback implements AccountManagerCallback<Bundle> { private boolean showFavs; public GetAuthTokenCallback(boolean showFavs) { this.showFavs = showFavs; Log.d("GetAuthTokenCallback", "GetAuthTokenCallback called."); } public void run(AccountManagerFuture<Bundle> result) { Bundle bundle; try { bundle = result.getResult(); Intent intent = (Intent)bundle.get(AccountManager.KEY_INTENT); if(intent != null) { // User input required startActivityForResult(intent, ACCOUNT_MANAGER_INTENT); } else { String auth_token = bundle.getString(AccountManager.KEY_AUTHTOKEN); new GetCookieTask(showFavs).execute(auth_token); } } catch (OperationCanceledException e) { Log.e("GetAuthTokenCallback", "OperationCancelledException", e); e.printStackTrace(); } catch (AuthenticatorException e) { Log.e("GetAuthTokenCallback", "AuthenticatorException", e); e.printStackTrace(); } catch (IOException e) { Log.e("GetAuthTokenCallback", "IOException", e); e.printStackTrace(); } } }; /* * stuff necessary for the login with google for synchronizing favorites */ private class GetCookieTask extends AsyncTask<String, Void, Boolean> { private boolean showFavs; public GetCookieTask(boolean showFavs) { this.showFavs = showFavs; Log.d("GetCookieTask", "GetCookieTask called."); } protected Boolean doInBackground(String... tokens) { DefaultHttpClient http_client = new DefaultHttpClient(); try { // Don't follow redirects http_client.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); HttpGet http_get = new HttpGet("https://viaja-facil.appspot.com/_ah/login?continue=http://localhost/&auth=" + tokens[0]); HttpResponse response; response = http_client.execute(http_get); if(response.getStatusLine().getStatusCode() != 302) { Log.w("GetCookieTask", "Response was not a redirect: " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase()); final char[] buffer = new char[0x10000]; StringBuilder out = new StringBuilder(); Reader in = new InputStreamReader(response.getEntity().getContent(), "UTF-8"); int read; do { read = in.read(buffer, 0, buffer.length); if (read>0) { out.append(buffer, 0, read); } } while (read>=0); Log.w("GetCookieTask", out.toString()); if(getFavsReRuns < 3) { getFavsReRuns++; AccountManager accountManager = AccountManager.get(getApplicationContext()); accountManager.invalidateAuthToken(getStoredAccount().type, tokens[0]); accountManager.getAuthToken(getStoredAccount(), "ah", false, new GetAuthTokenCallback(showFavs), null); } return false; } for(Cookie cookie : http_client.getCookieStore().getCookies()) { Log.d("GetCookieTask", "Got cookie: " + cookie.getName());; if(cookie.getName().equals("ACSID") || cookie.getName().equals("SACSID")) { appEngineCookie = cookie; final SharedPreferences preferences = getSharedPreferences(PREFS_COOKIE_PREFS, Activity.MODE_PRIVATE); preferences.edit().putString(PREFS_COOKIE_NAME, cookie.getName()) .putString(PREFS_COOKIE_VALUE, cookie.getValue()) .putLong(PREFS_COOKIE_TIME, cookie.getExpiryDate().getTime()) .commit(); //System.err.println("Domain: " + cookie.getDomain() + ", name: " + cookie.getName() + ", path: " + cookie.getPath() + ", value: " + cookie.getValue()); return true; } } } catch (ClientProtocolException e) { Log.e("GetCookieTask", "ClientProtocolException", e); e.printStackTrace(); } catch (IOException e) { Log.e("GetCookieTask", "IOException", e); e.printStackTrace(); } return false; } protected void onPostExecute(Boolean result) { if(result) { new GetFavoritesTask(showFavs).execute(); } else { Log.e("GetCookieTask", "Not starting next task since no cookie was received."); if(showFavs) { Toast.makeText(getContext(), "Error: " + getContext().getResources().getString(R.string.failed_downloading_favs), Toast.LENGTH_LONG).show(); Intent intent = new Intent(getBaseContext(), FavoritesActivity.class); startActivityForResult(intent, GET_FAVORITE); } } } } /* * Task to update/download favorites from server */ private class GetFavoritesTask extends AsyncTask<Void, Void, LoginInfo> { private boolean showFavs; public GetFavoritesTask(boolean showFavs) { this.showFavs = showFavs; Log.d("GetFavoritesTask", "GetFavoritesTask called."); } @Override protected LoginInfo doInBackground(Void... params) { try { DefaultHttpClient http_client = new DefaultHttpClient(); http_client.getCookieStore().addCookie(appEngineCookie); HttpGet method = new HttpGet("https://"+ViajaFacilActivity.appurlssl+"/rm/LoginServlet"); HttpResponse response = http_client.execute(method); HttpEntity responseEntity = response.getEntity(); LoginInfo li = LoginInfo.parseFrom(responseEntity.getContent()); Log.d("GetFavoritesTask", "Logged in as: " + li.getEmailAddress()); return li; } catch(Exception e) { Log.e("GetFavoritesTask", "Error", e); e.printStackTrace(); return null; } } @Override protected void onPostExecute(LoginInfo result) { if(result != null && result.getLoggedIn()) { final SharedPreferences preferences = getSharedPreferences("favs", Activity.MODE_PRIVATE); preferences.edit().putLong("lastsaved", System.currentTimeMillis()).commit(); downloadedFavs = true; FavoritesDbAdapter mDbHelper = new FavoritesDbAdapter(getContext()); mDbHelper.open(); mDbHelper.clearDB(); for(UserFavouritePositionProxy fpp : result.getFavouritesList()) { mDbHelper.addFavorite(fpp.getKey(), fpp.getName(), fpp.getLat(), fpp.getLon()); } mDbHelper.close(); if(showFavs) { Intent intent = new Intent(getBaseContext(), FavoritesActivity.class); startActivityForResult(intent, GET_FAVORITE); } } else { if(getFavsReRuns < 4) { getFavsReRuns++; Account storedAccount = getStoredAccount(); AccountManager accountManager = AccountManager.get(getApplicationContext()); accountManager.getAuthToken(storedAccount, "ah", false, new GetAuthTokenCallback(showFavs), null); } } } } public void addFavorite(UserFavouritePositionProxy fpp) { new AddFavoriteTask().execute(fpp); } /* * task to store an additional favorite on the server */ private class AddFavoriteTask extends AsyncTask<UserFavouritePositionProxy, Void, UserFavouritePositionProxy> { @Override protected UserFavouritePositionProxy doInBackground(UserFavouritePositionProxy... params) { Log.d("AddFavoriteTask", "AddFavoriteTask called."); try { DefaultHttpClient http_client = new DefaultHttpClient(); http_client.getCookieStore().addCookie(appEngineCookie); HttpPost method = new HttpPost("https://"+ViajaFacilActivity.appurlssl+"/rm/AddFavoriteServlet"); ByteArrayEntity byteArrEntity = new ByteArrayEntity(params[0].toByteArray()); byteArrEntity.setContentType("application/x-protobuf"); method.setEntity(byteArrEntity); HttpResponse response = http_client.execute(method); HttpEntity responseEntity = response.getEntity(); UserFavouritePositionProxy fpp = UserFavouritePositionProxy.parseFrom(responseEntity.getContent()); return fpp; } catch(Exception e) { Log.e("AddFavoriteTask", "Error", e); e.printStackTrace(); return null; } } @Override protected void onPostExecute(UserFavouritePositionProxy result) { if(result != null) { FavoritesDbAdapter mDbHelper = new FavoritesDbAdapter(getContext()); mDbHelper.open(); mDbHelper.addFavorite(result.getKey(), result.getName(), result.getLat(), result.getLon()); mDbHelper.close(); } else { Toast.makeText(getContext(), "Error: " + getContext().getResources().getString(R.string.failed_adding_fav), Toast.LENGTH_LONG).show(); } } } }