/* * Copyright (c) 2013, Will Szumski * Copyright (c) 2013, Doug Szumski * * This file is part of Cyclismo. * * Cyclismo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cyclismo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cyclismo. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright 2012 Google Inc. * * 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 org.cowboycoders.cyclismo.io.maps; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.content.Context; import android.os.AsyncTask; import android.util.Log; import com.google.android.common.gdata.AndroidXmlParserFactory; import com.google.common.annotations.VisibleForTesting; import com.google.wireless.gdata.client.GDataClient; import com.google.wireless.gdata.client.HttpException; import com.google.wireless.gdata.parser.GDataParser; import com.google.wireless.gdata.parser.ParseException; import org.cowboycoders.cyclismo.Constants; import org.cowboycoders.cyclismo.io.gdata.GDataClientFactory; import org.cowboycoders.cyclismo.io.gdata.maps.MapFeatureEntry; import org.cowboycoders.cyclismo.io.gdata.maps.MapsClient; import org.cowboycoders.cyclismo.io.gdata.maps.MapsConstants; import org.cowboycoders.cyclismo.io.gdata.maps.MapsGDataConverter; import org.cowboycoders.cyclismo.io.gdata.maps.MapsMapMetadata; import org.cowboycoders.cyclismo.io.gdata.maps.XmlMapsGDataParserFactory; import java.io.IOException; import java.util.ArrayList; /** * AsyncTask for {@link ChooseMapActivity} to get all the maps from Google Maps. * * @author Jimmy Shih */ public class ChooseMapAsyncTask extends AsyncTask<Void, Integer, Boolean> { private static final String TAG = ChooseMapAsyncTask.class.getSimpleName(); private ChooseMapActivity activity; private final Account account; private final Context context; private final GDataClient gDataClient; private final MapsClient mapsClient; /** * True if can retry sending to Google Fusion Tables. */ private boolean canRetry; /** * True if the AsyncTask has completed. */ private boolean completed; /** * True if the result is success. */ private boolean success; // The following variables are for per request states private String authToken; private ArrayList<String> mapIds; private ArrayList<MapsMapMetadata> mapData; public ChooseMapAsyncTask(ChooseMapActivity activity, Account account) { this(activity, account, activity.getApplicationContext(), GDataClientFactory .getGDataClient(activity.getApplicationContext()), new MapsClient( GDataClientFactory.getGDataClient(activity.getApplicationContext()), new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()))); } /** * Creates this constructor for test. */ public ChooseMapAsyncTask(ChooseMapActivity activity, Account account, Context context, GDataClient gDataClient, MapsClient mapsClient) { this.activity = activity; this.account = account; this.context = context; this.gDataClient = gDataClient; this.mapsClient = mapsClient; canRetry = true; completed = false; success = false; } /** * Sets the activity associated with this AyncTask. * * @param activity the activity. */ public void setActivity(ChooseMapActivity activity) { this.activity = activity; if (completed && activity != null) { activity.onAsyncTaskCompleted(success, mapIds, mapData); } } @Override protected void onPreExecute() { activity.showProgressDialog(); } @Override protected Boolean doInBackground(Void... params) { try { return getMaps(); } finally { if (gDataClient != null) { gDataClient.close(); } } } @Override protected void onPostExecute(Boolean result) { success = result; completed = true; if (activity != null) { activity.onAsyncTaskCompleted(success, mapIds, mapData); } } /** * Gets all the maps from Google Maps. * * @return true if success. */ @VisibleForTesting boolean getMaps() { // Reset the per request states authToken = null; mapIds = new ArrayList<String>(); mapData = new ArrayList<MapsMapMetadata>(); try { authToken = AccountManager.get(context).blockingGetAuthToken( account, MapsConstants.SERVICE_NAME, false); } catch (OperationCanceledException e) { Log.d(TAG, "Unable to get auth token", e); return retryUpload(); } catch (AuthenticatorException e) { Log.d(TAG, "Unable to get auth token", e); return retryUpload(); } catch (IOException e) { Log.d(TAG, "Unable to get auth token", e); return retryUpload(); } if (isCancelled()) { return false; } GDataParser gDataParser = null; try { gDataParser = mapsClient.getParserForFeed( MapFeatureEntry.class, MapsClient.getMapsFeed(), authToken); gDataParser.init(); while (gDataParser.hasMoreData()) { MapFeatureEntry entry = (MapFeatureEntry) gDataParser.readNextEntry(null); mapIds.add(MapsGDataConverter.getMapidForEntry(entry)); mapData.add(MapsGDataConverter.getMapMetadataForEntry(entry)); } } catch (ParseException e) { Log.d(TAG, "Unable to get maps", e); return retryUpload(); } catch (IOException e) { Log.d(TAG, "Unable to get maps", e); return retryUpload(); } catch (HttpException e) { Log.d(TAG, "Unable to get maps", e); return retryUpload(); } finally { if (gDataParser != null) { gDataParser.close(); } } return true; } /** * Retries upload. Invalidates the authToken. If can retry, invokes * {@link ChooseMapAsyncTask#getMaps()}. Returns false if cannot retry. */ @VisibleForTesting boolean retryUpload() { if (isCancelled()) { return false; } AccountManager.get(context).invalidateAuthToken(Constants.ACCOUNT_TYPE, authToken); if (canRetry) { canRetry = false; return getMaps(); } return false; } /** * Gets the complete status of task. */ @VisibleForTesting boolean getCompleted() { return completed; } /** * Sets the complete status of task. * @param completed */ @VisibleForTesting void setCompleted(boolean completed) { this.completed = completed; } /** * Sets the status of canRetry. * @param canRetry status of canRetry */ @VisibleForTesting void setCanRetry(boolean canRetry) { this.canRetry = canRetry; } /** * Gets the status of canRetry. */ @VisibleForTesting boolean getCanRetry() { return canRetry; } }